5 #include "ev_operations.h"
8 #define NALLOC(p,n) p = (typeof(p))malloc((n) * sizeof(*p))
10 void evalue_set_si(evalue
*ev
, int n
, int d
) {
11 value_set_si(ev
->d
, d
);
13 value_set_si(ev
->x
.n
, n
);
16 void evalue_set(evalue
*ev
, Value n
, Value d
) {
17 value_assign(ev
->d
, d
);
19 value_assign(ev
->x
.n
, n
);
22 void aep_evalue(evalue
*e
, int *ref
) {
27 if (value_notzero_p(e
->d
))
28 return; /* a rational number, its already reduced */
30 return; /* hum... an overflow probably occured */
32 /* First check the components of p */
33 for (i
=0;i
<p
->size
;i
++)
34 aep_evalue(&p
->arr
[i
],ref
);
41 p
->pos
= ref
[p
->pos
-1]+1;
47 void addeliminatedparams_evalue(evalue
*e
,Matrix
*CT
) {
53 if (value_notzero_p(e
->d
))
54 return; /* a rational number, its already reduced */
56 return; /* hum... an overflow probably occured */
59 ref
= (int *)malloc(sizeof(int)*(CT
->NbRows
-1));
60 for(i
=0;i
<CT
->NbRows
-1;i
++)
61 for(j
=0;j
<CT
->NbColumns
;j
++)
62 if(value_notzero_p(CT
->p
[i
][j
])) {
67 /* Transform the references in e, using ref */
71 } /* addeliminatedparams_evalue */
73 static int mod_rational_smaller(evalue
*e1
, evalue
*e2
)
79 assert(value_notzero_p(e1
->d
));
80 assert(value_notzero_p(e2
->d
));
81 value_multiply(m
, e1
->x
.n
, e2
->d
);
82 value_division(m
, m
, e1
->d
);
83 if (value_lt(m
, e2
->x
.n
))
85 else if (value_gt(m
, e2
->x
.n
))
94 static int mod_term_smaller_r(evalue
*e1
, evalue
*e2
)
96 if (value_notzero_p(e1
->d
)) {
97 if (value_zero_p(e2
->d
))
99 int r
= mod_rational_smaller(e1
, e2
);
100 return r
== -1 ? 0 : r
;
102 if (value_notzero_p(e2
->d
))
104 if (e1
->x
.p
->pos
< e2
->x
.p
->pos
)
106 else if (e1
->x
.p
->pos
> e2
->x
.p
->pos
)
109 int r
= mod_rational_smaller(&e1
->x
.p
->arr
[1], &e2
->x
.p
->arr
[1]);
111 ? mod_term_smaller_r(&e1
->x
.p
->arr
[0], &e2
->x
.p
->arr
[0])
116 static int mod_term_smaller(evalue
*e1
, evalue
*e2
)
118 assert(value_zero_p(e1
->d
));
119 assert(value_zero_p(e2
->d
));
120 assert(e1
->x
.p
->type
== fractional
);
121 assert(e2
->x
.p
->type
== fractional
);
122 return mod_term_smaller_r(&e1
->x
.p
->arr
[0], &e2
->x
.p
->arr
[0]);
125 /* Negative pos means inequality */
126 /* s is negative of substitution if m is not zero */
135 struct fixed_param
*fixed
;
140 static int relations_depth(evalue
*e
)
145 value_zero_p(e
->d
) && e
->x
.p
->type
== relation
;
146 e
= &e
->x
.p
->arr
[1], ++d
);
150 static void Lcm3(Value i
, Value j
, Value
*res
)
156 value_multiply(*res
,i
,j
);
157 value_division(*res
, *res
, aux
);
161 static void poly_denom(evalue
*p
, Value
*d
)
165 while (value_zero_p(p
->d
)) {
166 assert(p
->x
.p
->type
== polynomial
);
167 assert(p
->x
.p
->size
== 2);
168 assert(value_notzero_p(p
->x
.p
->arr
[1].d
));
169 Lcm3(*d
, p
->x
.p
->arr
[1].d
, d
);
175 #define EVALUE_IS_ONE(ev) (value_pos_p((ev).d) && value_one_p((ev).x.n))
177 static void realloc_substitution(struct subst
*s
, int d
)
179 struct fixed_param
*n
;
182 for (i
= 0; i
< s
->n
; ++i
)
189 static int add_modulo_substitution(struct subst
*s
, evalue
*r
)
195 assert(value_zero_p(r
->d
) && r
->x
.p
->type
== relation
);
198 /* May have been reduced already */
199 if (value_notzero_p(m
->d
))
202 assert(value_zero_p(m
->d
) && m
->x
.p
->type
== fractional
);
203 assert(m
->x
.p
->size
== 3);
205 /* fractional was inverted during reduction
206 * invert it back and move constant in
208 if (!EVALUE_IS_ONE(m
->x
.p
->arr
[2])) {
209 assert(value_pos_p(m
->x
.p
->arr
[2].d
));
210 assert(value_mone_p(m
->x
.p
->arr
[2].x
.n
));
211 value_set_si(m
->x
.p
->arr
[2].x
.n
, 1);
212 value_increment(m
->x
.p
->arr
[1].x
.n
, m
->x
.p
->arr
[1].x
.n
);
213 assert(value_eq(m
->x
.p
->arr
[1].x
.n
, m
->x
.p
->arr
[1].d
));
214 value_set_si(m
->x
.p
->arr
[1].x
.n
, 1);
215 eadd(&m
->x
.p
->arr
[1], &m
->x
.p
->arr
[0]);
216 value_set_si(m
->x
.p
->arr
[1].x
.n
, 0);
217 value_set_si(m
->x
.p
->arr
[1].d
, 1);
220 /* Oops. Nested identical relations. */
221 if (!EVALUE_IS_ZERO(m
->x
.p
->arr
[1]))
224 if (s
->n
>= s
->max
) {
225 int d
= relations_depth(r
);
226 realloc_substitution(s
, d
);
230 assert(value_zero_p(p
->d
) && p
->x
.p
->type
== polynomial
);
231 assert(p
->x
.p
->size
== 2);
234 assert(value_pos_p(f
->x
.n
));
236 value_init(s
->fixed
[s
->n
].m
);
237 value_assign(s
->fixed
[s
->n
].m
, f
->d
);
238 s
->fixed
[s
->n
].pos
= p
->x
.p
->pos
;
239 value_init(s
->fixed
[s
->n
].d
);
240 value_assign(s
->fixed
[s
->n
].d
, f
->x
.n
);
241 value_init(s
->fixed
[s
->n
].s
.d
);
242 evalue_copy(&s
->fixed
[s
->n
].s
, &p
->x
.p
->arr
[0]);
248 void _reduce_evalue (evalue
*e
, struct subst
*s
, int fract
) {
254 if (value_notzero_p(e
->d
)) {
256 mpz_fdiv_r(e
->x
.n
, e
->x
.n
, e
->d
);
257 return; /* a rational number, its already reduced */
261 return; /* hum... an overflow probably occured */
263 /* First reduce the components of p */
264 add
= p
->type
== relation
;
265 for (i
=0; i
<p
->size
; i
++) {
267 add
= add_modulo_substitution(s
, e
);
269 if (i
== 0 && p
->type
==fractional
)
270 _reduce_evalue(&p
->arr
[i
], s
, 1);
272 _reduce_evalue(&p
->arr
[i
], s
, fract
);
274 if (add
&& i
== p
->size
-1) {
276 value_clear(s
->fixed
[s
->n
].m
);
277 value_clear(s
->fixed
[s
->n
].d
);
278 free_evalue_refs(&s
->fixed
[s
->n
].s
);
279 } else if (add
&& i
== 1)
280 s
->fixed
[s
->n
-1].pos
*= -1;
283 if (p
->type
==periodic
) {
285 /* Try to reduce the period */
286 for (i
=1; i
<=(p
->size
)/2; i
++) {
287 if ((p
->size
% i
)==0) {
289 /* Can we reduce the size to i ? */
291 for (k
=j
+i
; k
<e
->x
.p
->size
; k
+=i
)
292 if (!eequal(&p
->arr
[j
], &p
->arr
[k
])) goto you_lose
;
295 for (j
=i
; j
<p
->size
; j
++) free_evalue_refs(&p
->arr
[j
]);
299 you_lose
: /* OK, lets not do it */
304 /* Try to reduce its strength */
307 memcpy(e
,&p
->arr
[0],sizeof(evalue
));
311 else if (p
->type
==polynomial
) {
312 for (k
= 0; s
&& k
< s
->n
; ++k
) {
313 if (s
->fixed
[k
].pos
== p
->pos
) {
314 int divide
= value_notone_p(s
->fixed
[k
].d
);
317 if (value_notzero_p(s
->fixed
[k
].m
)) {
320 assert(p
->size
== 2);
321 if (divide
&& value_ne(s
->fixed
[k
].d
, p
->arr
[1].x
.n
))
323 if (!mpz_divisible_p(s
->fixed
[k
].m
, p
->arr
[1].d
))
330 value_assign(d
.d
, s
->fixed
[k
].d
);
332 if (value_notzero_p(s
->fixed
[k
].m
))
333 value_oppose(d
.x
.n
, s
->fixed
[k
].m
);
335 value_set_si(d
.x
.n
, 1);
338 for (i
=p
->size
-1;i
>=1;i
--) {
339 emul(&s
->fixed
[k
].s
, &p
->arr
[i
]);
341 emul(&d
, &p
->arr
[i
]);
342 eadd(&p
->arr
[i
], &p
->arr
[i
-1]);
343 free_evalue_refs(&(p
->arr
[i
]));
346 _reduce_evalue(&p
->arr
[0], s
, fract
);
349 free_evalue_refs(&d
);
355 /* Try to reduce the degree */
356 for (i
=p
->size
-1;i
>=1;i
--) {
357 if (!(value_one_p(p
->arr
[i
].d
) && value_zero_p(p
->arr
[i
].x
.n
)))
359 /* Zero coefficient */
360 free_evalue_refs(&(p
->arr
[i
]));
365 /* Try to reduce its strength */
368 memcpy(e
,&p
->arr
[0],sizeof(evalue
));
372 else if (p
->type
==fractional
) {
376 if (value_notzero_p(p
->arr
[0].d
)) {
378 value_assign(v
.d
, p
->arr
[0].d
);
380 mpz_fdiv_r(v
.x
.n
, p
->arr
[0].x
.n
, p
->arr
[0].d
);
385 evalue
*pp
= &p
->arr
[0];
386 assert(value_zero_p(pp
->d
) && pp
->x
.p
->type
== polynomial
);
387 assert(pp
->x
.p
->size
== 2);
389 /* search for exact duplicate among the modulo inequalities */
391 f
= &pp
->x
.p
->arr
[1];
392 for (k
= 0; s
&& k
< s
->n
; ++k
) {
393 if (-s
->fixed
[k
].pos
== pp
->x
.p
->pos
&&
394 value_eq(s
->fixed
[k
].d
, f
->x
.n
) &&
395 value_eq(s
->fixed
[k
].m
, f
->d
) &&
396 eequal(&s
->fixed
[k
].s
, &pp
->x
.p
->arr
[0]))
403 /* replace { E/m } by { (E-1)/m } + 1/m */
408 evalue_set_si(&extra
, 1, 1);
409 value_assign(extra
.d
, g
);
410 eadd(&extra
, &v
.x
.p
->arr
[1]);
411 free_evalue_refs(&extra
);
413 /* We've been going in circles; stop now */
414 if (value_ge(v
.x
.p
->arr
[1].x
.n
, v
.x
.p
->arr
[1].d
)) {
415 free_evalue_refs(&v
);
417 evalue_set_si(&v
, 0, 1);
422 value_set_si(v
.d
, 0);
423 v
.x
.p
= new_enode(fractional
, 3, -1);
424 evalue_set_si(&v
.x
.p
->arr
[1], 1, 1);
425 value_assign(v
.x
.p
->arr
[1].d
, g
);
426 evalue_set_si(&v
.x
.p
->arr
[2], 1, 1);
427 evalue_copy(&v
.x
.p
->arr
[0], &p
->arr
[0]);
430 for (f
= &v
.x
.p
->arr
[0]; value_zero_p(f
->d
);
433 value_division(f
->d
, g
, f
->d
);
434 value_multiply(f
->x
.n
, f
->x
.n
, f
->d
);
435 value_assign(f
->d
, g
);
436 value_decrement(f
->x
.n
, f
->x
.n
);
437 mpz_fdiv_r(f
->x
.n
, f
->x
.n
, f
->d
);
439 Gcd(f
->d
, f
->x
.n
, &g
);
440 value_division(f
->d
, f
->d
, g
);
441 value_division(f
->x
.n
, f
->x
.n
, g
);
450 /* reduction may have made this fractional arg smaller */
451 i
= reorder
? p
->size
: 1;
452 for ( ; i
< p
->size
; ++i
)
453 if (value_zero_p(p
->arr
[i
].d
) &&
454 p
->arr
[i
].x
.p
->type
== fractional
&&
455 !mod_term_smaller(e
, &p
->arr
[i
]))
459 value_set_si(v
.d
, 0);
460 v
.x
.p
= new_enode(fractional
, 3, -1);
461 evalue_set_si(&v
.x
.p
->arr
[1], 0, 1);
462 evalue_set_si(&v
.x
.p
->arr
[2], 1, 1);
463 evalue_copy(&v
.x
.p
->arr
[0], &p
->arr
[0]);
473 for (pp
= &p
->arr
[0]; value_zero_p(pp
->d
);
474 pp
= &pp
->x
.p
->arr
[0]) {
475 f
= &pp
->x
.p
->arr
[1];
476 assert(value_pos_p(f
->d
));
477 mpz_mul_ui(twice
, f
->x
.n
, 2);
478 if (value_lt(twice
, f
->d
))
480 if (value_eq(twice
, f
->d
))
488 value_set_si(v
.d
, 0);
489 v
.x
.p
= new_enode(fractional
, 3, -1);
490 evalue_set_si(&v
.x
.p
->arr
[1], 0, 1);
491 poly_denom(&p
->arr
[0], &twice
);
492 value_assign(v
.x
.p
->arr
[1].d
, twice
);
493 value_decrement(v
.x
.p
->arr
[1].x
.n
, twice
);
494 evalue_set_si(&v
.x
.p
->arr
[2], -1, 1);
495 evalue_copy(&v
.x
.p
->arr
[0], &p
->arr
[0]);
497 for (pp
= &v
.x
.p
->arr
[0]; value_zero_p(pp
->d
);
498 pp
= &pp
->x
.p
->arr
[0]) {
499 f
= &pp
->x
.p
->arr
[1];
500 value_oppose(f
->x
.n
, f
->x
.n
);
501 mpz_fdiv_r(f
->x
.n
, f
->x
.n
, f
->d
);
503 value_division(pp
->d
, twice
, pp
->d
);
504 value_multiply(pp
->x
.n
, pp
->x
.n
, pp
->d
);
505 value_assign(pp
->d
, twice
);
506 value_oppose(pp
->x
.n
, pp
->x
.n
);
507 value_decrement(pp
->x
.n
, pp
->x
.n
);
508 mpz_fdiv_r(pp
->x
.n
, pp
->x
.n
, pp
->d
);
518 for (i
=p
->size
-1;i
>=2;i
--) {
519 emul(&v
, &p
->arr
[i
]);
520 eadd(&p
->arr
[i
], &p
->arr
[i
-1]);
521 free_evalue_refs(&(p
->arr
[i
]));
524 free_evalue_refs(&v
);
525 _reduce_evalue(&p
->arr
[1], s
, fract
);
528 /* Try to reduce the degree */
529 for (i
=p
->size
-1;i
>=2;i
--) {
530 if (!(value_one_p(p
->arr
[i
].d
) && value_zero_p(p
->arr
[i
].x
.n
)))
532 /* Zero coefficient */
533 free_evalue_refs(&(p
->arr
[i
]));
538 /* Try to reduce its strength */
541 memcpy(e
,&p
->arr
[1],sizeof(evalue
));
542 free_evalue_refs(&(p
->arr
[0]));
546 else if (p
->type
== relation
) {
547 if (p
->size
== 3 && eequal(&p
->arr
[1], &p
->arr
[2])) {
548 free_evalue_refs(&(p
->arr
[2]));
549 free_evalue_refs(&(p
->arr
[0]));
556 if (p
->size
== 3 && EVALUE_IS_ZERO(p
->arr
[2])) {
557 free_evalue_refs(&(p
->arr
[2]));
560 if (p
->size
== 2 && EVALUE_IS_ZERO(p
->arr
[1])) {
561 free_evalue_refs(&(p
->arr
[1]));
562 free_evalue_refs(&(p
->arr
[0]));
563 evalue_set_si(e
, 0, 1);
570 /* Relation was reduced by means of an identical
571 * inequality => remove
573 if (value_zero_p(m
->d
) && !EVALUE_IS_ZERO(m
->x
.p
->arr
[1]))
576 if (reduced
|| value_notzero_p(p
->arr
[0].d
)) {
577 if (!reduced
&& value_zero_p(p
->arr
[0].x
.n
)) {
579 memcpy(e
,&p
->arr
[1],sizeof(evalue
));
581 free_evalue_refs(&(p
->arr
[2]));
585 memcpy(e
,&p
->arr
[2],sizeof(evalue
));
587 evalue_set_si(e
, 0, 1);
588 free_evalue_refs(&(p
->arr
[1]));
590 free_evalue_refs(&(p
->arr
[0]));
596 } /* reduce_evalue */
598 static void add_substitution(struct subst
*s
, Value
*row
, unsigned dim
)
603 for (k
= 0; k
< dim
; ++k
)
604 if (value_notzero_p(row
[k
+1]))
607 Vector_Normalize_Positive(row
+1, dim
+1, k
);
608 assert(s
->n
< s
->max
);
609 value_init(s
->fixed
[s
->n
].d
);
610 value_init(s
->fixed
[s
->n
].m
);
611 value_assign(s
->fixed
[s
->n
].d
, row
[k
+1]);
612 s
->fixed
[s
->n
].pos
= k
+1;
613 value_set_si(s
->fixed
[s
->n
].m
, 0);
614 r
= &s
->fixed
[s
->n
].s
;
616 for (l
= k
+1; l
< dim
; ++l
)
617 if (value_notzero_p(row
[l
+1])) {
618 value_set_si(r
->d
, 0);
619 r
->x
.p
= new_enode(polynomial
, 2, l
+ 1);
620 value_init(r
->x
.p
->arr
[1].x
.n
);
621 value_oppose(r
->x
.p
->arr
[1].x
.n
, row
[l
+1]);
622 value_set_si(r
->x
.p
->arr
[1].d
, 1);
626 value_oppose(r
->x
.n
, row
[dim
+1]);
627 value_set_si(r
->d
, 1);
631 void reduce_evalue (evalue
*e
) {
632 struct subst s
= { NULL
, 0, 0 };
634 if (value_notzero_p(e
->d
))
635 return; /* a rational number, its already reduced */
637 if (e
->x
.p
->type
== partition
) {
640 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
642 Polyhedron
*D
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]);
643 /* This shouldn't really happen;
644 * Empty domains should not be added.
651 D
= DomainConvex(D
, 0);
652 if (!D
->next
&& D
->NbEq
) {
656 realloc_substitution(&s
, dim
);
658 int d
= relations_depth(&e
->x
.p
->arr
[2*i
+1]);
660 NALLOC(s
.fixed
, s
.max
);
663 for (j
= 0; j
< D
->NbEq
; ++j
)
664 add_substitution(&s
, D
->Constraint
[j
], dim
);
666 if (D
!= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]))
668 _reduce_evalue(&e
->x
.p
->arr
[2*i
+1], &s
, 0);
669 if (EVALUE_IS_ZERO(e
->x
.p
->arr
[2*i
+1])) {
671 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
672 Domain_Free(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]));
673 value_clear(e
->x
.p
->arr
[2*i
].d
);
675 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
676 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
681 for (j
= 0; j
< s
.n
; ++j
) {
682 value_clear(s
.fixed
[j
].d
);
683 free_evalue_refs(&s
.fixed
[j
].s
);
687 if (e
->x
.p
->size
== 0) {
689 evalue_set_si(e
, 0, 1);
694 _reduce_evalue(e
, &s
, 0);
697 void print_evalue(FILE *DST
,evalue
*e
,char **pname
) {
699 if(value_notzero_p(e
->d
)) {
700 if(value_notone_p(e
->d
)) {
701 value_print(DST
,VALUE_FMT
,e
->x
.n
);
703 value_print(DST
,VALUE_FMT
,e
->d
);
706 value_print(DST
,VALUE_FMT
,e
->x
.n
);
710 print_enode(DST
,e
->x
.p
,pname
);
714 void print_enode(FILE *DST
,enode
*p
,char **pname
) {
719 fprintf(DST
, "NULL");
725 for (i
=0; i
<p
->size
; i
++) {
726 print_evalue(DST
, &p
->arr
[i
], pname
);
730 fprintf(DST
, " }\n");
734 for (i
=p
->size
-1; i
>=0; i
--) {
735 print_evalue(DST
, &p
->arr
[i
], pname
);
736 if (i
==1) fprintf(DST
, " * %s + ", pname
[p
->pos
-1]);
738 fprintf(DST
, " * %s^%d + ", pname
[p
->pos
-1], i
);
740 fprintf(DST
, " )\n");
744 for (i
=0; i
<p
->size
; i
++) {
745 print_evalue(DST
, &p
->arr
[i
], pname
);
746 if (i
!=(p
->size
-1)) fprintf(DST
, ", ");
748 fprintf(DST
," ]_%s", pname
[p
->pos
-1]);
752 for (i
=p
->size
-1; i
>=1; i
--) {
753 print_evalue(DST
, &p
->arr
[i
], pname
);
757 print_evalue(DST
, &p
->arr
[0], pname
);
760 fprintf(DST
, "^%d + ", i
-1);
765 fprintf(DST
, " )\n");
769 print_evalue(DST
, &p
->arr
[0], pname
);
770 fprintf(DST
, "= 0 ] * \n");
771 print_evalue(DST
, &p
->arr
[1], pname
);
773 fprintf(DST
, " +\n [ ");
774 print_evalue(DST
, &p
->arr
[0], pname
);
775 fprintf(DST
, "!= 0 ] * \n");
776 print_evalue(DST
, &p
->arr
[2], pname
);
780 for (i
=0; i
<p
->size
/2; i
++) {
781 Print_Domain(DST
, EVALUE_DOMAIN(p
->arr
[2*i
]), pname
);
782 print_evalue(DST
, &p
->arr
[2*i
+1], pname
);
791 static void eadd_rev(evalue
*e1
, evalue
*res
)
795 evalue_copy(&ev
, e1
);
797 free_evalue_refs(res
);
801 static void eadd_rev_cst (evalue
*e1
, evalue
*res
)
805 evalue_copy(&ev
, e1
);
806 eadd(res
, &ev
.x
.p
->arr
[ev
.x
.p
->type
==fractional
]);
807 free_evalue_refs(res
);
811 struct section
{ Polyhedron
* D
; evalue E
; };
813 void eadd_partitions (evalue
*e1
,evalue
*res
)
818 s
= (struct section
*)
819 malloc((e1
->x
.p
->size
/2+1) * (res
->x
.p
->size
/2+1) *
820 sizeof(struct section
));
824 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
825 assert(res
->x
.p
->size
>= 2);
826 fd
= DomainDifference(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
827 EVALUE_DOMAIN(res
->x
.p
->arr
[0]), 0);
829 for (i
= 1; i
< res
->x
.p
->size
/2; ++i
) {
831 fd
= DomainDifference(fd
, EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
840 value_init(s
[n
].E
.d
);
841 evalue_copy(&s
[n
].E
, &e1
->x
.p
->arr
[2*j
+1]);
845 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
) {
846 fd
= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]);
847 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
849 d
= DomainIntersection(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
850 EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
856 fd
= DomainDifference(fd
, EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]), 0);
857 if (t
!= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]))
859 value_init(s
[n
].E
.d
);
860 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*i
+1]);
861 eadd(&e1
->x
.p
->arr
[2*j
+1], &s
[n
].E
);
866 s
[n
].E
= res
->x
.p
->arr
[2*i
+1];
870 free_evalue_refs(&res
->x
.p
->arr
[2*i
+1]);
873 if (fd
!= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]))
874 Domain_Free(EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]));
875 value_clear(res
->x
.p
->arr
[2*i
].d
);
879 res
->x
.p
= new_enode(partition
, 2*n
, -1);
880 for (j
= 0; j
< n
; ++j
) {
881 s
[j
].D
= DomainConstraintSimplify(s
[j
].D
, 0);
882 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
883 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
884 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
890 static void explicit_complement(evalue
*res
)
892 enode
*rel
= new_enode(relation
, 3, 0);
894 value_clear(rel
->arr
[0].d
);
895 rel
->arr
[0] = res
->x
.p
->arr
[0];
896 value_clear(rel
->arr
[1].d
);
897 rel
->arr
[1] = res
->x
.p
->arr
[1];
898 value_set_si(rel
->arr
[2].d
, 1);
899 value_init(rel
->arr
[2].x
.n
);
900 value_set_si(rel
->arr
[2].x
.n
, 0);
905 void eadd(evalue
*e1
,evalue
*res
) {
908 if (value_notzero_p(e1
->d
) && value_notzero_p(res
->d
)) {
909 /* Add two rational numbers */
915 value_multiply(m1
,e1
->x
.n
,res
->d
);
916 value_multiply(m2
,res
->x
.n
,e1
->d
);
917 value_addto(res
->x
.n
,m1
,m2
);
918 value_multiply(res
->d
,e1
->d
,res
->d
);
919 Gcd(res
->x
.n
,res
->d
,&g
);
920 if (value_notone_p(g
)) {
921 value_division(res
->d
,res
->d
,g
);
922 value_division(res
->x
.n
,res
->x
.n
,g
);
924 value_clear(g
); value_clear(m1
); value_clear(m2
);
927 else if (value_notzero_p(e1
->d
) && value_zero_p(res
->d
)) {
928 switch (res
->x
.p
->type
) {
930 /* Add the constant to the constant term of a polynomial*/
931 eadd(e1
, &res
->x
.p
->arr
[0]);
934 /* Add the constant to all elements of a periodic number */
935 for (i
=0; i
<res
->x
.p
->size
; i
++) {
936 eadd(e1
, &res
->x
.p
->arr
[i
]);
940 fprintf(stderr
, "eadd: cannot add const with vector\n");
943 eadd(e1
, &res
->x
.p
->arr
[1]);
946 assert(EVALUE_IS_ZERO(*e1
));
947 break; /* Do nothing */
949 /* Create (zero) complement if needed */
950 if (res
->x
.p
->size
< 3 && !EVALUE_IS_ZERO(*e1
))
951 explicit_complement(res
);
952 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
953 eadd(e1
, &res
->x
.p
->arr
[i
]);
959 /* add polynomial or periodic to constant
960 * you have to exchange e1 and res, before doing addition */
962 else if (value_zero_p(e1
->d
) && value_notzero_p(res
->d
)) {
966 else { // ((e1->d==0) && (res->d==0))
967 assert(!((e1
->x
.p
->type
== partition
) ^
968 (res
->x
.p
->type
== partition
)));
969 if (e1
->x
.p
->type
== partition
) {
970 eadd_partitions(e1
, res
);
973 if (e1
->x
.p
->type
== relation
&&
974 (res
->x
.p
->type
!= relation
||
975 mod_term_smaller(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]))) {
979 if (res
->x
.p
->type
== relation
) {
980 if (e1
->x
.p
->type
== relation
&&
981 eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0])) {
982 if (res
->x
.p
->size
< 3 && e1
->x
.p
->size
== 3)
983 explicit_complement(res
);
984 if (e1
->x
.p
->size
< 3 && res
->x
.p
->size
== 3)
985 explicit_complement(e1
);
986 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
987 eadd(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
990 if (res
->x
.p
->size
< 3)
991 explicit_complement(res
);
992 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
993 eadd(e1
, &res
->x
.p
->arr
[i
]);
996 if ((e1
->x
.p
->type
!= res
->x
.p
->type
) ) {
997 /* adding to evalues of different type. two cases are possible
998 * res is periodic and e1 is polynomial, you have to exchange
999 * e1 and res then to add e1 to the constant term of res */
1000 if (e1
->x
.p
->type
== polynomial
) {
1001 eadd_rev_cst(e1
, res
);
1003 else if (res
->x
.p
->type
== polynomial
) {
1004 /* res is polynomial and e1 is periodic,
1005 add e1 to the constant term of res */
1007 eadd(e1
,&res
->x
.p
->arr
[0]);
1013 else if (e1
->x
.p
->pos
!= res
->x
.p
->pos
||
1014 (res
->x
.p
->type
== fractional
&&
1015 !eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]))) {
1016 /* adding evalues of different position (i.e function of different unknowns
1017 * to case are possible */
1019 switch (res
->x
.p
->type
) {
1021 if(mod_term_smaller(res
, e1
))
1022 eadd(e1
,&res
->x
.p
->arr
[1]);
1024 eadd_rev_cst(e1
, res
);
1026 case polynomial
: // res and e1 are polynomials
1027 // add e1 to the constant term of res
1029 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1030 eadd(e1
,&res
->x
.p
->arr
[0]);
1032 eadd_rev_cst(e1
, res
);
1033 // value_clear(g); value_clear(m1); value_clear(m2);
1035 case periodic
: // res and e1 are pointers to periodic numbers
1036 //add e1 to all elements of res
1038 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1039 for (i
=0;i
<res
->x
.p
->size
;i
++) {
1040 eadd(e1
,&res
->x
.p
->arr
[i
]);
1049 //same type , same pos and same size
1050 if (e1
->x
.p
->size
== res
->x
.p
->size
) {
1051 // add any element in e1 to the corresponding element in res
1052 if (res
->x
.p
->type
== fractional
)
1053 assert(eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]));
1054 i
= res
->x
.p
->type
== fractional
? 1 : 0;
1055 for (; i
<res
->x
.p
->size
; i
++) {
1056 eadd(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1061 /* Sizes are different */
1062 switch(res
->x
.p
->type
) {
1065 /* VIN100: if e1-size > res-size you have to copy e1 in a */
1066 /* new enode and add res to that new node. If you do not do */
1067 /* that, you lose the the upper weight part of e1 ! */
1069 if(e1
->x
.p
->size
> res
->x
.p
->size
)
1073 if (res
->x
.p
->type
== fractional
)
1074 assert(eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]));
1075 i
= res
->x
.p
->type
== fractional
? 1 : 0;
1076 for (; i
<e1
->x
.p
->size
; i
++) {
1077 eadd(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1084 /* add two periodics of the same pos (unknown) but whith different sizes (periods) */
1087 /* you have to create a new evalue 'ne' in whitch size equals to the lcm
1088 of the sizes of e1 and res, then to copy res periodicaly in ne, after
1089 to add periodicaly elements of e1 to elements of ne, and finaly to
1094 value_init(ex
); value_init(ey
);value_init(ep
);
1097 value_set_si(ex
,e1
->x
.p
->size
);
1098 value_set_si(ey
,res
->x
.p
->size
);
1099 value_assign (ep
,*Lcm(ex
,ey
));
1100 p
=(int)mpz_get_si(ep
);
1101 ne
= (evalue
*) malloc (sizeof(evalue
));
1103 value_set_si( ne
->d
,0);
1105 ne
->x
.p
=new_enode(res
->x
.p
->type
,p
, res
->x
.p
->pos
);
1107 value_assign(ne
->x
.p
->arr
[i
].d
, res
->x
.p
->arr
[i
%y
].d
);
1108 if (value_notzero_p(ne
->x
.p
->arr
[i
].d
)) {
1109 value_init(ne
->x
.p
->arr
[i
].x
.n
);
1110 value_assign(ne
->x
.p
->arr
[i
].x
.n
, res
->x
.p
->arr
[i
%y
].x
.n
);
1113 ne
->x
.p
->arr
[i
].x
.p
=ecopy(res
->x
.p
->arr
[i
%y
].x
.p
);
1117 eadd(&e1
->x
.p
->arr
[i
%x
], &ne
->x
.p
->arr
[i
]);
1120 value_assign(res
->d
, ne
->d
);
1126 fprintf(stderr
, "eadd: ?cannot add vectors of different length\n");
1133 static void emul_rev (evalue
*e1
, evalue
*res
)
1137 evalue_copy(&ev
, e1
);
1139 free_evalue_refs(res
);
1143 static void emul_poly (evalue
*e1
, evalue
*res
)
1145 int i
, j
, o
= res
->x
.p
->type
== fractional
;
1147 int size
=(e1
->x
.p
->size
+ res
->x
.p
->size
- o
- 1);
1149 value_set_si(tmp
.d
,0);
1150 tmp
.x
.p
=new_enode(res
->x
.p
->type
, size
, res
->x
.p
->pos
);
1152 evalue_copy(&tmp
.x
.p
->arr
[0], &e1
->x
.p
->arr
[0]);
1153 for (i
=o
; i
< e1
->x
.p
->size
; i
++) {
1154 evalue_copy(&tmp
.x
.p
->arr
[i
], &e1
->x
.p
->arr
[i
]);
1155 emul(&res
->x
.p
->arr
[o
], &tmp
.x
.p
->arr
[i
]);
1158 evalue_set_si(&tmp
.x
.p
->arr
[i
], 0, 1);
1159 for (i
=o
+1; i
<res
->x
.p
->size
; i
++)
1160 for (j
=o
; j
<e1
->x
.p
->size
; j
++) {
1163 evalue_copy(&ev
, &e1
->x
.p
->arr
[j
]);
1164 emul(&res
->x
.p
->arr
[i
], &ev
);
1165 eadd(&ev
, &tmp
.x
.p
->arr
[i
+j
-o
]);
1166 free_evalue_refs(&ev
);
1168 free_evalue_refs(res
);
1172 void emul_partitions (evalue
*e1
,evalue
*res
)
1177 s
= (struct section
*)
1178 malloc((e1
->x
.p
->size
/2) * (res
->x
.p
->size
/2) *
1179 sizeof(struct section
));
1183 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
) {
1184 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
1185 d
= DomainIntersection(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
1186 EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
1192 /* This code is only needed because the partitions
1193 are not true partitions.
1195 for (k
= 0; k
< n
; ++k
) {
1196 if (DomainIncludes(s
[k
].D
, d
))
1198 if (DomainIncludes(d
, s
[k
].D
)) {
1199 Domain_Free(s
[k
].D
);
1200 free_evalue_refs(&s
[k
].E
);
1211 value_init(s
[n
].E
.d
);
1212 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*i
+1]);
1213 emul(&e1
->x
.p
->arr
[2*j
+1], &s
[n
].E
);
1217 Domain_Free(EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]));
1218 value_clear(res
->x
.p
->arr
[2*i
].d
);
1219 free_evalue_refs(&res
->x
.p
->arr
[2*i
+1]);
1223 res
->x
.p
= new_enode(partition
, 2*n
, -1);
1224 for (j
= 0; j
< n
; ++j
) {
1225 s
[j
].D
= DomainConstraintSimplify(s
[j
].D
, 0);
1226 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
1227 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
1228 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
1234 #define value_two_p(val) (mpz_cmp_si(val,2) == 0)
1236 /* Computes the product of two evalues "e1" and "res" and puts the result in "res". you must
1237 * do a copy of "res" befor calling this function if you nead it after. The vector type of
1238 * evalues is not treated here */
1240 void emul (evalue
*e1
, evalue
*res
){
1243 if((value_zero_p(e1
->d
)&&e1
->x
.p
->type
==evector
)||(value_zero_p(res
->d
)&&(res
->x
.p
->type
==evector
))) {
1244 fprintf(stderr
, "emul: do not proced on evector type !\n");
1248 if (value_zero_p(e1
->d
) && e1
->x
.p
->type
== partition
) {
1249 if (value_zero_p(res
->d
) && res
->x
.p
->type
== partition
)
1250 emul_partitions(e1
, res
);
1253 } else if (value_zero_p(res
->d
) && res
->x
.p
->type
== partition
) {
1254 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
)
1255 emul(e1
, &res
->x
.p
->arr
[2*i
+1]);
1257 if (value_zero_p(res
->d
) && res
->x
.p
->type
== relation
) {
1258 if (value_zero_p(e1
->d
) && e1
->x
.p
->type
== relation
&&
1259 eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0])) {
1260 if (res
->x
.p
->size
< 3 && e1
->x
.p
->size
== 3)
1261 explicit_complement(res
);
1262 if (e1
->x
.p
->size
< 3 && res
->x
.p
->size
== 3)
1263 explicit_complement(e1
);
1264 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1265 emul(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1268 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1269 emul(e1
, &res
->x
.p
->arr
[i
]);
1271 if(value_zero_p(e1
->d
)&& value_zero_p(res
->d
)) {
1272 switch(e1
->x
.p
->type
) {
1274 switch(res
->x
.p
->type
) {
1276 if(e1
->x
.p
->pos
== res
->x
.p
->pos
) {
1277 /* Product of two polynomials of the same variable */
1282 /* Product of two polynomials of different variables */
1284 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1285 for( i
=0; i
<res
->x
.p
->size
; i
++)
1286 emul(e1
, &res
->x
.p
->arr
[i
]);
1294 /* Product of a polynomial and a periodic or fractional */
1299 switch(res
->x
.p
->type
) {
1301 if(e1
->x
.p
->pos
==res
->x
.p
->pos
&& e1
->x
.p
->size
==res
->x
.p
->size
) {
1302 /* Product of two periodics of the same parameter and period */
1304 for(i
=0; i
<res
->x
.p
->size
;i
++)
1305 emul(&(e1
->x
.p
->arr
[i
]), &(res
->x
.p
->arr
[i
]));
1310 if(e1
->x
.p
->pos
==res
->x
.p
->pos
&& e1
->x
.p
->size
!=res
->x
.p
->size
) {
1311 /* Product of two periodics of the same parameter and different periods */
1315 value_init(x
); value_init(y
);value_init(z
);
1318 value_set_si(x
,e1
->x
.p
->size
);
1319 value_set_si(y
,res
->x
.p
->size
);
1320 value_assign (z
,*Lcm(x
,y
));
1321 lcm
=(int)mpz_get_si(z
);
1322 newp
= (evalue
*) malloc (sizeof(evalue
));
1323 value_init(newp
->d
);
1324 value_set_si( newp
->d
,0);
1325 newp
->x
.p
=new_enode(periodic
,lcm
, e1
->x
.p
->pos
);
1326 for(i
=0;i
<lcm
;i
++) {
1327 value_assign(newp
->x
.p
->arr
[i
].d
, res
->x
.p
->arr
[i
%iy
].d
);
1328 if (value_notzero_p(newp
->x
.p
->arr
[i
].d
)) {
1329 value_assign(newp
->x
.p
->arr
[i
].x
.n
, res
->x
.p
->arr
[i
%iy
].x
.n
);
1332 newp
->x
.p
->arr
[i
].x
.p
=ecopy(res
->x
.p
->arr
[i
%iy
].x
.p
);
1337 emul(&e1
->x
.p
->arr
[i
%ix
], &newp
->x
.p
->arr
[i
]);
1339 value_assign(res
->d
,newp
->d
);
1342 value_clear(x
); value_clear(y
);value_clear(z
);
1346 /* Product of two periodics of different parameters */
1348 for(i
=0; i
<res
->x
.p
->size
; i
++)
1349 emul(e1
, &(res
->x
.p
->arr
[i
]));
1355 /* Product of a periodic and a polynomial */
1357 for(i
=0; i
<res
->x
.p
->size
; i
++)
1358 emul(e1
, &(res
->x
.p
->arr
[i
]));
1364 switch(res
->x
.p
->type
) {
1366 for(i
=0; i
<res
->x
.p
->size
; i
++)
1367 emul(e1
, &(res
->x
.p
->arr
[i
]));
1372 if (e1
->x
.p
->pos
== res
->x
.p
->pos
&&
1373 eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0])) {
1376 poly_denom(&e1
->x
.p
->arr
[0], &d
.d
);
1377 if (!value_two_p(d
.d
))
1381 value_set_si(d
.x
.n
, 1);
1383 /* { x }^2 == { x }/2 */
1384 /* a0 b0 + (a0 b1 + a1 b0 + a1 b1/2) { x } */
1385 assert(e1
->x
.p
->size
== 3);
1386 assert(res
->x
.p
->size
== 3);
1388 evalue_copy(&tmp
, &res
->x
.p
->arr
[2]);
1390 eadd(&res
->x
.p
->arr
[1], &tmp
);
1391 emul(&e1
->x
.p
->arr
[2], &tmp
);
1392 emul(&e1
->x
.p
->arr
[1], res
);
1393 eadd(&tmp
, &res
->x
.p
->arr
[2]);
1394 free_evalue_refs(&tmp
);
1399 if(mod_term_smaller(res
, e1
))
1400 for(i
=1; i
<res
->x
.p
->size
; i
++)
1401 emul(e1
, &(res
->x
.p
->arr
[i
]));
1416 if (value_notzero_p(e1
->d
)&& value_notzero_p(res
->d
)) {
1417 /* Product of two rational numbers */
1421 value_multiply(res
->d
,e1
->d
,res
->d
);
1422 value_multiply(res
->x
.n
,e1
->x
.n
,res
->x
.n
);
1423 Gcd(res
->x
.n
, res
->d
,&g
);
1424 if (value_notone_p(g
)) {
1425 value_division(res
->d
,res
->d
,g
);
1426 value_division(res
->x
.n
,res
->x
.n
,g
);
1432 if(value_zero_p(e1
->d
)&& value_notzero_p(res
->d
)) {
1433 /* Product of an expression (polynomial or peririodic) and a rational number */
1439 /* Product of a rationel number and an expression (polynomial or peririodic) */
1441 i
= res
->x
.p
->type
== fractional
? 1 : 0;
1442 for (; i
<res
->x
.p
->size
; i
++)
1443 emul(e1
, &res
->x
.p
->arr
[i
]);
1454 void emask(evalue
*mask
, evalue
*res
) {
1460 if (EVALUE_IS_ZERO(*res
))
1463 assert(value_zero_p(mask
->d
));
1464 assert(mask
->x
.p
->type
== partition
);
1465 assert(value_zero_p(res
->d
));
1466 assert(res
->x
.p
->type
== partition
);
1468 s
= (struct section
*)
1469 malloc((mask
->x
.p
->size
/2+1) * (res
->x
.p
->size
/2) *
1470 sizeof(struct section
));
1474 evalue_set_si(&mone
, -1, 1);
1477 for (j
= 0; j
< res
->x
.p
->size
/2; ++j
) {
1478 assert(mask
->x
.p
->size
>= 2);
1479 fd
= DomainDifference(EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]),
1480 EVALUE_DOMAIN(mask
->x
.p
->arr
[0]), 0);
1482 for (i
= 1; i
< mask
->x
.p
->size
/2; ++i
) {
1484 fd
= DomainDifference(fd
, EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]), 0);
1493 value_init(s
[n
].E
.d
);
1494 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*j
+1]);
1498 for (i
= 0; i
< mask
->x
.p
->size
/2; ++i
) {
1499 if (EVALUE_IS_ONE(mask
->x
.p
->arr
[2*i
+1]))
1502 fd
= EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]);
1503 eadd(&mone
, &mask
->x
.p
->arr
[2*i
+1]);
1504 emul(&mone
, &mask
->x
.p
->arr
[2*i
+1]);
1505 for (j
= 0; j
< res
->x
.p
->size
/2; ++j
) {
1507 d
= DomainIntersection(EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]),
1508 EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]), 0);
1514 fd
= DomainDifference(fd
, EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]), 0);
1515 if (t
!= EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]))
1517 value_init(s
[n
].E
.d
);
1518 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*j
+1]);
1519 emul(&mask
->x
.p
->arr
[2*i
+1], &s
[n
].E
);
1525 /* Just ignore; this may have been previously masked off */
1529 free_evalue_refs(&mone
);
1530 free_evalue_refs(mask
);
1531 free_evalue_refs(res
);
1534 evalue_set_si(res
, 0, 1);
1536 res
->x
.p
= new_enode(partition
, 2*n
, -1);
1537 for (j
= 0; j
< n
; ++j
) {
1538 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
1539 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
1540 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
1547 void evalue_copy(evalue
*dst
, evalue
*src
)
1549 value_assign(dst
->d
, src
->d
);
1550 if(value_notzero_p(src
->d
)) {
1551 value_init(dst
->x
.n
);
1552 value_assign(dst
->x
.n
, src
->x
.n
);
1554 dst
->x
.p
= ecopy(src
->x
.p
);
1557 enode
*new_enode(enode_type type
,int size
,int pos
) {
1563 fprintf(stderr
, "Allocating enode of size 0 !\n" );
1566 res
= (enode
*) malloc(sizeof(enode
) + (size
-1)*sizeof(evalue
));
1570 for(i
=0; i
<size
; i
++) {
1571 value_init(res
->arr
[i
].d
);
1572 value_set_si(res
->arr
[i
].d
,0);
1573 res
->arr
[i
].x
.p
= 0;
1578 enode
*ecopy(enode
*e
) {
1583 res
= new_enode(e
->type
,e
->size
,e
->pos
);
1584 for(i
=0;i
<e
->size
;++i
) {
1585 value_assign(res
->arr
[i
].d
,e
->arr
[i
].d
);
1586 if(value_zero_p(res
->arr
[i
].d
))
1587 res
->arr
[i
].x
.p
= ecopy(e
->arr
[i
].x
.p
);
1588 else if (EVALUE_IS_DOMAIN(res
->arr
[i
]))
1589 EVALUE_SET_DOMAIN(res
->arr
[i
], Domain_Copy(EVALUE_DOMAIN(e
->arr
[i
])));
1591 value_init(res
->arr
[i
].x
.n
);
1592 value_assign(res
->arr
[i
].x
.n
,e
->arr
[i
].x
.n
);
1598 int ecmp(const evalue
*e1
, const evalue
*e2
)
1604 if (value_notzero_p(e1
->d
) && value_notzero_p(e2
->d
)) {
1608 value_multiply(m
, e1
->x
.n
, e2
->d
);
1609 value_multiply(m2
, e2
->x
.n
, e1
->d
);
1611 if (value_lt(m
, m2
))
1613 else if (value_gt(m
, m2
))
1623 if (value_notzero_p(e1
->d
))
1625 if (value_notzero_p(e2
->d
))
1631 if (p1
->type
!= p2
->type
)
1632 return p1
->type
- p2
->type
;
1633 if (p1
->pos
!= p2
->pos
)
1634 return p1
->pos
- p2
->pos
;
1635 if (p1
->size
!= p2
->size
)
1636 return p1
->size
- p2
->size
;
1638 for (i
= p1
->size
-1; i
>= 0; --i
)
1639 if ((r
= ecmp(&p1
->arr
[i
], &p2
->arr
[i
])) != 0)
1645 int eequal(evalue
*e1
,evalue
*e2
) {
1650 if (value_ne(e1
->d
,e2
->d
))
1653 /* e1->d == e2->d */
1654 if (value_notzero_p(e1
->d
)) {
1655 if (value_ne(e1
->x
.n
,e2
->x
.n
))
1658 /* e1->d == e2->d != 0 AND e1->n == e2->n */
1662 /* e1->d == e2->d == 0 */
1665 if (p1
->type
!= p2
->type
) return 0;
1666 if (p1
->size
!= p2
->size
) return 0;
1667 if (p1
->pos
!= p2
->pos
) return 0;
1668 for (i
=0; i
<p1
->size
; i
++)
1669 if (!eequal(&p1
->arr
[i
], &p2
->arr
[i
]) )
1674 void free_evalue_refs(evalue
*e
) {
1679 if (EVALUE_IS_DOMAIN(*e
)) {
1680 Domain_Free(EVALUE_DOMAIN(*e
));
1683 } else if (value_pos_p(e
->d
)) {
1685 /* 'e' stores a constant */
1687 value_clear(e
->x
.n
);
1690 assert(value_zero_p(e
->d
));
1693 if (!p
) return; /* null pointer */
1694 for (i
=0; i
<p
->size
; i
++) {
1695 free_evalue_refs(&(p
->arr
[i
]));
1699 } /* free_evalue_refs */
1701 static void mod2table_r(evalue
*e
, Vector
*periods
, Value m
, int p
,
1702 Vector
* val
, evalue
*res
)
1704 unsigned nparam
= periods
->Size
;
1707 double d
= compute_evalue(e
, val
->p
);
1708 d
*= VALUE_TO_DOUBLE(m
);
1713 value_assign(res
->d
, m
);
1714 value_init(res
->x
.n
);
1715 value_set_double(res
->x
.n
, d
);
1716 mpz_fdiv_r(res
->x
.n
, res
->x
.n
, m
);
1719 if (value_one_p(periods
->p
[p
]))
1720 mod2table_r(e
, periods
, m
, p
+1, val
, res
);
1725 value_assign(tmp
, periods
->p
[p
]);
1726 value_set_si(res
->d
, 0);
1727 res
->x
.p
= new_enode(periodic
, VALUE_TO_INT(tmp
), p
+1);
1729 value_decrement(tmp
, tmp
);
1730 value_assign(val
->p
[p
], tmp
);
1731 mod2table_r(e
, periods
, m
, p
+1, val
,
1732 &res
->x
.p
->arr
[VALUE_TO_INT(tmp
)]);
1733 } while (value_pos_p(tmp
));
1739 static void rel2table(evalue
*e
, int zero
)
1741 if (value_pos_p(e
->d
)) {
1742 if (value_zero_p(e
->x
.n
) == zero
)
1743 value_set_si(e
->x
.n
, 1);
1745 value_set_si(e
->x
.n
, 0);
1746 value_set_si(e
->d
, 1);
1749 for (i
= 0; i
< e
->x
.p
->size
; ++i
)
1750 rel2table(&e
->x
.p
->arr
[i
], zero
);
1754 void evalue_mod2table(evalue
*e
, int nparam
)
1759 if (EVALUE_IS_DOMAIN(*e
) || value_pos_p(e
->d
))
1762 for (i
=0; i
<p
->size
; i
++) {
1763 evalue_mod2table(&(p
->arr
[i
]), nparam
);
1765 if (p
->type
== relation
) {
1771 evalue_copy(©
, &p
->arr
[0]);
1773 rel2table(&p
->arr
[0], 1);
1774 emul(&p
->arr
[0], &p
->arr
[1]);
1776 rel2table(©
, 0);
1777 emul(©
, &p
->arr
[2]);
1778 eadd(&p
->arr
[2], &p
->arr
[1]);
1779 free_evalue_refs(&p
->arr
[2]);
1780 free_evalue_refs(©
);
1782 free_evalue_refs(&p
->arr
[0]);
1787 } else if (p
->type
== fractional
) {
1788 Vector
*periods
= Vector_Alloc(nparam
);
1789 Vector
*val
= Vector_Alloc(nparam
);
1795 value_set_si(tmp
, 1);
1796 Vector_Set(periods
->p
, 1, nparam
);
1797 Vector_Set(val
->p
, 0, nparam
);
1798 for (ev
= &p
->arr
[0]; value_zero_p(ev
->d
); ev
= &ev
->x
.p
->arr
[0]) {
1801 assert(p
->type
== polynomial
);
1802 assert(p
->size
== 2);
1803 value_assign(periods
->p
[p
->pos
-1], p
->arr
[1].d
);
1804 Lcm3(tmp
, p
->arr
[1].d
, &tmp
);
1807 mod2table_r(&p
->arr
[0], periods
, tmp
, 0, val
, &EP
);
1810 evalue_set_si(&res
, 0, 1);
1811 /* Compute the polynomial using Horner's rule */
1812 for (i
=p
->size
-1;i
>1;i
--) {
1813 eadd(&p
->arr
[i
], &res
);
1816 eadd(&p
->arr
[1], &res
);
1818 free_evalue_refs(e
);
1819 free_evalue_refs(&EP
);
1824 Vector_Free(periods
);
1826 } /* evalue_mod2table */
1828 /********************************************************/
1829 /* function in domain */
1830 /* check if the parameters in list_args */
1831 /* verifies the constraints of Domain P */
1832 /********************************************************/
1833 int in_domain(Polyhedron
*P
, Value
*list_args
) {
1836 Value v
; /* value of the constraint of a row when
1837 parameters are instanciated*/
1843 /*P->Constraint constraint matrice of polyhedron P*/
1844 for(row
=0;row
<P
->NbConstraints
;row
++) {
1845 value_assign(v
,P
->Constraint
[row
][P
->Dimension
+1]); /*constant part*/
1846 for(col
=1;col
<P
->Dimension
+1;col
++) {
1847 value_multiply(tmp
,P
->Constraint
[row
][col
],list_args
[col
-1]);
1848 value_addto(v
,v
,tmp
);
1850 if (value_notzero_p(P
->Constraint
[row
][0])) {
1852 /*if v is not >=0 then this constraint is not respected */
1853 if (value_neg_p(v
)) {
1857 return P
->next
? in_domain(P
->next
, list_args
) : 0;
1862 /*if v is not = 0 then this constraint is not respected */
1863 if (value_notzero_p(v
))
1868 /*if not return before this point => all
1869 the constraints are respected */
1875 /****************************************************/
1876 /* function compute enode */
1877 /* compute the value of enode p with parameters */
1878 /* list "list_args */
1879 /* compute the polynomial or the periodic */
1880 /****************************************************/
1882 static double compute_enode(enode
*p
, Value
*list_args
) {
1894 if (p
->type
== polynomial
) {
1896 value_assign(param
,list_args
[p
->pos
-1]);
1898 /* Compute the polynomial using Horner's rule */
1899 for (i
=p
->size
-1;i
>0;i
--) {
1900 res
+=compute_evalue(&p
->arr
[i
],list_args
);
1901 res
*=VALUE_TO_DOUBLE(param
);
1903 res
+=compute_evalue(&p
->arr
[0],list_args
);
1905 else if (p
->type
== fractional
) {
1906 double d
= compute_evalue(&p
->arr
[0], list_args
);
1907 d
-= floor(d
+1e-10);
1909 /* Compute the polynomial using Horner's rule */
1910 for (i
=p
->size
-1;i
>1;i
--) {
1911 res
+=compute_evalue(&p
->arr
[i
],list_args
);
1914 res
+=compute_evalue(&p
->arr
[1],list_args
);
1916 else if (p
->type
== periodic
) {
1917 value_assign(param
,list_args
[p
->pos
-1]);
1919 /* Choose the right element of the periodic */
1920 value_absolute(m
,param
);
1921 value_set_si(param
,p
->size
);
1922 value_modulus(m
,m
,param
);
1923 res
= compute_evalue(&p
->arr
[VALUE_TO_INT(m
)],list_args
);
1925 else if (p
->type
== relation
) {
1926 if (fabs(compute_evalue(&p
->arr
[0], list_args
)) < 1e-10)
1927 res
= compute_evalue(&p
->arr
[1], list_args
);
1928 else if (p
->size
> 2)
1929 res
= compute_evalue(&p
->arr
[2], list_args
);
1931 else if (p
->type
== partition
) {
1932 for (i
= 0; i
< p
->size
/2; ++i
)
1933 if (in_domain(EVALUE_DOMAIN(p
->arr
[2*i
]), list_args
)) {
1934 res
= compute_evalue(&p
->arr
[2*i
+1], list_args
);
1941 } /* compute_enode */
1943 /*************************************************/
1944 /* return the value of Ehrhart Polynomial */
1945 /* It returns a double, because since it is */
1946 /* a recursive function, some intermediate value */
1947 /* might not be integral */
1948 /*************************************************/
1950 double compute_evalue(evalue
*e
,Value
*list_args
) {
1954 if (value_notzero_p(e
->d
)) {
1955 if (value_notone_p(e
->d
))
1956 res
= VALUE_TO_DOUBLE(e
->x
.n
) / VALUE_TO_DOUBLE(e
->d
);
1958 res
= VALUE_TO_DOUBLE(e
->x
.n
);
1961 res
= compute_enode(e
->x
.p
,list_args
);
1963 } /* compute_evalue */
1966 /****************************************************/
1967 /* function compute_poly : */
1968 /* Check for the good validity domain */
1969 /* return the number of point in the Polyhedron */
1970 /* in allocated memory */
1971 /* Using the Ehrhart pseudo-polynomial */
1972 /****************************************************/
1973 Value
*compute_poly(Enumeration
*en
,Value
*list_args
) {
1976 /* double d; int i; */
1978 tmp
= (Value
*) malloc (sizeof(Value
));
1979 assert(tmp
!= NULL
);
1981 value_set_si(*tmp
,0);
1984 return(tmp
); /* no ehrhart polynomial */
1985 if(en
->ValidityDomain
) {
1986 if(!en
->ValidityDomain
->Dimension
) { /* no parameters */
1987 value_set_double(*tmp
,compute_evalue(&en
->EP
,list_args
)+.25);
1992 return(tmp
); /* no Validity Domain */
1994 if(in_domain(en
->ValidityDomain
,list_args
)) {
1996 #ifdef EVAL_EHRHART_DEBUG
1997 Print_Domain(stdout
,en
->ValidityDomain
);
1998 print_evalue(stdout
,&en
->EP
);
2001 /* d = compute_evalue(&en->EP,list_args);
2003 printf("(double)%lf = %d\n", d, i ); */
2004 value_set_double(*tmp
,compute_evalue(&en
->EP
,list_args
)+.25);
2010 value_set_si(*tmp
,0);
2011 return(tmp
); /* no compatible domain with the arguments */
2012 } /* compute_poly */
2014 size_t value_size(Value v
) {
2015 return (v
[0]._mp_size
> 0 ? v
[0]._mp_size
: -v
[0]._mp_size
)
2016 * sizeof(v
[0]._mp_d
[0]);
2019 size_t domain_size(Polyhedron
*D
)
2022 size_t s
= sizeof(*D
);
2024 for (i
= 0; i
< D
->NbConstraints
; ++i
)
2025 for (j
= 0; j
< D
->Dimension
+2; ++j
)
2026 s
+= value_size(D
->Constraint
[i
][j
]);
2028 for (i
= 0; i
< D
->NbRays
; ++i
)
2029 for (j
= 0; j
< D
->Dimension
+2; ++j
)
2030 s
+= value_size(D
->Ray
[i
][j
]);
2032 return D
->next
? s
+domain_size(D
->next
) : s
;
2035 size_t enode_size(enode
*p
) {
2036 size_t s
= sizeof(*p
) - sizeof(p
->arr
[0]);
2039 if (p
->type
== partition
)
2040 for (i
= 0; i
< p
->size
/2; ++i
) {
2041 s
+= domain_size(EVALUE_DOMAIN(p
->arr
[2*i
]));
2042 s
+= evalue_size(&p
->arr
[2*i
+1]);
2045 for (i
= 0; i
< p
->size
; ++i
) {
2046 s
+= evalue_size(&p
->arr
[i
]);
2051 size_t evalue_size(evalue
*e
)
2053 size_t s
= sizeof(*e
);
2054 s
+= value_size(e
->d
);
2055 if (value_notzero_p(e
->d
))
2056 s
+= value_size(e
->x
.n
);
2058 s
+= enode_size(e
->x
.p
);
2062 static evalue
*find_second(evalue
*base
, evalue
*cst
, evalue
*e
, Value m
)
2064 evalue
*found
= NULL
;
2069 if (value_pos_p(e
->d
) || e
->x
.p
->type
!= fractional
)
2072 value_init(offset
.d
);
2073 value_init(offset
.x
.n
);
2074 poly_denom(&e
->x
.p
->arr
[0], &offset
.d
);
2075 Lcm3(m
, offset
.d
, &offset
.d
);
2076 value_set_si(offset
.x
.n
, 1);
2079 evalue_copy(©
, cst
);
2082 mpz_fdiv_r(cst
->x
.n
, cst
->x
.n
, cst
->d
);
2084 if (eequal(base
, &e
->x
.p
->arr
[0]))
2085 found
= &e
->x
.p
->arr
[0];
2087 value_set_si(offset
.x
.n
, -2);
2090 mpz_fdiv_r(cst
->x
.n
, cst
->x
.n
, cst
->d
);
2092 if (eequal(base
, &e
->x
.p
->arr
[0]))
2095 free_evalue_refs(cst
);
2096 free_evalue_refs(&offset
);
2099 for (i
= 1; !found
&& i
< e
->x
.p
->size
; ++i
)
2100 found
= find_second(base
, cst
, &e
->x
.p
->arr
[i
], m
);
2105 static evalue
*find_relation_pair(evalue
*e
)
2108 evalue
*found
= NULL
;
2110 if (EVALUE_IS_DOMAIN(*e
) || value_pos_p(e
->d
))
2113 if (e
->x
.p
->type
== fractional
) {
2118 poly_denom(&e
->x
.p
->arr
[0], &m
);
2120 for (cst
= &e
->x
.p
->arr
[0]; value_zero_p(cst
->d
);
2121 cst
= &cst
->x
.p
->arr
[0])
2124 for (i
= 1; !found
&& i
< e
->x
.p
->size
; ++i
)
2125 found
= find_second(&e
->x
.p
->arr
[0], cst
, &e
->x
.p
->arr
[i
], m
);
2130 i
= e
->x
.p
->type
== relation
;
2131 for (; !found
&& i
< e
->x
.p
->size
; ++i
)
2132 found
= find_relation_pair(&e
->x
.p
->arr
[i
]);
2137 void evalue_mod2relation(evalue
*e
) {
2140 if (value_zero_p(e
->d
) && e
->x
.p
->type
== partition
) {
2143 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
2144 evalue_mod2relation(&e
->x
.p
->arr
[2*i
+1]);
2149 while ((d
= find_relation_pair(e
)) != NULL
) {
2153 value_init(split
.d
);
2154 value_set_si(split
.d
, 0);
2155 split
.x
.p
= new_enode(relation
, 3, 0);
2156 evalue_set_si(&split
.x
.p
->arr
[1], 1, 1);
2157 evalue_set_si(&split
.x
.p
->arr
[2], 1, 1);
2159 ev
= &split
.x
.p
->arr
[0];
2160 value_set_si(ev
->d
, 0);
2161 ev
->x
.p
= new_enode(fractional
, 3, -1);
2162 evalue_set_si(&ev
->x
.p
->arr
[1], 0, 1);
2163 evalue_set_si(&ev
->x
.p
->arr
[2], 1, 1);
2164 evalue_copy(&ev
->x
.p
->arr
[0], d
);
2170 free_evalue_refs(&split
);
2174 static int evalue_comp(const void * a
, const void * b
)
2176 const evalue
*e1
= *(const evalue
**)a
;
2177 const evalue
*e2
= *(const evalue
**)b
;
2178 return ecmp(e1
, e2
);
2181 void evalue_combine(evalue
*e
)
2188 if (value_notzero_p(e
->d
) || e
->x
.p
->type
!= partition
)
2191 NALLOC(evs
, e
->x
.p
->size
/2);
2192 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
2193 evs
[i
] = &e
->x
.p
->arr
[2*i
+1];
2194 qsort(evs
, e
->x
.p
->size
/2, sizeof(evs
[0]), evalue_comp
);
2195 p
= new_enode(partition
, e
->x
.p
->size
, -1);
2196 for (i
= 0, k
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2197 if (k
== 0 || ecmp(&p
->arr
[2*k
-1], evs
[i
]) != 0) {
2198 p
->arr
[2*k
] = *(evs
[i
]-1);
2199 p
->arr
[2*k
+1] = *(evs
[i
]);
2202 Polyhedron
*D
= EVALUE_DOMAIN(*(evs
[i
]-1));
2207 L
->next
= EVALUE_DOMAIN(p
->arr
[2*k
-2]);
2208 EVALUE_SET_DOMAIN(p
->arr
[2*k
-2], D
);
2209 free_evalue_refs(evs
[i
]);
2216 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2218 if (value_notzero_p(e
->x
.p
->arr
[2*i
+1].d
))
2220 H
= DomainConvex(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]), 0);
2223 for (k
= 0; k
< e
->x
.p
->size
/2; ++k
) {
2224 Polyhedron
*D
, *N
, **P
;
2227 P
= &EVALUE_DOMAIN(e
->x
.p
->arr
[2*k
]);
2234 if (D
->NbEq
<= H
->NbEq
) {
2240 tmp
.x
.p
= new_enode(partition
, 2, -1);
2241 EVALUE_SET_DOMAIN(tmp
.x
.p
->arr
[0], Polyhedron_Copy(D
));
2242 evalue_copy(&tmp
.x
.p
->arr
[1], &e
->x
.p
->arr
[2*i
+1]);
2243 reduce_evalue(&tmp
);
2244 if (value_notzero_p(tmp
.d
) ||
2245 ecmp(&tmp
.x
.p
->arr
[1], &e
->x
.p
->arr
[2*k
+1]) != 0)
2248 D
->next
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]);
2249 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]) = D
;
2252 free_evalue_refs(&tmp
);
2257 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2259 Polyhedron
*D
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]);
2261 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
2263 if (2*i
< e
->x
.p
->size
) {
2264 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
2265 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
2272 H
= DomainConvex(D
, 0);
2273 E
= DomainDifference(H
, D
, 0);
2275 D
= DomainDifference(H
, E
, 0);
2278 EVALUE_SET_DOMAIN(p
->arr
[2*i
], D
);