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 /***********************************************************************/
16 #include <barvinok/evalue.h>
17 #include <barvinok/barvinok.h>
18 #include <barvinok/util.h>
20 #ifndef value_pmodulus
21 #define value_pmodulus(ref,val1,val2) (mpz_fdiv_r((ref),(val1),(val2)))
24 #define ALLOC(type) (type*)malloc(sizeof(type))
27 #define NALLOC(p,n) p = (typeof(p))malloc((n) * sizeof(*p))
29 #define NALLOC(p,n) p = (void *)malloc((n) * sizeof(*p))
32 void evalue_set_si(evalue
*ev
, int n
, int d
) {
33 value_set_si(ev
->d
, d
);
35 value_set_si(ev
->x
.n
, n
);
38 void evalue_set(evalue
*ev
, Value n
, Value d
) {
39 value_assign(ev
->d
, d
);
41 value_assign(ev
->x
.n
, n
);
46 evalue
*EP
= ALLOC(evalue
);
48 evalue_set_si(EP
, 0, 1);
52 void aep_evalue(evalue
*e
, int *ref
) {
57 if (value_notzero_p(e
->d
))
58 return; /* a rational number, its already reduced */
60 return; /* hum... an overflow probably occured */
62 /* First check the components of p */
63 for (i
=0;i
<p
->size
;i
++)
64 aep_evalue(&p
->arr
[i
],ref
);
71 p
->pos
= ref
[p
->pos
-1]+1;
77 void addeliminatedparams_evalue(evalue
*e
,Matrix
*CT
) {
83 if (value_notzero_p(e
->d
))
84 return; /* a rational number, its already reduced */
86 return; /* hum... an overflow probably occured */
89 ref
= (int *)malloc(sizeof(int)*(CT
->NbRows
-1));
90 for(i
=0;i
<CT
->NbRows
-1;i
++)
91 for(j
=0;j
<CT
->NbColumns
;j
++)
92 if(value_notzero_p(CT
->p
[i
][j
])) {
97 /* Transform the references in e, using ref */
101 } /* addeliminatedparams_evalue */
103 void addeliminatedparams_enum(evalue
*e
, Matrix
*CT
, Polyhedron
*CEq
,
104 unsigned MaxRays
, unsigned nparam
)
109 if (CT
->NbRows
== CT
->NbColumns
)
112 if (EVALUE_IS_ZERO(*e
))
115 if (value_notzero_p(e
->d
)) {
118 value_set_si(res
.d
, 0);
119 res
.x
.p
= new_enode(partition
, 2, nparam
);
120 EVALUE_SET_DOMAIN(res
.x
.p
->arr
[0],
121 DomainConstraintSimplify(Polyhedron_Copy(CEq
), MaxRays
));
122 value_clear(res
.x
.p
->arr
[1].d
);
123 res
.x
.p
->arr
[1] = *e
;
130 assert(p
->type
== partition
);
133 for (i
=0; i
<p
->size
/2; i
++) {
134 Polyhedron
*D
= EVALUE_DOMAIN(p
->arr
[2*i
]);
135 Polyhedron
*T
= DomainPreimage(D
, CT
, MaxRays
);
138 T
= DomainIntersection(D
, CEq
, MaxRays
);
140 EVALUE_SET_DOMAIN(p
->arr
[2*i
], T
);
141 addeliminatedparams_evalue(&p
->arr
[2*i
+1], CT
);
145 static int mod_rational_smaller(evalue
*e1
, evalue
*e2
)
153 assert(value_notzero_p(e1
->d
));
154 assert(value_notzero_p(e2
->d
));
155 value_multiply(m
, e1
->x
.n
, e2
->d
);
156 value_multiply(m2
, e2
->x
.n
, e1
->d
);
159 else if (value_gt(m
, m2
))
169 static int mod_term_smaller_r(evalue
*e1
, evalue
*e2
)
171 if (value_notzero_p(e1
->d
)) {
173 if (value_zero_p(e2
->d
))
175 r
= mod_rational_smaller(e1
, e2
);
176 return r
== -1 ? 0 : r
;
178 if (value_notzero_p(e2
->d
))
180 if (e1
->x
.p
->pos
< e2
->x
.p
->pos
)
182 else if (e1
->x
.p
->pos
> e2
->x
.p
->pos
)
185 int r
= mod_rational_smaller(&e1
->x
.p
->arr
[1], &e2
->x
.p
->arr
[1]);
187 ? mod_term_smaller_r(&e1
->x
.p
->arr
[0], &e2
->x
.p
->arr
[0])
192 static int mod_term_smaller(const evalue
*e1
, const evalue
*e2
)
194 assert(value_zero_p(e1
->d
));
195 assert(value_zero_p(e2
->d
));
196 assert(e1
->x
.p
->type
== fractional
|| e1
->x
.p
->type
== flooring
);
197 assert(e2
->x
.p
->type
== fractional
|| e2
->x
.p
->type
== flooring
);
198 return mod_term_smaller_r(&e1
->x
.p
->arr
[0], &e2
->x
.p
->arr
[0]);
201 /* Negative pos means inequality */
202 /* s is negative of substitution if m is not zero */
211 struct fixed_param
*fixed
;
216 static int relations_depth(evalue
*e
)
221 value_zero_p(e
->d
) && e
->x
.p
->type
== relation
;
222 e
= &e
->x
.p
->arr
[1], ++d
);
226 static void poly_denom_not_constant(evalue
**pp
, Value
*d
)
231 while (value_zero_p(p
->d
)) {
232 assert(p
->x
.p
->type
== polynomial
);
233 assert(p
->x
.p
->size
== 2);
234 assert(value_notzero_p(p
->x
.p
->arr
[1].d
));
235 value_lcm(*d
, p
->x
.p
->arr
[1].d
, d
);
241 static void poly_denom(evalue
*p
, Value
*d
)
243 poly_denom_not_constant(&p
, d
);
244 value_lcm(*d
, p
->d
, d
);
247 static void realloc_substitution(struct subst
*s
, int d
)
249 struct fixed_param
*n
;
252 for (i
= 0; i
< s
->n
; ++i
)
259 static int add_modulo_substitution(struct subst
*s
, evalue
*r
)
265 assert(value_zero_p(r
->d
) && r
->x
.p
->type
== relation
);
268 /* May have been reduced already */
269 if (value_notzero_p(m
->d
))
272 assert(value_zero_p(m
->d
) && m
->x
.p
->type
== fractional
);
273 assert(m
->x
.p
->size
== 3);
275 /* fractional was inverted during reduction
276 * invert it back and move constant in
278 if (!EVALUE_IS_ONE(m
->x
.p
->arr
[2])) {
279 assert(value_pos_p(m
->x
.p
->arr
[2].d
));
280 assert(value_mone_p(m
->x
.p
->arr
[2].x
.n
));
281 value_set_si(m
->x
.p
->arr
[2].x
.n
, 1);
282 value_increment(m
->x
.p
->arr
[1].x
.n
, m
->x
.p
->arr
[1].x
.n
);
283 assert(value_eq(m
->x
.p
->arr
[1].x
.n
, m
->x
.p
->arr
[1].d
));
284 value_set_si(m
->x
.p
->arr
[1].x
.n
, 1);
285 eadd(&m
->x
.p
->arr
[1], &m
->x
.p
->arr
[0]);
286 value_set_si(m
->x
.p
->arr
[1].x
.n
, 0);
287 value_set_si(m
->x
.p
->arr
[1].d
, 1);
290 /* Oops. Nested identical relations. */
291 if (!EVALUE_IS_ZERO(m
->x
.p
->arr
[1]))
294 if (s
->n
>= s
->max
) {
295 int d
= relations_depth(r
);
296 realloc_substitution(s
, d
);
300 assert(value_zero_p(p
->d
) && p
->x
.p
->type
== polynomial
);
301 assert(p
->x
.p
->size
== 2);
304 assert(value_pos_p(f
->x
.n
));
306 value_init(s
->fixed
[s
->n
].m
);
307 value_assign(s
->fixed
[s
->n
].m
, f
->d
);
308 s
->fixed
[s
->n
].pos
= p
->x
.p
->pos
;
309 value_init(s
->fixed
[s
->n
].d
);
310 value_assign(s
->fixed
[s
->n
].d
, f
->x
.n
);
311 value_init(s
->fixed
[s
->n
].s
.d
);
312 evalue_copy(&s
->fixed
[s
->n
].s
, &p
->x
.p
->arr
[0]);
318 static int type_offset(enode
*p
)
320 return p
->type
== fractional
? 1 :
321 p
->type
== flooring
? 1 : 0;
324 static void reorder_terms(enode
*p
, evalue
*v
)
327 int offset
= type_offset(p
);
329 for (i
= p
->size
-1; i
>= offset
+1; i
--) {
331 eadd(&p
->arr
[i
], &p
->arr
[i
-1]);
332 free_evalue_refs(&(p
->arr
[i
]));
338 void _reduce_evalue (evalue
*e
, struct subst
*s
, int fract
) {
344 if (value_notzero_p(e
->d
)) {
346 mpz_fdiv_r(e
->x
.n
, e
->x
.n
, e
->d
);
347 return; /* a rational number, its already reduced */
351 return; /* hum... an overflow probably occured */
353 /* First reduce the components of p */
354 add
= p
->type
== relation
;
355 for (i
=0; i
<p
->size
; i
++) {
357 add
= add_modulo_substitution(s
, e
);
359 if (i
== 0 && p
->type
==fractional
)
360 _reduce_evalue(&p
->arr
[i
], s
, 1);
362 _reduce_evalue(&p
->arr
[i
], s
, fract
);
364 if (add
&& i
== p
->size
-1) {
366 value_clear(s
->fixed
[s
->n
].m
);
367 value_clear(s
->fixed
[s
->n
].d
);
368 free_evalue_refs(&s
->fixed
[s
->n
].s
);
369 } else if (add
&& i
== 1)
370 s
->fixed
[s
->n
-1].pos
*= -1;
373 if (p
->type
==periodic
) {
375 /* Try to reduce the period */
376 for (i
=1; i
<=(p
->size
)/2; i
++) {
377 if ((p
->size
% i
)==0) {
379 /* Can we reduce the size to i ? */
381 for (k
=j
+i
; k
<e
->x
.p
->size
; k
+=i
)
382 if (!eequal(&p
->arr
[j
], &p
->arr
[k
])) goto you_lose
;
385 for (j
=i
; j
<p
->size
; j
++) free_evalue_refs(&p
->arr
[j
]);
389 you_lose
: /* OK, lets not do it */
394 /* Try to reduce its strength */
397 memcpy(e
,&p
->arr
[0],sizeof(evalue
));
401 else if (p
->type
==polynomial
) {
402 for (k
= 0; s
&& k
< s
->n
; ++k
) {
403 if (s
->fixed
[k
].pos
== p
->pos
) {
404 int divide
= value_notone_p(s
->fixed
[k
].d
);
407 if (value_notzero_p(s
->fixed
[k
].m
)) {
410 assert(p
->size
== 2);
411 if (divide
&& value_ne(s
->fixed
[k
].d
, p
->arr
[1].x
.n
))
413 if (!mpz_divisible_p(s
->fixed
[k
].m
, p
->arr
[1].d
))
420 value_assign(d
.d
, s
->fixed
[k
].d
);
422 if (value_notzero_p(s
->fixed
[k
].m
))
423 value_oppose(d
.x
.n
, s
->fixed
[k
].m
);
425 value_set_si(d
.x
.n
, 1);
428 for (i
=p
->size
-1;i
>=1;i
--) {
429 emul(&s
->fixed
[k
].s
, &p
->arr
[i
]);
431 emul(&d
, &p
->arr
[i
]);
432 eadd(&p
->arr
[i
], &p
->arr
[i
-1]);
433 free_evalue_refs(&(p
->arr
[i
]));
436 _reduce_evalue(&p
->arr
[0], s
, fract
);
439 free_evalue_refs(&d
);
445 /* Try to reduce the degree */
446 for (i
=p
->size
-1;i
>=1;i
--) {
447 if (!(value_one_p(p
->arr
[i
].d
) && value_zero_p(p
->arr
[i
].x
.n
)))
449 /* Zero coefficient */
450 free_evalue_refs(&(p
->arr
[i
]));
455 /* Try to reduce its strength */
458 memcpy(e
,&p
->arr
[0],sizeof(evalue
));
462 else if (p
->type
==fractional
) {
466 if (value_notzero_p(p
->arr
[0].d
)) {
468 value_assign(v
.d
, p
->arr
[0].d
);
470 mpz_fdiv_r(v
.x
.n
, p
->arr
[0].x
.n
, p
->arr
[0].d
);
475 evalue
*pp
= &p
->arr
[0];
476 assert(value_zero_p(pp
->d
) && pp
->x
.p
->type
== polynomial
);
477 assert(pp
->x
.p
->size
== 2);
479 /* search for exact duplicate among the modulo inequalities */
481 f
= &pp
->x
.p
->arr
[1];
482 for (k
= 0; s
&& k
< s
->n
; ++k
) {
483 if (-s
->fixed
[k
].pos
== pp
->x
.p
->pos
&&
484 value_eq(s
->fixed
[k
].d
, f
->x
.n
) &&
485 value_eq(s
->fixed
[k
].m
, f
->d
) &&
486 eequal(&s
->fixed
[k
].s
, &pp
->x
.p
->arr
[0]))
493 /* replace { E/m } by { (E-1)/m } + 1/m */
498 evalue_set_si(&extra
, 1, 1);
499 value_assign(extra
.d
, g
);
500 eadd(&extra
, &v
.x
.p
->arr
[1]);
501 free_evalue_refs(&extra
);
503 /* We've been going in circles; stop now */
504 if (value_ge(v
.x
.p
->arr
[1].x
.n
, v
.x
.p
->arr
[1].d
)) {
505 free_evalue_refs(&v
);
507 evalue_set_si(&v
, 0, 1);
512 value_set_si(v
.d
, 0);
513 v
.x
.p
= new_enode(fractional
, 3, -1);
514 evalue_set_si(&v
.x
.p
->arr
[1], 1, 1);
515 value_assign(v
.x
.p
->arr
[1].d
, g
);
516 evalue_set_si(&v
.x
.p
->arr
[2], 1, 1);
517 evalue_copy(&v
.x
.p
->arr
[0], &p
->arr
[0]);
520 for (f
= &v
.x
.p
->arr
[0]; value_zero_p(f
->d
);
523 value_division(f
->d
, g
, f
->d
);
524 value_multiply(f
->x
.n
, f
->x
.n
, f
->d
);
525 value_assign(f
->d
, g
);
526 value_decrement(f
->x
.n
, f
->x
.n
);
527 mpz_fdiv_r(f
->x
.n
, f
->x
.n
, f
->d
);
529 Gcd(f
->d
, f
->x
.n
, &g
);
530 value_division(f
->d
, f
->d
, g
);
531 value_division(f
->x
.n
, f
->x
.n
, g
);
540 /* reduction may have made this fractional arg smaller */
541 i
= reorder
? p
->size
: 1;
542 for ( ; i
< p
->size
; ++i
)
543 if (value_zero_p(p
->arr
[i
].d
) &&
544 p
->arr
[i
].x
.p
->type
== fractional
&&
545 !mod_term_smaller(e
, &p
->arr
[i
]))
549 value_set_si(v
.d
, 0);
550 v
.x
.p
= new_enode(fractional
, 3, -1);
551 evalue_set_si(&v
.x
.p
->arr
[1], 0, 1);
552 evalue_set_si(&v
.x
.p
->arr
[2], 1, 1);
553 evalue_copy(&v
.x
.p
->arr
[0], &p
->arr
[0]);
561 evalue
*pp
= &p
->arr
[0];
564 poly_denom_not_constant(&pp
, &m
);
565 mpz_fdiv_r(r
, m
, pp
->d
);
566 if (value_notzero_p(r
)) {
568 value_set_si(v
.d
, 0);
569 v
.x
.p
= new_enode(fractional
, 3, -1);
571 value_multiply(r
, m
, pp
->x
.n
);
572 value_multiply(v
.x
.p
->arr
[1].d
, m
, pp
->d
);
573 value_init(v
.x
.p
->arr
[1].x
.n
);
574 mpz_fdiv_r(v
.x
.p
->arr
[1].x
.n
, r
, pp
->d
);
575 mpz_fdiv_q(r
, r
, pp
->d
);
577 evalue_set_si(&v
.x
.p
->arr
[2], 1, 1);
578 evalue_copy(&v
.x
.p
->arr
[0], &p
->arr
[0]);
580 while (value_zero_p(pp
->d
))
581 pp
= &pp
->x
.p
->arr
[0];
583 value_assign(pp
->d
, m
);
584 value_assign(pp
->x
.n
, r
);
586 Gcd(pp
->d
, pp
->x
.n
, &r
);
587 value_division(pp
->d
, pp
->d
, r
);
588 value_division(pp
->x
.n
, pp
->x
.n
, r
);
601 for (pp
= &p
->arr
[0]; value_zero_p(pp
->d
);
602 pp
= &pp
->x
.p
->arr
[0]) {
603 f
= &pp
->x
.p
->arr
[1];
604 assert(value_pos_p(f
->d
));
605 mpz_mul_ui(twice
, f
->x
.n
, 2);
606 if (value_lt(twice
, f
->d
))
608 if (value_eq(twice
, f
->d
))
616 value_set_si(v
.d
, 0);
617 v
.x
.p
= new_enode(fractional
, 3, -1);
618 evalue_set_si(&v
.x
.p
->arr
[1], 0, 1);
619 poly_denom(&p
->arr
[0], &twice
);
620 value_assign(v
.x
.p
->arr
[1].d
, twice
);
621 value_decrement(v
.x
.p
->arr
[1].x
.n
, twice
);
622 evalue_set_si(&v
.x
.p
->arr
[2], -1, 1);
623 evalue_copy(&v
.x
.p
->arr
[0], &p
->arr
[0]);
625 for (pp
= &v
.x
.p
->arr
[0]; value_zero_p(pp
->d
);
626 pp
= &pp
->x
.p
->arr
[0]) {
627 f
= &pp
->x
.p
->arr
[1];
628 value_oppose(f
->x
.n
, f
->x
.n
);
629 mpz_fdiv_r(f
->x
.n
, f
->x
.n
, f
->d
);
631 value_division(pp
->d
, twice
, pp
->d
);
632 value_multiply(pp
->x
.n
, pp
->x
.n
, pp
->d
);
633 value_assign(pp
->d
, twice
);
634 value_oppose(pp
->x
.n
, pp
->x
.n
);
635 value_decrement(pp
->x
.n
, pp
->x
.n
);
636 mpz_fdiv_r(pp
->x
.n
, pp
->x
.n
, pp
->d
);
638 /* Maybe we should do this during reduction of
641 Gcd(pp
->d
, pp
->x
.n
, &twice
);
642 value_division(pp
->d
, pp
->d
, twice
);
643 value_division(pp
->x
.n
, pp
->x
.n
, twice
);
653 reorder_terms(p
, &v
);
654 _reduce_evalue(&p
->arr
[1], s
, fract
);
657 /* Try to reduce the degree */
658 for (i
=p
->size
-1;i
>=2;i
--) {
659 if (!(value_one_p(p
->arr
[i
].d
) && value_zero_p(p
->arr
[i
].x
.n
)))
661 /* Zero coefficient */
662 free_evalue_refs(&(p
->arr
[i
]));
667 /* Try to reduce its strength */
670 memcpy(e
,&p
->arr
[1],sizeof(evalue
));
671 free_evalue_refs(&(p
->arr
[0]));
675 else if (p
->type
== flooring
) {
676 /* Try to reduce the degree */
677 for (i
=p
->size
-1;i
>=2;i
--) {
678 if (!EVALUE_IS_ZERO(p
->arr
[i
]))
680 /* Zero coefficient */
681 free_evalue_refs(&(p
->arr
[i
]));
686 /* Try to reduce its strength */
689 memcpy(e
,&p
->arr
[1],sizeof(evalue
));
690 free_evalue_refs(&(p
->arr
[0]));
694 else if (p
->type
== relation
) {
695 if (p
->size
== 3 && eequal(&p
->arr
[1], &p
->arr
[2])) {
696 free_evalue_refs(&(p
->arr
[2]));
697 free_evalue_refs(&(p
->arr
[0]));
704 if (p
->size
== 3 && EVALUE_IS_ZERO(p
->arr
[2])) {
705 free_evalue_refs(&(p
->arr
[2]));
708 if (p
->size
== 2 && EVALUE_IS_ZERO(p
->arr
[1])) {
709 free_evalue_refs(&(p
->arr
[1]));
710 free_evalue_refs(&(p
->arr
[0]));
711 evalue_set_si(e
, 0, 1);
718 /* Relation was reduced by means of an identical
719 * inequality => remove
721 if (value_zero_p(m
->d
) && !EVALUE_IS_ZERO(m
->x
.p
->arr
[1]))
724 if (reduced
|| value_notzero_p(p
->arr
[0].d
)) {
725 if (!reduced
&& value_zero_p(p
->arr
[0].x
.n
)) {
727 memcpy(e
,&p
->arr
[1],sizeof(evalue
));
729 free_evalue_refs(&(p
->arr
[2]));
733 memcpy(e
,&p
->arr
[2],sizeof(evalue
));
735 evalue_set_si(e
, 0, 1);
736 free_evalue_refs(&(p
->arr
[1]));
738 free_evalue_refs(&(p
->arr
[0]));
744 } /* reduce_evalue */
746 static void add_substitution(struct subst
*s
, Value
*row
, unsigned dim
)
751 for (k
= 0; k
< dim
; ++k
)
752 if (value_notzero_p(row
[k
+1]))
755 Vector_Normalize_Positive(row
+1, dim
+1, k
);
756 assert(s
->n
< s
->max
);
757 value_init(s
->fixed
[s
->n
].d
);
758 value_init(s
->fixed
[s
->n
].m
);
759 value_assign(s
->fixed
[s
->n
].d
, row
[k
+1]);
760 s
->fixed
[s
->n
].pos
= k
+1;
761 value_set_si(s
->fixed
[s
->n
].m
, 0);
762 r
= &s
->fixed
[s
->n
].s
;
764 for (l
= k
+1; l
< dim
; ++l
)
765 if (value_notzero_p(row
[l
+1])) {
766 value_set_si(r
->d
, 0);
767 r
->x
.p
= new_enode(polynomial
, 2, l
+ 1);
768 value_init(r
->x
.p
->arr
[1].x
.n
);
769 value_oppose(r
->x
.p
->arr
[1].x
.n
, row
[l
+1]);
770 value_set_si(r
->x
.p
->arr
[1].d
, 1);
774 value_oppose(r
->x
.n
, row
[dim
+1]);
775 value_set_si(r
->d
, 1);
779 static void _reduce_evalue_in_domain(evalue
*e
, Polyhedron
*D
, struct subst
*s
)
782 Polyhedron
*orig
= D
;
787 D
= DomainConvex(D
, 0);
788 if (!D
->next
&& D
->NbEq
) {
792 realloc_substitution(s
, dim
);
794 int d
= relations_depth(e
);
796 NALLOC(s
->fixed
, s
->max
);
799 for (j
= 0; j
< D
->NbEq
; ++j
)
800 add_substitution(s
, D
->Constraint
[j
], dim
);
804 _reduce_evalue(e
, s
, 0);
807 for (j
= 0; j
< s
->n
; ++j
) {
808 value_clear(s
->fixed
[j
].d
);
809 value_clear(s
->fixed
[j
].m
);
810 free_evalue_refs(&s
->fixed
[j
].s
);
815 void reduce_evalue_in_domain(evalue
*e
, Polyhedron
*D
)
817 struct subst s
= { NULL
, 0, 0 };
819 if (EVALUE_IS_ZERO(*e
))
823 evalue_set_si(e
, 0, 1);
826 _reduce_evalue_in_domain(e
, D
, &s
);
831 void reduce_evalue (evalue
*e
) {
832 struct subst s
= { NULL
, 0, 0 };
834 if (value_notzero_p(e
->d
))
835 return; /* a rational number, its already reduced */
837 if (e
->x
.p
->type
== partition
) {
840 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
841 Polyhedron
*D
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]);
843 /* This shouldn't really happen;
844 * Empty domains should not be added.
846 POL_ENSURE_VERTICES(D
);
848 _reduce_evalue_in_domain(&e
->x
.p
->arr
[2*i
+1], D
, &s
);
850 if (emptyQ(D
) || EVALUE_IS_ZERO(e
->x
.p
->arr
[2*i
+1])) {
851 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
852 Domain_Free(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]));
853 value_clear(e
->x
.p
->arr
[2*i
].d
);
855 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
856 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
860 if (e
->x
.p
->size
== 0) {
862 evalue_set_si(e
, 0, 1);
865 _reduce_evalue(e
, &s
, 0);
870 void print_evalue(FILE *DST
,evalue
*e
,char **pname
) {
872 if(value_notzero_p(e
->d
)) {
873 if(value_notone_p(e
->d
)) {
874 value_print(DST
,VALUE_FMT
,e
->x
.n
);
876 value_print(DST
,VALUE_FMT
,e
->d
);
879 value_print(DST
,VALUE_FMT
,e
->x
.n
);
883 print_enode(DST
,e
->x
.p
,pname
);
887 void print_enode(FILE *DST
,enode
*p
,char **pname
) {
892 fprintf(DST
, "NULL");
898 for (i
=0; i
<p
->size
; i
++) {
899 print_evalue(DST
, &p
->arr
[i
], pname
);
903 fprintf(DST
, " }\n");
907 for (i
=p
->size
-1; i
>=0; i
--) {
908 print_evalue(DST
, &p
->arr
[i
], pname
);
909 if (i
==1) fprintf(DST
, " * %s + ", pname
[p
->pos
-1]);
911 fprintf(DST
, " * %s^%d + ", pname
[p
->pos
-1], i
);
913 fprintf(DST
, " )\n");
917 for (i
=0; i
<p
->size
; i
++) {
918 print_evalue(DST
, &p
->arr
[i
], pname
);
919 if (i
!=(p
->size
-1)) fprintf(DST
, ", ");
921 fprintf(DST
," ]_%s", pname
[p
->pos
-1]);
926 for (i
=p
->size
-1; i
>=1; i
--) {
927 print_evalue(DST
, &p
->arr
[i
], pname
);
930 fprintf(DST
, p
->type
== flooring
? "[" : "{");
931 print_evalue(DST
, &p
->arr
[0], pname
);
932 fprintf(DST
, p
->type
== flooring
? "]" : "}");
934 fprintf(DST
, "^%d + ", i
-1);
939 fprintf(DST
, " )\n");
943 print_evalue(DST
, &p
->arr
[0], pname
);
944 fprintf(DST
, "= 0 ] * \n");
945 print_evalue(DST
, &p
->arr
[1], pname
);
947 fprintf(DST
, " +\n [ ");
948 print_evalue(DST
, &p
->arr
[0], pname
);
949 fprintf(DST
, "!= 0 ] * \n");
950 print_evalue(DST
, &p
->arr
[2], pname
);
954 char **names
= pname
;
955 int maxdim
= EVALUE_DOMAIN(p
->arr
[0])->Dimension
;
956 if (!pname
|| p
->pos
< maxdim
) {
957 NALLOC(names
, maxdim
);
958 for (i
= 0; i
< p
->pos
; ++i
) {
962 NALLOC(names
[i
], 10);
963 snprintf(names
[i
], 10, "%c", 'P'+i
);
966 for ( ; i
< maxdim
; ++i
) {
967 NALLOC(names
[i
], 10);
968 snprintf(names
[i
], 10, "_p%d", i
);
972 for (i
=0; i
<p
->size
/2; i
++) {
973 Print_Domain(DST
, EVALUE_DOMAIN(p
->arr
[2*i
]), names
);
974 print_evalue(DST
, &p
->arr
[2*i
+1], names
);
977 if (!pname
|| p
->pos
< maxdim
) {
978 for (i
= pname
? p
->pos
: 0; i
< maxdim
; ++i
)
991 static void eadd_rev(const evalue
*e1
, evalue
*res
)
995 evalue_copy(&ev
, e1
);
997 free_evalue_refs(res
);
1001 static void eadd_rev_cst(const evalue
*e1
, evalue
*res
)
1005 evalue_copy(&ev
, e1
);
1006 eadd(res
, &ev
.x
.p
->arr
[type_offset(ev
.x
.p
)]);
1007 free_evalue_refs(res
);
1011 static int is_zero_on(evalue
*e
, Polyhedron
*D
)
1016 tmp
.x
.p
= new_enode(partition
, 2, D
->Dimension
);
1017 EVALUE_SET_DOMAIN(tmp
.x
.p
->arr
[0], Domain_Copy(D
));
1018 evalue_copy(&tmp
.x
.p
->arr
[1], e
);
1019 reduce_evalue(&tmp
);
1020 is_zero
= EVALUE_IS_ZERO(tmp
);
1021 free_evalue_refs(&tmp
);
1025 struct section
{ Polyhedron
* D
; evalue E
; };
1027 void eadd_partitions(const evalue
*e1
, evalue
*res
)
1032 s
= (struct section
*)
1033 malloc((e1
->x
.p
->size
/2+1) * (res
->x
.p
->size
/2+1) *
1034 sizeof(struct section
));
1036 assert(e1
->x
.p
->pos
== res
->x
.p
->pos
);
1037 assert(e1
->x
.p
->pos
== EVALUE_DOMAIN(e1
->x
.p
->arr
[0])->Dimension
);
1038 assert(res
->x
.p
->pos
== EVALUE_DOMAIN(res
->x
.p
->arr
[0])->Dimension
);
1041 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
1042 assert(res
->x
.p
->size
>= 2);
1043 fd
= DomainDifference(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
1044 EVALUE_DOMAIN(res
->x
.p
->arr
[0]), 0);
1046 for (i
= 1; i
< res
->x
.p
->size
/2; ++i
) {
1048 fd
= DomainDifference(fd
, EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
1057 /* See if we can extend one of the domains in res to cover fd */
1058 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
)
1059 if (is_zero_on(&res
->x
.p
->arr
[2*i
+1], fd
))
1061 if (i
< res
->x
.p
->size
/2) {
1062 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*i
],
1063 DomainConcat(fd
, EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
])));
1066 value_init(s
[n
].E
.d
);
1067 evalue_copy(&s
[n
].E
, &e1
->x
.p
->arr
[2*j
+1]);
1071 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
) {
1072 fd
= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]);
1073 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
1075 d
= DomainIntersection(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
1076 EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
1082 fd
= DomainDifference(fd
, EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]), 0);
1083 if (t
!= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]))
1085 value_init(s
[n
].E
.d
);
1086 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*i
+1]);
1087 eadd(&e1
->x
.p
->arr
[2*j
+1], &s
[n
].E
);
1088 if (!emptyQ(fd
) && is_zero_on(&e1
->x
.p
->arr
[2*j
+1], fd
)) {
1089 d
= DomainConcat(fd
, d
);
1090 fd
= Empty_Polyhedron(fd
->Dimension
);
1096 s
[n
].E
= res
->x
.p
->arr
[2*i
+1];
1100 free_evalue_refs(&res
->x
.p
->arr
[2*i
+1]);
1103 if (fd
!= EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]))
1104 Domain_Free(EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]));
1105 value_clear(res
->x
.p
->arr
[2*i
].d
);
1110 res
->x
.p
= new_enode(partition
, 2*n
, e1
->x
.p
->pos
);
1111 for (j
= 0; j
< n
; ++j
) {
1112 s
[j
].D
= DomainConstraintSimplify(s
[j
].D
, 0);
1113 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
1114 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
1115 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
1121 static void explicit_complement(evalue
*res
)
1123 enode
*rel
= new_enode(relation
, 3, 0);
1125 value_clear(rel
->arr
[0].d
);
1126 rel
->arr
[0] = res
->x
.p
->arr
[0];
1127 value_clear(rel
->arr
[1].d
);
1128 rel
->arr
[1] = res
->x
.p
->arr
[1];
1129 value_set_si(rel
->arr
[2].d
, 1);
1130 value_init(rel
->arr
[2].x
.n
);
1131 value_set_si(rel
->arr
[2].x
.n
, 0);
1136 void eadd(const evalue
*e1
, evalue
*res
)
1139 if (value_notzero_p(e1
->d
) && value_notzero_p(res
->d
)) {
1140 /* Add two rational numbers */
1146 value_multiply(m1
,e1
->x
.n
,res
->d
);
1147 value_multiply(m2
,res
->x
.n
,e1
->d
);
1148 value_addto(res
->x
.n
,m1
,m2
);
1149 value_multiply(res
->d
,e1
->d
,res
->d
);
1150 Gcd(res
->x
.n
,res
->d
,&g
);
1151 if (value_notone_p(g
)) {
1152 value_division(res
->d
,res
->d
,g
);
1153 value_division(res
->x
.n
,res
->x
.n
,g
);
1155 value_clear(g
); value_clear(m1
); value_clear(m2
);
1158 else if (value_notzero_p(e1
->d
) && value_zero_p(res
->d
)) {
1159 switch (res
->x
.p
->type
) {
1161 /* Add the constant to the constant term of a polynomial*/
1162 eadd(e1
, &res
->x
.p
->arr
[0]);
1165 /* Add the constant to all elements of a periodic number */
1166 for (i
=0; i
<res
->x
.p
->size
; i
++) {
1167 eadd(e1
, &res
->x
.p
->arr
[i
]);
1171 fprintf(stderr
, "eadd: cannot add const with vector\n");
1175 eadd(e1
, &res
->x
.p
->arr
[1]);
1178 assert(EVALUE_IS_ZERO(*e1
));
1179 break; /* Do nothing */
1181 /* Create (zero) complement if needed */
1182 if (res
->x
.p
->size
< 3 && !EVALUE_IS_ZERO(*e1
))
1183 explicit_complement(res
);
1184 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1185 eadd(e1
, &res
->x
.p
->arr
[i
]);
1191 /* add polynomial or periodic to constant
1192 * you have to exchange e1 and res, before doing addition */
1194 else if (value_zero_p(e1
->d
) && value_notzero_p(res
->d
)) {
1198 else { // ((e1->d==0) && (res->d==0))
1199 assert(!((e1
->x
.p
->type
== partition
) ^
1200 (res
->x
.p
->type
== partition
)));
1201 if (e1
->x
.p
->type
== partition
) {
1202 eadd_partitions(e1
, res
);
1205 if (e1
->x
.p
->type
== relation
&&
1206 (res
->x
.p
->type
!= relation
||
1207 mod_term_smaller(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]))) {
1211 if (res
->x
.p
->type
== relation
) {
1212 if (e1
->x
.p
->type
== relation
&&
1213 eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0])) {
1214 if (res
->x
.p
->size
< 3 && e1
->x
.p
->size
== 3)
1215 explicit_complement(res
);
1216 for (i
= 1; i
< e1
->x
.p
->size
; ++i
)
1217 eadd(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1220 if (res
->x
.p
->size
< 3)
1221 explicit_complement(res
);
1222 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1223 eadd(e1
, &res
->x
.p
->arr
[i
]);
1226 if ((e1
->x
.p
->type
!= res
->x
.p
->type
) ) {
1227 /* adding to evalues of different type. two cases are possible
1228 * res is periodic and e1 is polynomial, you have to exchange
1229 * e1 and res then to add e1 to the constant term of res */
1230 if (e1
->x
.p
->type
== polynomial
) {
1231 eadd_rev_cst(e1
, res
);
1233 else if (res
->x
.p
->type
== polynomial
) {
1234 /* res is polynomial and e1 is periodic,
1235 add e1 to the constant term of res */
1237 eadd(e1
,&res
->x
.p
->arr
[0]);
1243 else if (e1
->x
.p
->pos
!= res
->x
.p
->pos
||
1244 ((res
->x
.p
->type
== fractional
||
1245 res
->x
.p
->type
== flooring
) &&
1246 !eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]))) {
1247 /* adding evalues of different position (i.e function of different unknowns
1248 * to case are possible */
1250 switch (res
->x
.p
->type
) {
1253 if (mod_term_smaller(res
, e1
))
1254 eadd(e1
,&res
->x
.p
->arr
[1]);
1256 eadd_rev_cst(e1
, res
);
1258 case polynomial
: // res and e1 are polynomials
1259 // add e1 to the constant term of res
1261 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1262 eadd(e1
,&res
->x
.p
->arr
[0]);
1264 eadd_rev_cst(e1
, res
);
1265 // value_clear(g); value_clear(m1); value_clear(m2);
1267 case periodic
: // res and e1 are pointers to periodic numbers
1268 //add e1 to all elements of res
1270 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1271 for (i
=0;i
<res
->x
.p
->size
;i
++) {
1272 eadd(e1
,&res
->x
.p
->arr
[i
]);
1283 //same type , same pos and same size
1284 if (e1
->x
.p
->size
== res
->x
.p
->size
) {
1285 // add any element in e1 to the corresponding element in res
1286 i
= type_offset(res
->x
.p
);
1288 assert(eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0]));
1289 for (; i
<res
->x
.p
->size
; i
++) {
1290 eadd(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1295 /* Sizes are different */
1296 switch(res
->x
.p
->type
) {
1300 /* VIN100: if e1-size > res-size you have to copy e1 in a */
1301 /* new enode and add res to that new node. If you do not do */
1302 /* that, you lose the the upper weight part of e1 ! */
1304 if(e1
->x
.p
->size
> res
->x
.p
->size
)
1307 i
= type_offset(res
->x
.p
);
1309 assert(eequal(&e1
->x
.p
->arr
[0],
1310 &res
->x
.p
->arr
[0]));
1311 for (; i
<e1
->x
.p
->size
; i
++) {
1312 eadd(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1319 /* add two periodics of the same pos (unknown) but whith different sizes (periods) */
1322 /* you have to create a new evalue 'ne' in whitch size equals to the lcm
1323 of the sizes of e1 and res, then to copy res periodicaly in ne, after
1324 to add periodicaly elements of e1 to elements of ne, and finaly to
1329 value_init(ex
); value_init(ey
);value_init(ep
);
1332 value_set_si(ex
,e1
->x
.p
->size
);
1333 value_set_si(ey
,res
->x
.p
->size
);
1334 value_assign (ep
,*Lcm(ex
,ey
));
1335 p
=(int)mpz_get_si(ep
);
1336 ne
= (evalue
*) malloc (sizeof(evalue
));
1338 value_set_si( ne
->d
,0);
1340 ne
->x
.p
=new_enode(res
->x
.p
->type
,p
, res
->x
.p
->pos
);
1342 evalue_copy(&ne
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
%y
]);
1345 eadd(&e1
->x
.p
->arr
[i
%x
], &ne
->x
.p
->arr
[i
]);
1348 value_assign(res
->d
, ne
->d
);
1354 fprintf(stderr
, "eadd: ?cannot add vectors of different length\n");
1363 static void emul_rev (evalue
*e1
, evalue
*res
)
1367 evalue_copy(&ev
, e1
);
1369 free_evalue_refs(res
);
1373 static void emul_poly (evalue
*e1
, evalue
*res
)
1375 int i
, j
, o
= type_offset(res
->x
.p
);
1377 int size
=(e1
->x
.p
->size
+ res
->x
.p
->size
- o
- 1);
1379 value_set_si(tmp
.d
,0);
1380 tmp
.x
.p
=new_enode(res
->x
.p
->type
, size
, res
->x
.p
->pos
);
1382 evalue_copy(&tmp
.x
.p
->arr
[0], &e1
->x
.p
->arr
[0]);
1383 for (i
=o
; i
< e1
->x
.p
->size
; i
++) {
1384 evalue_copy(&tmp
.x
.p
->arr
[i
], &e1
->x
.p
->arr
[i
]);
1385 emul(&res
->x
.p
->arr
[o
], &tmp
.x
.p
->arr
[i
]);
1388 evalue_set_si(&tmp
.x
.p
->arr
[i
], 0, 1);
1389 for (i
=o
+1; i
<res
->x
.p
->size
; i
++)
1390 for (j
=o
; j
<e1
->x
.p
->size
; j
++) {
1393 evalue_copy(&ev
, &e1
->x
.p
->arr
[j
]);
1394 emul(&res
->x
.p
->arr
[i
], &ev
);
1395 eadd(&ev
, &tmp
.x
.p
->arr
[i
+j
-o
]);
1396 free_evalue_refs(&ev
);
1398 free_evalue_refs(res
);
1402 void emul_partitions (evalue
*e1
,evalue
*res
)
1407 s
= (struct section
*)
1408 malloc((e1
->x
.p
->size
/2) * (res
->x
.p
->size
/2) *
1409 sizeof(struct section
));
1411 assert(e1
->x
.p
->pos
== res
->x
.p
->pos
);
1412 assert(e1
->x
.p
->pos
== EVALUE_DOMAIN(e1
->x
.p
->arr
[0])->Dimension
);
1413 assert(res
->x
.p
->pos
== EVALUE_DOMAIN(res
->x
.p
->arr
[0])->Dimension
);
1416 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
) {
1417 for (j
= 0; j
< e1
->x
.p
->size
/2; ++j
) {
1418 d
= DomainIntersection(EVALUE_DOMAIN(e1
->x
.p
->arr
[2*j
]),
1419 EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]), 0);
1425 /* This code is only needed because the partitions
1426 are not true partitions.
1428 for (k
= 0; k
< n
; ++k
) {
1429 if (DomainIncludes(s
[k
].D
, d
))
1431 if (DomainIncludes(d
, s
[k
].D
)) {
1432 Domain_Free(s
[k
].D
);
1433 free_evalue_refs(&s
[k
].E
);
1444 value_init(s
[n
].E
.d
);
1445 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*i
+1]);
1446 emul(&e1
->x
.p
->arr
[2*j
+1], &s
[n
].E
);
1450 Domain_Free(EVALUE_DOMAIN(res
->x
.p
->arr
[2*i
]));
1451 value_clear(res
->x
.p
->arr
[2*i
].d
);
1452 free_evalue_refs(&res
->x
.p
->arr
[2*i
+1]);
1457 evalue_set_si(res
, 0, 1);
1459 res
->x
.p
= new_enode(partition
, 2*n
, e1
->x
.p
->pos
);
1460 for (j
= 0; j
< n
; ++j
) {
1461 s
[j
].D
= DomainConstraintSimplify(s
[j
].D
, 0);
1462 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
1463 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
1464 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
1471 #define value_two_p(val) (mpz_cmp_si(val,2) == 0)
1473 /* Computes the product of two evalues "e1" and "res" and puts the result in "res". you must
1474 * do a copy of "res" befor calling this function if you nead it after. The vector type of
1475 * evalues is not treated here */
1477 void emul (evalue
*e1
, evalue
*res
){
1480 if((value_zero_p(e1
->d
)&&e1
->x
.p
->type
==evector
)||(value_zero_p(res
->d
)&&(res
->x
.p
->type
==evector
))) {
1481 fprintf(stderr
, "emul: do not proced on evector type !\n");
1485 if (EVALUE_IS_ZERO(*res
))
1488 if (value_zero_p(e1
->d
) && e1
->x
.p
->type
== partition
) {
1489 if (value_zero_p(res
->d
) && res
->x
.p
->type
== partition
)
1490 emul_partitions(e1
, res
);
1493 } else if (value_zero_p(res
->d
) && res
->x
.p
->type
== partition
) {
1494 for (i
= 0; i
< res
->x
.p
->size
/2; ++i
)
1495 emul(e1
, &res
->x
.p
->arr
[2*i
+1]);
1497 if (value_zero_p(res
->d
) && res
->x
.p
->type
== relation
) {
1498 if (value_zero_p(e1
->d
) && e1
->x
.p
->type
== relation
&&
1499 eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0])) {
1500 if (res
->x
.p
->size
< 3 && e1
->x
.p
->size
== 3)
1501 explicit_complement(res
);
1502 if (e1
->x
.p
->size
< 3 && res
->x
.p
->size
== 3)
1503 explicit_complement(e1
);
1504 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1505 emul(&e1
->x
.p
->arr
[i
], &res
->x
.p
->arr
[i
]);
1508 for (i
= 1; i
< res
->x
.p
->size
; ++i
)
1509 emul(e1
, &res
->x
.p
->arr
[i
]);
1511 if(value_zero_p(e1
->d
)&& value_zero_p(res
->d
)) {
1512 switch(e1
->x
.p
->type
) {
1514 switch(res
->x
.p
->type
) {
1516 if(e1
->x
.p
->pos
== res
->x
.p
->pos
) {
1517 /* Product of two polynomials of the same variable */
1522 /* Product of two polynomials of different variables */
1524 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1525 for( i
=0; i
<res
->x
.p
->size
; i
++)
1526 emul(e1
, &res
->x
.p
->arr
[i
]);
1535 /* Product of a polynomial and a periodic or fractional */
1542 switch(res
->x
.p
->type
) {
1544 if(e1
->x
.p
->pos
==res
->x
.p
->pos
&& e1
->x
.p
->size
==res
->x
.p
->size
) {
1545 /* Product of two periodics of the same parameter and period */
1547 for(i
=0; i
<res
->x
.p
->size
;i
++)
1548 emul(&(e1
->x
.p
->arr
[i
]), &(res
->x
.p
->arr
[i
]));
1553 if(e1
->x
.p
->pos
==res
->x
.p
->pos
&& e1
->x
.p
->size
!=res
->x
.p
->size
) {
1554 /* Product of two periodics of the same parameter and different periods */
1558 value_init(x
); value_init(y
);value_init(z
);
1561 value_set_si(x
,e1
->x
.p
->size
);
1562 value_set_si(y
,res
->x
.p
->size
);
1563 value_assign (z
,*Lcm(x
,y
));
1564 lcm
=(int)mpz_get_si(z
);
1565 newp
= (evalue
*) malloc (sizeof(evalue
));
1566 value_init(newp
->d
);
1567 value_set_si( newp
->d
,0);
1568 newp
->x
.p
=new_enode(periodic
,lcm
, e1
->x
.p
->pos
);
1569 for(i
=0;i
<lcm
;i
++) {
1570 evalue_copy(&newp
->x
.p
->arr
[i
],
1571 &res
->x
.p
->arr
[i
%iy
]);
1574 emul(&e1
->x
.p
->arr
[i
%ix
], &newp
->x
.p
->arr
[i
]);
1576 value_assign(res
->d
,newp
->d
);
1579 value_clear(x
); value_clear(y
);value_clear(z
);
1583 /* Product of two periodics of different parameters */
1585 if(res
->x
.p
->pos
< e1
->x
.p
->pos
)
1586 for(i
=0; i
<res
->x
.p
->size
; i
++)
1587 emul(e1
, &(res
->x
.p
->arr
[i
]));
1595 /* Product of a periodic and a polynomial */
1597 for(i
=0; i
<res
->x
.p
->size
; i
++)
1598 emul(e1
, &(res
->x
.p
->arr
[i
]));
1605 switch(res
->x
.p
->type
) {
1607 for(i
=0; i
<res
->x
.p
->size
; i
++)
1608 emul(e1
, &(res
->x
.p
->arr
[i
]));
1615 assert(e1
->x
.p
->type
== res
->x
.p
->type
);
1616 if (e1
->x
.p
->pos
== res
->x
.p
->pos
&&
1617 eequal(&e1
->x
.p
->arr
[0], &res
->x
.p
->arr
[0])) {
1620 poly_denom(&e1
->x
.p
->arr
[0], &d
.d
);
1621 if (e1
->x
.p
->type
!= fractional
|| !value_two_p(d
.d
))
1626 value_set_si(d
.x
.n
, 1);
1627 /* { x }^2 == { x }/2 */
1628 /* a0 b0 + (a0 b1 + a1 b0 + a1 b1/2) { x } */
1629 assert(e1
->x
.p
->size
== 3);
1630 assert(res
->x
.p
->size
== 3);
1632 evalue_copy(&tmp
, &res
->x
.p
->arr
[2]);
1634 eadd(&res
->x
.p
->arr
[1], &tmp
);
1635 emul(&e1
->x
.p
->arr
[2], &tmp
);
1636 emul(&e1
->x
.p
->arr
[1], res
);
1637 eadd(&tmp
, &res
->x
.p
->arr
[2]);
1638 free_evalue_refs(&tmp
);
1643 if(mod_term_smaller(res
, e1
))
1644 for(i
=1; i
<res
->x
.p
->size
; i
++)
1645 emul(e1
, &(res
->x
.p
->arr
[i
]));
1660 if (value_notzero_p(e1
->d
)&& value_notzero_p(res
->d
)) {
1661 /* Product of two rational numbers */
1665 value_multiply(res
->d
,e1
->d
,res
->d
);
1666 value_multiply(res
->x
.n
,e1
->x
.n
,res
->x
.n
);
1667 Gcd(res
->x
.n
, res
->d
,&g
);
1668 if (value_notone_p(g
)) {
1669 value_division(res
->d
,res
->d
,g
);
1670 value_division(res
->x
.n
,res
->x
.n
,g
);
1676 if(value_zero_p(e1
->d
)&& value_notzero_p(res
->d
)) {
1677 /* Product of an expression (polynomial or peririodic) and a rational number */
1683 /* Product of a rationel number and an expression (polynomial or peririodic) */
1685 i
= type_offset(res
->x
.p
);
1686 for (; i
<res
->x
.p
->size
; i
++)
1687 emul(e1
, &res
->x
.p
->arr
[i
]);
1697 /* Frees mask content ! */
1698 void emask(evalue
*mask
, evalue
*res
) {
1705 if (EVALUE_IS_ZERO(*res
)) {
1706 free_evalue_refs(mask
);
1710 assert(value_zero_p(mask
->d
));
1711 assert(mask
->x
.p
->type
== partition
);
1712 assert(value_zero_p(res
->d
));
1713 assert(res
->x
.p
->type
== partition
);
1714 assert(mask
->x
.p
->pos
== res
->x
.p
->pos
);
1715 assert(res
->x
.p
->pos
== EVALUE_DOMAIN(res
->x
.p
->arr
[0])->Dimension
);
1716 assert(mask
->x
.p
->pos
== EVALUE_DOMAIN(mask
->x
.p
->arr
[0])->Dimension
);
1717 pos
= res
->x
.p
->pos
;
1719 s
= (struct section
*)
1720 malloc((mask
->x
.p
->size
/2+1) * (res
->x
.p
->size
/2) *
1721 sizeof(struct section
));
1725 evalue_set_si(&mone
, -1, 1);
1728 for (j
= 0; j
< res
->x
.p
->size
/2; ++j
) {
1729 assert(mask
->x
.p
->size
>= 2);
1730 fd
= DomainDifference(EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]),
1731 EVALUE_DOMAIN(mask
->x
.p
->arr
[0]), 0);
1733 for (i
= 1; i
< mask
->x
.p
->size
/2; ++i
) {
1735 fd
= DomainDifference(fd
, EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]), 0);
1744 value_init(s
[n
].E
.d
);
1745 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*j
+1]);
1749 for (i
= 0; i
< mask
->x
.p
->size
/2; ++i
) {
1750 if (EVALUE_IS_ONE(mask
->x
.p
->arr
[2*i
+1]))
1753 fd
= EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]);
1754 eadd(&mone
, &mask
->x
.p
->arr
[2*i
+1]);
1755 emul(&mone
, &mask
->x
.p
->arr
[2*i
+1]);
1756 for (j
= 0; j
< res
->x
.p
->size
/2; ++j
) {
1758 d
= DomainIntersection(EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]),
1759 EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]), 0);
1765 fd
= DomainDifference(fd
, EVALUE_DOMAIN(res
->x
.p
->arr
[2*j
]), 0);
1766 if (t
!= EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]))
1768 value_init(s
[n
].E
.d
);
1769 evalue_copy(&s
[n
].E
, &res
->x
.p
->arr
[2*j
+1]);
1770 emul(&mask
->x
.p
->arr
[2*i
+1], &s
[n
].E
);
1776 /* Just ignore; this may have been previously masked off */
1778 if (fd
!= EVALUE_DOMAIN(mask
->x
.p
->arr
[2*i
]))
1782 free_evalue_refs(&mone
);
1783 free_evalue_refs(mask
);
1784 free_evalue_refs(res
);
1787 evalue_set_si(res
, 0, 1);
1789 res
->x
.p
= new_enode(partition
, 2*n
, pos
);
1790 for (j
= 0; j
< n
; ++j
) {
1791 EVALUE_SET_DOMAIN(res
->x
.p
->arr
[2*j
], s
[j
].D
);
1792 value_clear(res
->x
.p
->arr
[2*j
+1].d
);
1793 res
->x
.p
->arr
[2*j
+1] = s
[j
].E
;
1800 void evalue_copy(evalue
*dst
, const evalue
*src
)
1802 value_assign(dst
->d
, src
->d
);
1803 if(value_notzero_p(src
->d
)) {
1804 value_init(dst
->x
.n
);
1805 value_assign(dst
->x
.n
, src
->x
.n
);
1807 dst
->x
.p
= ecopy(src
->x
.p
);
1810 enode
*new_enode(enode_type type
,int size
,int pos
) {
1816 fprintf(stderr
, "Allocating enode of size 0 !\n" );
1819 res
= (enode
*) malloc(sizeof(enode
) + (size
-1)*sizeof(evalue
));
1823 for(i
=0; i
<size
; i
++) {
1824 value_init(res
->arr
[i
].d
);
1825 value_set_si(res
->arr
[i
].d
,0);
1826 res
->arr
[i
].x
.p
= 0;
1831 enode
*ecopy(enode
*e
) {
1836 res
= new_enode(e
->type
,e
->size
,e
->pos
);
1837 for(i
=0;i
<e
->size
;++i
) {
1838 value_assign(res
->arr
[i
].d
,e
->arr
[i
].d
);
1839 if(value_zero_p(res
->arr
[i
].d
))
1840 res
->arr
[i
].x
.p
= ecopy(e
->arr
[i
].x
.p
);
1841 else if (EVALUE_IS_DOMAIN(res
->arr
[i
]))
1842 EVALUE_SET_DOMAIN(res
->arr
[i
], Domain_Copy(EVALUE_DOMAIN(e
->arr
[i
])));
1844 value_init(res
->arr
[i
].x
.n
);
1845 value_assign(res
->arr
[i
].x
.n
,e
->arr
[i
].x
.n
);
1851 int ecmp(const evalue
*e1
, const evalue
*e2
)
1857 if (value_notzero_p(e1
->d
) && value_notzero_p(e2
->d
)) {
1861 value_multiply(m
, e1
->x
.n
, e2
->d
);
1862 value_multiply(m2
, e2
->x
.n
, e1
->d
);
1864 if (value_lt(m
, m2
))
1866 else if (value_gt(m
, m2
))
1876 if (value_notzero_p(e1
->d
))
1878 if (value_notzero_p(e2
->d
))
1884 if (p1
->type
!= p2
->type
)
1885 return p1
->type
- p2
->type
;
1886 if (p1
->pos
!= p2
->pos
)
1887 return p1
->pos
- p2
->pos
;
1888 if (p1
->size
!= p2
->size
)
1889 return p1
->size
- p2
->size
;
1891 for (i
= p1
->size
-1; i
>= 0; --i
)
1892 if ((r
= ecmp(&p1
->arr
[i
], &p2
->arr
[i
])) != 0)
1898 int eequal(evalue
*e1
,evalue
*e2
) {
1903 if (value_ne(e1
->d
,e2
->d
))
1906 /* e1->d == e2->d */
1907 if (value_notzero_p(e1
->d
)) {
1908 if (value_ne(e1
->x
.n
,e2
->x
.n
))
1911 /* e1->d == e2->d != 0 AND e1->n == e2->n */
1915 /* e1->d == e2->d == 0 */
1918 if (p1
->type
!= p2
->type
) return 0;
1919 if (p1
->size
!= p2
->size
) return 0;
1920 if (p1
->pos
!= p2
->pos
) return 0;
1921 for (i
=0; i
<p1
->size
; i
++)
1922 if (!eequal(&p1
->arr
[i
], &p2
->arr
[i
]) )
1927 void free_evalue_refs(evalue
*e
) {
1932 if (EVALUE_IS_DOMAIN(*e
)) {
1933 Domain_Free(EVALUE_DOMAIN(*e
));
1936 } else if (value_pos_p(e
->d
)) {
1938 /* 'e' stores a constant */
1940 value_clear(e
->x
.n
);
1943 assert(value_zero_p(e
->d
));
1946 if (!p
) return; /* null pointer */
1947 for (i
=0; i
<p
->size
; i
++) {
1948 free_evalue_refs(&(p
->arr
[i
]));
1952 } /* free_evalue_refs */
1954 static void mod2table_r(evalue
*e
, Vector
*periods
, Value m
, int p
,
1955 Vector
* val
, evalue
*res
)
1957 unsigned nparam
= periods
->Size
;
1960 double d
= compute_evalue(e
, val
->p
);
1961 d
*= VALUE_TO_DOUBLE(m
);
1966 value_assign(res
->d
, m
);
1967 value_init(res
->x
.n
);
1968 value_set_double(res
->x
.n
, d
);
1969 mpz_fdiv_r(res
->x
.n
, res
->x
.n
, m
);
1972 if (value_one_p(periods
->p
[p
]))
1973 mod2table_r(e
, periods
, m
, p
+1, val
, res
);
1978 value_assign(tmp
, periods
->p
[p
]);
1979 value_set_si(res
->d
, 0);
1980 res
->x
.p
= new_enode(periodic
, VALUE_TO_INT(tmp
), p
+1);
1982 value_decrement(tmp
, tmp
);
1983 value_assign(val
->p
[p
], tmp
);
1984 mod2table_r(e
, periods
, m
, p
+1, val
,
1985 &res
->x
.p
->arr
[VALUE_TO_INT(tmp
)]);
1986 } while (value_pos_p(tmp
));
1992 static void rel2table(evalue
*e
, int zero
)
1994 if (value_pos_p(e
->d
)) {
1995 if (value_zero_p(e
->x
.n
) == zero
)
1996 value_set_si(e
->x
.n
, 1);
1998 value_set_si(e
->x
.n
, 0);
1999 value_set_si(e
->d
, 1);
2002 for (i
= 0; i
< e
->x
.p
->size
; ++i
)
2003 rel2table(&e
->x
.p
->arr
[i
], zero
);
2007 void evalue_mod2table(evalue
*e
, int nparam
)
2012 if (EVALUE_IS_DOMAIN(*e
) || value_pos_p(e
->d
))
2015 for (i
=0; i
<p
->size
; i
++) {
2016 evalue_mod2table(&(p
->arr
[i
]), nparam
);
2018 if (p
->type
== relation
) {
2023 evalue_copy(©
, &p
->arr
[0]);
2025 rel2table(&p
->arr
[0], 1);
2026 emul(&p
->arr
[0], &p
->arr
[1]);
2028 rel2table(©
, 0);
2029 emul(©
, &p
->arr
[2]);
2030 eadd(&p
->arr
[2], &p
->arr
[1]);
2031 free_evalue_refs(&p
->arr
[2]);
2032 free_evalue_refs(©
);
2034 free_evalue_refs(&p
->arr
[0]);
2038 } else if (p
->type
== fractional
) {
2039 Vector
*periods
= Vector_Alloc(nparam
);
2040 Vector
*val
= Vector_Alloc(nparam
);
2046 value_set_si(tmp
, 1);
2047 Vector_Set(periods
->p
, 1, nparam
);
2048 Vector_Set(val
->p
, 0, nparam
);
2049 for (ev
= &p
->arr
[0]; value_zero_p(ev
->d
); ev
= &ev
->x
.p
->arr
[0]) {
2052 assert(p
->type
== polynomial
);
2053 assert(p
->size
== 2);
2054 value_assign(periods
->p
[p
->pos
-1], p
->arr
[1].d
);
2055 value_lcm(tmp
, p
->arr
[1].d
, &tmp
);
2057 value_lcm(tmp
, ev
->d
, &tmp
);
2059 mod2table_r(&p
->arr
[0], periods
, tmp
, 0, val
, &EP
);
2062 evalue_set_si(&res
, 0, 1);
2063 /* Compute the polynomial using Horner's rule */
2064 for (i
=p
->size
-1;i
>1;i
--) {
2065 eadd(&p
->arr
[i
], &res
);
2068 eadd(&p
->arr
[1], &res
);
2070 free_evalue_refs(e
);
2071 free_evalue_refs(&EP
);
2076 Vector_Free(periods
);
2078 } /* evalue_mod2table */
2080 /********************************************************/
2081 /* function in domain */
2082 /* check if the parameters in list_args */
2083 /* verifies the constraints of Domain P */
2084 /********************************************************/
2085 int in_domain(Polyhedron
*P
, Value
*list_args
)
2088 Value v
; /* value of the constraint of a row when
2089 parameters are instantiated*/
2093 for (row
= 0; row
< P
->NbConstraints
; row
++) {
2094 Inner_Product(P
->Constraint
[row
]+1, list_args
, P
->Dimension
, &v
);
2095 value_addto(v
, v
, P
->Constraint
[row
][P
->Dimension
+1]); /*constant part*/
2096 if (value_neg_p(v
) ||
2097 value_zero_p(P
->Constraint
[row
][0]) && value_notzero_p(v
)) {
2104 return in
|| (P
->next
&& in_domain(P
->next
, list_args
));
2107 /****************************************************/
2108 /* function compute enode */
2109 /* compute the value of enode p with parameters */
2110 /* list "list_args */
2111 /* compute the polynomial or the periodic */
2112 /****************************************************/
2114 static double compute_enode(enode
*p
, Value
*list_args
) {
2126 if (p
->type
== polynomial
) {
2128 value_assign(param
,list_args
[p
->pos
-1]);
2130 /* Compute the polynomial using Horner's rule */
2131 for (i
=p
->size
-1;i
>0;i
--) {
2132 res
+=compute_evalue(&p
->arr
[i
],list_args
);
2133 res
*=VALUE_TO_DOUBLE(param
);
2135 res
+=compute_evalue(&p
->arr
[0],list_args
);
2137 else if (p
->type
== fractional
) {
2138 double d
= compute_evalue(&p
->arr
[0], list_args
);
2139 d
-= floor(d
+1e-10);
2141 /* Compute the polynomial using Horner's rule */
2142 for (i
=p
->size
-1;i
>1;i
--) {
2143 res
+=compute_evalue(&p
->arr
[i
],list_args
);
2146 res
+=compute_evalue(&p
->arr
[1],list_args
);
2148 else if (p
->type
== flooring
) {
2149 double d
= compute_evalue(&p
->arr
[0], list_args
);
2152 /* Compute the polynomial using Horner's rule */
2153 for (i
=p
->size
-1;i
>1;i
--) {
2154 res
+=compute_evalue(&p
->arr
[i
],list_args
);
2157 res
+=compute_evalue(&p
->arr
[1],list_args
);
2159 else if (p
->type
== periodic
) {
2160 value_assign(m
,list_args
[p
->pos
-1]);
2162 /* Choose the right element of the periodic */
2163 value_set_si(param
,p
->size
);
2164 value_pmodulus(m
,m
,param
);
2165 res
= compute_evalue(&p
->arr
[VALUE_TO_INT(m
)],list_args
);
2167 else if (p
->type
== relation
) {
2168 if (fabs(compute_evalue(&p
->arr
[0], list_args
)) < 1e-10)
2169 res
= compute_evalue(&p
->arr
[1], list_args
);
2170 else if (p
->size
> 2)
2171 res
= compute_evalue(&p
->arr
[2], list_args
);
2173 else if (p
->type
== partition
) {
2174 int dim
= EVALUE_DOMAIN(p
->arr
[0])->Dimension
;
2175 Value
*vals
= list_args
;
2178 for (i
= 0; i
< dim
; ++i
) {
2179 value_init(vals
[i
]);
2181 value_assign(vals
[i
], list_args
[i
]);
2184 for (i
= 0; i
< p
->size
/2; ++i
)
2185 if (DomainContains(EVALUE_DOMAIN(p
->arr
[2*i
]), vals
, p
->pos
, 0, 1)) {
2186 res
= compute_evalue(&p
->arr
[2*i
+1], vals
);
2190 for (i
= 0; i
< dim
; ++i
)
2191 value_clear(vals
[i
]);
2200 } /* compute_enode */
2202 /*************************************************/
2203 /* return the value of Ehrhart Polynomial */
2204 /* It returns a double, because since it is */
2205 /* a recursive function, some intermediate value */
2206 /* might not be integral */
2207 /*************************************************/
2209 double compute_evalue(evalue
*e
,Value
*list_args
) {
2213 if (value_notzero_p(e
->d
)) {
2214 if (value_notone_p(e
->d
))
2215 res
= VALUE_TO_DOUBLE(e
->x
.n
) / VALUE_TO_DOUBLE(e
->d
);
2217 res
= VALUE_TO_DOUBLE(e
->x
.n
);
2220 res
= compute_enode(e
->x
.p
,list_args
);
2222 } /* compute_evalue */
2225 /****************************************************/
2226 /* function compute_poly : */
2227 /* Check for the good validity domain */
2228 /* return the number of point in the Polyhedron */
2229 /* in allocated memory */
2230 /* Using the Ehrhart pseudo-polynomial */
2231 /****************************************************/
2232 Value
*compute_poly(Enumeration
*en
,Value
*list_args
) {
2235 /* double d; int i; */
2237 tmp
= (Value
*) malloc (sizeof(Value
));
2238 assert(tmp
!= NULL
);
2240 value_set_si(*tmp
,0);
2243 return(tmp
); /* no ehrhart polynomial */
2244 if(en
->ValidityDomain
) {
2245 if(!en
->ValidityDomain
->Dimension
) { /* no parameters */
2246 value_set_double(*tmp
,compute_evalue(&en
->EP
,list_args
)+.25);
2251 return(tmp
); /* no Validity Domain */
2253 if(in_domain(en
->ValidityDomain
,list_args
)) {
2255 #ifdef EVAL_EHRHART_DEBUG
2256 Print_Domain(stdout
,en
->ValidityDomain
);
2257 print_evalue(stdout
,&en
->EP
);
2260 /* d = compute_evalue(&en->EP,list_args);
2262 printf("(double)%lf = %d\n", d, i ); */
2263 value_set_double(*tmp
,compute_evalue(&en
->EP
,list_args
)+.25);
2269 value_set_si(*tmp
,0);
2270 return(tmp
); /* no compatible domain with the arguments */
2271 } /* compute_poly */
2273 size_t value_size(Value v
) {
2274 return (v
[0]._mp_size
> 0 ? v
[0]._mp_size
: -v
[0]._mp_size
)
2275 * sizeof(v
[0]._mp_d
[0]);
2278 size_t domain_size(Polyhedron
*D
)
2281 size_t s
= sizeof(*D
);
2283 for (i
= 0; i
< D
->NbConstraints
; ++i
)
2284 for (j
= 0; j
< D
->Dimension
+2; ++j
)
2285 s
+= value_size(D
->Constraint
[i
][j
]);
2288 for (i = 0; i < D->NbRays; ++i)
2289 for (j = 0; j < D->Dimension+2; ++j)
2290 s += value_size(D->Ray[i][j]);
2293 return D
->next
? s
+domain_size(D
->next
) : s
;
2296 size_t enode_size(enode
*p
) {
2297 size_t s
= sizeof(*p
) - sizeof(p
->arr
[0]);
2300 if (p
->type
== partition
)
2301 for (i
= 0; i
< p
->size
/2; ++i
) {
2302 s
+= domain_size(EVALUE_DOMAIN(p
->arr
[2*i
]));
2303 s
+= evalue_size(&p
->arr
[2*i
+1]);
2306 for (i
= 0; i
< p
->size
; ++i
) {
2307 s
+= evalue_size(&p
->arr
[i
]);
2312 size_t evalue_size(evalue
*e
)
2314 size_t s
= sizeof(*e
);
2315 s
+= value_size(e
->d
);
2316 if (value_notzero_p(e
->d
))
2317 s
+= value_size(e
->x
.n
);
2319 s
+= enode_size(e
->x
.p
);
2323 static evalue
*find_second(evalue
*base
, evalue
*cst
, evalue
*e
, Value m
)
2325 evalue
*found
= NULL
;
2330 if (value_pos_p(e
->d
) || e
->x
.p
->type
!= fractional
)
2333 value_init(offset
.d
);
2334 value_init(offset
.x
.n
);
2335 poly_denom(&e
->x
.p
->arr
[0], &offset
.d
);
2336 value_lcm(m
, offset
.d
, &offset
.d
);
2337 value_set_si(offset
.x
.n
, 1);
2340 evalue_copy(©
, cst
);
2343 mpz_fdiv_r(cst
->x
.n
, cst
->x
.n
, cst
->d
);
2345 if (eequal(base
, &e
->x
.p
->arr
[0]))
2346 found
= &e
->x
.p
->arr
[0];
2348 value_set_si(offset
.x
.n
, -2);
2351 mpz_fdiv_r(cst
->x
.n
, cst
->x
.n
, cst
->d
);
2353 if (eequal(base
, &e
->x
.p
->arr
[0]))
2356 free_evalue_refs(cst
);
2357 free_evalue_refs(&offset
);
2360 for (i
= 1; !found
&& i
< e
->x
.p
->size
; ++i
)
2361 found
= find_second(base
, cst
, &e
->x
.p
->arr
[i
], m
);
2366 static evalue
*find_relation_pair(evalue
*e
)
2369 evalue
*found
= NULL
;
2371 if (EVALUE_IS_DOMAIN(*e
) || value_pos_p(e
->d
))
2374 if (e
->x
.p
->type
== fractional
) {
2379 poly_denom(&e
->x
.p
->arr
[0], &m
);
2381 for (cst
= &e
->x
.p
->arr
[0]; value_zero_p(cst
->d
);
2382 cst
= &cst
->x
.p
->arr
[0])
2385 for (i
= 1; !found
&& i
< e
->x
.p
->size
; ++i
)
2386 found
= find_second(&e
->x
.p
->arr
[0], cst
, &e
->x
.p
->arr
[i
], m
);
2391 i
= e
->x
.p
->type
== relation
;
2392 for (; !found
&& i
< e
->x
.p
->size
; ++i
)
2393 found
= find_relation_pair(&e
->x
.p
->arr
[i
]);
2398 void evalue_mod2relation(evalue
*e
) {
2401 if (value_zero_p(e
->d
) && e
->x
.p
->type
== partition
) {
2404 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2405 evalue_mod2relation(&e
->x
.p
->arr
[2*i
+1]);
2406 if (EVALUE_IS_ZERO(e
->x
.p
->arr
[2*i
+1])) {
2407 value_clear(e
->x
.p
->arr
[2*i
].d
);
2408 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
2410 if (2*i
< e
->x
.p
->size
) {
2411 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
2412 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
2417 if (e
->x
.p
->size
== 0) {
2419 evalue_set_si(e
, 0, 1);
2425 while ((d
= find_relation_pair(e
)) != NULL
) {
2429 value_init(split
.d
);
2430 value_set_si(split
.d
, 0);
2431 split
.x
.p
= new_enode(relation
, 3, 0);
2432 evalue_set_si(&split
.x
.p
->arr
[1], 1, 1);
2433 evalue_set_si(&split
.x
.p
->arr
[2], 1, 1);
2435 ev
= &split
.x
.p
->arr
[0];
2436 value_set_si(ev
->d
, 0);
2437 ev
->x
.p
= new_enode(fractional
, 3, -1);
2438 evalue_set_si(&ev
->x
.p
->arr
[1], 0, 1);
2439 evalue_set_si(&ev
->x
.p
->arr
[2], 1, 1);
2440 evalue_copy(&ev
->x
.p
->arr
[0], d
);
2446 free_evalue_refs(&split
);
2450 static int evalue_comp(const void * a
, const void * b
)
2452 const evalue
*e1
= *(const evalue
**)a
;
2453 const evalue
*e2
= *(const evalue
**)b
;
2454 return ecmp(e1
, e2
);
2457 void evalue_combine(evalue
*e
)
2464 if (value_notzero_p(e
->d
) || e
->x
.p
->type
!= partition
)
2467 NALLOC(evs
, e
->x
.p
->size
/2);
2468 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
2469 evs
[i
] = &e
->x
.p
->arr
[2*i
+1];
2470 qsort(evs
, e
->x
.p
->size
/2, sizeof(evs
[0]), evalue_comp
);
2471 p
= new_enode(partition
, e
->x
.p
->size
, e
->x
.p
->pos
);
2472 for (i
= 0, k
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2473 if (k
== 0 || ecmp(&p
->arr
[2*k
-1], evs
[i
]) != 0) {
2474 value_clear(p
->arr
[2*k
].d
);
2475 value_clear(p
->arr
[2*k
+1].d
);
2476 p
->arr
[2*k
] = *(evs
[i
]-1);
2477 p
->arr
[2*k
+1] = *(evs
[i
]);
2480 Polyhedron
*D
= EVALUE_DOMAIN(*(evs
[i
]-1));
2483 value_clear((evs
[i
]-1)->d
);
2487 L
->next
= EVALUE_DOMAIN(p
->arr
[2*k
-2]);
2488 EVALUE_SET_DOMAIN(p
->arr
[2*k
-2], D
);
2489 free_evalue_refs(evs
[i
]);
2493 for (i
= 2*k
; i
< p
->size
; ++i
)
2494 value_clear(p
->arr
[i
].d
);
2501 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2503 if (value_notzero_p(e
->x
.p
->arr
[2*i
+1].d
))
2505 H
= DomainConvex(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]), 0);
2508 for (k
= 0; k
< e
->x
.p
->size
/2; ++k
) {
2509 Polyhedron
*D
, *N
, **P
;
2512 P
= &EVALUE_DOMAIN(e
->x
.p
->arr
[2*k
]);
2519 if (D
->NbEq
<= H
->NbEq
) {
2525 tmp
.x
.p
= new_enode(partition
, 2, e
->x
.p
->pos
);
2526 EVALUE_SET_DOMAIN(tmp
.x
.p
->arr
[0], Polyhedron_Copy(D
));
2527 evalue_copy(&tmp
.x
.p
->arr
[1], &e
->x
.p
->arr
[2*i
+1]);
2528 reduce_evalue(&tmp
);
2529 if (value_notzero_p(tmp
.d
) ||
2530 ecmp(&tmp
.x
.p
->arr
[1], &e
->x
.p
->arr
[2*k
+1]) != 0)
2533 D
->next
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]);
2534 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]) = D
;
2537 free_evalue_refs(&tmp
);
2543 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
2545 Polyhedron
*D
= EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]);
2547 value_clear(e
->x
.p
->arr
[2*i
].d
);
2548 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
2550 if (2*i
< e
->x
.p
->size
) {
2551 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
2552 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
2559 H
= DomainConvex(D
, 0);
2560 E
= DomainDifference(H
, D
, 0);
2562 D
= DomainDifference(H
, E
, 0);
2565 EVALUE_SET_DOMAIN(p
->arr
[2*i
], D
);
2569 /* May change coefficients to become non-standard if fiddle is set
2570 * => reduce p afterwards to correct
2572 static Polyhedron
*polynomial_projection(enode
*p
, Polyhedron
*D
, Value
*d
,
2573 Matrix
**R
, int fiddle
)
2577 unsigned dim
= D
->Dimension
;
2578 Matrix
*T
= Matrix_Alloc(2, dim
+1);
2583 assert(p
->type
== fractional
);
2585 value_set_si(T
->p
[1][dim
], 1);
2587 while (value_zero_p(pp
->d
)) {
2588 assert(pp
->x
.p
->type
== polynomial
);
2589 assert(pp
->x
.p
->size
== 2);
2590 assert(value_notzero_p(pp
->x
.p
->arr
[1].d
));
2591 value_division(T
->p
[0][pp
->x
.p
->pos
-1], *d
, pp
->x
.p
->arr
[1].d
);
2592 mpz_mul_ui(twice
, pp
->x
.p
->arr
[1].x
.n
, 2);
2593 if (fiddle
&& value_gt(twice
, pp
->x
.p
->arr
[1].d
))
2594 value_subtract(pp
->x
.p
->arr
[1].x
.n
,
2595 pp
->x
.p
->arr
[1].x
.n
, pp
->x
.p
->arr
[1].d
);
2596 value_multiply(T
->p
[0][pp
->x
.p
->pos
-1],
2597 T
->p
[0][pp
->x
.p
->pos
-1], pp
->x
.p
->arr
[1].x
.n
);
2598 pp
= &pp
->x
.p
->arr
[0];
2600 value_division(T
->p
[0][dim
], *d
, pp
->d
);
2601 value_multiply(T
->p
[0][dim
], T
->p
[0][dim
], pp
->x
.n
);
2602 I
= DomainImage(D
, T
, 0);
2603 H
= DomainConvex(I
, 0);
2612 int evalue_range_reduction_in_domain(evalue
*e
, Polyhedron
*D
)
2622 if (value_notzero_p(e
->d
))
2627 if (p
->type
== relation
) {
2633 I
= polynomial_projection(p
->arr
[0].x
.p
, D
, &d
, &T
, 1);
2634 bounded
= line_minmax(I
, &min
, &max
); /* frees I */
2635 equal
= value_eq(min
, max
);
2636 mpz_cdiv_q(min
, min
, d
);
2637 mpz_fdiv_q(max
, max
, d
);
2639 if (bounded
&& value_gt(min
, max
)) {
2645 evalue_set_si(e
, 0, 1);
2648 free_evalue_refs(&(p
->arr
[1]));
2649 free_evalue_refs(&(p
->arr
[0]));
2655 return r
? r
: evalue_range_reduction_in_domain(e
, D
);
2656 } else if (bounded
&& equal
) {
2659 free_evalue_refs(&(p
->arr
[2]));
2662 free_evalue_refs(&(p
->arr
[0]));
2668 return evalue_range_reduction_in_domain(e
, D
);
2669 } else if (bounded
&& value_eq(min
, max
)) {
2670 /* zero for a single value */
2672 Matrix
*M
= Matrix_Alloc(1, D
->Dimension
+2);
2673 Vector_Copy(T
->p
[0], M
->p
[0]+1, D
->Dimension
+1);
2674 value_multiply(min
, min
, d
);
2675 value_subtract(M
->p
[0][D
->Dimension
+1],
2676 M
->p
[0][D
->Dimension
+1], min
);
2677 E
= DomainAddConstraints(D
, M
, 0);
2683 r
= evalue_range_reduction_in_domain(&p
->arr
[1], E
);
2685 r
|= evalue_range_reduction_in_domain(&p
->arr
[2], D
);
2687 _reduce_evalue(&p
->arr
[0].x
.p
->arr
[0], 0, 1);
2695 _reduce_evalue(&p
->arr
[0].x
.p
->arr
[0], 0, 1);
2698 i
= p
->type
== relation
? 1 :
2699 p
->type
== fractional
? 1 : 0;
2700 for (; i
<p
->size
; i
++)
2701 r
|= evalue_range_reduction_in_domain(&p
->arr
[i
], D
);
2703 if (p
->type
!= fractional
) {
2704 if (r
&& p
->type
== polynomial
) {
2707 value_set_si(f
.d
, 0);
2708 f
.x
.p
= new_enode(polynomial
, 2, p
->pos
);
2709 evalue_set_si(&f
.x
.p
->arr
[0], 0, 1);
2710 evalue_set_si(&f
.x
.p
->arr
[1], 1, 1);
2711 reorder_terms(p
, &f
);
2722 I
= polynomial_projection(p
, D
, &d
, &T
, 1);
2724 bounded
= line_minmax(I
, &min
, &max
); /* frees I */
2725 mpz_fdiv_q(min
, min
, d
);
2726 mpz_fdiv_q(max
, max
, d
);
2727 value_subtract(d
, max
, min
);
2729 if (bounded
&& value_eq(min
, max
)) {
2732 value_init(inc
.x
.n
);
2733 value_set_si(inc
.d
, 1);
2734 value_oppose(inc
.x
.n
, min
);
2735 eadd(&inc
, &p
->arr
[0]);
2736 reorder_terms(p
, &p
->arr
[0]); /* frees arr[0] */
2740 free_evalue_refs(&inc
);
2742 } else if (bounded
&& value_one_p(d
) && p
->size
> 3) {
2749 value_set_si(rem
.d
, 0);
2750 rem
.x
.p
= new_enode(fractional
, 3, -1);
2751 evalue_copy(&rem
.x
.p
->arr
[0], &p
->arr
[0]);
2752 value_clear(rem
.x
.p
->arr
[1].d
);
2753 value_clear(rem
.x
.p
->arr
[2].d
);
2754 rem
.x
.p
->arr
[1] = p
->arr
[1];
2755 rem
.x
.p
->arr
[2] = p
->arr
[2];
2756 for (i
= 3; i
< p
->size
; ++i
)
2757 p
->arr
[i
-2] = p
->arr
[i
];
2761 value_init(inc
.x
.n
);
2762 value_set_si(inc
.d
, 1);
2763 value_oppose(inc
.x
.n
, min
);
2766 evalue_copy(&t
, &p
->arr
[0]);
2770 value_set_si(f
.d
, 0);
2771 f
.x
.p
= new_enode(fractional
, 3, -1);
2772 evalue_copy(&f
.x
.p
->arr
[0], &p
->arr
[0]);
2773 evalue_set_si(&f
.x
.p
->arr
[1], 1, 1);
2774 evalue_set_si(&f
.x
.p
->arr
[2], 2, 1);
2776 value_init(factor
.d
);
2777 evalue_set_si(&factor
, -1, 1);
2783 value_clear(f
.x
.p
->arr
[1].x
.n
);
2784 value_clear(f
.x
.p
->arr
[2].x
.n
);
2785 evalue_set_si(&f
.x
.p
->arr
[1], 0, 1);
2786 evalue_set_si(&f
.x
.p
->arr
[2], -1, 1);
2792 free_evalue_refs(&inc
);
2793 free_evalue_refs(&t
);
2794 free_evalue_refs(&f
);
2795 free_evalue_refs(&factor
);
2796 free_evalue_refs(&rem
);
2798 evalue_range_reduction_in_domain(e
, D
);
2802 _reduce_evalue(&p
->arr
[0], 0, 1);
2806 value_set_si(f
.d
, 0);
2807 f
.x
.p
= new_enode(fractional
, 3, -1);
2808 value_clear(f
.x
.p
->arr
[0].d
);
2809 f
.x
.p
->arr
[0] = p
->arr
[0];
2810 evalue_set_si(&f
.x
.p
->arr
[1], 0, 1);
2811 evalue_set_si(&f
.x
.p
->arr
[2], 1, 1);
2812 reorder_terms(p
, &f
);
2826 void evalue_range_reduction(evalue
*e
)
2829 if (value_notzero_p(e
->d
) || e
->x
.p
->type
!= partition
)
2832 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
2833 if (evalue_range_reduction_in_domain(&e
->x
.p
->arr
[2*i
+1],
2834 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]))) {
2835 reduce_evalue(&e
->x
.p
->arr
[2*i
+1]);
2837 if (EVALUE_IS_ZERO(e
->x
.p
->arr
[2*i
+1])) {
2838 free_evalue_refs(&e
->x
.p
->arr
[2*i
+1]);
2839 Domain_Free(EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]));
2840 value_clear(e
->x
.p
->arr
[2*i
].d
);
2842 e
->x
.p
->arr
[2*i
] = e
->x
.p
->arr
[e
->x
.p
->size
];
2843 e
->x
.p
->arr
[2*i
+1] = e
->x
.p
->arr
[e
->x
.p
->size
+1];
2851 Enumeration
* partition2enumeration(evalue
*EP
)
2854 Enumeration
*en
, *res
= NULL
;
2856 if (EVALUE_IS_ZERO(*EP
)) {
2861 for (i
= 0; i
< EP
->x
.p
->size
/2; ++i
) {
2862 assert(EP
->x
.p
->pos
== EVALUE_DOMAIN(EP
->x
.p
->arr
[2*i
])->Dimension
);
2863 en
= (Enumeration
*)malloc(sizeof(Enumeration
));
2866 res
->ValidityDomain
= EVALUE_DOMAIN(EP
->x
.p
->arr
[2*i
]);
2867 value_clear(EP
->x
.p
->arr
[2*i
].d
);
2868 res
->EP
= EP
->x
.p
->arr
[2*i
+1];
2876 int evalue_frac2floor_in_domain(evalue
*e
, Polyhedron
*D
)
2886 if (value_notzero_p(e
->d
))
2891 i
= p
->type
== relation
? 1 :
2892 p
->type
== fractional
? 1 : 0;
2893 for (; i
<p
->size
; i
++)
2894 r
|= evalue_frac2floor_in_domain(&p
->arr
[i
], D
);
2896 if (p
->type
!= fractional
) {
2897 if (r
&& p
->type
== polynomial
) {
2900 value_set_si(f
.d
, 0);
2901 f
.x
.p
= new_enode(polynomial
, 2, p
->pos
);
2902 evalue_set_si(&f
.x
.p
->arr
[0], 0, 1);
2903 evalue_set_si(&f
.x
.p
->arr
[1], 1, 1);
2904 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
);
2948 value_set_si(fl
.d
, 0);
2949 fl
.x
.p
= new_enode(flooring
, 3, -1);
2950 evalue_set_si(&fl
.x
.p
->arr
[1], 0, 1);
2951 evalue_set_si(&fl
.x
.p
->arr
[2], -1, 1);
2952 evalue_copy(&fl
.x
.p
->arr
[0], &p
->arr
[0]);
2954 eadd(&fl
, &p
->arr
[0]);
2955 reorder_terms(p
, &p
->arr
[0]);
2959 free_evalue_refs(&fl
);
2964 void evalue_frac2floor(evalue
*e
)
2967 if (value_notzero_p(e
->d
) || e
->x
.p
->type
!= partition
)
2970 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
)
2971 if (evalue_frac2floor_in_domain(&e
->x
.p
->arr
[2*i
+1],
2972 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
])))
2973 reduce_evalue(&e
->x
.p
->arr
[2*i
+1]);
2976 static Matrix
*esum_add_constraint(int nvar
, Polyhedron
*D
, Matrix
*C
,
2981 int nparam
= D
->Dimension
- nvar
;
2984 nr
= D
->NbConstraints
+ 2;
2985 nc
= D
->Dimension
+ 2 + 1;
2986 C
= Matrix_Alloc(nr
, nc
);
2987 for (i
= 0; i
< D
->NbConstraints
; ++i
) {
2988 Vector_Copy(D
->Constraint
[i
], C
->p
[i
], 1 + nvar
);
2989 Vector_Copy(D
->Constraint
[i
] + 1 + nvar
, C
->p
[i
] + 1 + nvar
+ 1,
2990 D
->Dimension
+ 1 - nvar
);
2995 nc
= C
->NbColumns
+ 1;
2996 C
= Matrix_Alloc(nr
, nc
);
2997 for (i
= 0; i
< oldC
->NbRows
; ++i
) {
2998 Vector_Copy(oldC
->p
[i
], C
->p
[i
], 1 + nvar
);
2999 Vector_Copy(oldC
->p
[i
] + 1 + nvar
, C
->p
[i
] + 1 + nvar
+ 1,
3000 oldC
->NbColumns
- 1 - nvar
);
3003 value_set_si(C
->p
[nr
-2][0], 1);
3004 value_set_si(C
->p
[nr
-2][1 + nvar
], 1);
3005 value_set_si(C
->p
[nr
-2][nc
- 1], -1);
3007 Vector_Copy(row
->p
, C
->p
[nr
-1], 1 + nvar
+ 1);
3008 Vector_Copy(row
->p
+ 1 + nvar
+ 1, C
->p
[nr
-1] + C
->NbColumns
- 1 - nparam
,
3014 static void floor2frac_r(evalue
*e
, int nvar
)
3021 if (value_notzero_p(e
->d
))
3026 assert(p
->type
== flooring
);
3027 for (i
= 1; i
< p
->size
; i
++)
3028 floor2frac_r(&p
->arr
[i
], nvar
);
3030 for (pp
= &p
->arr
[0]; value_zero_p(pp
->d
); pp
= &pp
->x
.p
->arr
[0]) {
3031 assert(pp
->x
.p
->type
== polynomial
);
3032 pp
->x
.p
->pos
-= nvar
;
3036 value_set_si(f
.d
, 0);
3037 f
.x
.p
= new_enode(fractional
, 3, -1);
3038 evalue_set_si(&f
.x
.p
->arr
[1], 0, 1);
3039 evalue_set_si(&f
.x
.p
->arr
[2], -1, 1);
3040 evalue_copy(&f
.x
.p
->arr
[0], &p
->arr
[0]);
3042 eadd(&f
, &p
->arr
[0]);
3043 reorder_terms(p
, &p
->arr
[0]);
3047 free_evalue_refs(&f
);
3050 /* Convert flooring back to fractional and shift position
3051 * of the parameters by nvar
3053 static void floor2frac(evalue
*e
, int nvar
)
3055 floor2frac_r(e
, nvar
);
3059 evalue
*esum_over_domain_cst(int nvar
, Polyhedron
*D
, Matrix
*C
)
3062 int nparam
= D
->Dimension
- nvar
;
3066 D
= Constraints2Polyhedron(C
, 0);
3070 t
= barvinok_enumerate_e(D
, 0, nparam
, 0);
3072 /* Double check that D was not unbounded. */
3073 assert(!(value_pos_p(t
->d
) && value_neg_p(t
->x
.n
)));
3081 evalue
*esum_over_domain(evalue
*e
, int nvar
, Polyhedron
*D
,
3088 evalue
*factor
= NULL
;
3091 if (EVALUE_IS_ZERO(*e
))
3095 Polyhedron
*DD
= Disjoint_Domain(D
, 0, 0);
3102 res
= esum_over_domain(e
, nvar
, Q
, C
);
3105 for (Q
= DD
; Q
; Q
= DD
) {
3111 t
= esum_over_domain(e
, nvar
, Q
, C
);
3118 free_evalue_refs(t
);
3125 if (value_notzero_p(e
->d
)) {
3128 t
= esum_over_domain_cst(nvar
, D
, C
);
3130 if (!EVALUE_IS_ONE(*e
))
3136 switch (e
->x
.p
->type
) {
3138 evalue
*pp
= &e
->x
.p
->arr
[0];
3140 if (pp
->x
.p
->pos
> nvar
) {
3141 /* remainder is independent of the summated vars */
3147 floor2frac(&f
, nvar
);
3149 t
= esum_over_domain_cst(nvar
, D
, C
);
3153 free_evalue_refs(&f
);
3158 row
= Vector_Alloc(1 + D
->Dimension
+ 1 + 1);
3159 poly_denom(pp
, &row
->p
[1 + nvar
]);
3160 value_set_si(row
->p
[0], 1);
3161 for (pp
= &e
->x
.p
->arr
[0]; value_zero_p(pp
->d
);
3162 pp
= &pp
->x
.p
->arr
[0]) {
3164 assert(pp
->x
.p
->type
== polynomial
);
3166 if (pos
>= 1 + nvar
)
3168 value_assign(row
->p
[pos
], row
->p
[1+nvar
]);
3169 value_division(row
->p
[pos
], row
->p
[pos
], pp
->x
.p
->arr
[1].d
);
3170 value_multiply(row
->p
[pos
], row
->p
[pos
], pp
->x
.p
->arr
[1].x
.n
);
3172 value_assign(row
->p
[1 + D
->Dimension
+ 1], row
->p
[1+nvar
]);
3173 value_division(row
->p
[1 + D
->Dimension
+ 1],
3174 row
->p
[1 + D
->Dimension
+ 1],
3176 value_multiply(row
->p
[1 + D
->Dimension
+ 1],
3177 row
->p
[1 + D
->Dimension
+ 1],
3179 value_oppose(row
->p
[1 + nvar
], row
->p
[1 + nvar
]);
3183 int pos
= e
->x
.p
->pos
;
3186 factor
= ALLOC(evalue
);
3187 value_init(factor
->d
);
3188 value_set_si(factor
->d
, 0);
3189 factor
->x
.p
= new_enode(polynomial
, 2, pos
- nvar
);
3190 evalue_set_si(&factor
->x
.p
->arr
[0], 0, 1);
3191 evalue_set_si(&factor
->x
.p
->arr
[1], 1, 1);
3195 row
= Vector_Alloc(1 + D
->Dimension
+ 1 + 1);
3196 for (i
= 0; i
< D
->NbRays
; ++i
)
3197 if (value_notzero_p(D
->Ray
[i
][pos
]))
3199 assert(i
< D
->NbRays
);
3200 if (value_neg_p(D
->Ray
[i
][pos
])) {
3201 factor
= ALLOC(evalue
);
3202 value_init(factor
->d
);
3203 evalue_set_si(factor
, -1, 1);
3205 value_set_si(row
->p
[0], 1);
3206 value_set_si(row
->p
[pos
], 1);
3207 value_set_si(row
->p
[1 + nvar
], -1);
3214 i
= type_offset(e
->x
.p
);
3216 res
= esum_over_domain(&e
->x
.p
->arr
[i
], nvar
, D
, C
);
3221 evalue_copy(&cum
, factor
);
3225 for (; i
< e
->x
.p
->size
; ++i
) {
3229 C
= esum_add_constraint(nvar
, D
, C
, row
);
3235 Vector_Print(stderr, P_VALUE_FMT, row);
3237 Matrix_Print(stderr, P_VALUE_FMT, C);
3239 t
= esum_over_domain(&e
->x
.p
->arr
[i
], nvar
, D
, C
);
3248 free_evalue_refs(t
);
3251 if (factor
&& i
+1 < e
->x
.p
->size
)
3258 free_evalue_refs(factor
);
3259 free_evalue_refs(&cum
);
3271 evalue
*esum(evalue
*e
, int nvar
)
3274 evalue
*res
= ALLOC(evalue
);
3278 if (nvar
== 0 || EVALUE_IS_ZERO(*e
)) {
3279 evalue_copy(res
, e
);
3283 evalue_set_si(res
, 0, 1);
3285 assert(value_zero_p(e
->d
));
3286 assert(e
->x
.p
->type
== partition
);
3288 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
3290 t
= esum_over_domain(&e
->x
.p
->arr
[2*i
+1], nvar
,
3291 EVALUE_DOMAIN(e
->x
.p
->arr
[2*i
]), 0);
3293 free_evalue_refs(t
);
3302 /* Initial silly implementation */
3303 void eor(evalue
*e1
, evalue
*res
)
3309 evalue_set_si(&mone
, -1, 1);
3311 evalue_copy(&E
, res
);
3317 free_evalue_refs(&E
);
3318 free_evalue_refs(&mone
);
3321 /* computes denominator of polynomial evalue
3322 * d should point to an initialized value
3324 void evalue_denom(evalue
*e
, Value
*d
)
3328 if (value_notzero_p(e
->d
)) {
3329 value_lcm(*d
, e
->d
, d
);
3332 assert(e
->x
.p
->type
== polynomial
||
3333 e
->x
.p
->type
== fractional
||
3334 e
->x
.p
->type
== flooring
);
3335 offset
= type_offset(e
->x
.p
);
3336 for (i
= e
->x
.p
->size
-1; i
>= offset
; --i
)
3337 evalue_denom(&e
->x
.p
->arr
[i
], d
);