1 /***********************************************************************/
2 /* copyright 1997, Doran Wilde */
3 /* copyright 1997-2000, Vincent Loechner */
4 /* copyright 2003-2006, Sven Verdoolaege */
5 /* Permission is granted to copy, use, and distribute */
6 /* for any commercial or noncommercial purpose under the terms */
7 /* of the GNU General Public license, version 2, June 1991 */
8 /* (see file : LICENSE). */
9 /***********************************************************************/
15 #include <barvinok/evalue.h>
16 #include <barvinok/barvinok.h>
17 #include <barvinok/util.h>
19 #ifndef value_pmodulus
20 #define value_pmodulus(ref,val1,val2) (mpz_fdiv_r((ref),(val1),(val2)))
23 #define ALLOC(type) (type*)malloc(sizeof(type))
26 #define NALLOC(p,n) p = (typeof(p))malloc((n) * sizeof(*p))
28 #define NALLOC(p,n) p = (void *)malloc((n) * sizeof(*p))
31 void evalue_set_si(evalue
*ev
, int n
, int d
) {
32 value_set_si(ev
->d
, d
);
34 value_set_si(ev
->x
.n
, n
);
37 void evalue_set(evalue
*ev
, Value n
, Value d
) {
38 value_assign(ev
->d
, d
);
40 value_assign(ev
->x
.n
, n
);
45 evalue
*EP
= ALLOC(evalue
);
47 evalue_set_si(EP
, 0, 1);
51 void aep_evalue(evalue
*e
, int *ref
) {
56 if (value_notzero_p(e
->d
))
57 return; /* a rational number, its already reduced */
59 return; /* hum... an overflow probably occured */
61 /* First check the components of p */
62 for (i
=0;i
<p
->size
;i
++)
63 aep_evalue(&p
->arr
[i
],ref
);
70 p
->pos
= ref
[p
->pos
-1]+1;
76 void addeliminatedparams_evalue(evalue
*e
,Matrix
*CT
) {
82 if (value_notzero_p(e
->d
))
83 return; /* a rational number, its already reduced */
85 return; /* hum... an overflow probably occured */
88 ref
= (int *)malloc(sizeof(int)*(CT
->NbRows
-1));
89 for(i
=0;i
<CT
->NbRows
-1;i
++)
90 for(j
=0;j
<CT
->NbColumns
;j
++)
91 if(value_notzero_p(CT
->p
[i
][j
])) {
96 /* Transform the references in e, using ref */
100 } /* addeliminatedparams_evalue */
102 void addeliminatedparams_enum(evalue
*e
, Matrix
*CT
, Polyhedron
*CEq
,
103 unsigned MaxRays
, unsigned nparam
)
108 if (CT
->NbRows
== CT
->NbColumns
)
111 if (EVALUE_IS_ZERO(*e
))
114 if (value_notzero_p(e
->d
)) {
117 value_set_si(res
.d
, 0);
118 res
.x
.p
= new_enode(partition
, 2, nparam
);
119 EVALUE_SET_DOMAIN(res
.x
.p
->arr
[0],
120 DomainConstraintSimplify(Polyhedron_Copy(CEq
), MaxRays
));
121 value_clear(res
.x
.p
->arr
[1].d
);
122 res
.x
.p
->arr
[1] = *e
;
129 assert(p
->type
== partition
);
132 for (i
=0; i
<p
->size
/2; i
++) {
133 Polyhedron
*D
= EVALUE_DOMAIN(p
->arr
[2*i
]);
134 Polyhedron
*T
= DomainPreimage(D
, CT
, MaxRays
);
137 T
= DomainIntersection(D
, CEq
, MaxRays
);
139 EVALUE_SET_DOMAIN(p
->arr
[2*i
], T
);
140 addeliminatedparams_evalue(&p
->arr
[2*i
+1], CT
);
144 static int mod_rational_smaller(evalue
*e1
, evalue
*e2
)
152 assert(value_notzero_p(e1
->d
));
153 assert(value_notzero_p(e2
->d
));
154 value_multiply(m
, e1
->x
.n
, e2
->d
);
155 value_multiply(m2
, e2
->x
.n
, e1
->d
);
158 else if (value_gt(m
, m2
))
168 static int mod_term_smaller_r(evalue
*e1
, evalue
*e2
)
170 if (value_notzero_p(e1
->d
)) {
172 if (value_zero_p(e2
->d
))
174 r
= mod_rational_smaller(e1
, e2
);
175 return r
== -1 ? 0 : r
;
177 if (value_notzero_p(e2
->d
))
179 if (e1
->x
.p
->pos
< e2
->x
.p
->pos
)
181 else if (e1
->x
.p
->pos
> e2
->x
.p
->pos
)
184 int r
= mod_rational_smaller(&e1
->x
.p
->arr
[1], &e2
->x
.p
->arr
[1]);
186 ? mod_term_smaller_r(&e1
->x
.p
->arr
[0], &e2
->x
.p
->arr
[0])
191 static int mod_term_smaller(const evalue
*e1
, const evalue
*e2
)
193 assert(value_zero_p(e1
->d
));
194 assert(value_zero_p(e2
->d
));
195 assert(e1
->x
.p
->type
== fractional
|| e1
->x
.p
->type
== flooring
);
196 assert(e2
->x
.p
->type
== fractional
|| e2
->x
.p
->type
== flooring
);
197 return mod_term_smaller_r(&e1
->x
.p
->arr
[0], &e2
->x
.p
->arr
[0]);
200 /* Negative pos means inequality */
201 /* s is negative of substitution if m is not zero */
210 struct fixed_param
*fixed
;
215 static int relations_depth(evalue
*e
)
220 value_zero_p(e
->d
) && e
->x
.p
->type
== relation
;
221 e
= &e
->x
.p
->arr
[1], ++d
);
225 static void poly_denom_not_constant(evalue
**pp
, Value
*d
)
230 while (value_zero_p(p
->d
)) {
231 assert(p
->x
.p
->type
== polynomial
);
232 assert(p
->x
.p
->size
== 2);
233 assert(value_notzero_p(p
->x
.p
->arr
[1].d
));
234 value_lcm(*d
, p
->x
.p
->arr
[1].d
, d
);
240 static void poly_denom(evalue
*p
, Value
*d
)
242 poly_denom_not_constant(&p
, d
);
243 value_lcm(*d
, p
->d
, d
);
246 static void realloc_substitution(struct subst
*s
, int d
)
248 struct fixed_param
*n
;
251 for (i
= 0; i
< s
->n
; ++i
)
258 static int add_modulo_substitution(struct subst
*s
, evalue
*r
)
264 assert(value_zero_p(r
->d
) && r
->x
.p
->type
== relation
);
267 /* May have been reduced already */
268 if (value_notzero_p(m
->d
))
271 assert(value_zero_p(m
->d
) && m
->x
.p
->type
== fractional
);
272 assert(m
->x
.p
->size
== 3);
274 /* fractional was inverted during reduction
275 * invert it back and move constant in
277 if (!EVALUE_IS_ONE(m
->x
.p
->arr
[2])) {
278 assert(value_pos_p(m
->x
.p
->arr
[2].d
));
279 assert(value_mone_p(m
->x
.p
->arr
[2].x
.n
));
280 value_set_si(m
->x
.p
->arr
[2].x
.n
, 1);
281 value_increment(m
->x
.p
->arr
[1].x
.n
, m
->x
.p
->arr
[1].x
.n
);
282 assert(value_eq(m
->x
.p
->arr
[1].x
.n
, m
->x
.p
->arr
[1].d
));
283 value_set_si(m
->x
.p
->arr
[1].x
.n
, 1);
284 eadd(&m
->x
.p
->arr
[1], &m
->x
.p
->arr
[0]);
285 value_set_si(m
->x
.p
->arr
[1].x
.n
, 0);
286 value_set_si(m
->x
.p
->arr
[1].d
, 1);
289 /* Oops. Nested identical relations. */
290 if (!EVALUE_IS_ZERO(m
->x
.p
->arr
[1]))
293 if (s
->n
>= s
->max
) {
294 int d
= relations_depth(r
);
295 realloc_substitution(s
, d
);
299 assert(value_zero_p(p
->d
) && p
->x
.p
->type
== polynomial
);
300 assert(p
->x
.p
->size
== 2);
303 assert(value_pos_p(f
->x
.n
));
305 value_init(s
->fixed
[s
->n
].m
);
306 value_assign(s
->fixed
[s
->n
].m
, f
->d
);
307 s
->fixed
[s
->n
].pos
= p
->x
.p
->pos
;
308 value_init(s
->fixed
[s
->n
].d
);
309 value_assign(s
->fixed
[s
->n
].d
, f
->x
.n
);
310 value_init(s
->fixed
[s
->n
].s
.d
);
311 evalue_copy(&s
->fixed
[s
->n
].s
, &p
->x
.p
->arr
[0]);
317 static int type_offset(enode
*p
)
319 return p
->type
== fractional
? 1 :
320 p
->type
== flooring
? 1 : 0;
323 static void reorder_terms(enode
*p
, evalue
*v
)
326 int offset
= type_offset(p
);
328 for (i
= p
->size
-1; i
>= offset
+1; i
--) {
330 eadd(&p
->arr
[i
], &p
->arr
[i
-1]);
331 free_evalue_refs(&(p
->arr
[i
]));
337 void _reduce_evalue (evalue
*e
, struct subst
*s
, int fract
) {
343 if (value_notzero_p(e
->d
)) {
345 mpz_fdiv_r(e
->x
.n
, e
->x
.n
, e
->d
);
346 return; /* a rational number, its already reduced */
350 return; /* hum... an overflow probably occured */
352 /* First reduce the components of p */
353 add
= p
->type
== relation
;
354 for (i
=0; i
<p
->size
; i
++) {
356 add
= add_modulo_substitution(s
, e
);
358 if (i
== 0 && p
->type
==fractional
)
359 _reduce_evalue(&p
->arr
[i
], s
, 1);
361 _reduce_evalue(&p
->arr
[i
], s
, fract
);
363 if (add
&& i
== p
->size
-1) {
365 value_clear(s
->fixed
[s
->n
].m
);
366 value_clear(s
->fixed
[s
->n
].d
);
367 free_evalue_refs(&s
->fixed
[s
->n
].s
);
368 } else if (add
&& i
== 1)
369 s
->fixed
[s
->n
-1].pos
*= -1;
372 if (p
->type
==periodic
) {
374 /* Try to reduce the period */
375 for (i
=1; i
<=(p
->size
)/2; i
++) {
376 if ((p
->size
% i
)==0) {
378 /* Can we reduce the size to i ? */
380 for (k
=j
+i
; k
<e
->x
.p
->size
; k
+=i
)
381 if (!eequal(&p
->arr
[j
], &p
->arr
[k
])) goto you_lose
;
384 for (j
=i
; j
<p
->size
; j
++) free_evalue_refs(&p
->arr
[j
]);
388 you_lose
: /* OK, lets not do it */
393 /* Try to reduce its strength */
396 memcpy(e
,&p
->arr
[0],sizeof(evalue
));
400 else if (p
->type
==polynomial
) {
401 for (k
= 0; s
&& k
< s
->n
; ++k
) {
402 if (s
->fixed
[k
].pos
== p
->pos
) {
403 int divide
= value_notone_p(s
->fixed
[k
].d
);
406 if (value_notzero_p(s
->fixed
[k
].m
)) {
409 assert(p
->size
== 2);
410 if (divide
&& value_ne(s
->fixed
[k
].d
, p
->arr
[1].x
.n
))
412 if (!mpz_divisible_p(s
->fixed
[k
].m
, p
->arr
[1].d
))
419 value_assign(d
.d
, s
->fixed
[k
].d
);
421 if (value_notzero_p(s
->fixed
[k
].m
))
422 value_oppose(d
.x
.n
, s
->fixed
[k
].m
);
424 value_set_si(d
.x
.n
, 1);
427 for (i
=p
->size
-1;i
>=1;i
--) {
428 emul(&s
->fixed
[k
].s
, &p
->arr
[i
]);
430 emul(&d
, &p
->arr
[i
]);
431 eadd(&p
->arr
[i
], &p
->arr
[i
-1]);
432 free_evalue_refs(&(p
->arr
[i
]));
435 _reduce_evalue(&p
->arr
[0], s
, fract
);
438 free_evalue_refs(&d
);
444 /* Try to reduce the degree */
445 for (i
=p
->size
-1;i
>=1;i
--) {
446 if (!(value_one_p(p
->arr
[i
].d
) && value_zero_p(p
->arr
[i
].x
.n
)))
448 /* Zero coefficient */
449 free_evalue_refs(&(p
->arr
[i
]));
454 /* Try to reduce its strength */
457 memcpy(e
,&p
->arr
[0],sizeof(evalue
));
461 else if (p
->type
==fractional
) {
465 if (value_notzero_p(p
->arr
[0].d
)) {
467 value_assign(v
.d
, p
->arr
[0].d
);
469 mpz_fdiv_r(v
.x
.n
, p
->arr
[0].x
.n
, p
->arr
[0].d
);
474 evalue
*pp
= &p
->arr
[0];
475 assert(value_zero_p(pp
->d
) && pp
->x
.p
->type
== polynomial
);
476 assert(pp
->x
.p
->size
== 2);
478 /* search for exact duplicate among the modulo inequalities */
480 f
= &pp
->x
.p
->arr
[1];
481 for (k
= 0; s
&& k
< s
->n
; ++k
) {
482 if (-s
->fixed
[k
].pos
== pp
->x
.p
->pos
&&
483 value_eq(s
->fixed
[k
].d
, f
->x
.n
) &&
484 value_eq(s
->fixed
[k
].m
, f
->d
) &&
485 eequal(&s
->fixed
[k
].s
, &pp
->x
.p
->arr
[0]))
492 /* replace { E/m } by { (E-1)/m } + 1/m */
497 evalue_set_si(&extra
, 1, 1);
498 value_assign(extra
.d
, g
);
499 eadd(&extra
, &v
.x
.p
->arr
[1]);
500 free_evalue_refs(&extra
);
502 /* We've been going in circles; stop now */
503 if (value_ge(v
.x
.p
->arr
[1].x
.n
, v
.x
.p
->arr
[1].d
)) {
504 free_evalue_refs(&v
);
506 evalue_set_si(&v
, 0, 1);
511 value_set_si(v
.d
, 0);
512 v
.x
.p
= new_enode(fractional
, 3, -1);
513 evalue_set_si(&v
.x
.p
->arr
[1], 1, 1);
514 value_assign(v
.x
.p
->arr
[1].d
, g
);
515 evalue_set_si(&v
.x
.p
->arr
[2], 1, 1);
516 evalue_copy(&v
.x
.p
->arr
[0], &p
->arr
[0]);
519 for (f
= &v
.x
.p
->arr
[0]; value_zero_p(f
->d
);
522 value_division(f
->d
, g
, f
->d
);
523 value_multiply(f
->x
.n
, f
->x
.n
, f
->d
);
524 value_assign(f
->d
, g
);
525 value_decrement(f
->x
.n
, f
->x
.n
);
526 mpz_fdiv_r(f
->x
.n
, f
->x
.n
, f
->d
);
528 Gcd(f
->d
, f
->x
.n
, &g
);
529 value_division(f
->d
, f
->d
, g
);
530 value_division(f
->x
.n
, f
->x
.n
, g
);
539 /* reduction may have made this fractional arg smaller */
540 i
= reorder
? p
->size
: 1;
541 for ( ; i
< p
->size
; ++i
)
542 if (value_zero_p(p
->arr
[i
].d
) &&
543 p
->arr
[i
].x
.p
->type
== fractional
&&
544 !mod_term_smaller(e
, &p
->arr
[i
]))
548 value_set_si(v
.d
, 0);
549 v
.x
.p
= new_enode(fractional
, 3, -1);
550 evalue_set_si(&v
.x
.p
->arr
[1], 0, 1);
551 evalue_set_si(&v
.x
.p
->arr
[2], 1, 1);
552 evalue_copy(&v
.x
.p
->arr
[0], &p
->arr
[0]);
560 evalue
*pp
= &p
->arr
[0];
563 poly_denom_not_constant(&pp
, &m
);
564 mpz_fdiv_r(r
, m
, pp
->d
);
565 if (value_notzero_p(r
)) {
567 value_set_si(v
.d
, 0);
568 v
.x
.p
= new_enode(fractional
, 3, -1);
570 value_multiply(r
, m
, pp
->x
.n
);
571 value_multiply(v
.x
.p
->arr
[1].d
, m
, pp
->d
);
572 value_init(v
.x
.p
->arr
[1].x
.n
);
573 mpz_fdiv_r(v
.x
.p
->arr
[1].x
.n
, r
, pp
->d
);
574 mpz_fdiv_q(r
, r
, pp
->d
);
576 evalue_set_si(&v
.x
.p
->arr
[2], 1, 1);
577 evalue_copy(&v
.x
.p
->arr
[0], &p
->arr
[0]);
579 while (value_zero_p(pp
->d
))
580 pp
= &pp
->x
.p
->arr
[0];
582 value_assign(pp
->d
, m
);
583 value_assign(pp
->x
.n
, r
);
585 Gcd(pp
->d
, pp
->x
.n
, &r
);
586 value_division(pp
->d
, pp
->d
, r
);
587 value_division(pp
->x
.n
, pp
->x
.n
, r
);
600 for (pp
= &p
->arr
[0]; value_zero_p(pp
->d
);
601 pp
= &pp
->x
.p
->arr
[0]) {
602 f
= &pp
->x
.p
->arr
[1];
603 assert(value_pos_p(f
->d
));
604 mpz_mul_ui(twice
, f
->x
.n
, 2);
605 if (value_lt(twice
, f
->d
))
607 if (value_eq(twice
, f
->d
))
615 value_set_si(v
.d
, 0);
616 v
.x
.p
= new_enode(fractional
, 3, -1);
617 evalue_set_si(&v
.x
.p
->arr
[1], 0, 1);
618 poly_denom(&p
->arr
[0], &twice
);
619 value_assign(v
.x
.p
->arr
[1].d
, twice
);
620 value_decrement(v
.x
.p
->arr
[1].x
.n
, twice
);
621 evalue_set_si(&v
.x
.p
->arr
[2], -1, 1);
622 evalue_copy(&v
.x
.p
->arr
[0], &p
->arr
[0]);
624 for (pp
= &v
.x
.p
->arr
[0]; value_zero_p(pp
->d
);
625 pp
= &pp
->x
.p
->arr
[0]) {
626 f
= &pp
->x
.p
->arr
[1];
627 value_oppose(f
->x
.n
, f
->x
.n
);
628 mpz_fdiv_r(f
->x
.n
, f
->x
.n
, f
->d
);
630 value_division(pp
->d
, twice
, pp
->d
);
631 value_multiply(pp
->x
.n
, pp
->x
.n
, pp
->d
);
632 value_assign(pp
->d
, twice
);
633 value_oppose(pp
->x
.n
, pp
->x
.n
);
634 value_decrement(pp
->x
.n
, pp
->x
.n
);
635 mpz_fdiv_r(pp
->x
.n
, pp
->x
.n
, pp
->d
);
637 /* Maybe we should do this during reduction of
640 Gcd(pp
->d
, pp
->x
.n
, &twice
);
641 value_division(pp
->d
, pp
->d
, twice
);
642 value_division(pp
->x
.n
, pp
->x
.n
, twice
);
652 reorder_terms(p
, &v
);
653 _reduce_evalue(&p
->arr
[1], s
, fract
);
656 /* Try to reduce the degree */
657 for (i
=p
->size
-1;i
>=2;i
--) {
658 if (!(value_one_p(p
->arr
[i
].d
) && value_zero_p(p
->arr
[i
].x
.n
)))
660 /* Zero coefficient */
661 free_evalue_refs(&(p
->arr
[i
]));
666 /* Try to reduce its strength */
669 memcpy(e
,&p
->arr
[1],sizeof(evalue
));
670 free_evalue_refs(&(p
->arr
[0]));
674 else if (p
->type
== flooring
) {
675 /* Try to reduce the degree */
676 for (i
=p
->size
-1;i
>=2;i
--) {
677 if (!EVALUE_IS_ZERO(p
->arr
[i
]))
679 /* Zero coefficient */
680 free_evalue_refs(&(p
->arr
[i
]));
685 /* Try to reduce its strength */
688 memcpy(e
,&p
->arr
[1],sizeof(evalue
));
689 free_evalue_refs(&(p
->arr
[0]));
693 else if (p
->type
== relation
) {
694 if (p
->size
== 3 && eequal(&p
->arr
[1], &p
->arr
[2])) {
695 free_evalue_refs(&(p
->arr
[2]));
696 free_evalue_refs(&(p
->arr
[0]));
703 if (p
->size
== 3 && EVALUE_IS_ZERO(p
->arr
[2])) {
704 free_evalue_refs(&(p
->arr
[2]));
707 if (p
->size
== 2 && EVALUE_IS_ZERO(p
->arr
[1])) {
708 free_evalue_refs(&(p
->arr
[1]));
709 free_evalue_refs(&(p
->arr
[0]));
710 evalue_set_si(e
, 0, 1);
717 /* Relation was reduced by means of an identical
718 * inequality => remove
720 if (value_zero_p(m
->d
) && !EVALUE_IS_ZERO(m
->x
.p
->arr
[1]))
723 if (reduced
|| value_notzero_p(p
->arr
[0].d
)) {
724 if (!reduced
&& value_zero_p(p
->arr
[0].x
.n
)) {
726 memcpy(e
,&p
->arr
[1],sizeof(evalue
));
728 free_evalue_refs(&(p
->arr
[2]));
732 memcpy(e
,&p
->arr
[2],sizeof(evalue
));
734 evalue_set_si(e
, 0, 1);
735 free_evalue_refs(&(p
->arr
[1]));
737 free_evalue_refs(&(p
->arr
[0]));
743 } /* reduce_evalue */
745 static void add_substitution(struct subst
*s
, Value
*row
, unsigned dim
)
750 for (k
= 0; k
< dim
; ++k
)
751 if (value_notzero_p(row
[k
+1]))
754 Vector_Normalize_Positive(row
+1, dim
+1, k
);
755 assert(s
->n
< s
->max
);
756 value_init(s
->fixed
[s
->n
].d
);
757 value_init(s
->fixed
[s
->n
].m
);
758 value_assign(s
->fixed
[s
->n
].d
, row
[k
+1]);
759 s
->fixed
[s
->n
].pos
= k
+1;
760 value_set_si(s
->fixed
[s
->n
].m
, 0);
761 r
= &s
->fixed
[s
->n
].s
;
763 for (l
= k
+1; l
< dim
; ++l
)
764 if (value_notzero_p(row
[l
+1])) {
765 value_set_si(r
->d
, 0);
766 r
->x
.p
= new_enode(polynomial
, 2, l
+ 1);
767 value_init(r
->x
.p
->arr
[1].x
.n
);
768 value_oppose(r
->x
.p
->arr
[1].x
.n
, row
[l
+1]);
769 value_set_si(r
->x
.p
->arr
[1].d
, 1);
773 value_oppose(r
->x
.n
, row
[dim
+1]);
774 value_set_si(r
->d
, 1);
778 static void _reduce_evalue_in_domain(evalue
*e
, Polyhedron
*D
, struct subst
*s
)
781 Polyhedron
*orig
= D
;
786 D
= DomainConvex(D
, 0);
787 if (!D
->next
&& D
->NbEq
) {
791 realloc_substitution(s
, dim
);
793 int d
= relations_depth(e
);
795 NALLOC(s
->fixed
, s
->max
);
798 for (j
= 0; j
< D
->NbEq
; ++j
)
799 add_substitution(s
, D
->Constraint
[j
], dim
);
803 _reduce_evalue(e
, s
, 0);
806 for (j
= 0; j
< s
->n
; ++j
) {
807 value_clear(s
->fixed
[j
].d
);
808 value_clear(s
->fixed
[j
].m
);
809 free_evalue_refs(&s
->fixed
[j
].s
);
814 void reduce_evalue_in_domain(evalue
*e
, Polyhedron
*D
)
816 struct subst s
= { NULL
, 0, 0 };
818 if (EVALUE_IS_ZERO(*e
))
822 evalue_set_si(e
, 0, 1);
825 _reduce_evalue_in_domain(e
, D
, &s
);
830 void reduce_evalue (evalue
*e
) {
831 struct subst s
= { NULL
, 0, 0 };
833 if (value_notzero_p(e
->d
))
834 return; /* a rational number, its already reduced */
836 if (e
->x
.p
->type
== partition
) {
839 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
840 Polyhedron
*D
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]);
842 /* This shouldn't really happen;
843 * Empty domains should not be added.
845 POL_ENSURE_VERTICES(D
);
847 _reduce_evalue_in_domain(&e
->x
.p
->arr
[2*i
+1], D
, &s
);
849 if (emptyQ(D
) || EVALUE_IS_ZERO(e
->x
.p
->arr
[2*i
+1])) {
850 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
851 Domain_Free(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]));
852 value_clear(e
->x
.p
->arr
[2*i
].d
);
854 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
855 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
859 if (e
->x
.p
->size
== 0) {
861 evalue_set_si(e
, 0, 1);
864 _reduce_evalue(e
, &s
, 0);
869 void print_evalue(FILE *DST
,evalue
*e
,char **pname
) {
871 if(value_notzero_p(e
->d
)) {
872 if(value_notone_p(e
->d
)) {
873 value_print(DST
,VALUE_FMT
,e
->x
.n
);
875 value_print(DST
,VALUE_FMT
,e
->d
);
878 value_print(DST
,VALUE_FMT
,e
->x
.n
);
882 print_enode(DST
,e
->x
.p
,pname
);
886 void print_enode(FILE *DST
,enode
*p
,char **pname
) {
891 fprintf(DST
, "NULL");
897 for (i
=0; i
<p
->size
; i
++) {
898 print_evalue(DST
, &p
->arr
[i
], pname
);
902 fprintf(DST
, " }\n");
906 for (i
=p
->size
-1; i
>=0; i
--) {
907 print_evalue(DST
, &p
->arr
[i
], pname
);
908 if (i
==1) fprintf(DST
, " * %s + ", pname
[p
->pos
-1]);
910 fprintf(DST
, " * %s^%d + ", pname
[p
->pos
-1], i
);
912 fprintf(DST
, " )\n");
916 for (i
=0; i
<p
->size
; i
++) {
917 print_evalue(DST
, &p
->arr
[i
], pname
);
918 if (i
!=(p
->size
-1)) fprintf(DST
, ", ");
920 fprintf(DST
," ]_%s", pname
[p
->pos
-1]);
925 for (i
=p
->size
-1; i
>=1; i
--) {
926 print_evalue(DST
, &p
->arr
[i
], pname
);
929 fprintf(DST
, p
->type
== flooring
? "[" : "{");
930 print_evalue(DST
, &p
->arr
[0], pname
);
931 fprintf(DST
, p
->type
== flooring
? "]" : "}");
933 fprintf(DST
, "^%d + ", i
-1);
938 fprintf(DST
, " )\n");
942 print_evalue(DST
, &p
->arr
[0], pname
);
943 fprintf(DST
, "= 0 ] * \n");
944 print_evalue(DST
, &p
->arr
[1], pname
);
946 fprintf(DST
, " +\n [ ");
947 print_evalue(DST
, &p
->arr
[0], pname
);
948 fprintf(DST
, "!= 0 ] * \n");
949 print_evalue(DST
, &p
->arr
[2], pname
);
953 char **names
= pname
;
954 int maxdim
= EVALUE_DOMAIN(p
->arr
[0])->Dimension
;
955 if (!pname
|| p
->pos
< maxdim
) {
956 NALLOC(names
, maxdim
);
957 for (i
= 0; i
< p
->pos
; ++i
) {
961 NALLOC(names
[i
], 10);
962 snprintf(names
[i
], 10, "%c", 'P'+i
);
965 for ( ; i
< maxdim
; ++i
) {
966 NALLOC(names
[i
], 10);
967 snprintf(names
[i
], 10, "_p%d", i
);
971 for (i
=0; i
<p
->size
/2; i
++) {
972 Print_Domain(DST
, EVALUE_DOMAIN(p
->arr
[2*i
]), names
);
973 print_evalue(DST
, &p
->arr
[2*i
+1], names
);
976 if (!pname
|| p
->pos
< maxdim
) {
977 for (i
= pname
? p
->pos
: 0; i
< maxdim
; ++i
)
990 static void eadd_rev(const evalue
*e1
, evalue
*res
)
994 evalue_copy(&ev
, e1
);
996 free_evalue_refs(res
);
1000 static void eadd_rev_cst(const evalue
*e1
, evalue
*res
)
1004 evalue_copy(&ev
, e1
);
1005 eadd(res
, &ev
.x
.p
->arr
[type_offset(ev
.x
.p
)]);
1006 free_evalue_refs(res
);
1010 static int is_zero_on(evalue
*e
, Polyhedron
*D
)
1015 tmp
.x
.p
= new_enode(partition
, 2, D
->Dimension
);
1016 EVALUE_SET_DOMAIN(tmp
.x
.p
->arr
[0], Domain_Copy(D
));
1017 evalue_copy(&tmp
.x
.p
->arr
[1], e
);
1018 reduce_evalue(&tmp
);
1019 is_zero
= EVALUE_IS_ZERO(tmp
);
1020 free_evalue_refs(&tmp
);
1024 struct section
{ Polyhedron
* D
; evalue E
; };
1026 void eadd_partitions(const evalue
*e1
, evalue
*res
)
1031 s
= (struct section
*)
1032 malloc((e1
->x
.p
->size
/2+1) * (res
->x
.p
->size
/2+1) *
1033 sizeof(struct section
));
1035 assert(e1
->x
.p
->pos
== res
->x
.p
->pos
);
1036 assert(e1
->x
.p
->pos
== EVALUE_DOMAIN(e1
->x
.p
->arr
[0])->Dimension
);
1037 assert(res
->x
.p
->pos
== EVALUE_DOMAIN(res
->x
.p
->arr
[0])->Dimension
);
1040 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
1041 assert(res
->x
.p
->size
>= 2);
1042 fd
= DomainDifference(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
1043 EVALUE_DOMAIN(res
->x
.p
->arr
[0]), 0);
1045 for (i
= 1; i
< res
->x
.p
->size
/2; ++i
) {
1047 fd
= DomainDifference(fd
, EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
1056 /* See if we can extend one of the domains in res to cover fd */
1057 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
)
1058 if (is_zero_on(&res
->x
.p
->arr
[2*i
+1], fd
))
1060 if (i
< res
->x
.p
->size
/2) {
1061 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*i
],
1062 DomainConcat(fd
, EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
])));
1065 value_init(s
[n
].E
.d
);
1066 evalue_copy(&s
[n
].E
, &e1
->x
.p
->arr
[2*j
+1]);
1070 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
) {
1071 fd
= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]);
1072 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
1074 d
= DomainIntersection(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
1075 EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
1081 fd
= DomainDifference(fd
, EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]), 0);
1082 if (t
!= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]))
1084 value_init(s
[n
].E
.d
);
1085 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*i
+1]);
1086 eadd(&e1
->x
.p
->arr
[2*j
+1], &s
[n
].E
);
1087 if (!emptyQ(fd
) && is_zero_on(&e1
->x
.p
->arr
[2*j
+1], fd
)) {
1088 d
= DomainConcat(fd
, d
);
1089 fd
= Empty_Polyhedron(fd
->Dimension
);
1095 s
[n
].E
= res
->x
.p
->arr
[2*i
+1];
1099 free_evalue_refs(&res
->x
.p
->arr
[2*i
+1]);
1102 if (fd
!= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]))
1103 Domain_Free(EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]));
1104 value_clear(res
->x
.p
->arr
[2*i
].d
);
1109 res
->x
.p
= new_enode(partition
, 2*n
, e1
->x
.p
->pos
);
1110 for (j
= 0; j
< n
; ++j
) {
1111 s
[j
].D
= DomainConstraintSimplify(s
[j
].D
, 0);
1112 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
1113 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
1114 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
1120 static void explicit_complement(evalue
*res
)
1122 enode
*rel
= new_enode(relation
, 3, 0);
1124 value_clear(rel
->arr
[0].d
);
1125 rel
->arr
[0] = res
->x
.p
->arr
[0];
1126 value_clear(rel
->arr
[1].d
);
1127 rel
->arr
[1] = res
->x
.p
->arr
[1];
1128 value_set_si(rel
->arr
[2].d
, 1);
1129 value_init(rel
->arr
[2].x
.n
);
1130 value_set_si(rel
->arr
[2].x
.n
, 0);
1135 void eadd(const evalue
*e1
, evalue
*res
)
1138 if (value_notzero_p(e1
->d
) && value_notzero_p(res
->d
)) {
1139 /* Add two rational numbers */
1145 value_multiply(m1
,e1
->x
.n
,res
->d
);
1146 value_multiply(m2
,res
->x
.n
,e1
->d
);
1147 value_addto(res
->x
.n
,m1
,m2
);
1148 value_multiply(res
->d
,e1
->d
,res
->d
);
1149 Gcd(res
->x
.n
,res
->d
,&g
);
1150 if (value_notone_p(g
)) {
1151 value_division(res
->d
,res
->d
,g
);
1152 value_division(res
->x
.n
,res
->x
.n
,g
);
1154 value_clear(g
); value_clear(m1
); value_clear(m2
);
1157 else if (value_notzero_p(e1
->d
) && value_zero_p(res
->d
)) {
1158 switch (res
->x
.p
->type
) {
1160 /* Add the constant to the constant term of a polynomial*/
1161 eadd(e1
, &res
->x
.p
->arr
[0]);
1164 /* Add the constant to all elements of a periodic number */
1165 for (i
=0; i
<res
->x
.p
->size
; i
++) {
1166 eadd(e1
, &res
->x
.p
->arr
[i
]);
1170 fprintf(stderr
, "eadd: cannot add const with vector\n");
1174 eadd(e1
, &res
->x
.p
->arr
[1]);
1177 assert(EVALUE_IS_ZERO(*e1
));
1178 break; /* Do nothing */
1180 /* Create (zero) complement if needed */
1181 if (res
->x
.p
->size
< 3 && !EVALUE_IS_ZERO(*e1
))
1182 explicit_complement(res
);
1183 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1184 eadd(e1
, &res
->x
.p
->arr
[i
]);
1190 /* add polynomial or periodic to constant
1191 * you have to exchange e1 and res, before doing addition */
1193 else if (value_zero_p(e1
->d
) && value_notzero_p(res
->d
)) {
1197 else { // ((e1->d==0) && (res->d==0))
1198 assert(!((e1
->x
.p
->type
== partition
) ^
1199 (res
->x
.p
->type
== partition
)));
1200 if (e1
->x
.p
->type
== partition
) {
1201 eadd_partitions(e1
, res
);
1204 if (e1
->x
.p
->type
== relation
&&
1205 (res
->x
.p
->type
!= relation
||
1206 mod_term_smaller(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]))) {
1210 if (res
->x
.p
->type
== relation
) {
1211 if (e1
->x
.p
->type
== relation
&&
1212 eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0])) {
1213 if (res
->x
.p
->size
< 3 && e1
->x
.p
->size
== 3)
1214 explicit_complement(res
);
1215 for (i
= 1; i
< e1
->x
.p
->size
; ++i
)
1216 eadd(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1219 if (res
->x
.p
->size
< 3)
1220 explicit_complement(res
);
1221 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1222 eadd(e1
, &res
->x
.p
->arr
[i
]);
1225 if ((e1
->x
.p
->type
!= res
->x
.p
->type
) ) {
1226 /* adding to evalues of different type. two cases are possible
1227 * res is periodic and e1 is polynomial, you have to exchange
1228 * e1 and res then to add e1 to the constant term of res */
1229 if (e1
->x
.p
->type
== polynomial
) {
1230 eadd_rev_cst(e1
, res
);
1232 else if (res
->x
.p
->type
== polynomial
) {
1233 /* res is polynomial and e1 is periodic,
1234 add e1 to the constant term of res */
1236 eadd(e1
,&res
->x
.p
->arr
[0]);
1242 else if (e1
->x
.p
->pos
!= res
->x
.p
->pos
||
1243 ((res
->x
.p
->type
== fractional
||
1244 res
->x
.p
->type
== flooring
) &&
1245 !eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]))) {
1246 /* adding evalues of different position (i.e function of different unknowns
1247 * to case are possible */
1249 switch (res
->x
.p
->type
) {
1252 if (mod_term_smaller(res
, e1
))
1253 eadd(e1
,&res
->x
.p
->arr
[1]);
1255 eadd_rev_cst(e1
, res
);
1257 case polynomial
: // res and e1 are polynomials
1258 // add e1 to the constant term of res
1260 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1261 eadd(e1
,&res
->x
.p
->arr
[0]);
1263 eadd_rev_cst(e1
, res
);
1264 // value_clear(g); value_clear(m1); value_clear(m2);
1266 case periodic
: // res and e1 are pointers to periodic numbers
1267 //add e1 to all elements of res
1269 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1270 for (i
=0;i
<res
->x
.p
->size
;i
++) {
1271 eadd(e1
,&res
->x
.p
->arr
[i
]);
1282 //same type , same pos and same size
1283 if (e1
->x
.p
->size
== res
->x
.p
->size
) {
1284 // add any element in e1 to the corresponding element in res
1285 i
= type_offset(res
->x
.p
);
1287 assert(eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]));
1288 for (; i
<res
->x
.p
->size
; i
++) {
1289 eadd(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1294 /* Sizes are different */
1295 switch(res
->x
.p
->type
) {
1299 /* VIN100: if e1-size > res-size you have to copy e1 in a */
1300 /* new enode and add res to that new node. If you do not do */
1301 /* that, you lose the the upper weight part of e1 ! */
1303 if(e1
->x
.p
->size
> res
->x
.p
->size
)
1306 i
= type_offset(res
->x
.p
);
1308 assert(eequal(&e1
->x
.p
->arr
[0],
1309 &res
->x
.p
->arr
[0]));
1310 for (; i
<e1
->x
.p
->size
; i
++) {
1311 eadd(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1318 /* add two periodics of the same pos (unknown) but whith different sizes (periods) */
1321 /* you have to create a new evalue 'ne' in whitch size equals to the lcm
1322 of the sizes of e1 and res, then to copy res periodicaly in ne, after
1323 to add periodicaly elements of e1 to elements of ne, and finaly to
1328 value_init(ex
); value_init(ey
);value_init(ep
);
1331 value_set_si(ex
,e1
->x
.p
->size
);
1332 value_set_si(ey
,res
->x
.p
->size
);
1333 value_assign (ep
,*Lcm(ex
,ey
));
1334 p
=(int)mpz_get_si(ep
);
1335 ne
= (evalue
*) malloc (sizeof(evalue
));
1337 value_set_si( ne
->d
,0);
1339 ne
->x
.p
=new_enode(res
->x
.p
->type
,p
, res
->x
.p
->pos
);
1341 evalue_copy(&ne
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
%y
]);
1344 eadd(&e1
->x
.p
->arr
[i
%x
], &ne
->x
.p
->arr
[i
]);
1347 value_assign(res
->d
, ne
->d
);
1353 fprintf(stderr
, "eadd: ?cannot add vectors of different length\n");
1362 static void emul_rev (evalue
*e1
, evalue
*res
)
1366 evalue_copy(&ev
, e1
);
1368 free_evalue_refs(res
);
1372 static void emul_poly (evalue
*e1
, evalue
*res
)
1374 int i
, j
, o
= type_offset(res
->x
.p
);
1376 int size
=(e1
->x
.p
->size
+ res
->x
.p
->size
- o
- 1);
1378 value_set_si(tmp
.d
,0);
1379 tmp
.x
.p
=new_enode(res
->x
.p
->type
, size
, res
->x
.p
->pos
);
1381 evalue_copy(&tmp
.x
.p
->arr
[0], &e1
->x
.p
->arr
[0]);
1382 for (i
=o
; i
< e1
->x
.p
->size
; i
++) {
1383 evalue_copy(&tmp
.x
.p
->arr
[i
], &e1
->x
.p
->arr
[i
]);
1384 emul(&res
->x
.p
->arr
[o
], &tmp
.x
.p
->arr
[i
]);
1387 evalue_set_si(&tmp
.x
.p
->arr
[i
], 0, 1);
1388 for (i
=o
+1; i
<res
->x
.p
->size
; i
++)
1389 for (j
=o
; j
<e1
->x
.p
->size
; j
++) {
1392 evalue_copy(&ev
, &e1
->x
.p
->arr
[j
]);
1393 emul(&res
->x
.p
->arr
[i
], &ev
);
1394 eadd(&ev
, &tmp
.x
.p
->arr
[i
+j
-o
]);
1395 free_evalue_refs(&ev
);
1397 free_evalue_refs(res
);
1401 void emul_partitions (evalue
*e1
,evalue
*res
)
1406 s
= (struct section
*)
1407 malloc((e1
->x
.p
->size
/2) * (res
->x
.p
->size
/2) *
1408 sizeof(struct section
));
1410 assert(e1
->x
.p
->pos
== res
->x
.p
->pos
);
1411 assert(e1
->x
.p
->pos
== EVALUE_DOMAIN(e1
->x
.p
->arr
[0])->Dimension
);
1412 assert(res
->x
.p
->pos
== EVALUE_DOMAIN(res
->x
.p
->arr
[0])->Dimension
);
1415 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
) {
1416 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
1417 d
= DomainIntersection(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
1418 EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
1424 /* This code is only needed because the partitions
1425 are not true partitions.
1427 for (k
= 0; k
< n
; ++k
) {
1428 if (DomainIncludes(s
[k
].D
, d
))
1430 if (DomainIncludes(d
, s
[k
].D
)) {
1431 Domain_Free(s
[k
].D
);
1432 free_evalue_refs(&s
[k
].E
);
1443 value_init(s
[n
].E
.d
);
1444 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*i
+1]);
1445 emul(&e1
->x
.p
->arr
[2*j
+1], &s
[n
].E
);
1449 Domain_Free(EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]));
1450 value_clear(res
->x
.p
->arr
[2*i
].d
);
1451 free_evalue_refs(&res
->x
.p
->arr
[2*i
+1]);
1456 evalue_set_si(res
, 0, 1);
1458 res
->x
.p
= new_enode(partition
, 2*n
, e1
->x
.p
->pos
);
1459 for (j
= 0; j
< n
; ++j
) {
1460 s
[j
].D
= DomainConstraintSimplify(s
[j
].D
, 0);
1461 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
1462 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
1463 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
1470 #define value_two_p(val) (mpz_cmp_si(val,2) == 0)
1472 /* Computes the product of two evalues "e1" and "res" and puts the result in "res". you must
1473 * do a copy of "res" befor calling this function if you nead it after. The vector type of
1474 * evalues is not treated here */
1476 void emul (evalue
*e1
, evalue
*res
){
1479 if((value_zero_p(e1
->d
)&&e1
->x
.p
->type
==evector
)||(value_zero_p(res
->d
)&&(res
->x
.p
->type
==evector
))) {
1480 fprintf(stderr
, "emul: do not proced on evector type !\n");
1484 if (EVALUE_IS_ZERO(*res
))
1487 if (value_zero_p(e1
->d
) && e1
->x
.p
->type
== partition
) {
1488 if (value_zero_p(res
->d
) && res
->x
.p
->type
== partition
)
1489 emul_partitions(e1
, res
);
1492 } else if (value_zero_p(res
->d
) && res
->x
.p
->type
== partition
) {
1493 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
)
1494 emul(e1
, &res
->x
.p
->arr
[2*i
+1]);
1496 if (value_zero_p(res
->d
) && res
->x
.p
->type
== relation
) {
1497 if (value_zero_p(e1
->d
) && e1
->x
.p
->type
== relation
&&
1498 eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0])) {
1499 if (res
->x
.p
->size
< 3 && e1
->x
.p
->size
== 3)
1500 explicit_complement(res
);
1501 if (e1
->x
.p
->size
< 3 && res
->x
.p
->size
== 3)
1502 explicit_complement(e1
);
1503 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1504 emul(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1507 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1508 emul(e1
, &res
->x
.p
->arr
[i
]);
1510 if(value_zero_p(e1
->d
)&& value_zero_p(res
->d
)) {
1511 switch(e1
->x
.p
->type
) {
1513 switch(res
->x
.p
->type
) {
1515 if(e1
->x
.p
->pos
== res
->x
.p
->pos
) {
1516 /* Product of two polynomials of the same variable */
1521 /* Product of two polynomials of different variables */
1523 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1524 for( i
=0; i
<res
->x
.p
->size
; i
++)
1525 emul(e1
, &res
->x
.p
->arr
[i
]);
1534 /* Product of a polynomial and a periodic or fractional */
1541 switch(res
->x
.p
->type
) {
1543 if(e1
->x
.p
->pos
==res
->x
.p
->pos
&& e1
->x
.p
->size
==res
->x
.p
->size
) {
1544 /* Product of two periodics of the same parameter and period */
1546 for(i
=0; i
<res
->x
.p
->size
;i
++)
1547 emul(&(e1
->x
.p
->arr
[i
]), &(res
->x
.p
->arr
[i
]));
1552 if(e1
->x
.p
->pos
==res
->x
.p
->pos
&& e1
->x
.p
->size
!=res
->x
.p
->size
) {
1553 /* Product of two periodics of the same parameter and different periods */
1557 value_init(x
); value_init(y
);value_init(z
);
1560 value_set_si(x
,e1
->x
.p
->size
);
1561 value_set_si(y
,res
->x
.p
->size
);
1562 value_assign (z
,*Lcm(x
,y
));
1563 lcm
=(int)mpz_get_si(z
);
1564 newp
= (evalue
*) malloc (sizeof(evalue
));
1565 value_init(newp
->d
);
1566 value_set_si( newp
->d
,0);
1567 newp
->x
.p
=new_enode(periodic
,lcm
, e1
->x
.p
->pos
);
1568 for(i
=0;i
<lcm
;i
++) {
1569 evalue_copy(&newp
->x
.p
->arr
[i
],
1570 &res
->x
.p
->arr
[i
%iy
]);
1573 emul(&e1
->x
.p
->arr
[i
%ix
], &newp
->x
.p
->arr
[i
]);
1575 value_assign(res
->d
,newp
->d
);
1578 value_clear(x
); value_clear(y
);value_clear(z
);
1582 /* Product of two periodics of different parameters */
1584 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1585 for(i
=0; i
<res
->x
.p
->size
; i
++)
1586 emul(e1
, &(res
->x
.p
->arr
[i
]));
1594 /* Product of a periodic and a polynomial */
1596 for(i
=0; i
<res
->x
.p
->size
; i
++)
1597 emul(e1
, &(res
->x
.p
->arr
[i
]));
1604 switch(res
->x
.p
->type
) {
1606 for(i
=0; i
<res
->x
.p
->size
; i
++)
1607 emul(e1
, &(res
->x
.p
->arr
[i
]));
1614 assert(e1
->x
.p
->type
== res
->x
.p
->type
);
1615 if (e1
->x
.p
->pos
== res
->x
.p
->pos
&&
1616 eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0])) {
1619 poly_denom(&e1
->x
.p
->arr
[0], &d
.d
);
1620 if (e1
->x
.p
->type
!= fractional
|| !value_two_p(d
.d
))
1625 value_set_si(d
.x
.n
, 1);
1626 /* { x }^2 == { x }/2 */
1627 /* a0 b0 + (a0 b1 + a1 b0 + a1 b1/2) { x } */
1628 assert(e1
->x
.p
->size
== 3);
1629 assert(res
->x
.p
->size
== 3);
1631 evalue_copy(&tmp
, &res
->x
.p
->arr
[2]);
1633 eadd(&res
->x
.p
->arr
[1], &tmp
);
1634 emul(&e1
->x
.p
->arr
[2], &tmp
);
1635 emul(&e1
->x
.p
->arr
[1], res
);
1636 eadd(&tmp
, &res
->x
.p
->arr
[2]);
1637 free_evalue_refs(&tmp
);
1642 if(mod_term_smaller(res
, e1
))
1643 for(i
=1; i
<res
->x
.p
->size
; i
++)
1644 emul(e1
, &(res
->x
.p
->arr
[i
]));
1659 if (value_notzero_p(e1
->d
)&& value_notzero_p(res
->d
)) {
1660 /* Product of two rational numbers */
1664 value_multiply(res
->d
,e1
->d
,res
->d
);
1665 value_multiply(res
->x
.n
,e1
->x
.n
,res
->x
.n
);
1666 Gcd(res
->x
.n
, res
->d
,&g
);
1667 if (value_notone_p(g
)) {
1668 value_division(res
->d
,res
->d
,g
);
1669 value_division(res
->x
.n
,res
->x
.n
,g
);
1675 if(value_zero_p(e1
->d
)&& value_notzero_p(res
->d
)) {
1676 /* Product of an expression (polynomial or peririodic) and a rational number */
1682 /* Product of a rationel number and an expression (polynomial or peririodic) */
1684 i
= type_offset(res
->x
.p
);
1685 for (; i
<res
->x
.p
->size
; i
++)
1686 emul(e1
, &res
->x
.p
->arr
[i
]);
1696 /* Frees mask content ! */
1697 void emask(evalue
*mask
, evalue
*res
) {
1704 if (EVALUE_IS_ZERO(*res
)) {
1705 free_evalue_refs(mask
);
1709 assert(value_zero_p(mask
->d
));
1710 assert(mask
->x
.p
->type
== partition
);
1711 assert(value_zero_p(res
->d
));
1712 assert(res
->x
.p
->type
== partition
);
1713 assert(mask
->x
.p
->pos
== res
->x
.p
->pos
);
1714 assert(res
->x
.p
->pos
== EVALUE_DOMAIN(res
->x
.p
->arr
[0])->Dimension
);
1715 assert(mask
->x
.p
->pos
== EVALUE_DOMAIN(mask
->x
.p
->arr
[0])->Dimension
);
1716 pos
= res
->x
.p
->pos
;
1718 s
= (struct section
*)
1719 malloc((mask
->x
.p
->size
/2+1) * (res
->x
.p
->size
/2) *
1720 sizeof(struct section
));
1724 evalue_set_si(&mone
, -1, 1);
1727 for (j
= 0; j
< res
->x
.p
->size
/2; ++j
) {
1728 assert(mask
->x
.p
->size
>= 2);
1729 fd
= DomainDifference(EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]),
1730 EVALUE_DOMAIN(mask
->x
.p
->arr
[0]), 0);
1732 for (i
= 1; i
< mask
->x
.p
->size
/2; ++i
) {
1734 fd
= DomainDifference(fd
, EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]), 0);
1743 value_init(s
[n
].E
.d
);
1744 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*j
+1]);
1748 for (i
= 0; i
< mask
->x
.p
->size
/2; ++i
) {
1749 if (EVALUE_IS_ONE(mask
->x
.p
->arr
[2*i
+1]))
1752 fd
= EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]);
1753 eadd(&mone
, &mask
->x
.p
->arr
[2*i
+1]);
1754 emul(&mone
, &mask
->x
.p
->arr
[2*i
+1]);
1755 for (j
= 0; j
< res
->x
.p
->size
/2; ++j
) {
1757 d
= DomainIntersection(EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]),
1758 EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]), 0);
1764 fd
= DomainDifference(fd
, EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]), 0);
1765 if (t
!= EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]))
1767 value_init(s
[n
].E
.d
);
1768 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*j
+1]);
1769 emul(&mask
->x
.p
->arr
[2*i
+1], &s
[n
].E
);
1775 /* Just ignore; this may have been previously masked off */
1777 if (fd
!= EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]))
1781 free_evalue_refs(&mone
);
1782 free_evalue_refs(mask
);
1783 free_evalue_refs(res
);
1786 evalue_set_si(res
, 0, 1);
1788 res
->x
.p
= new_enode(partition
, 2*n
, pos
);
1789 for (j
= 0; j
< n
; ++j
) {
1790 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
1791 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
1792 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
1799 void evalue_copy(evalue
*dst
, const evalue
*src
)
1801 value_assign(dst
->d
, src
->d
);
1802 if(value_notzero_p(src
->d
)) {
1803 value_init(dst
->x
.n
);
1804 value_assign(dst
->x
.n
, src
->x
.n
);
1806 dst
->x
.p
= ecopy(src
->x
.p
);
1809 enode
*new_enode(enode_type type
,int size
,int pos
) {
1815 fprintf(stderr
, "Allocating enode of size 0 !\n" );
1818 res
= (enode
*) malloc(sizeof(enode
) + (size
-1)*sizeof(evalue
));
1822 for(i
=0; i
<size
; i
++) {
1823 value_init(res
->arr
[i
].d
);
1824 value_set_si(res
->arr
[i
].d
,0);
1825 res
->arr
[i
].x
.p
= 0;
1830 enode
*ecopy(enode
*e
) {
1835 res
= new_enode(e
->type
,e
->size
,e
->pos
);
1836 for(i
=0;i
<e
->size
;++i
) {
1837 value_assign(res
->arr
[i
].d
,e
->arr
[i
].d
);
1838 if(value_zero_p(res
->arr
[i
].d
))
1839 res
->arr
[i
].x
.p
= ecopy(e
->arr
[i
].x
.p
);
1840 else if (EVALUE_IS_DOMAIN(res
->arr
[i
]))
1841 EVALUE_SET_DOMAIN(res
->arr
[i
], Domain_Copy(EVALUE_DOMAIN(e
->arr
[i
])));
1843 value_init(res
->arr
[i
].x
.n
);
1844 value_assign(res
->arr
[i
].x
.n
,e
->arr
[i
].x
.n
);
1850 int ecmp(const evalue
*e1
, const evalue
*e2
)
1856 if (value_notzero_p(e1
->d
) && value_notzero_p(e2
->d
)) {
1860 value_multiply(m
, e1
->x
.n
, e2
->d
);
1861 value_multiply(m2
, e2
->x
.n
, e1
->d
);
1863 if (value_lt(m
, m2
))
1865 else if (value_gt(m
, m2
))
1875 if (value_notzero_p(e1
->d
))
1877 if (value_notzero_p(e2
->d
))
1883 if (p1
->type
!= p2
->type
)
1884 return p1
->type
- p2
->type
;
1885 if (p1
->pos
!= p2
->pos
)
1886 return p1
->pos
- p2
->pos
;
1887 if (p1
->size
!= p2
->size
)
1888 return p1
->size
- p2
->size
;
1890 for (i
= p1
->size
-1; i
>= 0; --i
)
1891 if ((r
= ecmp(&p1
->arr
[i
], &p2
->arr
[i
])) != 0)
1897 int eequal(evalue
*e1
,evalue
*e2
) {
1902 if (value_ne(e1
->d
,e2
->d
))
1905 /* e1->d == e2->d */
1906 if (value_notzero_p(e1
->d
)) {
1907 if (value_ne(e1
->x
.n
,e2
->x
.n
))
1910 /* e1->d == e2->d != 0 AND e1->n == e2->n */
1914 /* e1->d == e2->d == 0 */
1917 if (p1
->type
!= p2
->type
) return 0;
1918 if (p1
->size
!= p2
->size
) return 0;
1919 if (p1
->pos
!= p2
->pos
) return 0;
1920 for (i
=0; i
<p1
->size
; i
++)
1921 if (!eequal(&p1
->arr
[i
], &p2
->arr
[i
]) )
1926 void free_evalue_refs(evalue
*e
) {
1931 if (EVALUE_IS_DOMAIN(*e
)) {
1932 Domain_Free(EVALUE_DOMAIN(*e
));
1935 } else if (value_pos_p(e
->d
)) {
1937 /* 'e' stores a constant */
1939 value_clear(e
->x
.n
);
1942 assert(value_zero_p(e
->d
));
1945 if (!p
) return; /* null pointer */
1946 for (i
=0; i
<p
->size
; i
++) {
1947 free_evalue_refs(&(p
->arr
[i
]));
1951 } /* free_evalue_refs */
1953 static void mod2table_r(evalue
*e
, Vector
*periods
, Value m
, int p
,
1954 Vector
* val
, evalue
*res
)
1956 unsigned nparam
= periods
->Size
;
1959 double d
= compute_evalue(e
, val
->p
);
1960 d
*= VALUE_TO_DOUBLE(m
);
1965 value_assign(res
->d
, m
);
1966 value_init(res
->x
.n
);
1967 value_set_double(res
->x
.n
, d
);
1968 mpz_fdiv_r(res
->x
.n
, res
->x
.n
, m
);
1971 if (value_one_p(periods
->p
[p
]))
1972 mod2table_r(e
, periods
, m
, p
+1, val
, res
);
1977 value_assign(tmp
, periods
->p
[p
]);
1978 value_set_si(res
->d
, 0);
1979 res
->x
.p
= new_enode(periodic
, VALUE_TO_INT(tmp
), p
+1);
1981 value_decrement(tmp
, tmp
);
1982 value_assign(val
->p
[p
], tmp
);
1983 mod2table_r(e
, periods
, m
, p
+1, val
,
1984 &res
->x
.p
->arr
[VALUE_TO_INT(tmp
)]);
1985 } while (value_pos_p(tmp
));
1991 static void rel2table(evalue
*e
, int zero
)
1993 if (value_pos_p(e
->d
)) {
1994 if (value_zero_p(e
->x
.n
) == zero
)
1995 value_set_si(e
->x
.n
, 1);
1997 value_set_si(e
->x
.n
, 0);
1998 value_set_si(e
->d
, 1);
2001 for (i
= 0; i
< e
->x
.p
->size
; ++i
)
2002 rel2table(&e
->x
.p
->arr
[i
], zero
);
2006 void evalue_mod2table(evalue
*e
, int nparam
)
2011 if (EVALUE_IS_DOMAIN(*e
) || value_pos_p(e
->d
))
2014 for (i
=0; i
<p
->size
; i
++) {
2015 evalue_mod2table(&(p
->arr
[i
]), nparam
);
2017 if (p
->type
== relation
) {
2022 evalue_copy(©
, &p
->arr
[0]);
2024 rel2table(&p
->arr
[0], 1);
2025 emul(&p
->arr
[0], &p
->arr
[1]);
2027 rel2table(©
, 0);
2028 emul(©
, &p
->arr
[2]);
2029 eadd(&p
->arr
[2], &p
->arr
[1]);
2030 free_evalue_refs(&p
->arr
[2]);
2031 free_evalue_refs(©
);
2033 free_evalue_refs(&p
->arr
[0]);
2037 } else if (p
->type
== fractional
) {
2038 Vector
*periods
= Vector_Alloc(nparam
);
2039 Vector
*val
= Vector_Alloc(nparam
);
2045 value_set_si(tmp
, 1);
2046 Vector_Set(periods
->p
, 1, nparam
);
2047 Vector_Set(val
->p
, 0, nparam
);
2048 for (ev
= &p
->arr
[0]; value_zero_p(ev
->d
); ev
= &ev
->x
.p
->arr
[0]) {
2051 assert(p
->type
== polynomial
);
2052 assert(p
->size
== 2);
2053 value_assign(periods
->p
[p
->pos
-1], p
->arr
[1].d
);
2054 value_lcm(tmp
, p
->arr
[1].d
, &tmp
);
2056 value_lcm(tmp
, ev
->d
, &tmp
);
2058 mod2table_r(&p
->arr
[0], periods
, tmp
, 0, val
, &EP
);
2061 evalue_set_si(&res
, 0, 1);
2062 /* Compute the polynomial using Horner's rule */
2063 for (i
=p
->size
-1;i
>1;i
--) {
2064 eadd(&p
->arr
[i
], &res
);
2067 eadd(&p
->arr
[1], &res
);
2069 free_evalue_refs(e
);
2070 free_evalue_refs(&EP
);
2075 Vector_Free(periods
);
2077 } /* evalue_mod2table */
2079 /********************************************************/
2080 /* function in domain */
2081 /* check if the parameters in list_args */
2082 /* verifies the constraints of Domain P */
2083 /********************************************************/
2084 int in_domain(Polyhedron
*P
, Value
*list_args
)
2087 Value v
; /* value of the constraint of a row when
2088 parameters are instantiated*/
2092 for (row
= 0; row
< P
->NbConstraints
; row
++) {
2093 Inner_Product(P
->Constraint
[row
]+1, list_args
, P
->Dimension
, &v
);
2094 value_addto(v
, v
, P
->Constraint
[row
][P
->Dimension
+1]); /*constant part*/
2095 if (value_neg_p(v
) ||
2096 value_zero_p(P
->Constraint
[row
][0]) && value_notzero_p(v
)) {
2103 return in
|| (P
->next
&& in_domain(P
->next
, list_args
));
2106 /****************************************************/
2107 /* function compute enode */
2108 /* compute the value of enode p with parameters */
2109 /* list "list_args */
2110 /* compute the polynomial or the periodic */
2111 /****************************************************/
2113 static double compute_enode(enode
*p
, Value
*list_args
) {
2125 if (p
->type
== polynomial
) {
2127 value_assign(param
,list_args
[p
->pos
-1]);
2129 /* Compute the polynomial using Horner's rule */
2130 for (i
=p
->size
-1;i
>0;i
--) {
2131 res
+=compute_evalue(&p
->arr
[i
],list_args
);
2132 res
*=VALUE_TO_DOUBLE(param
);
2134 res
+=compute_evalue(&p
->arr
[0],list_args
);
2136 else if (p
->type
== fractional
) {
2137 double d
= compute_evalue(&p
->arr
[0], list_args
);
2138 d
-= floor(d
+1e-10);
2140 /* Compute the polynomial using Horner's rule */
2141 for (i
=p
->size
-1;i
>1;i
--) {
2142 res
+=compute_evalue(&p
->arr
[i
],list_args
);
2145 res
+=compute_evalue(&p
->arr
[1],list_args
);
2147 else if (p
->type
== flooring
) {
2148 double d
= compute_evalue(&p
->arr
[0], list_args
);
2151 /* Compute the polynomial using Horner's rule */
2152 for (i
=p
->size
-1;i
>1;i
--) {
2153 res
+=compute_evalue(&p
->arr
[i
],list_args
);
2156 res
+=compute_evalue(&p
->arr
[1],list_args
);
2158 else if (p
->type
== periodic
) {
2159 value_assign(m
,list_args
[p
->pos
-1]);
2161 /* Choose the right element of the periodic */
2162 value_set_si(param
,p
->size
);
2163 value_pmodulus(m
,m
,param
);
2164 res
= compute_evalue(&p
->arr
[VALUE_TO_INT(m
)],list_args
);
2166 else if (p
->type
== relation
) {
2167 if (fabs(compute_evalue(&p
->arr
[0], list_args
)) < 1e-10)
2168 res
= compute_evalue(&p
->arr
[1], list_args
);
2169 else if (p
->size
> 2)
2170 res
= compute_evalue(&p
->arr
[2], list_args
);
2172 else if (p
->type
== partition
) {
2173 int dim
= EVALUE_DOMAIN(p
->arr
[0])->Dimension
;
2174 Value
*vals
= list_args
;
2177 for (i
= 0; i
< dim
; ++i
) {
2178 value_init(vals
[i
]);
2180 value_assign(vals
[i
], list_args
[i
]);
2183 for (i
= 0; i
< p
->size
/2; ++i
)
2184 if (DomainContains(EVALUE_DOMAIN(p
->arr
[2*i
]), vals
, p
->pos
, 0, 1)) {
2185 res
= compute_evalue(&p
->arr
[2*i
+1], vals
);
2189 for (i
= 0; i
< dim
; ++i
)
2190 value_clear(vals
[i
]);
2199 } /* compute_enode */
2201 /*************************************************/
2202 /* return the value of Ehrhart Polynomial */
2203 /* It returns a double, because since it is */
2204 /* a recursive function, some intermediate value */
2205 /* might not be integral */
2206 /*************************************************/
2208 double compute_evalue(evalue
*e
,Value
*list_args
) {
2212 if (value_notzero_p(e
->d
)) {
2213 if (value_notone_p(e
->d
))
2214 res
= VALUE_TO_DOUBLE(e
->x
.n
) / VALUE_TO_DOUBLE(e
->d
);
2216 res
= VALUE_TO_DOUBLE(e
->x
.n
);
2219 res
= compute_enode(e
->x
.p
,list_args
);
2221 } /* compute_evalue */
2224 /****************************************************/
2225 /* function compute_poly : */
2226 /* Check for the good validity domain */
2227 /* return the number of point in the Polyhedron */
2228 /* in allocated memory */
2229 /* Using the Ehrhart pseudo-polynomial */
2230 /****************************************************/
2231 Value
*compute_poly(Enumeration
*en
,Value
*list_args
) {
2234 /* double d; int i; */
2236 tmp
= (Value
*) malloc (sizeof(Value
));
2237 assert(tmp
!= NULL
);
2239 value_set_si(*tmp
,0);
2242 return(tmp
); /* no ehrhart polynomial */
2243 if(en
->ValidityDomain
) {
2244 if(!en
->ValidityDomain
->Dimension
) { /* no parameters */
2245 value_set_double(*tmp
,compute_evalue(&en
->EP
,list_args
)+.25);
2250 return(tmp
); /* no Validity Domain */
2252 if(in_domain(en
->ValidityDomain
,list_args
)) {
2254 #ifdef EVAL_EHRHART_DEBUG
2255 Print_Domain(stdout
,en
->ValidityDomain
);
2256 print_evalue(stdout
,&en
->EP
);
2259 /* d = compute_evalue(&en->EP,list_args);
2261 printf("(double)%lf = %d\n", d, i ); */
2262 value_set_double(*tmp
,compute_evalue(&en
->EP
,list_args
)+.25);
2268 value_set_si(*tmp
,0);
2269 return(tmp
); /* no compatible domain with the arguments */
2270 } /* compute_poly */
2272 size_t value_size(Value v
) {
2273 return (v
[0]._mp_size
> 0 ? v
[0]._mp_size
: -v
[0]._mp_size
)
2274 * sizeof(v
[0]._mp_d
[0]);
2277 size_t domain_size(Polyhedron
*D
)
2280 size_t s
= sizeof(*D
);
2282 for (i
= 0; i
< D
->NbConstraints
; ++i
)
2283 for (j
= 0; j
< D
->Dimension
+2; ++j
)
2284 s
+= value_size(D
->Constraint
[i
][j
]);
2287 for (i = 0; i < D->NbRays; ++i)
2288 for (j = 0; j < D->Dimension+2; ++j)
2289 s += value_size(D->Ray[i][j]);
2292 return D
->next
? s
+domain_size(D
->next
) : s
;
2295 size_t enode_size(enode
*p
) {
2296 size_t s
= sizeof(*p
) - sizeof(p
->arr
[0]);
2299 if (p
->type
== partition
)
2300 for (i
= 0; i
< p
->size
/2; ++i
) {
2301 s
+= domain_size(EVALUE_DOMAIN(p
->arr
[2*i
]));
2302 s
+= evalue_size(&p
->arr
[2*i
+1]);
2305 for (i
= 0; i
< p
->size
; ++i
) {
2306 s
+= evalue_size(&p
->arr
[i
]);
2311 size_t evalue_size(evalue
*e
)
2313 size_t s
= sizeof(*e
);
2314 s
+= value_size(e
->d
);
2315 if (value_notzero_p(e
->d
))
2316 s
+= value_size(e
->x
.n
);
2318 s
+= enode_size(e
->x
.p
);
2322 static evalue
*find_second(evalue
*base
, evalue
*cst
, evalue
*e
, Value m
)
2324 evalue
*found
= NULL
;
2329 if (value_pos_p(e
->d
) || e
->x
.p
->type
!= fractional
)
2332 value_init(offset
.d
);
2333 value_init(offset
.x
.n
);
2334 poly_denom(&e
->x
.p
->arr
[0], &offset
.d
);
2335 value_lcm(m
, offset
.d
, &offset
.d
);
2336 value_set_si(offset
.x
.n
, 1);
2339 evalue_copy(©
, cst
);
2342 mpz_fdiv_r(cst
->x
.n
, cst
->x
.n
, cst
->d
);
2344 if (eequal(base
, &e
->x
.p
->arr
[0]))
2345 found
= &e
->x
.p
->arr
[0];
2347 value_set_si(offset
.x
.n
, -2);
2350 mpz_fdiv_r(cst
->x
.n
, cst
->x
.n
, cst
->d
);
2352 if (eequal(base
, &e
->x
.p
->arr
[0]))
2355 free_evalue_refs(cst
);
2356 free_evalue_refs(&offset
);
2359 for (i
= 1; !found
&& i
< e
->x
.p
->size
; ++i
)
2360 found
= find_second(base
, cst
, &e
->x
.p
->arr
[i
], m
);
2365 static evalue
*find_relation_pair(evalue
*e
)
2368 evalue
*found
= NULL
;
2370 if (EVALUE_IS_DOMAIN(*e
) || value_pos_p(e
->d
))
2373 if (e
->x
.p
->type
== fractional
) {
2378 poly_denom(&e
->x
.p
->arr
[0], &m
);
2380 for (cst
= &e
->x
.p
->arr
[0]; value_zero_p(cst
->d
);
2381 cst
= &cst
->x
.p
->arr
[0])
2384 for (i
= 1; !found
&& i
< e
->x
.p
->size
; ++i
)
2385 found
= find_second(&e
->x
.p
->arr
[0], cst
, &e
->x
.p
->arr
[i
], m
);
2390 i
= e
->x
.p
->type
== relation
;
2391 for (; !found
&& i
< e
->x
.p
->size
; ++i
)
2392 found
= find_relation_pair(&e
->x
.p
->arr
[i
]);
2397 void evalue_mod2relation(evalue
*e
) {
2400 if (value_zero_p(e
->d
) && e
->x
.p
->type
== partition
) {
2403 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2404 evalue_mod2relation(&e
->x
.p
->arr
[2*i
+1]);
2405 if (EVALUE_IS_ZERO(e
->x
.p
->arr
[2*i
+1])) {
2406 value_clear(e
->x
.p
->arr
[2*i
].d
);
2407 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
2409 if (2*i
< e
->x
.p
->size
) {
2410 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
2411 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
2416 if (e
->x
.p
->size
== 0) {
2418 evalue_set_si(e
, 0, 1);
2424 while ((d
= find_relation_pair(e
)) != NULL
) {
2428 value_init(split
.d
);
2429 value_set_si(split
.d
, 0);
2430 split
.x
.p
= new_enode(relation
, 3, 0);
2431 evalue_set_si(&split
.x
.p
->arr
[1], 1, 1);
2432 evalue_set_si(&split
.x
.p
->arr
[2], 1, 1);
2434 ev
= &split
.x
.p
->arr
[0];
2435 value_set_si(ev
->d
, 0);
2436 ev
->x
.p
= new_enode(fractional
, 3, -1);
2437 evalue_set_si(&ev
->x
.p
->arr
[1], 0, 1);
2438 evalue_set_si(&ev
->x
.p
->arr
[2], 1, 1);
2439 evalue_copy(&ev
->x
.p
->arr
[0], d
);
2445 free_evalue_refs(&split
);
2449 static int evalue_comp(const void * a
, const void * b
)
2451 const evalue
*e1
= *(const evalue
**)a
;
2452 const evalue
*e2
= *(const evalue
**)b
;
2453 return ecmp(e1
, e2
);
2456 void evalue_combine(evalue
*e
)
2463 if (value_notzero_p(e
->d
) || e
->x
.p
->type
!= partition
)
2466 NALLOC(evs
, e
->x
.p
->size
/2);
2467 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
2468 evs
[i
] = &e
->x
.p
->arr
[2*i
+1];
2469 qsort(evs
, e
->x
.p
->size
/2, sizeof(evs
[0]), evalue_comp
);
2470 p
= new_enode(partition
, e
->x
.p
->size
, e
->x
.p
->pos
);
2471 for (i
= 0, k
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2472 if (k
== 0 || ecmp(&p
->arr
[2*k
-1], evs
[i
]) != 0) {
2473 value_clear(p
->arr
[2*k
].d
);
2474 value_clear(p
->arr
[2*k
+1].d
);
2475 p
->arr
[2*k
] = *(evs
[i
]-1);
2476 p
->arr
[2*k
+1] = *(evs
[i
]);
2479 Polyhedron
*D
= EVALUE_DOMAIN(*(evs
[i
]-1));
2482 value_clear((evs
[i
]-1)->d
);
2486 L
->next
= EVALUE_DOMAIN(p
->arr
[2*k
-2]);
2487 EVALUE_SET_DOMAIN(p
->arr
[2*k
-2], D
);
2488 free_evalue_refs(evs
[i
]);
2492 for (i
= 2*k
; i
< p
->size
; ++i
)
2493 value_clear(p
->arr
[i
].d
);
2500 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2502 if (value_notzero_p(e
->x
.p
->arr
[2*i
+1].d
))
2504 H
= DomainConvex(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]), 0);
2507 for (k
= 0; k
< e
->x
.p
->size
/2; ++k
) {
2508 Polyhedron
*D
, *N
, **P
;
2511 P
= &EVALUE_DOMAIN(e
->x
.p
->arr
[2*k
]);
2518 if (D
->NbEq
<= H
->NbEq
) {
2524 tmp
.x
.p
= new_enode(partition
, 2, e
->x
.p
->pos
);
2525 EVALUE_SET_DOMAIN(tmp
.x
.p
->arr
[0], Polyhedron_Copy(D
));
2526 evalue_copy(&tmp
.x
.p
->arr
[1], &e
->x
.p
->arr
[2*i
+1]);
2527 reduce_evalue(&tmp
);
2528 if (value_notzero_p(tmp
.d
) ||
2529 ecmp(&tmp
.x
.p
->arr
[1], &e
->x
.p
->arr
[2*k
+1]) != 0)
2532 D
->next
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]);
2533 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]) = D
;
2536 free_evalue_refs(&tmp
);
2542 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2544 Polyhedron
*D
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]);
2546 value_clear(e
->x
.p
->arr
[2*i
].d
);
2547 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
2549 if (2*i
< e
->x
.p
->size
) {
2550 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
2551 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
2558 H
= DomainConvex(D
, 0);
2559 E
= DomainDifference(H
, D
, 0);
2561 D
= DomainDifference(H
, E
, 0);
2564 EVALUE_SET_DOMAIN(p
->arr
[2*i
], D
);
2568 /* May change coefficients to become non-standard if fiddle is set
2569 * => reduce p afterwards to correct
2571 static Polyhedron
*polynomial_projection(enode
*p
, Polyhedron
*D
, Value
*d
,
2572 Matrix
**R
, int fiddle
)
2576 unsigned dim
= D
->Dimension
;
2577 Matrix
*T
= Matrix_Alloc(2, dim
+1);
2582 assert(p
->type
== fractional
);
2584 value_set_si(T
->p
[1][dim
], 1);
2586 while (value_zero_p(pp
->d
)) {
2587 assert(pp
->x
.p
->type
== polynomial
);
2588 assert(pp
->x
.p
->size
== 2);
2589 assert(value_notzero_p(pp
->x
.p
->arr
[1].d
));
2590 value_division(T
->p
[0][pp
->x
.p
->pos
-1], *d
, pp
->x
.p
->arr
[1].d
);
2591 mpz_mul_ui(twice
, pp
->x
.p
->arr
[1].x
.n
, 2);
2592 if (fiddle
&& value_gt(twice
, pp
->x
.p
->arr
[1].d
))
2593 value_subtract(pp
->x
.p
->arr
[1].x
.n
,
2594 pp
->x
.p
->arr
[1].x
.n
, pp
->x
.p
->arr
[1].d
);
2595 value_multiply(T
->p
[0][pp
->x
.p
->pos
-1],
2596 T
->p
[0][pp
->x
.p
->pos
-1], pp
->x
.p
->arr
[1].x
.n
);
2597 pp
= &pp
->x
.p
->arr
[0];
2599 value_division(T
->p
[0][dim
], *d
, pp
->d
);
2600 value_multiply(T
->p
[0][dim
], T
->p
[0][dim
], pp
->x
.n
);
2601 I
= DomainImage(D
, T
, 0);
2602 H
= DomainConvex(I
, 0);
2611 int evalue_range_reduction_in_domain(evalue
*e
, Polyhedron
*D
)
2621 if (value_notzero_p(e
->d
))
2626 if (p
->type
== relation
) {
2632 I
= polynomial_projection(p
->arr
[0].x
.p
, D
, &d
, &T
, 1);
2633 bounded
= line_minmax(I
, &min
, &max
); /* frees I */
2634 equal
= value_eq(min
, max
);
2635 mpz_cdiv_q(min
, min
, d
);
2636 mpz_fdiv_q(max
, max
, d
);
2638 if (bounded
&& value_gt(min
, max
)) {
2644 evalue_set_si(e
, 0, 1);
2647 free_evalue_refs(&(p
->arr
[1]));
2648 free_evalue_refs(&(p
->arr
[0]));
2654 return r
? r
: evalue_range_reduction_in_domain(e
, D
);
2655 } else if (bounded
&& equal
) {
2658 free_evalue_refs(&(p
->arr
[2]));
2661 free_evalue_refs(&(p
->arr
[0]));
2667 return evalue_range_reduction_in_domain(e
, D
);
2668 } else if (bounded
&& value_eq(min
, max
)) {
2669 /* zero for a single value */
2671 Matrix
*M
= Matrix_Alloc(1, D
->Dimension
+2);
2672 Vector_Copy(T
->p
[0], M
->p
[0]+1, D
->Dimension
+1);
2673 value_multiply(min
, min
, d
);
2674 value_subtract(M
->p
[0][D
->Dimension
+1],
2675 M
->p
[0][D
->Dimension
+1], min
);
2676 E
= DomainAddConstraints(D
, M
, 0);
2682 r
= evalue_range_reduction_in_domain(&p
->arr
[1], E
);
2684 r
|= evalue_range_reduction_in_domain(&p
->arr
[2], D
);
2686 _reduce_evalue(&p
->arr
[0].x
.p
->arr
[0], 0, 1);
2694 _reduce_evalue(&p
->arr
[0].x
.p
->arr
[0], 0, 1);
2697 i
= p
->type
== relation
? 1 :
2698 p
->type
== fractional
? 1 : 0;
2699 for (; i
<p
->size
; i
++)
2700 r
|= evalue_range_reduction_in_domain(&p
->arr
[i
], D
);
2702 if (p
->type
!= fractional
) {
2703 if (r
&& p
->type
== polynomial
) {
2706 value_set_si(f
.d
, 0);
2707 f
.x
.p
= new_enode(polynomial
, 2, p
->pos
);
2708 evalue_set_si(&f
.x
.p
->arr
[0], 0, 1);
2709 evalue_set_si(&f
.x
.p
->arr
[1], 1, 1);
2710 reorder_terms(p
, &f
);
2721 I
= polynomial_projection(p
, D
, &d
, &T
, 1);
2723 bounded
= line_minmax(I
, &min
, &max
); /* frees I */
2724 mpz_fdiv_q(min
, min
, d
);
2725 mpz_fdiv_q(max
, max
, d
);
2726 value_subtract(d
, max
, min
);
2728 if (bounded
&& value_eq(min
, max
)) {
2731 value_init(inc
.x
.n
);
2732 value_set_si(inc
.d
, 1);
2733 value_oppose(inc
.x
.n
, min
);
2734 eadd(&inc
, &p
->arr
[0]);
2735 reorder_terms(p
, &p
->arr
[0]); /* frees arr[0] */
2739 free_evalue_refs(&inc
);
2741 } else if (bounded
&& value_one_p(d
) && p
->size
> 3) {
2748 value_set_si(rem
.d
, 0);
2749 rem
.x
.p
= new_enode(fractional
, 3, -1);
2750 evalue_copy(&rem
.x
.p
->arr
[0], &p
->arr
[0]);
2751 value_clear(rem
.x
.p
->arr
[1].d
);
2752 value_clear(rem
.x
.p
->arr
[2].d
);
2753 rem
.x
.p
->arr
[1] = p
->arr
[1];
2754 rem
.x
.p
->arr
[2] = p
->arr
[2];
2755 for (i
= 3; i
< p
->size
; ++i
)
2756 p
->arr
[i
-2] = p
->arr
[i
];
2760 value_init(inc
.x
.n
);
2761 value_set_si(inc
.d
, 1);
2762 value_oppose(inc
.x
.n
, min
);
2765 evalue_copy(&t
, &p
->arr
[0]);
2769 value_set_si(f
.d
, 0);
2770 f
.x
.p
= new_enode(fractional
, 3, -1);
2771 evalue_copy(&f
.x
.p
->arr
[0], &p
->arr
[0]);
2772 evalue_set_si(&f
.x
.p
->arr
[1], 1, 1);
2773 evalue_set_si(&f
.x
.p
->arr
[2], 2, 1);
2775 value_init(factor
.d
);
2776 evalue_set_si(&factor
, -1, 1);
2782 value_clear(f
.x
.p
->arr
[1].x
.n
);
2783 value_clear(f
.x
.p
->arr
[2].x
.n
);
2784 evalue_set_si(&f
.x
.p
->arr
[1], 0, 1);
2785 evalue_set_si(&f
.x
.p
->arr
[2], -1, 1);
2791 free_evalue_refs(&inc
);
2792 free_evalue_refs(&t
);
2793 free_evalue_refs(&f
);
2794 free_evalue_refs(&factor
);
2795 free_evalue_refs(&rem
);
2797 evalue_range_reduction_in_domain(e
, D
);
2801 _reduce_evalue(&p
->arr
[0], 0, 1);
2805 value_set_si(f
.d
, 0);
2806 f
.x
.p
= new_enode(fractional
, 3, -1);
2807 value_clear(f
.x
.p
->arr
[0].d
);
2808 f
.x
.p
->arr
[0] = p
->arr
[0];
2809 evalue_set_si(&f
.x
.p
->arr
[1], 0, 1);
2810 evalue_set_si(&f
.x
.p
->arr
[2], 1, 1);
2811 reorder_terms(p
, &f
);
2825 void evalue_range_reduction(evalue
*e
)
2828 if (value_notzero_p(e
->d
) || e
->x
.p
->type
!= partition
)
2831 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
2832 if (evalue_range_reduction_in_domain(&e
->x
.p
->arr
[2*i
+1],
2833 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]))) {
2834 reduce_evalue(&e
->x
.p
->arr
[2*i
+1]);
2836 if (EVALUE_IS_ZERO(e
->x
.p
->arr
[2*i
+1])) {
2837 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
2838 Domain_Free(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]));
2839 value_clear(e
->x
.p
->arr
[2*i
].d
);
2841 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
2842 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
2850 Enumeration
* partition2enumeration(evalue
*EP
)
2853 Enumeration
*en
, *res
= NULL
;
2855 if (EVALUE_IS_ZERO(*EP
)) {
2860 for (i
= 0; i
< EP
->x
.p
->size
/2; ++i
) {
2861 assert(EP
->x
.p
->pos
== EVALUE_DOMAIN(EP
->x
.p
->arr
[2*i
])->Dimension
);
2862 en
= (Enumeration
*)malloc(sizeof(Enumeration
));
2865 res
->ValidityDomain
= EVALUE_DOMAIN(EP
->x
.p
->arr
[2*i
]);
2866 value_clear(EP
->x
.p
->arr
[2*i
].d
);
2867 res
->EP
= EP
->x
.p
->arr
[2*i
+1];
2875 int evalue_frac2floor_in_domain3(evalue
*e
, Polyhedron
*D
, int shift
)
2885 if (value_notzero_p(e
->d
))
2890 i
= p
->type
== relation
? 1 :
2891 p
->type
== fractional
? 1 : 0;
2892 for (; i
<p
->size
; i
++)
2893 r
|= evalue_frac2floor_in_domain3(&p
->arr
[i
], D
, shift
);
2895 if (p
->type
!= fractional
) {
2896 if (r
&& p
->type
== polynomial
) {
2899 value_set_si(f
.d
, 0);
2900 f
.x
.p
= new_enode(polynomial
, 2, p
->pos
);
2901 evalue_set_si(&f
.x
.p
->arr
[0], 0, 1);
2902 evalue_set_si(&f
.x
.p
->arr
[1], 1, 1);
2903 reorder_terms(p
, &f
);
2913 I
= polynomial_projection(p
, D
, &d
, &T
, 0);
2916 Polyhedron_Print(stderr, P_VALUE_FMT, I);
2919 assert(I
->NbEq
== 0); /* Should have been reduced */
2922 for (i
= 0; i
< I
->NbConstraints
; ++i
)
2923 if (value_pos_p(I
->Constraint
[i
][1]))
2926 if (i
< I
->NbConstraints
) {
2928 value_oppose(I
->Constraint
[i
][2], I
->Constraint
[i
][2]);
2929 mpz_cdiv_q(min
, I
->Constraint
[i
][2], I
->Constraint
[i
][1]);
2930 if (value_neg_p(min
)) {
2932 mpz_fdiv_q(min
, min
, d
);
2933 value_init(offset
.d
);
2934 value_set_si(offset
.d
, 1);
2935 value_init(offset
.x
.n
);
2936 value_oppose(offset
.x
.n
, min
);
2937 eadd(&offset
, &p
->arr
[0]);
2938 free_evalue_refs(&offset
);
2949 value_set_si(fl
.d
, 0);
2950 fl
.x
.p
= new_enode(flooring
, 3, -1);
2951 evalue_set_si(&fl
.x
.p
->arr
[1], 0, 1);
2952 evalue_set_si(&fl
.x
.p
->arr
[2], -1, 1);
2953 evalue_copy(&fl
.x
.p
->arr
[0], &p
->arr
[0]);
2955 eadd(&fl
, &p
->arr
[0]);
2956 reorder_terms(p
, &p
->arr
[0]);
2960 free_evalue_refs(&fl
);
2965 int evalue_frac2floor_in_domain(evalue
*e
, Polyhedron
*D
)
2967 return evalue_frac2floor_in_domain3(e
, D
, 1);
2970 void evalue_frac2floor2(evalue
*e
, int shift
)
2973 if (value_notzero_p(e
->d
) || e
->x
.p
->type
!= partition
)
2976 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
2977 if (evalue_frac2floor_in_domain3(&e
->x
.p
->arr
[2*i
+1],
2978 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]), shift
))
2979 reduce_evalue(&e
->x
.p
->arr
[2*i
+1]);
2982 void evalue_frac2floor(evalue
*e
)
2984 evalue_frac2floor2(e
, 1);
2987 static Matrix
*esum_add_constraint(int nvar
, Polyhedron
*D
, Matrix
*C
,
2992 int nparam
= D
->Dimension
- nvar
;
2995 nr
= D
->NbConstraints
+ 2;
2996 nc
= D
->Dimension
+ 2 + 1;
2997 C
= Matrix_Alloc(nr
, nc
);
2998 for (i
= 0; i
< D
->NbConstraints
; ++i
) {
2999 Vector_Copy(D
->Constraint
[i
], C
->p
[i
], 1 + nvar
);
3000 Vector_Copy(D
->Constraint
[i
] + 1 + nvar
, C
->p
[i
] + 1 + nvar
+ 1,
3001 D
->Dimension
+ 1 - nvar
);
3006 nc
= C
->NbColumns
+ 1;
3007 C
= Matrix_Alloc(nr
, nc
);
3008 for (i
= 0; i
< oldC
->NbRows
; ++i
) {
3009 Vector_Copy(oldC
->p
[i
], C
->p
[i
], 1 + nvar
);
3010 Vector_Copy(oldC
->p
[i
] + 1 + nvar
, C
->p
[i
] + 1 + nvar
+ 1,
3011 oldC
->NbColumns
- 1 - nvar
);
3014 value_set_si(C
->p
[nr
-2][0], 1);
3015 value_set_si(C
->p
[nr
-2][1 + nvar
], 1);
3016 value_set_si(C
->p
[nr
-2][nc
- 1], -1);
3018 Vector_Copy(row
->p
, C
->p
[nr
-1], 1 + nvar
+ 1);
3019 Vector_Copy(row
->p
+ 1 + nvar
+ 1, C
->p
[nr
-1] + C
->NbColumns
- 1 - nparam
,
3025 static void floor2frac_r(evalue
*e
, int nvar
)
3032 if (value_notzero_p(e
->d
))
3037 assert(p
->type
== flooring
);
3038 for (i
= 1; i
< p
->size
; i
++)
3039 floor2frac_r(&p
->arr
[i
], nvar
);
3041 for (pp
= &p
->arr
[0]; value_zero_p(pp
->d
); pp
= &pp
->x
.p
->arr
[0]) {
3042 assert(pp
->x
.p
->type
== polynomial
);
3043 pp
->x
.p
->pos
-= nvar
;
3047 value_set_si(f
.d
, 0);
3048 f
.x
.p
= new_enode(fractional
, 3, -1);
3049 evalue_set_si(&f
.x
.p
->arr
[1], 0, 1);
3050 evalue_set_si(&f
.x
.p
->arr
[2], -1, 1);
3051 evalue_copy(&f
.x
.p
->arr
[0], &p
->arr
[0]);
3053 eadd(&f
, &p
->arr
[0]);
3054 reorder_terms(p
, &p
->arr
[0]);
3058 free_evalue_refs(&f
);
3061 /* Convert flooring back to fractional and shift position
3062 * of the parameters by nvar
3064 static void floor2frac(evalue
*e
, int nvar
)
3066 floor2frac_r(e
, nvar
);
3070 evalue
*esum_over_domain_cst(int nvar
, Polyhedron
*D
, Matrix
*C
)
3073 int nparam
= D
->Dimension
- nvar
;
3077 D
= Constraints2Polyhedron(C
, 0);
3081 t
= barvinok_enumerate_e(D
, 0, nparam
, 0);
3083 /* Double check that D was not unbounded. */
3084 assert(!(value_pos_p(t
->d
) && value_neg_p(t
->x
.n
)));
3092 evalue
*esum_over_domain(evalue
*e
, int nvar
, Polyhedron
*D
,
3099 evalue
*factor
= NULL
;
3102 if (EVALUE_IS_ZERO(*e
))
3106 Polyhedron
*DD
= Disjoint_Domain(D
, 0, 0);
3113 res
= esum_over_domain(e
, nvar
, Q
, C
);
3116 for (Q
= DD
; Q
; Q
= DD
) {
3122 t
= esum_over_domain(e
, nvar
, Q
, C
);
3129 free_evalue_refs(t
);
3136 if (value_notzero_p(e
->d
)) {
3139 t
= esum_over_domain_cst(nvar
, D
, C
);
3141 if (!EVALUE_IS_ONE(*e
))
3147 switch (e
->x
.p
->type
) {
3149 evalue
*pp
= &e
->x
.p
->arr
[0];
3151 if (pp
->x
.p
->pos
> nvar
) {
3152 /* remainder is independent of the summated vars */
3158 floor2frac(&f
, nvar
);
3160 t
= esum_over_domain_cst(nvar
, D
, C
);
3164 free_evalue_refs(&f
);
3169 row
= Vector_Alloc(1 + D
->Dimension
+ 1 + 1);
3170 poly_denom(pp
, &row
->p
[1 + nvar
]);
3171 value_set_si(row
->p
[0], 1);
3172 for (pp
= &e
->x
.p
->arr
[0]; value_zero_p(pp
->d
);
3173 pp
= &pp
->x
.p
->arr
[0]) {
3175 assert(pp
->x
.p
->type
== polynomial
);
3177 if (pos
>= 1 + nvar
)
3179 value_assign(row
->p
[pos
], row
->p
[1+nvar
]);
3180 value_division(row
->p
[pos
], row
->p
[pos
], pp
->x
.p
->arr
[1].d
);
3181 value_multiply(row
->p
[pos
], row
->p
[pos
], pp
->x
.p
->arr
[1].x
.n
);
3183 value_assign(row
->p
[1 + D
->Dimension
+ 1], row
->p
[1+nvar
]);
3184 value_division(row
->p
[1 + D
->Dimension
+ 1],
3185 row
->p
[1 + D
->Dimension
+ 1],
3187 value_multiply(row
->p
[1 + D
->Dimension
+ 1],
3188 row
->p
[1 + D
->Dimension
+ 1],
3190 value_oppose(row
->p
[1 + nvar
], row
->p
[1 + nvar
]);
3194 int pos
= e
->x
.p
->pos
;
3197 factor
= ALLOC(evalue
);
3198 value_init(factor
->d
);
3199 value_set_si(factor
->d
, 0);
3200 factor
->x
.p
= new_enode(polynomial
, 2, pos
- nvar
);
3201 evalue_set_si(&factor
->x
.p
->arr
[0], 0, 1);
3202 evalue_set_si(&factor
->x
.p
->arr
[1], 1, 1);
3206 row
= Vector_Alloc(1 + D
->Dimension
+ 1 + 1);
3207 for (i
= 0; i
< D
->NbRays
; ++i
)
3208 if (value_notzero_p(D
->Ray
[i
][pos
]))
3210 assert(i
< D
->NbRays
);
3211 if (value_neg_p(D
->Ray
[i
][pos
])) {
3212 factor
= ALLOC(evalue
);
3213 value_init(factor
->d
);
3214 evalue_set_si(factor
, -1, 1);
3216 value_set_si(row
->p
[0], 1);
3217 value_set_si(row
->p
[pos
], 1);
3218 value_set_si(row
->p
[1 + nvar
], -1);
3225 i
= type_offset(e
->x
.p
);
3227 res
= esum_over_domain(&e
->x
.p
->arr
[i
], nvar
, D
, C
);
3232 evalue_copy(&cum
, factor
);
3236 for (; i
< e
->x
.p
->size
; ++i
) {
3240 C
= esum_add_constraint(nvar
, D
, C
, row
);
3246 Vector_Print(stderr, P_VALUE_FMT, row);
3248 Matrix_Print(stderr, P_VALUE_FMT, C);
3250 t
= esum_over_domain(&e
->x
.p
->arr
[i
], nvar
, D
, C
);
3259 free_evalue_refs(t
);
3262 if (factor
&& i
+1 < e
->x
.p
->size
)
3269 free_evalue_refs(factor
);
3270 free_evalue_refs(&cum
);
3282 evalue
*esum(evalue
*e
, int nvar
)
3285 evalue
*res
= ALLOC(evalue
);
3289 if (nvar
== 0 || EVALUE_IS_ZERO(*e
)) {
3290 evalue_copy(res
, e
);
3294 evalue_set_si(res
, 0, 1);
3296 assert(value_zero_p(e
->d
));
3297 assert(e
->x
.p
->type
== partition
);
3299 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
3301 t
= esum_over_domain(&e
->x
.p
->arr
[2*i
+1], nvar
,
3302 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]), 0);
3304 free_evalue_refs(t
);
3313 /* Initial silly implementation */
3314 void eor(evalue
*e1
, evalue
*res
)
3320 evalue_set_si(&mone
, -1, 1);
3322 evalue_copy(&E
, res
);
3328 free_evalue_refs(&E
);
3329 free_evalue_refs(&mone
);
3332 /* computes denominator of polynomial evalue
3333 * d should point to a value initialized to 1
3335 void evalue_denom(evalue
*e
, Value
*d
)
3339 if (value_notzero_p(e
->d
)) {
3340 value_lcm(*d
, e
->d
, d
);
3343 assert(e
->x
.p
->type
== polynomial
||
3344 e
->x
.p
->type
== fractional
||
3345 e
->x
.p
->type
== flooring
);
3346 offset
= type_offset(e
->x
.p
);
3347 for (i
= e
->x
.p
->size
-1; i
>= offset
; --i
)
3348 evalue_denom(&e
->x
.p
->arr
[i
], d
);