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 static void reorder_terms(enode
*p
, evalue
*v
)
251 int offset
= p
->type
== fractional
;
253 for (i
= p
->size
-1; i
>= offset
+1; i
--) {
255 eadd(&p
->arr
[i
], &p
->arr
[i
-1]);
256 free_evalue_refs(&(p
->arr
[i
]));
262 void _reduce_evalue (evalue
*e
, struct subst
*s
, int fract
) {
268 if (value_notzero_p(e
->d
)) {
270 mpz_fdiv_r(e
->x
.n
, e
->x
.n
, e
->d
);
271 return; /* a rational number, its already reduced */
275 return; /* hum... an overflow probably occured */
277 /* First reduce the components of p */
278 add
= p
->type
== relation
;
279 for (i
=0; i
<p
->size
; i
++) {
281 add
= add_modulo_substitution(s
, e
);
283 if (i
== 0 && p
->type
==fractional
)
284 _reduce_evalue(&p
->arr
[i
], s
, 1);
286 _reduce_evalue(&p
->arr
[i
], s
, fract
);
288 if (add
&& i
== p
->size
-1) {
290 value_clear(s
->fixed
[s
->n
].m
);
291 value_clear(s
->fixed
[s
->n
].d
);
292 free_evalue_refs(&s
->fixed
[s
->n
].s
);
293 } else if (add
&& i
== 1)
294 s
->fixed
[s
->n
-1].pos
*= -1;
297 if (p
->type
==periodic
) {
299 /* Try to reduce the period */
300 for (i
=1; i
<=(p
->size
)/2; i
++) {
301 if ((p
->size
% i
)==0) {
303 /* Can we reduce the size to i ? */
305 for (k
=j
+i
; k
<e
->x
.p
->size
; k
+=i
)
306 if (!eequal(&p
->arr
[j
], &p
->arr
[k
])) goto you_lose
;
309 for (j
=i
; j
<p
->size
; j
++) free_evalue_refs(&p
->arr
[j
]);
313 you_lose
: /* OK, lets not do it */
318 /* Try to reduce its strength */
321 memcpy(e
,&p
->arr
[0],sizeof(evalue
));
325 else if (p
->type
==polynomial
) {
326 for (k
= 0; s
&& k
< s
->n
; ++k
) {
327 if (s
->fixed
[k
].pos
== p
->pos
) {
328 int divide
= value_notone_p(s
->fixed
[k
].d
);
331 if (value_notzero_p(s
->fixed
[k
].m
)) {
334 assert(p
->size
== 2);
335 if (divide
&& value_ne(s
->fixed
[k
].d
, p
->arr
[1].x
.n
))
337 if (!mpz_divisible_p(s
->fixed
[k
].m
, p
->arr
[1].d
))
344 value_assign(d
.d
, s
->fixed
[k
].d
);
346 if (value_notzero_p(s
->fixed
[k
].m
))
347 value_oppose(d
.x
.n
, s
->fixed
[k
].m
);
349 value_set_si(d
.x
.n
, 1);
352 for (i
=p
->size
-1;i
>=1;i
--) {
353 emul(&s
->fixed
[k
].s
, &p
->arr
[i
]);
355 emul(&d
, &p
->arr
[i
]);
356 eadd(&p
->arr
[i
], &p
->arr
[i
-1]);
357 free_evalue_refs(&(p
->arr
[i
]));
360 _reduce_evalue(&p
->arr
[0], s
, fract
);
363 free_evalue_refs(&d
);
369 /* Try to reduce the degree */
370 for (i
=p
->size
-1;i
>=1;i
--) {
371 if (!(value_one_p(p
->arr
[i
].d
) && value_zero_p(p
->arr
[i
].x
.n
)))
373 /* Zero coefficient */
374 free_evalue_refs(&(p
->arr
[i
]));
379 /* Try to reduce its strength */
382 memcpy(e
,&p
->arr
[0],sizeof(evalue
));
386 else if (p
->type
==fractional
) {
390 if (value_notzero_p(p
->arr
[0].d
)) {
392 value_assign(v
.d
, p
->arr
[0].d
);
394 mpz_fdiv_r(v
.x
.n
, p
->arr
[0].x
.n
, p
->arr
[0].d
);
399 evalue
*pp
= &p
->arr
[0];
400 assert(value_zero_p(pp
->d
) && pp
->x
.p
->type
== polynomial
);
401 assert(pp
->x
.p
->size
== 2);
403 /* search for exact duplicate among the modulo inequalities */
405 f
= &pp
->x
.p
->arr
[1];
406 for (k
= 0; s
&& k
< s
->n
; ++k
) {
407 if (-s
->fixed
[k
].pos
== pp
->x
.p
->pos
&&
408 value_eq(s
->fixed
[k
].d
, f
->x
.n
) &&
409 value_eq(s
->fixed
[k
].m
, f
->d
) &&
410 eequal(&s
->fixed
[k
].s
, &pp
->x
.p
->arr
[0]))
417 /* replace { E/m } by { (E-1)/m } + 1/m */
422 evalue_set_si(&extra
, 1, 1);
423 value_assign(extra
.d
, g
);
424 eadd(&extra
, &v
.x
.p
->arr
[1]);
425 free_evalue_refs(&extra
);
427 /* We've been going in circles; stop now */
428 if (value_ge(v
.x
.p
->arr
[1].x
.n
, v
.x
.p
->arr
[1].d
)) {
429 free_evalue_refs(&v
);
431 evalue_set_si(&v
, 0, 1);
436 value_set_si(v
.d
, 0);
437 v
.x
.p
= new_enode(fractional
, 3, -1);
438 evalue_set_si(&v
.x
.p
->arr
[1], 1, 1);
439 value_assign(v
.x
.p
->arr
[1].d
, g
);
440 evalue_set_si(&v
.x
.p
->arr
[2], 1, 1);
441 evalue_copy(&v
.x
.p
->arr
[0], &p
->arr
[0]);
444 for (f
= &v
.x
.p
->arr
[0]; value_zero_p(f
->d
);
447 value_division(f
->d
, g
, f
->d
);
448 value_multiply(f
->x
.n
, f
->x
.n
, f
->d
);
449 value_assign(f
->d
, g
);
450 value_decrement(f
->x
.n
, f
->x
.n
);
451 mpz_fdiv_r(f
->x
.n
, f
->x
.n
, f
->d
);
453 Gcd(f
->d
, f
->x
.n
, &g
);
454 value_division(f
->d
, f
->d
, g
);
455 value_division(f
->x
.n
, f
->x
.n
, g
);
464 /* reduction may have made this fractional arg smaller */
465 i
= reorder
? p
->size
: 1;
466 for ( ; i
< p
->size
; ++i
)
467 if (value_zero_p(p
->arr
[i
].d
) &&
468 p
->arr
[i
].x
.p
->type
== fractional
&&
469 !mod_term_smaller(e
, &p
->arr
[i
]))
473 value_set_si(v
.d
, 0);
474 v
.x
.p
= new_enode(fractional
, 3, -1);
475 evalue_set_si(&v
.x
.p
->arr
[1], 0, 1);
476 evalue_set_si(&v
.x
.p
->arr
[2], 1, 1);
477 evalue_copy(&v
.x
.p
->arr
[0], &p
->arr
[0]);
487 for (pp
= &p
->arr
[0]; value_zero_p(pp
->d
);
488 pp
= &pp
->x
.p
->arr
[0]) {
489 f
= &pp
->x
.p
->arr
[1];
490 assert(value_pos_p(f
->d
));
491 mpz_mul_ui(twice
, f
->x
.n
, 2);
492 if (value_lt(twice
, f
->d
))
494 if (value_eq(twice
, f
->d
))
502 value_set_si(v
.d
, 0);
503 v
.x
.p
= new_enode(fractional
, 3, -1);
504 evalue_set_si(&v
.x
.p
->arr
[1], 0, 1);
505 poly_denom(&p
->arr
[0], &twice
);
506 value_assign(v
.x
.p
->arr
[1].d
, twice
);
507 value_decrement(v
.x
.p
->arr
[1].x
.n
, twice
);
508 evalue_set_si(&v
.x
.p
->arr
[2], -1, 1);
509 evalue_copy(&v
.x
.p
->arr
[0], &p
->arr
[0]);
511 for (pp
= &v
.x
.p
->arr
[0]; value_zero_p(pp
->d
);
512 pp
= &pp
->x
.p
->arr
[0]) {
513 f
= &pp
->x
.p
->arr
[1];
514 value_oppose(f
->x
.n
, f
->x
.n
);
515 mpz_fdiv_r(f
->x
.n
, f
->x
.n
, f
->d
);
517 value_division(pp
->d
, twice
, pp
->d
);
518 value_multiply(pp
->x
.n
, pp
->x
.n
, pp
->d
);
519 value_assign(pp
->d
, twice
);
520 value_oppose(pp
->x
.n
, pp
->x
.n
);
521 value_decrement(pp
->x
.n
, pp
->x
.n
);
522 mpz_fdiv_r(pp
->x
.n
, pp
->x
.n
, pp
->d
);
532 reorder_terms(p
, &v
);
533 _reduce_evalue(&p
->arr
[1], s
, fract
);
536 /* Try to reduce the degree */
537 for (i
=p
->size
-1;i
>=2;i
--) {
538 if (!(value_one_p(p
->arr
[i
].d
) && value_zero_p(p
->arr
[i
].x
.n
)))
540 /* Zero coefficient */
541 free_evalue_refs(&(p
->arr
[i
]));
546 /* Try to reduce its strength */
549 memcpy(e
,&p
->arr
[1],sizeof(evalue
));
550 free_evalue_refs(&(p
->arr
[0]));
554 else if (p
->type
== relation
) {
555 if (p
->size
== 3 && eequal(&p
->arr
[1], &p
->arr
[2])) {
556 free_evalue_refs(&(p
->arr
[2]));
557 free_evalue_refs(&(p
->arr
[0]));
564 if (p
->size
== 3 && EVALUE_IS_ZERO(p
->arr
[2])) {
565 free_evalue_refs(&(p
->arr
[2]));
568 if (p
->size
== 2 && EVALUE_IS_ZERO(p
->arr
[1])) {
569 free_evalue_refs(&(p
->arr
[1]));
570 free_evalue_refs(&(p
->arr
[0]));
571 evalue_set_si(e
, 0, 1);
578 /* Relation was reduced by means of an identical
579 * inequality => remove
581 if (value_zero_p(m
->d
) && !EVALUE_IS_ZERO(m
->x
.p
->arr
[1]))
584 if (reduced
|| value_notzero_p(p
->arr
[0].d
)) {
585 if (!reduced
&& value_zero_p(p
->arr
[0].x
.n
)) {
587 memcpy(e
,&p
->arr
[1],sizeof(evalue
));
589 free_evalue_refs(&(p
->arr
[2]));
593 memcpy(e
,&p
->arr
[2],sizeof(evalue
));
595 evalue_set_si(e
, 0, 1);
596 free_evalue_refs(&(p
->arr
[1]));
598 free_evalue_refs(&(p
->arr
[0]));
604 } /* reduce_evalue */
606 static void add_substitution(struct subst
*s
, Value
*row
, unsigned dim
)
611 for (k
= 0; k
< dim
; ++k
)
612 if (value_notzero_p(row
[k
+1]))
615 Vector_Normalize_Positive(row
+1, dim
+1, k
);
616 assert(s
->n
< s
->max
);
617 value_init(s
->fixed
[s
->n
].d
);
618 value_init(s
->fixed
[s
->n
].m
);
619 value_assign(s
->fixed
[s
->n
].d
, row
[k
+1]);
620 s
->fixed
[s
->n
].pos
= k
+1;
621 value_set_si(s
->fixed
[s
->n
].m
, 0);
622 r
= &s
->fixed
[s
->n
].s
;
624 for (l
= k
+1; l
< dim
; ++l
)
625 if (value_notzero_p(row
[l
+1])) {
626 value_set_si(r
->d
, 0);
627 r
->x
.p
= new_enode(polynomial
, 2, l
+ 1);
628 value_init(r
->x
.p
->arr
[1].x
.n
);
629 value_oppose(r
->x
.p
->arr
[1].x
.n
, row
[l
+1]);
630 value_set_si(r
->x
.p
->arr
[1].d
, 1);
634 value_oppose(r
->x
.n
, row
[dim
+1]);
635 value_set_si(r
->d
, 1);
639 void reduce_evalue (evalue
*e
) {
640 struct subst s
= { NULL
, 0, 0 };
642 if (value_notzero_p(e
->d
))
643 return; /* a rational number, its already reduced */
645 if (e
->x
.p
->type
== partition
) {
648 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
650 Polyhedron
*D
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]);
651 /* This shouldn't really happen;
652 * Empty domains should not be added.
659 D
= DomainConvex(D
, 0);
660 if (!D
->next
&& D
->NbEq
) {
664 realloc_substitution(&s
, dim
);
666 int d
= relations_depth(&e
->x
.p
->arr
[2*i
+1]);
668 NALLOC(s
.fixed
, s
.max
);
671 for (j
= 0; j
< D
->NbEq
; ++j
)
672 add_substitution(&s
, D
->Constraint
[j
], dim
);
674 if (D
!= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]))
676 _reduce_evalue(&e
->x
.p
->arr
[2*i
+1], &s
, 0);
677 if (EVALUE_IS_ZERO(e
->x
.p
->arr
[2*i
+1])) {
679 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
680 Domain_Free(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]));
681 value_clear(e
->x
.p
->arr
[2*i
].d
);
683 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
684 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
689 for (j
= 0; j
< s
.n
; ++j
) {
690 value_clear(s
.fixed
[j
].d
);
691 free_evalue_refs(&s
.fixed
[j
].s
);
695 if (e
->x
.p
->size
== 0) {
697 evalue_set_si(e
, 0, 1);
702 _reduce_evalue(e
, &s
, 0);
705 void print_evalue(FILE *DST
,evalue
*e
,char **pname
) {
707 if(value_notzero_p(e
->d
)) {
708 if(value_notone_p(e
->d
)) {
709 value_print(DST
,VALUE_FMT
,e
->x
.n
);
711 value_print(DST
,VALUE_FMT
,e
->d
);
714 value_print(DST
,VALUE_FMT
,e
->x
.n
);
718 print_enode(DST
,e
->x
.p
,pname
);
722 void print_enode(FILE *DST
,enode
*p
,char **pname
) {
727 fprintf(DST
, "NULL");
733 for (i
=0; i
<p
->size
; i
++) {
734 print_evalue(DST
, &p
->arr
[i
], pname
);
738 fprintf(DST
, " }\n");
742 for (i
=p
->size
-1; i
>=0; i
--) {
743 print_evalue(DST
, &p
->arr
[i
], pname
);
744 if (i
==1) fprintf(DST
, " * %s + ", pname
[p
->pos
-1]);
746 fprintf(DST
, " * %s^%d + ", pname
[p
->pos
-1], i
);
748 fprintf(DST
, " )\n");
752 for (i
=0; i
<p
->size
; i
++) {
753 print_evalue(DST
, &p
->arr
[i
], pname
);
754 if (i
!=(p
->size
-1)) fprintf(DST
, ", ");
756 fprintf(DST
," ]_%s", pname
[p
->pos
-1]);
760 for (i
=p
->size
-1; i
>=1; i
--) {
761 print_evalue(DST
, &p
->arr
[i
], pname
);
765 print_evalue(DST
, &p
->arr
[0], pname
);
768 fprintf(DST
, "^%d + ", i
-1);
773 fprintf(DST
, " )\n");
777 print_evalue(DST
, &p
->arr
[0], pname
);
778 fprintf(DST
, "= 0 ] * \n");
779 print_evalue(DST
, &p
->arr
[1], pname
);
781 fprintf(DST
, " +\n [ ");
782 print_evalue(DST
, &p
->arr
[0], pname
);
783 fprintf(DST
, "!= 0 ] * \n");
784 print_evalue(DST
, &p
->arr
[2], pname
);
788 for (i
=0; i
<p
->size
/2; i
++) {
789 Print_Domain(DST
, EVALUE_DOMAIN(p
->arr
[2*i
]), pname
);
790 print_evalue(DST
, &p
->arr
[2*i
+1], pname
);
799 static void eadd_rev(evalue
*e1
, evalue
*res
)
803 evalue_copy(&ev
, e1
);
805 free_evalue_refs(res
);
809 static void eadd_rev_cst (evalue
*e1
, evalue
*res
)
813 evalue_copy(&ev
, e1
);
814 eadd(res
, &ev
.x
.p
->arr
[ev
.x
.p
->type
==fractional
]);
815 free_evalue_refs(res
);
819 struct section
{ Polyhedron
* D
; evalue E
; };
821 void eadd_partitions (evalue
*e1
,evalue
*res
)
826 s
= (struct section
*)
827 malloc((e1
->x
.p
->size
/2+1) * (res
->x
.p
->size
/2+1) *
828 sizeof(struct section
));
832 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
833 assert(res
->x
.p
->size
>= 2);
834 fd
= DomainDifference(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
835 EVALUE_DOMAIN(res
->x
.p
->arr
[0]), 0);
837 for (i
= 1; i
< res
->x
.p
->size
/2; ++i
) {
839 fd
= DomainDifference(fd
, EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
848 value_init(s
[n
].E
.d
);
849 evalue_copy(&s
[n
].E
, &e1
->x
.p
->arr
[2*j
+1]);
853 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
) {
854 fd
= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]);
855 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
857 d
= DomainIntersection(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
858 EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
864 fd
= DomainDifference(fd
, EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]), 0);
865 if (t
!= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]))
867 value_init(s
[n
].E
.d
);
868 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*i
+1]);
869 eadd(&e1
->x
.p
->arr
[2*j
+1], &s
[n
].E
);
874 s
[n
].E
= res
->x
.p
->arr
[2*i
+1];
878 free_evalue_refs(&res
->x
.p
->arr
[2*i
+1]);
881 if (fd
!= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]))
882 Domain_Free(EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]));
883 value_clear(res
->x
.p
->arr
[2*i
].d
);
887 res
->x
.p
= new_enode(partition
, 2*n
, -1);
888 for (j
= 0; j
< n
; ++j
) {
889 s
[j
].D
= DomainConstraintSimplify(s
[j
].D
, 0);
890 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
891 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
892 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
898 static void explicit_complement(evalue
*res
)
900 enode
*rel
= new_enode(relation
, 3, 0);
902 value_clear(rel
->arr
[0].d
);
903 rel
->arr
[0] = res
->x
.p
->arr
[0];
904 value_clear(rel
->arr
[1].d
);
905 rel
->arr
[1] = res
->x
.p
->arr
[1];
906 value_set_si(rel
->arr
[2].d
, 1);
907 value_init(rel
->arr
[2].x
.n
);
908 value_set_si(rel
->arr
[2].x
.n
, 0);
913 void eadd(evalue
*e1
,evalue
*res
) {
916 if (value_notzero_p(e1
->d
) && value_notzero_p(res
->d
)) {
917 /* Add two rational numbers */
923 value_multiply(m1
,e1
->x
.n
,res
->d
);
924 value_multiply(m2
,res
->x
.n
,e1
->d
);
925 value_addto(res
->x
.n
,m1
,m2
);
926 value_multiply(res
->d
,e1
->d
,res
->d
);
927 Gcd(res
->x
.n
,res
->d
,&g
);
928 if (value_notone_p(g
)) {
929 value_division(res
->d
,res
->d
,g
);
930 value_division(res
->x
.n
,res
->x
.n
,g
);
932 value_clear(g
); value_clear(m1
); value_clear(m2
);
935 else if (value_notzero_p(e1
->d
) && value_zero_p(res
->d
)) {
936 switch (res
->x
.p
->type
) {
938 /* Add the constant to the constant term of a polynomial*/
939 eadd(e1
, &res
->x
.p
->arr
[0]);
942 /* Add the constant to all elements of a periodic number */
943 for (i
=0; i
<res
->x
.p
->size
; i
++) {
944 eadd(e1
, &res
->x
.p
->arr
[i
]);
948 fprintf(stderr
, "eadd: cannot add const with vector\n");
951 eadd(e1
, &res
->x
.p
->arr
[1]);
954 assert(EVALUE_IS_ZERO(*e1
));
955 break; /* Do nothing */
957 /* Create (zero) complement if needed */
958 if (res
->x
.p
->size
< 3 && !EVALUE_IS_ZERO(*e1
))
959 explicit_complement(res
);
960 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
961 eadd(e1
, &res
->x
.p
->arr
[i
]);
967 /* add polynomial or periodic to constant
968 * you have to exchange e1 and res, before doing addition */
970 else if (value_zero_p(e1
->d
) && value_notzero_p(res
->d
)) {
974 else { // ((e1->d==0) && (res->d==0))
975 assert(!((e1
->x
.p
->type
== partition
) ^
976 (res
->x
.p
->type
== partition
)));
977 if (e1
->x
.p
->type
== partition
) {
978 eadd_partitions(e1
, res
);
981 if (e1
->x
.p
->type
== relation
&&
982 (res
->x
.p
->type
!= relation
||
983 mod_term_smaller(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]))) {
987 if (res
->x
.p
->type
== relation
) {
988 if (e1
->x
.p
->type
== relation
&&
989 eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0])) {
990 if (res
->x
.p
->size
< 3 && e1
->x
.p
->size
== 3)
991 explicit_complement(res
);
992 if (e1
->x
.p
->size
< 3 && res
->x
.p
->size
== 3)
993 explicit_complement(e1
);
994 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
995 eadd(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
998 if (res
->x
.p
->size
< 3)
999 explicit_complement(res
);
1000 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1001 eadd(e1
, &res
->x
.p
->arr
[i
]);
1004 if ((e1
->x
.p
->type
!= res
->x
.p
->type
) ) {
1005 /* adding to evalues of different type. two cases are possible
1006 * res is periodic and e1 is polynomial, you have to exchange
1007 * e1 and res then to add e1 to the constant term of res */
1008 if (e1
->x
.p
->type
== polynomial
) {
1009 eadd_rev_cst(e1
, res
);
1011 else if (res
->x
.p
->type
== polynomial
) {
1012 /* res is polynomial and e1 is periodic,
1013 add e1 to the constant term of res */
1015 eadd(e1
,&res
->x
.p
->arr
[0]);
1021 else if (e1
->x
.p
->pos
!= res
->x
.p
->pos
||
1022 (res
->x
.p
->type
== fractional
&&
1023 !eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]))) {
1024 /* adding evalues of different position (i.e function of different unknowns
1025 * to case are possible */
1027 switch (res
->x
.p
->type
) {
1029 if(mod_term_smaller(res
, e1
))
1030 eadd(e1
,&res
->x
.p
->arr
[1]);
1032 eadd_rev_cst(e1
, res
);
1034 case polynomial
: // res and e1 are polynomials
1035 // add e1 to the constant term of res
1037 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1038 eadd(e1
,&res
->x
.p
->arr
[0]);
1040 eadd_rev_cst(e1
, res
);
1041 // value_clear(g); value_clear(m1); value_clear(m2);
1043 case periodic
: // res and e1 are pointers to periodic numbers
1044 //add e1 to all elements of res
1046 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1047 for (i
=0;i
<res
->x
.p
->size
;i
++) {
1048 eadd(e1
,&res
->x
.p
->arr
[i
]);
1057 //same type , same pos and same size
1058 if (e1
->x
.p
->size
== res
->x
.p
->size
) {
1059 // add any element in e1 to the corresponding element in res
1060 if (res
->x
.p
->type
== fractional
)
1061 assert(eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]));
1062 i
= res
->x
.p
->type
== fractional
? 1 : 0;
1063 for (; i
<res
->x
.p
->size
; i
++) {
1064 eadd(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1069 /* Sizes are different */
1070 switch(res
->x
.p
->type
) {
1073 /* VIN100: if e1-size > res-size you have to copy e1 in a */
1074 /* new enode and add res to that new node. If you do not do */
1075 /* that, you lose the the upper weight part of e1 ! */
1077 if(e1
->x
.p
->size
> res
->x
.p
->size
)
1081 if (res
->x
.p
->type
== fractional
)
1082 assert(eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]));
1083 i
= res
->x
.p
->type
== fractional
? 1 : 0;
1084 for (; i
<e1
->x
.p
->size
; i
++) {
1085 eadd(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1092 /* add two periodics of the same pos (unknown) but whith different sizes (periods) */
1095 /* you have to create a new evalue 'ne' in whitch size equals to the lcm
1096 of the sizes of e1 and res, then to copy res periodicaly in ne, after
1097 to add periodicaly elements of e1 to elements of ne, and finaly to
1102 value_init(ex
); value_init(ey
);value_init(ep
);
1105 value_set_si(ex
,e1
->x
.p
->size
);
1106 value_set_si(ey
,res
->x
.p
->size
);
1107 value_assign (ep
,*Lcm(ex
,ey
));
1108 p
=(int)mpz_get_si(ep
);
1109 ne
= (evalue
*) malloc (sizeof(evalue
));
1111 value_set_si( ne
->d
,0);
1113 ne
->x
.p
=new_enode(res
->x
.p
->type
,p
, res
->x
.p
->pos
);
1115 value_assign(ne
->x
.p
->arr
[i
].d
, res
->x
.p
->arr
[i
%y
].d
);
1116 if (value_notzero_p(ne
->x
.p
->arr
[i
].d
)) {
1117 value_init(ne
->x
.p
->arr
[i
].x
.n
);
1118 value_assign(ne
->x
.p
->arr
[i
].x
.n
, res
->x
.p
->arr
[i
%y
].x
.n
);
1121 ne
->x
.p
->arr
[i
].x
.p
=ecopy(res
->x
.p
->arr
[i
%y
].x
.p
);
1125 eadd(&e1
->x
.p
->arr
[i
%x
], &ne
->x
.p
->arr
[i
]);
1128 value_assign(res
->d
, ne
->d
);
1134 fprintf(stderr
, "eadd: ?cannot add vectors of different length\n");
1141 static void emul_rev (evalue
*e1
, evalue
*res
)
1145 evalue_copy(&ev
, e1
);
1147 free_evalue_refs(res
);
1151 static void emul_poly (evalue
*e1
, evalue
*res
)
1153 int i
, j
, o
= res
->x
.p
->type
== fractional
;
1155 int size
=(e1
->x
.p
->size
+ res
->x
.p
->size
- o
- 1);
1157 value_set_si(tmp
.d
,0);
1158 tmp
.x
.p
=new_enode(res
->x
.p
->type
, size
, res
->x
.p
->pos
);
1160 evalue_copy(&tmp
.x
.p
->arr
[0], &e1
->x
.p
->arr
[0]);
1161 for (i
=o
; i
< e1
->x
.p
->size
; i
++) {
1162 evalue_copy(&tmp
.x
.p
->arr
[i
], &e1
->x
.p
->arr
[i
]);
1163 emul(&res
->x
.p
->arr
[o
], &tmp
.x
.p
->arr
[i
]);
1166 evalue_set_si(&tmp
.x
.p
->arr
[i
], 0, 1);
1167 for (i
=o
+1; i
<res
->x
.p
->size
; i
++)
1168 for (j
=o
; j
<e1
->x
.p
->size
; j
++) {
1171 evalue_copy(&ev
, &e1
->x
.p
->arr
[j
]);
1172 emul(&res
->x
.p
->arr
[i
], &ev
);
1173 eadd(&ev
, &tmp
.x
.p
->arr
[i
+j
-o
]);
1174 free_evalue_refs(&ev
);
1176 free_evalue_refs(res
);
1180 void emul_partitions (evalue
*e1
,evalue
*res
)
1185 s
= (struct section
*)
1186 malloc((e1
->x
.p
->size
/2) * (res
->x
.p
->size
/2) *
1187 sizeof(struct section
));
1191 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
) {
1192 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
1193 d
= DomainIntersection(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
1194 EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
1200 /* This code is only needed because the partitions
1201 are not true partitions.
1203 for (k
= 0; k
< n
; ++k
) {
1204 if (DomainIncludes(s
[k
].D
, d
))
1206 if (DomainIncludes(d
, s
[k
].D
)) {
1207 Domain_Free(s
[k
].D
);
1208 free_evalue_refs(&s
[k
].E
);
1219 value_init(s
[n
].E
.d
);
1220 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*i
+1]);
1221 emul(&e1
->x
.p
->arr
[2*j
+1], &s
[n
].E
);
1225 Domain_Free(EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]));
1226 value_clear(res
->x
.p
->arr
[2*i
].d
);
1227 free_evalue_refs(&res
->x
.p
->arr
[2*i
+1]);
1231 res
->x
.p
= new_enode(partition
, 2*n
, -1);
1232 for (j
= 0; j
< n
; ++j
) {
1233 s
[j
].D
= DomainConstraintSimplify(s
[j
].D
, 0);
1234 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
1235 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
1236 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
1242 #define value_two_p(val) (mpz_cmp_si(val,2) == 0)
1244 /* Computes the product of two evalues "e1" and "res" and puts the result in "res". you must
1245 * do a copy of "res" befor calling this function if you nead it after. The vector type of
1246 * evalues is not treated here */
1248 void emul (evalue
*e1
, evalue
*res
){
1251 if((value_zero_p(e1
->d
)&&e1
->x
.p
->type
==evector
)||(value_zero_p(res
->d
)&&(res
->x
.p
->type
==evector
))) {
1252 fprintf(stderr
, "emul: do not proced on evector type !\n");
1256 if (value_zero_p(e1
->d
) && e1
->x
.p
->type
== partition
) {
1257 if (value_zero_p(res
->d
) && res
->x
.p
->type
== partition
)
1258 emul_partitions(e1
, res
);
1261 } else if (value_zero_p(res
->d
) && res
->x
.p
->type
== partition
) {
1262 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
)
1263 emul(e1
, &res
->x
.p
->arr
[2*i
+1]);
1265 if (value_zero_p(res
->d
) && res
->x
.p
->type
== relation
) {
1266 if (value_zero_p(e1
->d
) && e1
->x
.p
->type
== relation
&&
1267 eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0])) {
1268 if (res
->x
.p
->size
< 3 && e1
->x
.p
->size
== 3)
1269 explicit_complement(res
);
1270 if (e1
->x
.p
->size
< 3 && res
->x
.p
->size
== 3)
1271 explicit_complement(e1
);
1272 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1273 emul(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1276 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1277 emul(e1
, &res
->x
.p
->arr
[i
]);
1279 if(value_zero_p(e1
->d
)&& value_zero_p(res
->d
)) {
1280 switch(e1
->x
.p
->type
) {
1282 switch(res
->x
.p
->type
) {
1284 if(e1
->x
.p
->pos
== res
->x
.p
->pos
) {
1285 /* Product of two polynomials of the same variable */
1290 /* Product of two polynomials of different variables */
1292 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1293 for( i
=0; i
<res
->x
.p
->size
; i
++)
1294 emul(e1
, &res
->x
.p
->arr
[i
]);
1302 /* Product of a polynomial and a periodic or fractional */
1307 switch(res
->x
.p
->type
) {
1309 if(e1
->x
.p
->pos
==res
->x
.p
->pos
&& e1
->x
.p
->size
==res
->x
.p
->size
) {
1310 /* Product of two periodics of the same parameter and period */
1312 for(i
=0; i
<res
->x
.p
->size
;i
++)
1313 emul(&(e1
->x
.p
->arr
[i
]), &(res
->x
.p
->arr
[i
]));
1318 if(e1
->x
.p
->pos
==res
->x
.p
->pos
&& e1
->x
.p
->size
!=res
->x
.p
->size
) {
1319 /* Product of two periodics of the same parameter and different periods */
1323 value_init(x
); value_init(y
);value_init(z
);
1326 value_set_si(x
,e1
->x
.p
->size
);
1327 value_set_si(y
,res
->x
.p
->size
);
1328 value_assign (z
,*Lcm(x
,y
));
1329 lcm
=(int)mpz_get_si(z
);
1330 newp
= (evalue
*) malloc (sizeof(evalue
));
1331 value_init(newp
->d
);
1332 value_set_si( newp
->d
,0);
1333 newp
->x
.p
=new_enode(periodic
,lcm
, e1
->x
.p
->pos
);
1334 for(i
=0;i
<lcm
;i
++) {
1335 value_assign(newp
->x
.p
->arr
[i
].d
, res
->x
.p
->arr
[i
%iy
].d
);
1336 if (value_notzero_p(newp
->x
.p
->arr
[i
].d
)) {
1337 value_assign(newp
->x
.p
->arr
[i
].x
.n
, res
->x
.p
->arr
[i
%iy
].x
.n
);
1340 newp
->x
.p
->arr
[i
].x
.p
=ecopy(res
->x
.p
->arr
[i
%iy
].x
.p
);
1345 emul(&e1
->x
.p
->arr
[i
%ix
], &newp
->x
.p
->arr
[i
]);
1347 value_assign(res
->d
,newp
->d
);
1350 value_clear(x
); value_clear(y
);value_clear(z
);
1354 /* Product of two periodics of different parameters */
1356 for(i
=0; i
<res
->x
.p
->size
; i
++)
1357 emul(e1
, &(res
->x
.p
->arr
[i
]));
1363 /* Product of a periodic and a polynomial */
1365 for(i
=0; i
<res
->x
.p
->size
; i
++)
1366 emul(e1
, &(res
->x
.p
->arr
[i
]));
1372 switch(res
->x
.p
->type
) {
1374 for(i
=0; i
<res
->x
.p
->size
; i
++)
1375 emul(e1
, &(res
->x
.p
->arr
[i
]));
1380 if (e1
->x
.p
->pos
== res
->x
.p
->pos
&&
1381 eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0])) {
1384 poly_denom(&e1
->x
.p
->arr
[0], &d
.d
);
1385 if (!value_two_p(d
.d
))
1389 value_set_si(d
.x
.n
, 1);
1391 /* { x }^2 == { x }/2 */
1392 /* a0 b0 + (a0 b1 + a1 b0 + a1 b1/2) { x } */
1393 assert(e1
->x
.p
->size
== 3);
1394 assert(res
->x
.p
->size
== 3);
1396 evalue_copy(&tmp
, &res
->x
.p
->arr
[2]);
1398 eadd(&res
->x
.p
->arr
[1], &tmp
);
1399 emul(&e1
->x
.p
->arr
[2], &tmp
);
1400 emul(&e1
->x
.p
->arr
[1], res
);
1401 eadd(&tmp
, &res
->x
.p
->arr
[2]);
1402 free_evalue_refs(&tmp
);
1407 if(mod_term_smaller(res
, e1
))
1408 for(i
=1; i
<res
->x
.p
->size
; i
++)
1409 emul(e1
, &(res
->x
.p
->arr
[i
]));
1424 if (value_notzero_p(e1
->d
)&& value_notzero_p(res
->d
)) {
1425 /* Product of two rational numbers */
1429 value_multiply(res
->d
,e1
->d
,res
->d
);
1430 value_multiply(res
->x
.n
,e1
->x
.n
,res
->x
.n
);
1431 Gcd(res
->x
.n
, res
->d
,&g
);
1432 if (value_notone_p(g
)) {
1433 value_division(res
->d
,res
->d
,g
);
1434 value_division(res
->x
.n
,res
->x
.n
,g
);
1440 if(value_zero_p(e1
->d
)&& value_notzero_p(res
->d
)) {
1441 /* Product of an expression (polynomial or peririodic) and a rational number */
1447 /* Product of a rationel number and an expression (polynomial or peririodic) */
1449 i
= res
->x
.p
->type
== fractional
? 1 : 0;
1450 for (; i
<res
->x
.p
->size
; i
++)
1451 emul(e1
, &res
->x
.p
->arr
[i
]);
1462 void emask(evalue
*mask
, evalue
*res
) {
1468 if (EVALUE_IS_ZERO(*res
))
1471 assert(value_zero_p(mask
->d
));
1472 assert(mask
->x
.p
->type
== partition
);
1473 assert(value_zero_p(res
->d
));
1474 assert(res
->x
.p
->type
== partition
);
1476 s
= (struct section
*)
1477 malloc((mask
->x
.p
->size
/2+1) * (res
->x
.p
->size
/2) *
1478 sizeof(struct section
));
1482 evalue_set_si(&mone
, -1, 1);
1485 for (j
= 0; j
< res
->x
.p
->size
/2; ++j
) {
1486 assert(mask
->x
.p
->size
>= 2);
1487 fd
= DomainDifference(EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]),
1488 EVALUE_DOMAIN(mask
->x
.p
->arr
[0]), 0);
1490 for (i
= 1; i
< mask
->x
.p
->size
/2; ++i
) {
1492 fd
= DomainDifference(fd
, EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]), 0);
1501 value_init(s
[n
].E
.d
);
1502 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*j
+1]);
1506 for (i
= 0; i
< mask
->x
.p
->size
/2; ++i
) {
1507 if (EVALUE_IS_ONE(mask
->x
.p
->arr
[2*i
+1]))
1510 fd
= EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]);
1511 eadd(&mone
, &mask
->x
.p
->arr
[2*i
+1]);
1512 emul(&mone
, &mask
->x
.p
->arr
[2*i
+1]);
1513 for (j
= 0; j
< res
->x
.p
->size
/2; ++j
) {
1515 d
= DomainIntersection(EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]),
1516 EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]), 0);
1522 fd
= DomainDifference(fd
, EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]), 0);
1523 if (t
!= EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]))
1525 value_init(s
[n
].E
.d
);
1526 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*j
+1]);
1527 emul(&mask
->x
.p
->arr
[2*i
+1], &s
[n
].E
);
1533 /* Just ignore; this may have been previously masked off */
1537 free_evalue_refs(&mone
);
1538 free_evalue_refs(mask
);
1539 free_evalue_refs(res
);
1542 evalue_set_si(res
, 0, 1);
1544 res
->x
.p
= new_enode(partition
, 2*n
, -1);
1545 for (j
= 0; j
< n
; ++j
) {
1546 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
1547 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
1548 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
1555 void evalue_copy(evalue
*dst
, evalue
*src
)
1557 value_assign(dst
->d
, src
->d
);
1558 if(value_notzero_p(src
->d
)) {
1559 value_init(dst
->x
.n
);
1560 value_assign(dst
->x
.n
, src
->x
.n
);
1562 dst
->x
.p
= ecopy(src
->x
.p
);
1565 enode
*new_enode(enode_type type
,int size
,int pos
) {
1571 fprintf(stderr
, "Allocating enode of size 0 !\n" );
1574 res
= (enode
*) malloc(sizeof(enode
) + (size
-1)*sizeof(evalue
));
1578 for(i
=0; i
<size
; i
++) {
1579 value_init(res
->arr
[i
].d
);
1580 value_set_si(res
->arr
[i
].d
,0);
1581 res
->arr
[i
].x
.p
= 0;
1586 enode
*ecopy(enode
*e
) {
1591 res
= new_enode(e
->type
,e
->size
,e
->pos
);
1592 for(i
=0;i
<e
->size
;++i
) {
1593 value_assign(res
->arr
[i
].d
,e
->arr
[i
].d
);
1594 if(value_zero_p(res
->arr
[i
].d
))
1595 res
->arr
[i
].x
.p
= ecopy(e
->arr
[i
].x
.p
);
1596 else if (EVALUE_IS_DOMAIN(res
->arr
[i
]))
1597 EVALUE_SET_DOMAIN(res
->arr
[i
], Domain_Copy(EVALUE_DOMAIN(e
->arr
[i
])));
1599 value_init(res
->arr
[i
].x
.n
);
1600 value_assign(res
->arr
[i
].x
.n
,e
->arr
[i
].x
.n
);
1606 int ecmp(const evalue
*e1
, const evalue
*e2
)
1612 if (value_notzero_p(e1
->d
) && value_notzero_p(e2
->d
)) {
1616 value_multiply(m
, e1
->x
.n
, e2
->d
);
1617 value_multiply(m2
, e2
->x
.n
, e1
->d
);
1619 if (value_lt(m
, m2
))
1621 else if (value_gt(m
, m2
))
1631 if (value_notzero_p(e1
->d
))
1633 if (value_notzero_p(e2
->d
))
1639 if (p1
->type
!= p2
->type
)
1640 return p1
->type
- p2
->type
;
1641 if (p1
->pos
!= p2
->pos
)
1642 return p1
->pos
- p2
->pos
;
1643 if (p1
->size
!= p2
->size
)
1644 return p1
->size
- p2
->size
;
1646 for (i
= p1
->size
-1; i
>= 0; --i
)
1647 if ((r
= ecmp(&p1
->arr
[i
], &p2
->arr
[i
])) != 0)
1653 int eequal(evalue
*e1
,evalue
*e2
) {
1658 if (value_ne(e1
->d
,e2
->d
))
1661 /* e1->d == e2->d */
1662 if (value_notzero_p(e1
->d
)) {
1663 if (value_ne(e1
->x
.n
,e2
->x
.n
))
1666 /* e1->d == e2->d != 0 AND e1->n == e2->n */
1670 /* e1->d == e2->d == 0 */
1673 if (p1
->type
!= p2
->type
) return 0;
1674 if (p1
->size
!= p2
->size
) return 0;
1675 if (p1
->pos
!= p2
->pos
) return 0;
1676 for (i
=0; i
<p1
->size
; i
++)
1677 if (!eequal(&p1
->arr
[i
], &p2
->arr
[i
]) )
1682 void free_evalue_refs(evalue
*e
) {
1687 if (EVALUE_IS_DOMAIN(*e
)) {
1688 Domain_Free(EVALUE_DOMAIN(*e
));
1691 } else if (value_pos_p(e
->d
)) {
1693 /* 'e' stores a constant */
1695 value_clear(e
->x
.n
);
1698 assert(value_zero_p(e
->d
));
1701 if (!p
) return; /* null pointer */
1702 for (i
=0; i
<p
->size
; i
++) {
1703 free_evalue_refs(&(p
->arr
[i
]));
1707 } /* free_evalue_refs */
1709 static void mod2table_r(evalue
*e
, Vector
*periods
, Value m
, int p
,
1710 Vector
* val
, evalue
*res
)
1712 unsigned nparam
= periods
->Size
;
1715 double d
= compute_evalue(e
, val
->p
);
1716 d
*= VALUE_TO_DOUBLE(m
);
1721 value_assign(res
->d
, m
);
1722 value_init(res
->x
.n
);
1723 value_set_double(res
->x
.n
, d
);
1724 mpz_fdiv_r(res
->x
.n
, res
->x
.n
, m
);
1727 if (value_one_p(periods
->p
[p
]))
1728 mod2table_r(e
, periods
, m
, p
+1, val
, res
);
1733 value_assign(tmp
, periods
->p
[p
]);
1734 value_set_si(res
->d
, 0);
1735 res
->x
.p
= new_enode(periodic
, VALUE_TO_INT(tmp
), p
+1);
1737 value_decrement(tmp
, tmp
);
1738 value_assign(val
->p
[p
], tmp
);
1739 mod2table_r(e
, periods
, m
, p
+1, val
,
1740 &res
->x
.p
->arr
[VALUE_TO_INT(tmp
)]);
1741 } while (value_pos_p(tmp
));
1747 static void rel2table(evalue
*e
, int zero
)
1749 if (value_pos_p(e
->d
)) {
1750 if (value_zero_p(e
->x
.n
) == zero
)
1751 value_set_si(e
->x
.n
, 1);
1753 value_set_si(e
->x
.n
, 0);
1754 value_set_si(e
->d
, 1);
1757 for (i
= 0; i
< e
->x
.p
->size
; ++i
)
1758 rel2table(&e
->x
.p
->arr
[i
], zero
);
1762 void evalue_mod2table(evalue
*e
, int nparam
)
1767 if (EVALUE_IS_DOMAIN(*e
) || value_pos_p(e
->d
))
1770 for (i
=0; i
<p
->size
; i
++) {
1771 evalue_mod2table(&(p
->arr
[i
]), nparam
);
1773 if (p
->type
== relation
) {
1779 evalue_copy(©
, &p
->arr
[0]);
1781 rel2table(&p
->arr
[0], 1);
1782 emul(&p
->arr
[0], &p
->arr
[1]);
1784 rel2table(©
, 0);
1785 emul(©
, &p
->arr
[2]);
1786 eadd(&p
->arr
[2], &p
->arr
[1]);
1787 free_evalue_refs(&p
->arr
[2]);
1788 free_evalue_refs(©
);
1790 free_evalue_refs(&p
->arr
[0]);
1795 } else if (p
->type
== fractional
) {
1796 Vector
*periods
= Vector_Alloc(nparam
);
1797 Vector
*val
= Vector_Alloc(nparam
);
1803 value_set_si(tmp
, 1);
1804 Vector_Set(periods
->p
, 1, nparam
);
1805 Vector_Set(val
->p
, 0, nparam
);
1806 for (ev
= &p
->arr
[0]; value_zero_p(ev
->d
); ev
= &ev
->x
.p
->arr
[0]) {
1809 assert(p
->type
== polynomial
);
1810 assert(p
->size
== 2);
1811 value_assign(periods
->p
[p
->pos
-1], p
->arr
[1].d
);
1812 Lcm3(tmp
, p
->arr
[1].d
, &tmp
);
1815 mod2table_r(&p
->arr
[0], periods
, tmp
, 0, val
, &EP
);
1818 evalue_set_si(&res
, 0, 1);
1819 /* Compute the polynomial using Horner's rule */
1820 for (i
=p
->size
-1;i
>1;i
--) {
1821 eadd(&p
->arr
[i
], &res
);
1824 eadd(&p
->arr
[1], &res
);
1826 free_evalue_refs(e
);
1827 free_evalue_refs(&EP
);
1832 Vector_Free(periods
);
1834 } /* evalue_mod2table */
1836 /********************************************************/
1837 /* function in domain */
1838 /* check if the parameters in list_args */
1839 /* verifies the constraints of Domain P */
1840 /********************************************************/
1841 int in_domain(Polyhedron
*P
, Value
*list_args
) {
1844 Value v
; /* value of the constraint of a row when
1845 parameters are instanciated*/
1851 /*P->Constraint constraint matrice of polyhedron P*/
1852 for(row
=0;row
<P
->NbConstraints
;row
++) {
1853 value_assign(v
,P
->Constraint
[row
][P
->Dimension
+1]); /*constant part*/
1854 for(col
=1;col
<P
->Dimension
+1;col
++) {
1855 value_multiply(tmp
,P
->Constraint
[row
][col
],list_args
[col
-1]);
1856 value_addto(v
,v
,tmp
);
1858 if (value_notzero_p(P
->Constraint
[row
][0])) {
1860 /*if v is not >=0 then this constraint is not respected */
1861 if (value_neg_p(v
)) {
1865 return P
->next
? in_domain(P
->next
, list_args
) : 0;
1870 /*if v is not = 0 then this constraint is not respected */
1871 if (value_notzero_p(v
))
1876 /*if not return before this point => all
1877 the constraints are respected */
1883 /****************************************************/
1884 /* function compute enode */
1885 /* compute the value of enode p with parameters */
1886 /* list "list_args */
1887 /* compute the polynomial or the periodic */
1888 /****************************************************/
1890 static double compute_enode(enode
*p
, Value
*list_args
) {
1902 if (p
->type
== polynomial
) {
1904 value_assign(param
,list_args
[p
->pos
-1]);
1906 /* Compute the polynomial using Horner's rule */
1907 for (i
=p
->size
-1;i
>0;i
--) {
1908 res
+=compute_evalue(&p
->arr
[i
],list_args
);
1909 res
*=VALUE_TO_DOUBLE(param
);
1911 res
+=compute_evalue(&p
->arr
[0],list_args
);
1913 else if (p
->type
== fractional
) {
1914 double d
= compute_evalue(&p
->arr
[0], list_args
);
1915 d
-= floor(d
+1e-10);
1917 /* Compute the polynomial using Horner's rule */
1918 for (i
=p
->size
-1;i
>1;i
--) {
1919 res
+=compute_evalue(&p
->arr
[i
],list_args
);
1922 res
+=compute_evalue(&p
->arr
[1],list_args
);
1924 else if (p
->type
== periodic
) {
1925 value_assign(param
,list_args
[p
->pos
-1]);
1927 /* Choose the right element of the periodic */
1928 value_absolute(m
,param
);
1929 value_set_si(param
,p
->size
);
1930 value_modulus(m
,m
,param
);
1931 res
= compute_evalue(&p
->arr
[VALUE_TO_INT(m
)],list_args
);
1933 else if (p
->type
== relation
) {
1934 if (fabs(compute_evalue(&p
->arr
[0], list_args
)) < 1e-10)
1935 res
= compute_evalue(&p
->arr
[1], list_args
);
1936 else if (p
->size
> 2)
1937 res
= compute_evalue(&p
->arr
[2], list_args
);
1939 else if (p
->type
== partition
) {
1940 for (i
= 0; i
< p
->size
/2; ++i
)
1941 if (in_domain(EVALUE_DOMAIN(p
->arr
[2*i
]), list_args
)) {
1942 res
= compute_evalue(&p
->arr
[2*i
+1], list_args
);
1949 } /* compute_enode */
1951 /*************************************************/
1952 /* return the value of Ehrhart Polynomial */
1953 /* It returns a double, because since it is */
1954 /* a recursive function, some intermediate value */
1955 /* might not be integral */
1956 /*************************************************/
1958 double compute_evalue(evalue
*e
,Value
*list_args
) {
1962 if (value_notzero_p(e
->d
)) {
1963 if (value_notone_p(e
->d
))
1964 res
= VALUE_TO_DOUBLE(e
->x
.n
) / VALUE_TO_DOUBLE(e
->d
);
1966 res
= VALUE_TO_DOUBLE(e
->x
.n
);
1969 res
= compute_enode(e
->x
.p
,list_args
);
1971 } /* compute_evalue */
1974 /****************************************************/
1975 /* function compute_poly : */
1976 /* Check for the good validity domain */
1977 /* return the number of point in the Polyhedron */
1978 /* in allocated memory */
1979 /* Using the Ehrhart pseudo-polynomial */
1980 /****************************************************/
1981 Value
*compute_poly(Enumeration
*en
,Value
*list_args
) {
1984 /* double d; int i; */
1986 tmp
= (Value
*) malloc (sizeof(Value
));
1987 assert(tmp
!= NULL
);
1989 value_set_si(*tmp
,0);
1992 return(tmp
); /* no ehrhart polynomial */
1993 if(en
->ValidityDomain
) {
1994 if(!en
->ValidityDomain
->Dimension
) { /* no parameters */
1995 value_set_double(*tmp
,compute_evalue(&en
->EP
,list_args
)+.25);
2000 return(tmp
); /* no Validity Domain */
2002 if(in_domain(en
->ValidityDomain
,list_args
)) {
2004 #ifdef EVAL_EHRHART_DEBUG
2005 Print_Domain(stdout
,en
->ValidityDomain
);
2006 print_evalue(stdout
,&en
->EP
);
2009 /* d = compute_evalue(&en->EP,list_args);
2011 printf("(double)%lf = %d\n", d, i ); */
2012 value_set_double(*tmp
,compute_evalue(&en
->EP
,list_args
)+.25);
2018 value_set_si(*tmp
,0);
2019 return(tmp
); /* no compatible domain with the arguments */
2020 } /* compute_poly */
2022 size_t value_size(Value v
) {
2023 return (v
[0]._mp_size
> 0 ? v
[0]._mp_size
: -v
[0]._mp_size
)
2024 * sizeof(v
[0]._mp_d
[0]);
2027 size_t domain_size(Polyhedron
*D
)
2030 size_t s
= sizeof(*D
);
2032 for (i
= 0; i
< D
->NbConstraints
; ++i
)
2033 for (j
= 0; j
< D
->Dimension
+2; ++j
)
2034 s
+= value_size(D
->Constraint
[i
][j
]);
2036 for (i
= 0; i
< D
->NbRays
; ++i
)
2037 for (j
= 0; j
< D
->Dimension
+2; ++j
)
2038 s
+= value_size(D
->Ray
[i
][j
]);
2040 return D
->next
? s
+domain_size(D
->next
) : s
;
2043 size_t enode_size(enode
*p
) {
2044 size_t s
= sizeof(*p
) - sizeof(p
->arr
[0]);
2047 if (p
->type
== partition
)
2048 for (i
= 0; i
< p
->size
/2; ++i
) {
2049 s
+= domain_size(EVALUE_DOMAIN(p
->arr
[2*i
]));
2050 s
+= evalue_size(&p
->arr
[2*i
+1]);
2053 for (i
= 0; i
< p
->size
; ++i
) {
2054 s
+= evalue_size(&p
->arr
[i
]);
2059 size_t evalue_size(evalue
*e
)
2061 size_t s
= sizeof(*e
);
2062 s
+= value_size(e
->d
);
2063 if (value_notzero_p(e
->d
))
2064 s
+= value_size(e
->x
.n
);
2066 s
+= enode_size(e
->x
.p
);
2070 static evalue
*find_second(evalue
*base
, evalue
*cst
, evalue
*e
, Value m
)
2072 evalue
*found
= NULL
;
2077 if (value_pos_p(e
->d
) || e
->x
.p
->type
!= fractional
)
2080 value_init(offset
.d
);
2081 value_init(offset
.x
.n
);
2082 poly_denom(&e
->x
.p
->arr
[0], &offset
.d
);
2083 Lcm3(m
, offset
.d
, &offset
.d
);
2084 value_set_si(offset
.x
.n
, 1);
2087 evalue_copy(©
, cst
);
2090 mpz_fdiv_r(cst
->x
.n
, cst
->x
.n
, cst
->d
);
2092 if (eequal(base
, &e
->x
.p
->arr
[0]))
2093 found
= &e
->x
.p
->arr
[0];
2095 value_set_si(offset
.x
.n
, -2);
2098 mpz_fdiv_r(cst
->x
.n
, cst
->x
.n
, cst
->d
);
2100 if (eequal(base
, &e
->x
.p
->arr
[0]))
2103 free_evalue_refs(cst
);
2104 free_evalue_refs(&offset
);
2107 for (i
= 1; !found
&& i
< e
->x
.p
->size
; ++i
)
2108 found
= find_second(base
, cst
, &e
->x
.p
->arr
[i
], m
);
2113 static evalue
*find_relation_pair(evalue
*e
)
2116 evalue
*found
= NULL
;
2118 if (EVALUE_IS_DOMAIN(*e
) || value_pos_p(e
->d
))
2121 if (e
->x
.p
->type
== fractional
) {
2126 poly_denom(&e
->x
.p
->arr
[0], &m
);
2128 for (cst
= &e
->x
.p
->arr
[0]; value_zero_p(cst
->d
);
2129 cst
= &cst
->x
.p
->arr
[0])
2132 for (i
= 1; !found
&& i
< e
->x
.p
->size
; ++i
)
2133 found
= find_second(&e
->x
.p
->arr
[0], cst
, &e
->x
.p
->arr
[i
], m
);
2138 i
= e
->x
.p
->type
== relation
;
2139 for (; !found
&& i
< e
->x
.p
->size
; ++i
)
2140 found
= find_relation_pair(&e
->x
.p
->arr
[i
]);
2145 void evalue_mod2relation(evalue
*e
) {
2148 if (value_zero_p(e
->d
) && e
->x
.p
->type
== partition
) {
2151 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
2152 evalue_mod2relation(&e
->x
.p
->arr
[2*i
+1]);
2157 while ((d
= find_relation_pair(e
)) != NULL
) {
2161 value_init(split
.d
);
2162 value_set_si(split
.d
, 0);
2163 split
.x
.p
= new_enode(relation
, 3, 0);
2164 evalue_set_si(&split
.x
.p
->arr
[1], 1, 1);
2165 evalue_set_si(&split
.x
.p
->arr
[2], 1, 1);
2167 ev
= &split
.x
.p
->arr
[0];
2168 value_set_si(ev
->d
, 0);
2169 ev
->x
.p
= new_enode(fractional
, 3, -1);
2170 evalue_set_si(&ev
->x
.p
->arr
[1], 0, 1);
2171 evalue_set_si(&ev
->x
.p
->arr
[2], 1, 1);
2172 evalue_copy(&ev
->x
.p
->arr
[0], d
);
2178 free_evalue_refs(&split
);
2182 static int evalue_comp(const void * a
, const void * b
)
2184 const evalue
*e1
= *(const evalue
**)a
;
2185 const evalue
*e2
= *(const evalue
**)b
;
2186 return ecmp(e1
, e2
);
2189 void evalue_combine(evalue
*e
)
2196 if (value_notzero_p(e
->d
) || e
->x
.p
->type
!= partition
)
2199 NALLOC(evs
, e
->x
.p
->size
/2);
2200 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
2201 evs
[i
] = &e
->x
.p
->arr
[2*i
+1];
2202 qsort(evs
, e
->x
.p
->size
/2, sizeof(evs
[0]), evalue_comp
);
2203 p
= new_enode(partition
, e
->x
.p
->size
, -1);
2204 for (i
= 0, k
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2205 if (k
== 0 || ecmp(&p
->arr
[2*k
-1], evs
[i
]) != 0) {
2206 p
->arr
[2*k
] = *(evs
[i
]-1);
2207 p
->arr
[2*k
+1] = *(evs
[i
]);
2210 Polyhedron
*D
= EVALUE_DOMAIN(*(evs
[i
]-1));
2215 L
->next
= EVALUE_DOMAIN(p
->arr
[2*k
-2]);
2216 EVALUE_SET_DOMAIN(p
->arr
[2*k
-2], D
);
2217 free_evalue_refs(evs
[i
]);
2224 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2226 if (value_notzero_p(e
->x
.p
->arr
[2*i
+1].d
))
2228 H
= DomainConvex(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]), 0);
2231 for (k
= 0; k
< e
->x
.p
->size
/2; ++k
) {
2232 Polyhedron
*D
, *N
, **P
;
2235 P
= &EVALUE_DOMAIN(e
->x
.p
->arr
[2*k
]);
2242 if (D
->NbEq
<= H
->NbEq
) {
2248 tmp
.x
.p
= new_enode(partition
, 2, -1);
2249 EVALUE_SET_DOMAIN(tmp
.x
.p
->arr
[0], Polyhedron_Copy(D
));
2250 evalue_copy(&tmp
.x
.p
->arr
[1], &e
->x
.p
->arr
[2*i
+1]);
2251 reduce_evalue(&tmp
);
2252 if (value_notzero_p(tmp
.d
) ||
2253 ecmp(&tmp
.x
.p
->arr
[1], &e
->x
.p
->arr
[2*k
+1]) != 0)
2256 D
->next
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]);
2257 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]) = D
;
2260 free_evalue_refs(&tmp
);
2265 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2267 Polyhedron
*D
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]);
2269 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
2271 if (2*i
< e
->x
.p
->size
) {
2272 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
2273 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
2280 H
= DomainConvex(D
, 0);
2281 E
= DomainDifference(H
, D
, 0);
2283 D
= DomainDifference(H
, E
, 0);
2286 EVALUE_SET_DOMAIN(p
->arr
[2*i
], D
);
2290 /* May change coefficients to become non-standard
2291 * => reduce p afterwards to correct
2293 static Polyhedron
*polynomial_projection(enode
*p
, Polyhedron
*D
, Value
*d
,
2298 unsigned dim
= D
->Dimension
;
2299 Matrix
*T
= Matrix_Alloc(2, dim
+1);
2304 assert(p
->type
== fractional
);
2306 value_set_si(T
->p
[1][dim
], 1);
2308 while (value_zero_p(pp
->d
)) {
2309 assert(pp
->x
.p
->type
== polynomial
);
2310 assert(pp
->x
.p
->size
== 2);
2311 assert(value_notzero_p(pp
->x
.p
->arr
[1].d
));
2312 value_division(T
->p
[0][pp
->x
.p
->pos
-1], *d
, pp
->x
.p
->arr
[1].d
);
2313 mpz_mul_ui(twice
, pp
->x
.p
->arr
[1].x
.n
, 2);
2314 if (value_gt(twice
, pp
->x
.p
->arr
[1].d
))
2315 value_substract(pp
->x
.p
->arr
[1].x
.n
,
2316 pp
->x
.p
->arr
[1].x
.n
, pp
->x
.p
->arr
[1].d
);
2317 value_multiply(T
->p
[0][pp
->x
.p
->pos
-1],
2318 T
->p
[0][pp
->x
.p
->pos
-1], pp
->x
.p
->arr
[1].x
.n
);
2319 pp
= &pp
->x
.p
->arr
[0];
2321 value_division(T
->p
[0][dim
], *d
, pp
->d
);
2322 value_multiply(T
->p
[0][dim
], T
->p
[0][dim
], pp
->x
.n
);
2323 I
= DomainImage(D
, T
, 0);
2324 H
= DomainConvex(I
, 0);
2333 static int reduce_in_domain(evalue
*e
, Polyhedron
*D
)
2342 if (value_notzero_p(e
->d
))
2347 if (p
->type
== relation
) {
2353 I
= polynomial_projection(p
->arr
[0].x
.p
, D
, &d
, &T
);
2354 line_minmax(I
, &min
, &max
); /* frees I */
2355 equal
= value_eq(min
, max
);
2356 mpz_cdiv_q(min
, min
, d
);
2357 mpz_fdiv_q(max
, max
, d
);
2359 if (value_gt(min
, max
)) {
2365 evalue_set_si(e
, 0, 1);
2368 free_evalue_refs(&(p
->arr
[1]));
2369 free_evalue_refs(&(p
->arr
[0]));
2375 return r
? r
: reduce_in_domain(e
, D
);
2379 free_evalue_refs(&(p
->arr
[2]));
2381 free_evalue_refs(&(p
->arr
[0]));
2387 return reduce_in_domain(e
, D
);
2388 } else if (value_eq(min
, max
)) {
2389 /* zero for a single value */
2391 Matrix
*M
= Matrix_Alloc(1, D
->Dimension
+2);
2392 Vector_Copy(T
->p
[0], M
->p
[0]+1, D
->Dimension
+1);
2393 value_multiply(min
, min
, d
);
2394 value_substract(M
->p
[0][D
->Dimension
+1],
2395 M
->p
[0][D
->Dimension
+1], min
);
2396 E
= DomainAddConstraints(D
, M
, 0);
2402 r
= reduce_in_domain(&p
->arr
[1], E
);
2404 r
|= reduce_in_domain(&p
->arr
[2], D
);
2406 _reduce_evalue(&p
->arr
[0].x
.p
->arr
[0], 0, 1);
2414 _reduce_evalue(&p
->arr
[0].x
.p
->arr
[0], 0, 1);
2417 i
= p
->type
== relation
? 1 :
2418 p
->type
== fractional
? 1 : 0;
2419 for (; i
<p
->size
; i
++)
2420 r
|= reduce_in_domain(&p
->arr
[i
], D
);
2422 if (p
->type
!= fractional
) {
2423 if (r
&& p
->type
== polynomial
) {
2426 value_set_si(f
.d
, 0);
2427 f
.x
.p
= new_enode(polynomial
, 2, p
->pos
);
2428 evalue_set_si(&f
.x
.p
->arr
[0], 0, 1);
2429 evalue_set_si(&f
.x
.p
->arr
[1], 1, 1);
2430 reorder_terms(p
, &f
);
2440 I
= polynomial_projection(p
, D
, &d
, &T
);
2442 line_minmax(I
, &min
, &max
); /* frees I */
2443 mpz_fdiv_q(min
, min
, d
);
2444 mpz_fdiv_q(max
, max
, d
);
2446 if (value_eq(min
, max
)) {
2449 value_init(inc
.x
.n
);
2450 value_set_si(inc
.d
, 1);
2451 value_oppose(inc
.x
.n
, min
);
2452 eadd(&inc
, &p
->arr
[0]);
2453 reorder_terms(p
, &p
->arr
[0]); /* frees arr[0] */
2457 free_evalue_refs(&inc
);
2460 _reduce_evalue(&p
->arr
[0], 0, 1);
2464 value_set_si(f
.d
, 0);
2465 f
.x
.p
= new_enode(fractional
, 3, -1);
2466 value_clear(f
.x
.p
->arr
[0].d
);
2467 f
.x
.p
->arr
[0] = p
->arr
[0];
2468 evalue_set_si(&f
.x
.p
->arr
[1], 0, 1);
2469 evalue_set_si(&f
.x
.p
->arr
[2], 1, 1);
2470 reorder_terms(p
, &f
);
2483 void evalue_range_reduction(evalue
*e
)
2486 if (value_notzero_p(e
->d
) || e
->x
.p
->type
!= partition
)
2489 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
2490 if (reduce_in_domain(&e
->x
.p
->arr
[2*i
+1],
2491 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]))) {
2492 reduce_evalue(&e
->x
.p
->arr
[2*i
+1]);
2494 if (EVALUE_IS_ZERO(e
->x
.p
->arr
[2*i
+1])) {
2495 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
2496 Domain_Free(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]));
2497 value_clear(e
->x
.p
->arr
[2*i
].d
);
2499 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
2500 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];