3 #include <isl_set_polylib.h>
4 #include <isl/constraint.h>
6 #include <isl/val_gmp.h>
9 #include <isl/polynomial.h>
10 #include <barvinok/polylib.h>
11 #include <barvinok/evalue.h>
13 static __isl_give isl_qpolynomial
*extract_base(__isl_take isl_space
*space
,
22 isl_qpolynomial
*base
, *c
;
28 if (e
->x
.p
->type
== polynomial
)
29 return isl_qpolynomial_var_on_domain(space
,
30 isl_dim_param
, e
->x
.p
->pos
- 1);
32 ctx
= isl_space_get_ctx(space
);
33 nparam
= isl_space_dim(space
, isl_dim_param
);
34 v
= Vector_Alloc(2 + nparam
);
38 for (i
= 0; i
< nparam
; ++i
)
39 value_set_si(v
->p
[2 + i
], 0);
40 evalue_extract_affine(&e
->x
.p
->arr
[0], v
->p
+ 2, &v
->p
[1], &v
->p
[0]);
42 ls
= isl_local_space_from_space(isl_space_copy(space
));
43 aff
= isl_aff_zero_on_domain(ls
);
44 val
= isl_val_int_from_gmp(ctx
, v
->p
[1]);
45 aff
= isl_aff_set_constant_val(aff
, val
);
47 for (i
= 0; i
< nparam
; ++i
) {
48 val
= isl_val_int_from_gmp(ctx
, v
->p
[2 + i
]);
49 aff
= isl_aff_set_coefficient_val(aff
, isl_dim_param
, i
, val
);
52 val
= isl_val_int_from_gmp(ctx
, v
->p
[0]);
53 aff
= isl_aff_scale_down_val(aff
, val
);
55 aff
= isl_aff_floor(aff
);
56 base
= isl_qpolynomial_from_aff(aff
);
58 if (e
->x
.p
->type
== fractional
) {
59 base
= isl_qpolynomial_neg(base
);
61 val
= isl_val_from_gmp(ctx
, v
->p
[1], v
->p
[0]);
62 c
= isl_qpolynomial_val_on_domain(isl_space_copy(space
), val
);
63 base
= isl_qpolynomial_add(base
, c
);
65 for (i
= 0; i
< nparam
; ++i
) {
67 val
= isl_val_from_gmp(ctx
, v
->p
[2 + i
], v
->p
[0]);
68 c
= isl_qpolynomial_val_on_domain(isl_space_copy(space
),
70 t
= isl_qpolynomial_var_on_domain(isl_space_copy(space
),
72 t
= isl_qpolynomial_mul(c
, t
);
73 base
= isl_qpolynomial_add(base
, t
);
78 isl_space_free(space
);
82 isl_space_free(space
);
86 static int type_offset(enode
*p
)
88 return p
->type
== fractional
? 1 :
89 p
->type
== flooring
? 1 : 0;
92 __isl_give isl_qpolynomial
*isl_qpolynomial_from_evalue(
93 __isl_take isl_space
*space
, const evalue
*e
)
97 isl_qpolynomial
*base
;
100 if (EVALUE_IS_NAN(*e
))
101 return isl_qpolynomial_infty_on_domain(space
);
102 if (value_notzero_p(e
->d
)) {
103 isl_ctx
*ctx
= isl_space_get_ctx(space
);
104 isl_val
*val
= isl_val_from_gmp(ctx
, e
->x
.n
, e
->d
);
105 return isl_qpolynomial_val_on_domain(space
, val
);
108 offset
= type_offset(e
->x
.p
);
110 assert(e
->x
.p
->type
== polynomial
||
111 e
->x
.p
->type
== flooring
||
112 e
->x
.p
->type
== fractional
);
113 assert(e
->x
.p
->size
>= 1 + offset
);
115 base
= extract_base(isl_space_copy(space
), e
);
116 qp
= isl_qpolynomial_from_evalue(isl_space_copy(space
),
117 &e
->x
.p
->arr
[e
->x
.p
->size
- 1]);
119 for (i
= e
->x
.p
->size
- 2; i
>= offset
; --i
) {
120 qp
= isl_qpolynomial_mul(qp
, isl_qpolynomial_copy(base
));
121 qp
= isl_qpolynomial_add(qp
,
122 isl_qpolynomial_from_evalue(isl_space_copy(space
),
126 isl_qpolynomial_free(base
);
127 isl_space_free(space
);
132 static __isl_give isl_pw_qpolynomial
*guarded_evalue2pwqp(__isl_take isl_set
*set
,
135 static __isl_give isl_pw_qpolynomial
*relation2pwqp(__isl_take isl_set
*set
,
144 isl_pw_qpolynomial
*pwqp
;
146 struct isl_constraint
*c
;
147 struct isl_basic_set
*bset
;
148 struct isl_set
*guard
;
154 if (e
->x
.p
->size
== 1) {
155 dim
= isl_set_get_space(set
);
157 return isl_pw_qpolynomial_zero(dim
);
160 ctx
= isl_set_get_ctx(set
);
161 isl_assert(ctx
, e
->x
.p
->size
> 0, goto error
);
162 isl_assert(ctx
, e
->x
.p
->size
<= 3, goto error
);
163 isl_assert(ctx
, value_zero_p(e
->x
.p
->arr
[0].d
), goto error
);
164 isl_assert(ctx
, e
->x
.p
->arr
[0].x
.p
->type
== fractional
, goto error
);
165 fract
= &e
->x
.p
->arr
[0];
167 nparam
= isl_set_dim(set
, isl_dim_param
);
168 assert(isl_set_dim(set
, isl_dim_set
) == 0);
169 vec
= Vector_Alloc(2 + nparam
+ 1);
173 for (i
= 0; i
< nparam
; ++i
)
174 value_set_si(vec
->p
[2 + i
], 0);
175 evalue_extract_affine(&fract
->x
.p
->arr
[0],
176 vec
->p
+ 2, &vec
->p
[1], &vec
->p
[0]);
178 dim
= isl_set_get_space(set
);
180 bset
= isl_basic_set_universe(isl_space_copy(dim
));
181 aff
= isl_aff_zero_on_domain(isl_local_space_from_space(dim
));
182 v
= isl_val_int_from_gmp(ctx
, vec
->p
[1]);
183 aff
= isl_aff_set_constant_val(aff
, v
);
184 for (i
= 0; i
< nparam
; ++i
) {
185 v
= isl_val_int_from_gmp(ctx
, vec
->p
[2 + i
]);
186 aff
= isl_aff_set_coefficient_val(aff
, isl_dim_param
, i
, v
);
188 v
= isl_val_int_from_gmp(ctx
, vec
->p
[0]);
189 aff
= isl_aff_mod_val(aff
, v
);
190 c
= isl_equality_from_aff(aff
);
191 bset
= isl_basic_set_add_constraint(bset
, c
);
192 guard
= isl_set_from_basic_set(bset
);
195 pwqp
= guarded_evalue2pwqp(isl_set_intersect(isl_set_copy(set
),
196 isl_set_copy(guard
)),
199 if (e
->x
.p
->size
== 3) {
200 isl_pw_qpolynomial
*pwqpc
;
201 guard
= isl_set_complement(guard
);
202 pwqpc
= guarded_evalue2pwqp(isl_set_intersect(isl_set_copy(set
),
203 isl_set_copy(guard
)),
205 pwqp
= isl_pw_qpolynomial_add_disjoint(pwqp
, pwqpc
);
217 static __isl_give isl_pw_qpolynomial
*guarded_evalue2pwqp(__isl_take isl_set
*set
,
222 if (value_zero_p(e
->d
) && e
->x
.p
->type
== relation
)
223 return relation2pwqp(set
, e
);
225 qp
= isl_qpolynomial_from_evalue(isl_set_get_space(set
), e
);
227 return isl_pw_qpolynomial_alloc(set
, qp
);
230 __isl_give isl_pw_qpolynomial
*isl_pw_qpolynomial_from_evalue(
231 __isl_take isl_space
*space
, const evalue
*e
)
235 isl_pw_qpolynomial
*pwqp
;
239 if (EVALUE_IS_ZERO(*e
)) {
240 space
= isl_space_from_domain(space
);
241 space
= isl_space_add_dims(space
, isl_dim_out
, 1);
242 return isl_pw_qpolynomial_zero(space
);
245 if (value_notzero_p(e
->d
)) {
246 isl_ctx
*ctx
= isl_space_get_ctx(space
);
247 isl_set
*set
= isl_set_universe(isl_space_copy(space
));
248 isl_val
*val
= isl_val_from_gmp(ctx
, e
->x
.n
, e
->d
);
249 isl_qpolynomial
*qp
= isl_qpolynomial_val_on_domain(space
, val
);
250 return isl_pw_qpolynomial_alloc(set
, qp
);
253 assert(!EVALUE_IS_NAN(*e
));
255 assert(e
->x
.p
->type
== partition
);
257 pw_space
= isl_space_copy(space
);
258 pw_space
= isl_space_from_domain(pw_space
);
259 pw_space
= isl_space_add_dims(pw_space
, isl_dim_out
, 1);
260 pwqp
= isl_pw_qpolynomial_zero(pw_space
);
262 for (i
= 0; i
< e
->x
.p
->size
/2; ++i
) {
263 Polyhedron
*D
= EVALUE_DOMAIN(e
->x
.p
->arr
[2 * i
]);
265 isl_pw_qpolynomial
*pwqp_i
;
267 set
= isl_set_new_from_polylib(D
, isl_space_copy(space
));
268 pwqp_i
= guarded_evalue2pwqp(set
, &e
->x
.p
->arr
[2 * i
+ 1]);
270 pwqp
= isl_pw_qpolynomial_add_disjoint(pwqp
, pwqp_i
);
273 isl_space_free(space
);
277 isl_space_free(space
);
281 static evalue
*evalue_pow(evalue
*e
, int exp
)
297 static evalue
*div2evalue(__isl_take isl_aff
*div
)
311 if (isl_aff_dim(div
, isl_dim_div
) != 0)
312 isl_die(isl_aff_get_ctx(div
), isl_error_unsupported
,
313 "cannot handle nested divs", goto error
);
315 dim
= isl_aff_dim(div
, isl_dim_in
);
316 nparam
= isl_aff_dim(div
, isl_dim_param
);
318 ctx
= isl_aff_get_ctx(div
);
319 vec
= Vector_Alloc(1 + dim
+ nparam
+ 1);
322 v
= isl_aff_get_denominator_val(div
);
323 isl_val_get_num_gmp(v
, vec
->p
[0]);
324 div
= isl_aff_scale_val(div
, v
);
325 for (i
= 0; i
< dim
; ++i
) {
326 v
= isl_aff_get_coefficient_val(div
, isl_dim_in
, i
);
327 isl_val_get_num_gmp(v
, vec
->p
[1 + i
]);
330 for (i
= 0; i
< nparam
; ++i
) {
331 v
= isl_aff_get_coefficient_val(div
, isl_dim_param
, i
);
332 isl_val_get_num_gmp(v
, vec
->p
[1 + dim
+ i
]);
335 v
= isl_aff_get_constant_val(div
);
336 isl_val_get_num_gmp(v
, vec
->p
[1 + dim
+ nparam
]);
339 e
= isl_alloc_type(ctx
, evalue
);
343 value_set_si(e
->d
, 0);
344 e
->x
.p
= new_enode(flooring
, 3, -1);
345 evalue_set_si(&e
->x
.p
->arr
[1], 0, 1);
346 evalue_set_si(&e
->x
.p
->arr
[2], 1, 1);
347 value_clear(e
->x
.p
->arr
[0].d
);
348 aff
= affine2evalue(vec
->p
+ 1, vec
->p
[0], dim
+ nparam
);
349 e
->x
.p
->arr
[0] = *aff
;
360 static isl_stat
add_term(__isl_take isl_term
*term
, void *user
)
363 evalue
*sum
= (evalue
*)user
;
373 return isl_stat_error
;
375 nparam
= isl_term_dim(term
, isl_dim_param
);
376 dim
= isl_term_dim(term
, isl_dim_set
);
377 n_div
= isl_term_dim(term
, isl_dim_div
);
379 ctx
= isl_term_get_ctx(term
);
380 e
= isl_alloc_type(ctx
, evalue
);
387 v
= isl_term_get_coefficient_val(term
);
388 isl_val_get_num_gmp(v
, n
);
389 isl_val_get_den_gmp(v
, d
);
396 for (i
= 0; i
< dim
; ++i
) {
398 int exp
= isl_term_get_exp(term
, isl_dim_set
, i
);
403 pow
= evalue_pow(evalue_var(i
), exp
);
408 for (i
= 0; i
< nparam
; ++i
) {
410 int exp
= isl_term_get_exp(term
, isl_dim_param
, i
);
415 pow
= evalue_pow(evalue_var(dim
+ i
), exp
);
420 for (i
= 0; i
< n_div
; ++i
) {
424 int exp
= isl_term_get_exp(term
, isl_dim_div
, i
);
429 div
= isl_term_get_div(term
, i
);
430 floor
= div2evalue(div
);
433 pow
= evalue_pow(floor
, exp
);
453 return isl_stat_error
;
456 evalue
*isl_qpolynomial_to_evalue(__isl_keep isl_qpolynomial
*qp
)
464 if (isl_qpolynomial_foreach_term(qp
, add_term
, e
) < 0)
473 static isl_stat
add_guarded_qp(__isl_take isl_set
*set
,
474 __isl_take isl_qpolynomial
*qp
, void *user
)
479 evalue
*sum
= (evalue
*)user
;
481 e
= isl_alloc_type(isl_set_get_ctx(set
), evalue
);
485 D
= isl_set_to_polylib(set
);
489 f
= isl_qpolynomial_to_evalue(qp
);
496 e
->x
.p
= new_enode(partition
, 2, D
->Dimension
);
497 EVALUE_SET_DOMAIN(e
->x
.p
->arr
[0], D
);
499 value_clear(e
->x
.p
->arr
[1].d
);
507 isl_qpolynomial_free(qp
);
513 isl_qpolynomial_free(qp
);
514 return isl_stat_error
;
517 evalue
*isl_pw_qpolynomial_to_evalue(__isl_keep isl_pw_qpolynomial
*pwqp
)
525 if (isl_pw_qpolynomial_foreach_piece(pwqp
, add_guarded_qp
, e
))