2 #include <isl_set_polylib.h>
3 #include <isl/constraint.h>
4 #include <isl/val_gmp.h>
5 #include <barvinok/evalue.h>
7 static __isl_give isl_qpolynomial
*extract_base(__isl_take isl_space
*dim
,
15 isl_qpolynomial
*base
, *c
;
21 if (e
->x
.p
->type
== polynomial
)
22 return isl_qpolynomial_var_on_domain(dim
, isl_dim_param
, e
->x
.p
->pos
- 1);
24 ctx
= isl_space_get_ctx(dim
);
25 nparam
= isl_space_dim(dim
, isl_dim_param
);
26 v
= Vector_Alloc(2 + nparam
);
30 for (i
= 0; i
< nparam
; ++i
)
31 value_set_si(v
->p
[2 + i
], 0);
32 evalue_extract_affine(&e
->x
.p
->arr
[0], v
->p
+ 2, &v
->p
[1], &v
->p
[0]);
34 ls
= isl_local_space_from_space(isl_space_copy(dim
));
35 aff
= isl_aff_zero_on_domain(ls
);
36 aff
= isl_aff_set_constant(aff
, v
->p
[1]);
37 aff
= isl_aff_set_denominator(aff
, v
->p
[0]);
39 for (i
= 0; i
< nparam
; ++i
)
40 aff
= isl_aff_set_coefficient(aff
, isl_dim_param
, i
,
43 aff
= isl_aff_floor(aff
);
44 base
= isl_qpolynomial_from_aff(aff
);
46 if (e
->x
.p
->type
== fractional
) {
47 base
= isl_qpolynomial_neg(base
);
49 c
= isl_qpolynomial_rat_cst_on_domain(isl_space_copy(dim
), v
->p
[1], v
->p
[0]);
50 base
= isl_qpolynomial_add(base
, c
);
52 for (i
= 0; i
< nparam
; ++i
) {
54 c
= isl_qpolynomial_rat_cst_on_domain(isl_space_copy(dim
),
55 v
->p
[2 + i
], v
->p
[0]);
56 t
= isl_qpolynomial_var_on_domain(isl_space_copy(dim
),
58 t
= isl_qpolynomial_mul(c
, t
);
59 base
= isl_qpolynomial_add(base
, t
);
72 static int type_offset(enode
*p
)
74 return p
->type
== fractional
? 1 :
75 p
->type
== flooring
? 1 : 0;
78 __isl_give isl_qpolynomial
*isl_qpolynomial_from_evalue(__isl_take isl_space
*dim
,
83 isl_qpolynomial
*base
;
86 if (EVALUE_IS_NAN(*e
))
87 return isl_qpolynomial_infty_on_domain(dim
);
88 if (value_notzero_p(e
->d
))
89 return isl_qpolynomial_rat_cst_on_domain(dim
, e
->x
.n
, e
->d
);
91 offset
= type_offset(e
->x
.p
);
93 assert(e
->x
.p
->type
== polynomial
||
94 e
->x
.p
->type
== flooring
||
95 e
->x
.p
->type
== fractional
);
96 assert(e
->x
.p
->size
>= 1 + offset
);
98 base
= extract_base(isl_space_copy(dim
), e
);
99 qp
= isl_qpolynomial_from_evalue(isl_space_copy(dim
),
100 &e
->x
.p
->arr
[e
->x
.p
->size
- 1]);
102 for (i
= e
->x
.p
->size
- 2; i
>= offset
; --i
) {
103 qp
= isl_qpolynomial_mul(qp
, isl_qpolynomial_copy(base
));
104 qp
= isl_qpolynomial_add(qp
,
105 isl_qpolynomial_from_evalue(isl_space_copy(dim
),
109 isl_qpolynomial_free(base
);
115 static __isl_give isl_pw_qpolynomial
*guarded_evalue2pwqp(__isl_take isl_set
*set
,
118 static __isl_give isl_pw_qpolynomial
*relation2pwqp(__isl_take isl_set
*set
,
127 isl_pw_qpolynomial
*pwqp
;
128 struct isl_constraint
*c
;
129 struct isl_basic_set
*bset
;
130 struct isl_set
*guard
;
136 if (e
->x
.p
->size
== 1) {
137 dim
= isl_set_get_space(set
);
139 return isl_pw_qpolynomial_zero(dim
);
142 ctx
= isl_set_get_ctx(set
);
143 isl_assert(ctx
, e
->x
.p
->size
> 0, goto error
);
144 isl_assert(ctx
, e
->x
.p
->size
<= 3, goto error
);
145 isl_assert(ctx
, value_zero_p(e
->x
.p
->arr
[0].d
), goto error
);
146 isl_assert(ctx
, e
->x
.p
->arr
[0].x
.p
->type
== fractional
, goto error
);
147 fract
= &e
->x
.p
->arr
[0];
149 nparam
= isl_set_dim(set
, isl_dim_param
);
150 vec
= Vector_Alloc(2 + nparam
+ 1);
154 for (i
= 0; i
< nparam
; ++i
)
155 value_set_si(vec
->p
[2 + i
], 0);
156 evalue_extract_affine(&fract
->x
.p
->arr
[0],
157 vec
->p
+ 2, &vec
->p
[1], &vec
->p
[0]);
159 dim
= isl_set_get_space(set
);
160 dim
= isl_space_add_dims(dim
, isl_dim_set
, 1);
162 bset
= isl_basic_set_universe(isl_space_copy(dim
));
163 c
= isl_equality_alloc(isl_local_space_from_space(dim
));
164 v
= isl_val_int_from_gmp(ctx
, vec
->p
[0]);
166 c
= isl_constraint_set_coefficient_val(c
, isl_dim_set
, 0, v
);
167 v
= isl_val_int_from_gmp(ctx
, vec
->p
[1]);
168 c
= isl_constraint_set_constant_val(c
, v
);
169 for (i
= 0; i
< nparam
; ++i
) {
170 v
= isl_val_int_from_gmp(ctx
, vec
->p
[2 + i
]);
171 c
= isl_constraint_set_coefficient_val(c
, isl_dim_param
, i
, v
);
173 bset
= isl_basic_set_add_constraint(bset
, c
);
174 bset
= isl_basic_set_params(bset
);
175 guard
= isl_set_from_basic_set(bset
);
178 pwqp
= guarded_evalue2pwqp(isl_set_intersect(isl_set_copy(set
),
179 isl_set_copy(guard
)),
182 if (e
->x
.p
->size
== 3) {
183 isl_pw_qpolynomial
*pwqpc
;
184 guard
= isl_set_complement(guard
);
185 pwqpc
= guarded_evalue2pwqp(isl_set_intersect(isl_set_copy(set
),
186 isl_set_copy(guard
)),
188 pwqp
= isl_pw_qpolynomial_add_disjoint(pwqp
, pwqpc
);
200 static __isl_give isl_pw_qpolynomial
*guarded_evalue2pwqp(__isl_take isl_set
*set
,
205 if (value_zero_p(e
->d
) && e
->x
.p
->type
== relation
)
206 return relation2pwqp(set
, e
);
208 qp
= isl_qpolynomial_from_evalue(isl_set_get_space(set
), e
);
210 return isl_pw_qpolynomial_alloc(set
, qp
);
213 __isl_give isl_pw_qpolynomial
*isl_pw_qpolynomial_from_evalue(__isl_take isl_space
*dim
, const evalue
*e
)
217 isl_pw_qpolynomial
*pwqp
;
221 if (EVALUE_IS_ZERO(*e
)) {
222 dim
= isl_space_from_domain(dim
);
223 dim
= isl_space_add_dims(dim
, isl_dim_out
, 1);
224 return isl_pw_qpolynomial_zero(dim
);
227 if (value_notzero_p(e
->d
)) {
228 isl_set
*set
= isl_set_universe(isl_space_copy(dim
));
229 isl_qpolynomial
*qp
= isl_qpolynomial_rat_cst_on_domain(dim
, e
->x
.n
, e
->d
);
230 return isl_pw_qpolynomial_alloc(set
, qp
);
233 assert(!EVALUE_IS_NAN(*e
));
235 assert(e
->x
.p
->type
== partition
);
237 pw_space
= isl_space_copy(dim
);
238 pw_space
= isl_space_from_domain(pw_space
);
239 pw_space
= isl_space_add_dims(pw_space
, isl_dim_out
, 1);
240 pwqp
= isl_pw_qpolynomial_zero(pw_space
);
242 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
243 Polyhedron
*D
= EVALUE_DOMAIN(e
->x
.p
->arr
[2 * i
]);
244 isl_set
*set
= isl_set_new_from_polylib(D
, isl_space_copy(dim
));
245 isl_pw_qpolynomial
*pwqp_i
;
247 pwqp_i
= guarded_evalue2pwqp(set
, &e
->x
.p
->arr
[2 * i
+ 1]);
249 pwqp
= isl_pw_qpolynomial_add_disjoint(pwqp
, pwqp_i
);
260 static evalue
*evalue_pow(evalue
*e
, int exp
)
276 static evalue
*div2evalue(__isl_take isl_aff
*div
)
289 if (isl_aff_dim(div
, isl_dim_div
) != 0)
290 isl_die(isl_aff_get_ctx(div
), isl_error_unsupported
,
291 "cannot handle nested divs", goto error
);
293 dim
= isl_aff_dim(div
, isl_dim_in
);
294 nparam
= isl_aff_dim(div
, isl_dim_param
);
296 ctx
= isl_aff_get_ctx(div
);
297 vec
= Vector_Alloc(1 + dim
+ nparam
+ 1);
300 for (i
= 0; i
< dim
; ++i
)
301 isl_aff_get_coefficient(div
, isl_dim_in
, i
, &vec
->p
[1 + i
]);
302 for (i
= 0; i
< nparam
; ++i
)
303 isl_aff_get_coefficient(div
, isl_dim_param
, i
,
304 &vec
->p
[1 + dim
+ i
]);
305 isl_aff_get_denominator(div
, &vec
->p
[0]);
306 isl_aff_get_constant(div
, &vec
->p
[1 + dim
+ nparam
]);
308 e
= isl_alloc_type(ctx
, evalue
);
312 value_set_si(e
->d
, 0);
313 e
->x
.p
= new_enode(flooring
, 3, -1);
314 evalue_set_si(&e
->x
.p
->arr
[1], 0, 1);
315 evalue_set_si(&e
->x
.p
->arr
[2], 1, 1);
316 value_clear(e
->x
.p
->arr
[0].d
);
317 aff
= affine2evalue(vec
->p
+ 1, vec
->p
[0], dim
+ nparam
);
318 e
->x
.p
->arr
[0] = *aff
;
329 static int add_term(__isl_take isl_term
*term
, void *user
)
332 evalue
*sum
= (evalue
*)user
;
344 nparam
= isl_term_dim(term
, isl_dim_param
);
345 dim
= isl_term_dim(term
, isl_dim_set
);
346 n_div
= isl_term_dim(term
, isl_dim_div
);
348 ctx
= isl_term_get_ctx(term
);
349 e
= isl_alloc_type(ctx
, evalue
);
356 v
= isl_term_get_coefficient_val(term
);
357 isl_val_get_num_gmp(v
, n
);
358 isl_val_get_den_gmp(v
, d
);
365 for (i
= 0; i
< dim
; ++i
) {
367 int exp
= isl_term_get_exp(term
, isl_dim_set
, i
);
372 pow
= evalue_pow(evalue_var(i
), exp
);
377 for (i
= 0; i
< nparam
; ++i
) {
379 int exp
= isl_term_get_exp(term
, isl_dim_param
, i
);
384 pow
= evalue_pow(evalue_var(dim
+ i
), exp
);
389 for (i
= 0; i
< n_div
; ++i
) {
393 int exp
= isl_term_get_exp(term
, isl_dim_div
, i
);
398 div
= isl_term_get_div(term
, i
);
399 floor
= div2evalue(div
);
402 pow
= evalue_pow(floor
, exp
);
425 evalue
*isl_qpolynomial_to_evalue(__isl_keep isl_qpolynomial
*qp
)
433 if (isl_qpolynomial_foreach_term(qp
, add_term
, e
) < 0)
442 static int add_guarded_qp(__isl_take isl_set
*set
, __isl_take isl_qpolynomial
*qp
,
448 evalue
*sum
= (evalue
*)user
;
451 e
= isl_alloc_type(isl_set_get_ctx(set
), evalue
);
455 D
= isl_set_to_polylib(set
);
459 f
= isl_qpolynomial_to_evalue(qp
);
465 dim
= isl_set_dim(set
, isl_dim_param
) + isl_set_dim(set
, isl_dim_set
);
467 e
->x
.p
= new_enode(partition
, 2, D
->Dimension
);
468 EVALUE_SET_DOMAIN(e
->x
.p
->arr
[0], D
);
470 value_clear(e
->x
.p
->arr
[1].d
);
478 isl_qpolynomial_free(qp
);
484 isl_qpolynomial_free(qp
);
488 evalue
*isl_pw_qpolynomial_to_evalue(__isl_keep isl_pw_qpolynomial
*pwqp
)
496 if (isl_pw_qpolynomial_foreach_piece(pwqp
, add_guarded_qp
, e
))