1 #include <isl_set_polylib.h>
2 #include <isl/constraint.h>
3 #include <barvinok/evalue.h>
5 static __isl_give isl_qpolynomial
*extract_base(__isl_take isl_dim
*dim
,
12 isl_qpolynomial
*base
, *c
;
18 if (e
->x
.p
->type
== polynomial
)
19 return isl_qpolynomial_var(dim
, isl_dim_param
, e
->x
.p
->pos
- 1);
21 ctx
= isl_dim_get_ctx(dim
);
22 nparam
= isl_dim_size(dim
, isl_dim_param
);
23 v
= isl_vec_alloc(ctx
, 2 + nparam
);
27 isl_seq_clr(v
->el
+ 2, nparam
);
28 evalue_extract_affine(&e
->x
.p
->arr
[0], v
->el
+ 2, &v
->el
[1], &v
->el
[0]);
30 div
= isl_div_alloc(isl_dim_copy(dim
));
31 isl_div_set_constant(div
, v
->el
[1]);
32 isl_div_set_denominator(div
, v
->el
[0]);
34 for (i
= 0; i
< nparam
; ++i
)
35 isl_div_set_coefficient(div
, isl_dim_param
, i
, v
->el
[2 + i
]);
37 base
= isl_qpolynomial_div(div
);
39 if (e
->x
.p
->type
== fractional
) {
40 base
= isl_qpolynomial_neg(base
);
42 c
= isl_qpolynomial_rat_cst(isl_dim_copy(dim
), v
->el
[1], v
->el
[0]);
43 base
= isl_qpolynomial_add(base
, c
);
45 for (i
= 0; i
< nparam
; ++i
) {
47 c
= isl_qpolynomial_rat_cst(isl_dim_copy(dim
),
48 v
->el
[2 + i
], v
->el
[0]);
49 t
= isl_qpolynomial_var(isl_dim_copy(dim
),
51 t
= isl_qpolynomial_mul(c
, t
);
52 base
= isl_qpolynomial_add(base
, t
);
65 static int type_offset(enode
*p
)
67 return p
->type
== fractional
? 1 :
68 p
->type
== flooring
? 1 : 0;
71 __isl_give isl_qpolynomial
*isl_qpolynomial_from_evalue(__isl_take isl_dim
*dim
,
76 isl_qpolynomial
*base
;
79 if (EVALUE_IS_NAN(*e
))
80 return isl_qpolynomial_infty(dim
);
81 if (value_notzero_p(e
->d
))
82 return isl_qpolynomial_rat_cst(dim
, e
->x
.n
, e
->d
);
84 offset
= type_offset(e
->x
.p
);
86 assert(e
->x
.p
->type
== polynomial
||
87 e
->x
.p
->type
== flooring
||
88 e
->x
.p
->type
== fractional
);
89 assert(e
->x
.p
->size
>= 1 + offset
);
91 base
= extract_base(isl_dim_copy(dim
), e
);
92 qp
= isl_qpolynomial_from_evalue(isl_dim_copy(dim
),
93 &e
->x
.p
->arr
[e
->x
.p
->size
- 1]);
95 for (i
= e
->x
.p
->size
- 2; i
>= offset
; --i
) {
96 qp
= isl_qpolynomial_mul(qp
, isl_qpolynomial_copy(base
));
97 qp
= isl_qpolynomial_add(qp
,
98 isl_qpolynomial_from_evalue(isl_dim_copy(dim
),
102 isl_qpolynomial_free(base
);
108 static __isl_give isl_pw_qpolynomial
*guarded_evalue2pwqp(__isl_take isl_set
*set
,
111 static __isl_give isl_pw_qpolynomial
*relation2pwqp(__isl_take isl_set
*set
,
119 isl_pw_qpolynomial
*pwqp
;
120 struct isl_constraint
*c
;
121 struct isl_basic_set
*bset
;
122 struct isl_set
*guard
;
128 if (e
->x
.p
->size
== 1) {
129 dim
= isl_set_get_dim(set
);
131 return isl_pw_qpolynomial_zero(dim
);
134 ctx
= isl_set_get_ctx(set
);
135 isl_assert(ctx
, e
->x
.p
->size
> 0, goto error
);
136 isl_assert(ctx
, e
->x
.p
->size
<= 3, goto error
);
137 isl_assert(ctx
, value_zero_p(e
->x
.p
->arr
[0].d
), goto error
);
138 isl_assert(ctx
, e
->x
.p
->arr
[0].x
.p
->type
== fractional
, goto error
);
139 fract
= &e
->x
.p
->arr
[0];
141 nparam
= isl_set_dim(set
, isl_dim_param
);
142 vec
= isl_vec_alloc(ctx
, 2 + nparam
+ 1);
146 isl_seq_clr(vec
->el
+ 2, nparam
);
147 evalue_extract_affine(&fract
->x
.p
->arr
[0],
148 vec
->el
+ 2, &vec
->el
[1], &vec
->el
[0]);
150 dim
= isl_set_get_dim(set
);
151 dim
= isl_dim_add(dim
, isl_dim_set
, 1);
153 bset
= isl_basic_set_universe(dim
);
154 c
= isl_equality_alloc(isl_dim_copy(dim
));
155 isl_int_neg(vec
->el
[0], vec
->el
[0]);
156 isl_constraint_set_coefficient(c
, isl_dim_set
, 0, vec
->el
[0]);
157 isl_constraint_set_constant(c
, vec
->el
[1]);
158 for (i
= 0; i
< nparam
; ++i
)
159 isl_constraint_set_coefficient(c
, isl_dim_param
, i
, vec
->el
[2+i
]);
160 bset
= isl_basic_set_add_constraint(bset
, c
);
161 bset
= isl_basic_set_project_out(bset
, isl_dim_set
, 0, 1);
162 guard
= isl_set_from_basic_set(bset
);
165 pwqp
= guarded_evalue2pwqp(isl_set_intersect(isl_set_copy(set
),
166 isl_set_copy(guard
)),
169 if (e
->x
.p
->size
== 3) {
170 isl_pw_qpolynomial
*pwqpc
;
171 guard
= isl_set_complement(guard
);
172 pwqpc
= guarded_evalue2pwqp(isl_set_intersect(isl_set_copy(set
),
173 isl_set_copy(guard
)),
175 pwqp
= isl_pw_qpolynomial_add_disjoint(pwqp
, pwqpc
);
187 static __isl_give isl_pw_qpolynomial
*guarded_evalue2pwqp(__isl_take isl_set
*set
,
192 if (value_zero_p(e
->d
) && e
->x
.p
->type
== relation
)
193 return relation2pwqp(set
, e
);
195 qp
= isl_qpolynomial_from_evalue(isl_set_get_dim(set
), e
);
197 return isl_pw_qpolynomial_alloc(set
, qp
);
200 __isl_give isl_pw_qpolynomial
*isl_pw_qpolynomial_from_evalue(__isl_take isl_dim
*dim
, const evalue
*e
)
203 isl_pw_qpolynomial
*pwqp
;
207 if (EVALUE_IS_ZERO(*e
))
208 return isl_pw_qpolynomial_zero(dim
);
210 if (value_notzero_p(e
->d
)) {
211 isl_set
*set
= isl_set_universe(isl_dim_copy(dim
));
212 isl_qpolynomial
*qp
= isl_qpolynomial_rat_cst(dim
, e
->x
.n
, e
->d
);
213 return isl_pw_qpolynomial_alloc(set
, qp
);
216 assert(!EVALUE_IS_NAN(*e
));
218 assert(e
->x
.p
->type
== partition
);
220 pwqp
= isl_pw_qpolynomial_zero(isl_dim_copy(dim
));
222 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
223 Polyhedron
*D
= EVALUE_DOMAIN(e
->x
.p
->arr
[2 * i
]);
224 isl_set
*set
= isl_set_new_from_polylib(D
, isl_dim_copy(dim
));
225 isl_pw_qpolynomial
*pwqp_i
;
227 pwqp_i
= guarded_evalue2pwqp(set
, &e
->x
.p
->arr
[2 * i
+ 1]);
229 pwqp
= isl_pw_qpolynomial_add_disjoint(pwqp
, pwqp_i
);
240 static evalue
*evalue_pow(evalue
*e
, int exp
)
256 static evalue
*div2evalue(__isl_take isl_div
*div
)
268 dim
= isl_div_dim(div
, isl_dim_set
);
269 nparam
= isl_div_dim(div
, isl_dim_param
);
271 vec
= isl_vec_alloc(div
->ctx
, 1 + dim
+ nparam
+ 1);
274 for (i
= 0; i
< dim
; ++i
)
275 isl_div_get_coefficient(div
, isl_dim_set
, i
, &vec
->el
[1 + i
]);
276 for (i
= 0; i
< nparam
; ++i
)
277 isl_div_get_coefficient(div
, isl_dim_param
, i
,
278 &vec
->el
[1 + dim
+ i
]);
279 isl_div_get_denominator(div
, &vec
->el
[0]);
280 isl_div_get_constant(div
, &vec
->el
[1 + dim
+ nparam
]);
282 e
= isl_alloc_type(div
->ctx
, evalue
);
286 value_set_si(e
->d
, 0);
287 e
->x
.p
= new_enode(flooring
, 3, -1);
288 evalue_set_si(&e
->x
.p
->arr
[1], 0, 1);
289 evalue_set_si(&e
->x
.p
->arr
[2], 1, 1);
290 value_clear(e
->x
.p
->arr
[0].d
);
291 aff
= affine2evalue(vec
->el
+ 1, vec
->el
[0], dim
+ nparam
);
292 e
->x
.p
->arr
[0] = *aff
;
303 static int add_term(__isl_take isl_term
*term
, void *user
)
306 evalue
*sum
= (evalue
*)user
;
317 nparam
= isl_term_dim(term
, isl_dim_param
);
318 dim
= isl_term_dim(term
, isl_dim_set
);
319 n_div
= isl_term_dim(term
, isl_dim_div
);
321 ctx
= isl_term_get_ctx(term
);
322 e
= isl_alloc_type(ctx
, evalue
);
329 isl_term_get_num(term
, &n
);
330 isl_term_get_den(term
, &d
);
334 for (i
= 0; i
< dim
; ++i
) {
336 int exp
= isl_term_get_exp(term
, isl_dim_set
, i
);
341 pow
= evalue_pow(evalue_var(i
), exp
);
346 for (i
= 0; i
< nparam
; ++i
) {
348 int exp
= isl_term_get_exp(term
, isl_dim_param
, i
);
353 pow
= evalue_pow(evalue_var(dim
+ i
), exp
);
358 for (i
= 0; i
< n_div
; ++i
) {
362 int exp
= isl_term_get_exp(term
, isl_dim_div
, i
);
367 div
= isl_term_get_div(term
, i
);
368 floor
= div2evalue(div
);
369 pow
= evalue_pow(floor
, exp
);
388 evalue
*isl_qpolynomial_to_evalue(__isl_keep isl_qpolynomial
*qp
)
396 if (isl_qpolynomial_foreach_term(qp
, add_term
, e
) < 0)
405 static int add_guarded_qp(__isl_take isl_set
*set
, __isl_take isl_qpolynomial
*qp
,
411 evalue
*sum
= (evalue
*)user
;
414 e
= isl_alloc_type(isl_set_get_ctx(set
), evalue
);
418 D
= isl_set_to_polylib(set
);
422 f
= isl_qpolynomial_to_evalue(qp
);
428 dim
= isl_set_dim(set
, isl_dim_param
) + isl_set_dim(set
, isl_dim_set
);
430 e
->x
.p
= new_enode(partition
, 2, D
->Dimension
);
431 EVALUE_SET_DOMAIN(e
->x
.p
->arr
[0], D
);
433 value_clear(e
->x
.p
->arr
[1].d
);
441 isl_qpolynomial_free(qp
);
447 isl_qpolynomial_free(qp
);
451 evalue
*isl_pw_qpolynomial_to_evalue(__isl_keep isl_pw_qpolynomial
*pwqp
)
459 if (isl_pw_qpolynomial_foreach_piece(pwqp
, add_guarded_qp
, e
))