3 #define xFN(TYPE,NAME) TYPE ## _ ## NAME
4 #define FN(TYPE,NAME) xFN(TYPE,NAME)
5 #define xS(TYPE,NAME) struct TYPE ## _ ## NAME
6 #define S(TYPE,NAME) xS(TYPE,NAME)
9 __isl_give PW
*FN(PW
,alloc_size
)(__isl_take isl_space
*dim
,
10 enum isl_fold type
, int n
)
12 __isl_give PW
*FN(PW
,alloc_size
)(__isl_take isl_space
*dim
, int n
)
20 ctx
= isl_space_get_ctx(dim
);
21 isl_assert(ctx
, n
>= 0, goto error
);
22 pw
= isl_alloc(ctx
, struct PW
,
23 sizeof(struct PW
) + (n
- 1) * sizeof(S(PW
,piece
)));
41 __isl_give PW
*FN(PW
,ZERO
)(__isl_take isl_space
*dim
, enum isl_fold type
)
43 return FN(PW
,alloc_size
)(dim
, type
, 0);
46 __isl_give PW
*FN(PW
,ZERO
)(__isl_take isl_space
*dim
)
48 return FN(PW
,alloc_size
)(dim
, 0);
52 __isl_give PW
*FN(PW
,add_piece
)(__isl_take PW
*pw
,
53 __isl_take isl_set
*set
, __isl_take EL
*el
)
56 isl_space
*el_dim
= NULL
;
58 if (!pw
|| !set
|| !el
)
61 if (isl_set_plain_is_empty(set
) || FN(EL
,EL_IS_ZERO
)(el
)) {
67 ctx
= isl_set_get_ctx(set
);
69 if (pw
->type
!= el
->type
)
70 isl_die(ctx
, isl_error_invalid
, "fold types don't match",
73 el_dim
= FN(EL
,get_space(el
));
74 isl_assert(ctx
, isl_space_is_equal(pw
->dim
, el_dim
), goto error
);
75 isl_assert(ctx
, pw
->n
< pw
->size
, goto error
);
77 pw
->p
[pw
->n
].set
= set
;
78 pw
->p
[pw
->n
].FIELD
= el
;
81 isl_space_free(el_dim
);
84 isl_space_free(el_dim
);
92 __isl_give PW
*FN(PW
,alloc
)(enum isl_fold type
,
93 __isl_take isl_set
*set
, __isl_take EL
*el
)
95 __isl_give PW
*FN(PW
,alloc
)(__isl_take isl_set
*set
, __isl_take EL
*el
)
104 pw
= FN(PW
,alloc_size
)(FN(EL
,get_space
)(el
), type
, 1);
106 pw
= FN(PW
,alloc_size
)(FN(EL
,get_space
)(el
), 1);
109 return FN(PW
,add_piece
)(pw
, set
, el
);
116 __isl_give PW
*FN(PW
,dup
)(__isl_keep PW
*pw
)
125 dup
= FN(PW
,alloc_size
)(isl_space_copy(pw
->dim
), pw
->type
, pw
->n
);
127 dup
= FN(PW
,alloc_size
)(isl_space_copy(pw
->dim
), pw
->n
);
132 for (i
= 0; i
< pw
->n
; ++i
)
133 dup
= FN(PW
,add_piece
)(dup
, isl_set_copy(pw
->p
[i
].set
),
134 FN(EL
,copy
)(pw
->p
[i
].FIELD
));
139 __isl_give PW
*FN(PW
,cow
)(__isl_take PW
*pw
)
147 return FN(PW
,dup
)(pw
);
150 __isl_give PW
*FN(PW
,copy
)(__isl_keep PW
*pw
)
159 void *FN(PW
,free
)(__isl_take PW
*pw
)
168 for (i
= 0; i
< pw
->n
; ++i
) {
169 isl_set_free(pw
->p
[i
].set
);
170 FN(EL
,free
)(pw
->p
[i
].FIELD
);
172 isl_space_free(pw
->dim
);
178 const char *FN(PW
,get_dim_name
)(__isl_keep PW
*pw
, enum isl_dim_type type
,
181 return pw
? isl_space_get_dim_name(pw
->dim
, type
, pos
) : NULL
;
184 int FN(PW
,has_dim_id
)(__isl_keep PW
*pw
, enum isl_dim_type type
, unsigned pos
)
186 return pw
? isl_space_has_dim_id(pw
->dim
, type
, pos
) : -1;
189 __isl_give isl_id
*FN(PW
,get_dim_id
)(__isl_keep PW
*pw
, enum isl_dim_type type
,
192 return pw
? isl_space_get_dim_id(pw
->dim
, type
, pos
) : NULL
;
195 int FN(PW
,has_tuple_name
)(__isl_keep PW
*pw
, enum isl_dim_type type
)
197 return pw
? isl_space_has_tuple_name(pw
->dim
, type
) : -1;
200 const char *FN(PW
,get_tuple_name
)(__isl_keep PW
*pw
, enum isl_dim_type type
)
202 return pw
? isl_space_get_tuple_name(pw
->dim
, type
) : NULL
;
205 int FN(PW
,has_tuple_id
)(__isl_keep PW
*pw
, enum isl_dim_type type
)
207 return pw
? isl_space_has_tuple_id(pw
->dim
, type
) : -1;
210 __isl_give isl_id
*FN(PW
,get_tuple_id
)(__isl_keep PW
*pw
, enum isl_dim_type type
)
212 return pw
? isl_space_get_tuple_id(pw
->dim
, type
) : NULL
;
215 int FN(PW
,IS_ZERO
)(__isl_keep PW
*pw
)
224 __isl_give PW
*FN(PW
,realign_domain
)(__isl_take PW
*pw
,
225 __isl_take isl_reordering
*exp
)
233 for (i
= 0; i
< pw
->n
; ++i
) {
234 pw
->p
[i
].set
= isl_set_realign(pw
->p
[i
].set
,
235 isl_reordering_copy(exp
));
238 pw
->p
[i
].FIELD
= FN(EL
,realign_domain
)(pw
->p
[i
].FIELD
,
239 isl_reordering_copy(exp
));
244 pw
= FN(PW
,reset_domain_space
)(pw
, isl_space_copy(exp
->dim
));
246 isl_reordering_free(exp
);
249 isl_reordering_free(exp
);
254 /* Align the parameters of "pw" to those of "model".
256 __isl_give PW
*FN(PW
,align_params
)(__isl_take PW
*pw
, __isl_take isl_space
*model
)
263 ctx
= isl_space_get_ctx(model
);
264 if (!isl_space_has_named_params(model
))
265 isl_die(ctx
, isl_error_invalid
,
266 "model has unnamed parameters", goto error
);
267 if (!isl_space_has_named_params(pw
->dim
))
268 isl_die(ctx
, isl_error_invalid
,
269 "input has unnamed parameters", goto error
);
270 if (!isl_space_match(pw
->dim
, isl_dim_param
, model
, isl_dim_param
)) {
273 model
= isl_space_drop_dims(model
, isl_dim_in
,
274 0, isl_space_dim(model
, isl_dim_in
));
275 model
= isl_space_drop_dims(model
, isl_dim_out
,
276 0, isl_space_dim(model
, isl_dim_out
));
277 exp
= isl_parameter_alignment_reordering(pw
->dim
, model
);
278 exp
= isl_reordering_extend_space(exp
,
279 FN(PW
,get_domain_space
)(pw
));
280 pw
= FN(PW
,realign_domain
)(pw
, exp
);
283 isl_space_free(model
);
286 isl_space_free(model
);
291 static __isl_give PW
*FN(PW
,align_params_pw_pw_and
)(__isl_take PW
*pw1
,
293 __isl_give PW
*(*fn
)(__isl_take PW
*pw1
, __isl_take PW
*pw2
))
299 if (isl_space_match(pw1
->dim
, isl_dim_param
, pw2
->dim
, isl_dim_param
))
301 ctx
= FN(PW
,get_ctx
)(pw1
);
302 if (!isl_space_has_named_params(pw1
->dim
) ||
303 !isl_space_has_named_params(pw2
->dim
))
304 isl_die(ctx
, isl_error_invalid
,
305 "unaligned unnamed parameters", goto error
);
306 pw1
= FN(PW
,align_params
)(pw1
, FN(PW
,get_space
)(pw2
));
307 pw2
= FN(PW
,align_params
)(pw2
, FN(PW
,get_space
)(pw1
));
315 static __isl_give PW
*FN(PW
,align_params_pw_set_and
)(__isl_take PW
*pw
,
316 __isl_take isl_set
*set
,
317 __isl_give PW
*(*fn
)(__isl_take PW
*pw
, __isl_take isl_set
*set
))
323 if (isl_space_match(pw
->dim
, isl_dim_param
, set
->dim
, isl_dim_param
))
325 ctx
= FN(PW
,get_ctx
)(pw
);
326 if (!isl_space_has_named_params(pw
->dim
) ||
327 !isl_space_has_named_params(set
->dim
))
328 isl_die(ctx
, isl_error_invalid
,
329 "unaligned unnamed parameters", goto error
);
330 pw
= FN(PW
,align_params
)(pw
, isl_set_get_space(set
));
331 set
= isl_set_align_params(set
, FN(PW
,get_space
)(pw
));
340 static __isl_give PW
*FN(PW
,union_add_aligned
)(__isl_take PW
*pw1
,
351 ctx
= isl_space_get_ctx(pw1
->dim
);
353 if (pw1
->type
!= pw2
->type
)
354 isl_die(ctx
, isl_error_invalid
,
355 "fold types don't match", goto error
);
357 isl_assert(ctx
, isl_space_is_equal(pw1
->dim
, pw2
->dim
), goto error
);
359 if (FN(PW
,IS_ZERO
)(pw1
)) {
364 if (FN(PW
,IS_ZERO
)(pw2
)) {
369 n
= (pw1
->n
+ 1) * (pw2
->n
+ 1);
371 res
= FN(PW
,alloc_size
)(isl_space_copy(pw1
->dim
), pw1
->type
, n
);
373 res
= FN(PW
,alloc_size
)(isl_space_copy(pw1
->dim
), n
);
376 for (i
= 0; i
< pw1
->n
; ++i
) {
377 set
= isl_set_copy(pw1
->p
[i
].set
);
378 for (j
= 0; j
< pw2
->n
; ++j
) {
379 struct isl_set
*common
;
381 common
= isl_set_intersect(isl_set_copy(pw1
->p
[i
].set
),
382 isl_set_copy(pw2
->p
[j
].set
));
383 if (isl_set_plain_is_empty(common
)) {
384 isl_set_free(common
);
387 set
= isl_set_subtract(set
,
388 isl_set_copy(pw2
->p
[j
].set
));
390 sum
= FN(EL
,add_on_domain
)(common
,
391 FN(EL
,copy
)(pw1
->p
[i
].FIELD
),
392 FN(EL
,copy
)(pw2
->p
[j
].FIELD
));
394 res
= FN(PW
,add_piece
)(res
, common
, sum
);
396 res
= FN(PW
,add_piece
)(res
, set
, FN(EL
,copy
)(pw1
->p
[i
].FIELD
));
399 for (j
= 0; j
< pw2
->n
; ++j
) {
400 set
= isl_set_copy(pw2
->p
[j
].set
);
401 for (i
= 0; i
< pw1
->n
; ++i
)
402 set
= isl_set_subtract(set
,
403 isl_set_copy(pw1
->p
[i
].set
));
404 res
= FN(PW
,add_piece
)(res
, set
, FN(EL
,copy
)(pw2
->p
[j
].FIELD
));
417 /* Private version of "union_add". For isl_pw_qpolynomial and
418 * isl_pw_qpolynomial_fold, we prefer to simply call it "add".
420 static __isl_give PW
*FN(PW
,union_add_
)(__isl_take PW
*pw1
, __isl_take PW
*pw2
)
422 return FN(PW
,align_params_pw_pw_and
)(pw1
, pw2
,
423 &FN(PW
,union_add_aligned
));
426 /* Make sure "pw" has room for at least "n" more pieces.
428 * If there is only one reference to pw, we extend it in place.
429 * Otherwise, we create a new PW and copy the pieces.
431 static __isl_give PW
*FN(PW
,grow
)(__isl_take PW
*pw
, int n
)
439 if (pw
->n
+ n
<= pw
->size
)
441 ctx
= FN(PW
,get_ctx
)(pw
);
444 res
= isl_realloc(ctx
, pw
, struct PW
,
445 sizeof(struct PW
) + (n
- 1) * sizeof(S(PW
,piece
)));
447 return FN(PW
,free
)(pw
);
452 res
= FN(PW
,alloc_size
)(isl_space_copy(pw
->dim
), pw
->type
, n
);
454 res
= FN(PW
,alloc_size
)(isl_space_copy(pw
->dim
), n
);
457 return FN(PW
,free
)(pw
);
458 for (i
= 0; i
< pw
->n
; ++i
)
459 res
= FN(PW
,add_piece
)(res
, isl_set_copy(pw
->p
[i
].set
),
460 FN(EL
,copy
)(pw
->p
[i
].FIELD
));
465 static __isl_give PW
*FN(PW
,add_disjoint_aligned
)(__isl_take PW
*pw1
,
474 if (pw1
->size
< pw1
->n
+ pw2
->n
&& pw1
->n
< pw2
->n
)
475 return FN(PW
,add_disjoint_aligned
)(pw2
, pw1
);
477 ctx
= isl_space_get_ctx(pw1
->dim
);
479 if (pw1
->type
!= pw2
->type
)
480 isl_die(ctx
, isl_error_invalid
,
481 "fold types don't match", goto error
);
483 isl_assert(ctx
, isl_space_is_equal(pw1
->dim
, pw2
->dim
), goto error
);
485 if (FN(PW
,IS_ZERO
)(pw1
)) {
490 if (FN(PW
,IS_ZERO
)(pw2
)) {
495 pw1
= FN(PW
,grow
)(pw1
, pw2
->n
);
499 for (i
= 0; i
< pw2
->n
; ++i
)
500 pw1
= FN(PW
,add_piece
)(pw1
,
501 isl_set_copy(pw2
->p
[i
].set
),
502 FN(EL
,copy
)(pw2
->p
[i
].FIELD
));
513 __isl_give PW
*FN(PW
,add_disjoint
)(__isl_take PW
*pw1
, __isl_take PW
*pw2
)
515 return FN(PW
,align_params_pw_pw_and
)(pw1
, pw2
,
516 &FN(PW
,add_disjoint_aligned
));
519 /* This function is currently only used from isl_aff.c
521 static __isl_give PW
*FN(PW
,on_shared_domain_in
)(__isl_take PW
*pw1
,
522 __isl_take PW
*pw2
, __isl_take isl_space
*space
,
523 __isl_give EL
*(*fn
)(__isl_take EL
*el1
, __isl_take EL
*el2
))
524 __attribute__ ((unused
));
526 /* Apply "fn" to pairs of elements from pw1 and pw2 on shared domains.
527 * The result of "fn" (and therefore also of this function) lives in "space".
529 static __isl_give PW
*FN(PW
,on_shared_domain_in
)(__isl_take PW
*pw1
,
530 __isl_take PW
*pw2
, __isl_take isl_space
*space
,
531 __isl_give EL
*(*fn
)(__isl_take EL
*el1
, __isl_take EL
*el2
))
541 res
= FN(PW
,alloc_size
)(isl_space_copy(space
), pw1
->type
, n
);
543 res
= FN(PW
,alloc_size
)(isl_space_copy(space
), n
);
546 for (i
= 0; i
< pw1
->n
; ++i
) {
547 for (j
= 0; j
< pw2
->n
; ++j
) {
552 common
= isl_set_intersect(
553 isl_set_copy(pw1
->p
[i
].set
),
554 isl_set_copy(pw2
->p
[j
].set
));
555 empty
= isl_set_plain_is_empty(common
);
556 if (empty
< 0 || empty
) {
557 isl_set_free(common
);
563 res_ij
= fn(FN(EL
,copy
)(pw1
->p
[i
].FIELD
),
564 FN(EL
,copy
)(pw2
->p
[j
].FIELD
));
565 res_ij
= FN(EL
,gist
)(res_ij
, isl_set_copy(common
));
567 res
= FN(PW
,add_piece
)(res
, common
, res_ij
);
571 isl_space_free(space
);
576 isl_space_free(space
);
583 /* This function is currently only used from isl_aff.c
585 static __isl_give PW
*FN(PW
,on_shared_domain
)(__isl_take PW
*pw1
,
587 __isl_give EL
*(*fn
)(__isl_take EL
*el1
, __isl_take EL
*el2
))
588 __attribute__ ((unused
));
590 /* Apply "fn" to pairs of elements from pw1 and pw2 on shared domains.
591 * The result of "fn" is assumed to live in the same space as "pw1" and "pw2".
593 static __isl_give PW
*FN(PW
,on_shared_domain
)(__isl_take PW
*pw1
,
595 __isl_give EL
*(*fn
)(__isl_take EL
*el1
, __isl_take EL
*el2
))
602 space
= isl_space_copy(pw1
->dim
);
603 return FN(PW
,on_shared_domain_in
)(pw1
, pw2
, space
, fn
);
611 __isl_give PW
*FN(PW
,neg
)(__isl_take PW
*pw
)
618 if (FN(PW
,IS_ZERO
)(pw
))
625 for (i
= 0; i
< pw
->n
; ++i
) {
626 pw
->p
[i
].FIELD
= FN(EL
,neg
)(pw
->p
[i
].FIELD
);
628 return FN(PW
,free
)(pw
);
634 __isl_give PW
*FN(PW
,sub
)(__isl_take PW
*pw1
, __isl_take PW
*pw2
)
636 return FN(PW
,add
)(pw1
, FN(PW
,neg
)(pw2
));
641 __isl_give isl_qpolynomial
*FN(PW
,eval
)(__isl_take PW
*pw
,
642 __isl_take isl_point
*pnt
)
647 isl_space
*pnt_dim
= NULL
;
652 ctx
= isl_point_get_ctx(pnt
);
653 pnt_dim
= isl_point_get_space(pnt
);
654 isl_assert(ctx
, isl_space_is_domain_internal(pnt_dim
, pw
->dim
),
657 for (i
= 0; i
< pw
->n
; ++i
) {
658 found
= isl_set_contains_point(pw
->p
[i
].set
, pnt
);
665 qp
= FN(EL
,eval
)(FN(EL
,copy
)(pw
->p
[i
].FIELD
),
666 isl_point_copy(pnt
));
668 qp
= isl_qpolynomial_zero_on_domain(FN(PW
,get_domain_space
)(pw
));
670 isl_space_free(pnt_dim
);
675 isl_space_free(pnt_dim
);
681 __isl_give isl_set
*FN(PW
,domain
)(__isl_take PW
*pw
)
689 dom
= isl_set_empty(FN(PW
,get_domain_space
)(pw
));
690 for (i
= 0; i
< pw
->n
; ++i
)
691 dom
= isl_set_union_disjoint(dom
, isl_set_copy(pw
->p
[i
].set
));
698 /* Restrict the domain of "pw" by combining each cell
699 * with "set" through a call to "fn", where "fn" may be
700 * isl_set_intersect or isl_set_intersect_params.
702 static __isl_give PW
*FN(PW
,intersect_aligned
)(__isl_take PW
*pw
,
703 __isl_take isl_set
*set
,
704 __isl_give isl_set
*(*fn
)(__isl_take isl_set
*set1
,
705 __isl_take isl_set
*set2
))
721 for (i
= pw
->n
- 1; i
>= 0; --i
) {
723 pw
->p
[i
].set
= fn(pw
->p
[i
].set
, isl_set_copy(set
));
726 aff
= isl_set_affine_hull(isl_set_copy(pw
->p
[i
].set
));
727 pw
->p
[i
].FIELD
= FN(EL
,substitute_equalities
)(pw
->p
[i
].FIELD
,
731 if (isl_set_plain_is_empty(pw
->p
[i
].set
)) {
732 isl_set_free(pw
->p
[i
].set
);
733 FN(EL
,free
)(pw
->p
[i
].FIELD
);
735 pw
->p
[i
] = pw
->p
[pw
->n
- 1];
748 static __isl_give PW
*FN(PW
,intersect_domain_aligned
)(__isl_take PW
*pw
,
749 __isl_take isl_set
*set
)
751 return FN(PW
,intersect_aligned
)(pw
, set
, &isl_set_intersect
);
754 __isl_give PW
*FN(PW
,intersect_domain
)(__isl_take PW
*pw
,
755 __isl_take isl_set
*context
)
757 return FN(PW
,align_params_pw_set_and
)(pw
, context
,
758 &FN(PW
,intersect_domain_aligned
));
761 static __isl_give PW
*FN(PW
,intersect_params_aligned
)(__isl_take PW
*pw
,
762 __isl_take isl_set
*set
)
764 return FN(PW
,intersect_aligned
)(pw
, set
, &isl_set_intersect_params
);
767 /* Intersect the domain of "pw" with the parameter domain "context".
769 __isl_give PW
*FN(PW
,intersect_params
)(__isl_take PW
*pw
,
770 __isl_take isl_set
*context
)
772 return FN(PW
,align_params_pw_set_and
)(pw
, context
,
773 &FN(PW
,intersect_params_aligned
));
776 static __isl_give PW
*FN(PW
,gist_aligned
)(__isl_take PW
*pw
,
777 __isl_take isl_set
*context
,
778 __isl_give EL
*(*fn_el
)(__isl_take EL
*el
,
779 __isl_take isl_set
*set
),
780 __isl_give isl_set
*(*fn_dom
)(__isl_take isl_set
*set
,
781 __isl_take isl_basic_set
*bset
))
784 isl_basic_set
*hull
= NULL
;
790 isl_set_free(context
);
794 if (!isl_space_match(pw
->dim
, isl_dim_param
,
795 context
->dim
, isl_dim_param
)) {
796 pw
= FN(PW
,align_params
)(pw
, isl_set_get_space(context
));
797 context
= isl_set_align_params(context
, FN(PW
,get_space
)(pw
));
800 context
= isl_set_compute_divs(context
);
801 hull
= isl_set_simple_hull(isl_set_copy(context
));
807 for (i
= pw
->n
- 1; i
>= 0; --i
) {
811 set_i
= isl_set_intersect(isl_set_copy(pw
->p
[i
].set
),
812 isl_set_copy(context
));
813 empty
= isl_set_plain_is_empty(set_i
);
814 pw
->p
[i
].FIELD
= fn_el(pw
->p
[i
].FIELD
, set_i
);
815 pw
->p
[i
].set
= fn_dom(pw
->p
[i
].set
, isl_basic_set_copy(hull
));
816 if (!pw
->p
[i
].FIELD
|| !pw
->p
[i
].set
)
819 isl_set_free(pw
->p
[i
].set
);
820 FN(EL
,free
)(pw
->p
[i
].FIELD
);
822 pw
->p
[i
] = pw
->p
[pw
->n
- 1];
827 isl_basic_set_free(hull
);
828 isl_set_free(context
);
833 isl_basic_set_free(hull
);
834 isl_set_free(context
);
838 static __isl_give PW
*FN(PW
,gist_domain_aligned
)(__isl_take PW
*pw
,
839 __isl_take isl_set
*set
)
841 return FN(PW
,gist_aligned
)(pw
, set
, &FN(EL
,gist
),
842 &isl_set_gist_basic_set
);
845 __isl_give PW
*FN(PW
,gist
)(__isl_take PW
*pw
, __isl_take isl_set
*context
)
847 return FN(PW
,align_params_pw_set_and
)(pw
, context
,
848 &FN(PW
,gist_domain_aligned
));
851 static __isl_give PW
*FN(PW
,gist_params_aligned
)(__isl_take PW
*pw
,
852 __isl_take isl_set
*set
)
854 return FN(PW
,gist_aligned
)(pw
, set
, &FN(EL
,gist_params
),
855 &isl_set_gist_params_basic_set
);
858 __isl_give PW
*FN(PW
,gist_params
)(__isl_take PW
*pw
,
859 __isl_take isl_set
*context
)
861 return FN(PW
,align_params_pw_set_and
)(pw
, context
,
862 &FN(PW
,gist_params_aligned
));
865 __isl_give PW
*FN(PW
,coalesce
)(__isl_take PW
*pw
)
874 for (i
= pw
->n
- 1; i
>= 0; --i
) {
875 for (j
= i
- 1; j
>= 0; --j
) {
876 if (!FN(EL
,plain_is_equal
)(pw
->p
[i
].FIELD
,
879 pw
->p
[j
].set
= isl_set_union(pw
->p
[j
].set
,
881 FN(EL
,free
)(pw
->p
[i
].FIELD
);
883 pw
->p
[i
] = pw
->p
[pw
->n
- 1];
889 pw
->p
[i
].set
= isl_set_coalesce(pw
->p
[i
].set
);
900 isl_ctx
*FN(PW
,get_ctx
)(__isl_keep PW
*pw
)
902 return pw
? isl_space_get_ctx(pw
->dim
) : NULL
;
905 #ifndef NO_INVOLVES_DIMS
906 int FN(PW
,involves_dims
)(__isl_keep PW
*pw
, enum isl_dim_type type
,
907 unsigned first
, unsigned n
)
910 enum isl_dim_type set_type
;
914 if (pw
->n
== 0 || n
== 0)
917 set_type
= type
== isl_dim_in
? isl_dim_set
: type
;
919 for (i
= 0; i
< pw
->n
; ++i
) {
920 int involves
= FN(EL
,involves_dims
)(pw
->p
[i
].FIELD
,
922 if (involves
< 0 || involves
)
924 involves
= isl_set_involves_dims(pw
->p
[i
].set
,
926 if (involves
< 0 || involves
)
933 __isl_give PW
*FN(PW
,set_dim_name
)(__isl_take PW
*pw
,
934 enum isl_dim_type type
, unsigned pos
, const char *s
)
937 enum isl_dim_type set_type
;
943 set_type
= type
== isl_dim_in
? isl_dim_set
: type
;
945 pw
->dim
= isl_space_set_dim_name(pw
->dim
, type
, pos
, s
);
949 for (i
= 0; i
< pw
->n
; ++i
) {
950 pw
->p
[i
].set
= isl_set_set_dim_name(pw
->p
[i
].set
,
954 pw
->p
[i
].FIELD
= FN(EL
,set_dim_name
)(pw
->p
[i
].FIELD
, type
, pos
, s
);
966 __isl_give PW
*FN(PW
,drop_dims
)(__isl_take PW
*pw
,
967 enum isl_dim_type type
, unsigned first
, unsigned n
)
970 enum isl_dim_type set_type
;
974 if (n
== 0 && !isl_space_get_tuple_name(pw
->dim
, type
))
977 set_type
= type
== isl_dim_in
? isl_dim_set
: type
;
982 pw
->dim
= isl_space_drop_dims(pw
->dim
, type
, first
, n
);
985 for (i
= 0; i
< pw
->n
; ++i
) {
986 pw
->p
[i
].FIELD
= FN(EL
,drop_dims
)(pw
->p
[i
].FIELD
, type
, first
, n
);
989 if (type
== isl_dim_out
)
991 pw
->p
[i
].set
= isl_set_drop(pw
->p
[i
].set
, set_type
, first
, n
);
1002 /* This function is very similar to drop_dims.
1003 * The only difference is that the cells may still involve
1004 * the specified dimensions. They are removed using
1005 * isl_set_project_out instead of isl_set_drop.
1007 __isl_give PW
*FN(PW
,project_out
)(__isl_take PW
*pw
,
1008 enum isl_dim_type type
, unsigned first
, unsigned n
)
1011 enum isl_dim_type set_type
;
1015 if (n
== 0 && !isl_space_get_tuple_name(pw
->dim
, type
))
1018 set_type
= type
== isl_dim_in
? isl_dim_set
: type
;
1020 pw
= FN(PW
,cow
)(pw
);
1023 pw
->dim
= isl_space_drop_dims(pw
->dim
, type
, first
, n
);
1026 for (i
= 0; i
< pw
->n
; ++i
) {
1027 pw
->p
[i
].set
= isl_set_project_out(pw
->p
[i
].set
,
1028 set_type
, first
, n
);
1031 pw
->p
[i
].FIELD
= FN(EL
,drop_dims
)(pw
->p
[i
].FIELD
, type
, first
, n
);
1032 if (!pw
->p
[i
].FIELD
)
1042 /* Project the domain of pw onto its parameter space.
1044 __isl_give PW
*FN(PW
,project_domain_on_params
)(__isl_take PW
*pw
)
1049 n
= FN(PW
,dim
)(pw
, isl_dim_in
);
1050 pw
= FN(PW
,project_out
)(pw
, isl_dim_in
, 0, n
);
1051 space
= FN(PW
,get_domain_space
)(pw
);
1052 space
= isl_space_params(space
);
1053 pw
= FN(PW
,reset_domain_space
)(pw
, space
);
1058 #ifndef NO_INSERT_DIMS
1059 __isl_give PW
*FN(PW
,insert_dims
)(__isl_take PW
*pw
, enum isl_dim_type type
,
1060 unsigned first
, unsigned n
)
1063 enum isl_dim_type set_type
;
1067 if (n
== 0 && !isl_space_is_named_or_nested(pw
->dim
, type
))
1070 set_type
= type
== isl_dim_in
? isl_dim_set
: type
;
1072 pw
= FN(PW
,cow
)(pw
);
1076 pw
->dim
= isl_space_insert_dims(pw
->dim
, type
, first
, n
);
1080 for (i
= 0; i
< pw
->n
; ++i
) {
1081 pw
->p
[i
].set
= isl_set_insert_dims(pw
->p
[i
].set
,
1082 set_type
, first
, n
);
1085 pw
->p
[i
].FIELD
= FN(EL
,insert_dims
)(pw
->p
[i
].FIELD
,
1087 if (!pw
->p
[i
].FIELD
)
1098 __isl_give PW
*FN(PW
,fix_dim
)(__isl_take PW
*pw
,
1099 enum isl_dim_type type
, unsigned pos
, isl_int v
)
1106 if (type
== isl_dim_in
)
1109 pw
= FN(PW
,cow
)(pw
);
1112 for (i
= 0; i
< pw
->n
; ++i
) {
1113 pw
->p
[i
].set
= isl_set_fix(pw
->p
[i
].set
, type
, pos
, v
);
1124 unsigned FN(PW
,dim
)(__isl_keep PW
*pw
, enum isl_dim_type type
)
1126 return pw
? isl_space_dim(pw
->dim
, type
) : 0;
1129 __isl_give PW
*FN(PW
,split_dims
)(__isl_take PW
*pw
,
1130 enum isl_dim_type type
, unsigned first
, unsigned n
)
1139 if (type
== isl_dim_in
)
1142 pw
= FN(PW
,cow
)(pw
);
1147 for (i
= 0; i
< pw
->n
; ++i
) {
1148 pw
->p
[i
].set
= isl_set_split_dims(pw
->p
[i
].set
, type
, first
, n
);
1160 /* Compute the maximal value attained by the piecewise quasipolynomial
1161 * on its domain or zero if the domain is empty.
1162 * In the worst case, the domain is scanned completely,
1163 * so the domain is assumed to be bounded.
1165 __isl_give isl_qpolynomial
*FN(PW
,opt
)(__isl_take PW
*pw
, int max
)
1168 isl_qpolynomial
*opt
;
1174 isl_space
*dim
= isl_space_copy(pw
->dim
);
1176 return isl_qpolynomial_zero_on_domain(isl_space_domain(dim
));
1179 opt
= FN(EL
,opt_on_domain
)(FN(EL
,copy
)(pw
->p
[0].FIELD
),
1180 isl_set_copy(pw
->p
[0].set
), max
);
1181 for (i
= 1; i
< pw
->n
; ++i
) {
1182 isl_qpolynomial
*opt_i
;
1183 opt_i
= FN(EL
,opt_on_domain
)(FN(EL
,copy
)(pw
->p
[i
].FIELD
),
1184 isl_set_copy(pw
->p
[i
].set
), max
);
1186 opt
= isl_qpolynomial_max_cst(opt
, opt_i
);
1188 opt
= isl_qpolynomial_min_cst(opt
, opt_i
);
1195 __isl_give isl_qpolynomial
*FN(PW
,max
)(__isl_take PW
*pw
)
1197 return FN(PW
,opt
)(pw
, 1);
1200 __isl_give isl_qpolynomial
*FN(PW
,min
)(__isl_take PW
*pw
)
1202 return FN(PW
,opt
)(pw
, 0);
1206 __isl_give isl_space
*FN(PW
,get_space
)(__isl_keep PW
*pw
)
1208 return pw
? isl_space_copy(pw
->dim
) : NULL
;
1211 __isl_give isl_space
*FN(PW
,get_domain_space
)(__isl_keep PW
*pw
)
1213 return pw
? isl_space_domain(isl_space_copy(pw
->dim
)) : NULL
;
1216 #ifndef NO_RESET_DIM
1217 /* Reset the space of "pw". Since we don't know if the elements
1218 * represent the spaces themselves or their domains, we pass along
1219 * both when we call their reset_space_and_domain.
1221 static __isl_give PW
*FN(PW
,reset_space_and_domain
)(__isl_take PW
*pw
,
1222 __isl_take isl_space
*space
, __isl_take isl_space
*domain
)
1226 pw
= FN(PW
,cow
)(pw
);
1227 if (!pw
|| !space
|| !domain
)
1230 for (i
= 0; i
< pw
->n
; ++i
) {
1231 pw
->p
[i
].set
= isl_set_reset_space(pw
->p
[i
].set
,
1232 isl_space_copy(domain
));
1235 pw
->p
[i
].FIELD
= FN(EL
,reset_space_and_domain
)(pw
->p
[i
].FIELD
,
1236 isl_space_copy(space
), isl_space_copy(domain
));
1237 if (!pw
->p
[i
].FIELD
)
1241 isl_space_free(domain
);
1243 isl_space_free(pw
->dim
);
1248 isl_space_free(domain
);
1249 isl_space_free(space
);
1254 __isl_give PW
*FN(PW
,reset_domain_space
)(__isl_take PW
*pw
,
1255 __isl_take isl_space
*domain
)
1259 space
= isl_space_extend_domain_with_range(isl_space_copy(domain
),
1260 FN(PW
,get_space
)(pw
));
1261 return FN(PW
,reset_space_and_domain
)(pw
, space
, domain
);
1264 __isl_give PW
*FN(PW
,reset_space
)(__isl_take PW
*pw
, __isl_take isl_space
*dim
)
1268 domain
= isl_space_domain(isl_space_copy(dim
));
1269 return FN(PW
,reset_space_and_domain
)(pw
, dim
, domain
);
1272 __isl_give PW
*FN(PW
,set_tuple_id
)(__isl_keep PW
*pw
, enum isl_dim_type type
,
1273 __isl_take isl_id
*id
)
1277 pw
= FN(PW
,cow
)(pw
);
1279 return isl_id_free(id
);
1281 space
= FN(PW
,get_space
)(pw
);
1282 space
= isl_space_set_tuple_id(space
, type
, id
);
1284 return FN(PW
,reset_space
)(pw
, space
);
1287 __isl_give PW
*FN(PW
,set_dim_id
)(__isl_take PW
*pw
,
1288 enum isl_dim_type type
, unsigned pos
, __isl_take isl_id
*id
)
1290 pw
= FN(PW
,cow
)(pw
);
1292 return isl_id_free(id
);
1293 pw
->dim
= isl_space_set_dim_id(pw
->dim
, type
, pos
, id
);
1294 return FN(PW
,reset_space
)(pw
, isl_space_copy(pw
->dim
));
1298 int FN(PW
,has_equal_space
)(__isl_keep PW
*pw1
, __isl_keep PW
*pw2
)
1303 return isl_space_is_equal(pw1
->dim
, pw2
->dim
);
1307 __isl_give PW
*FN(PW
,morph_domain
)(__isl_take PW
*pw
,
1308 __isl_take isl_morph
*morph
)
1316 ctx
= isl_space_get_ctx(pw
->dim
);
1317 isl_assert(ctx
, isl_space_is_domain_internal(morph
->dom
->dim
, pw
->dim
),
1320 pw
= FN(PW
,cow
)(pw
);
1323 pw
->dim
= isl_space_extend_domain_with_range(
1324 isl_space_copy(morph
->ran
->dim
), pw
->dim
);
1328 for (i
= 0; i
< pw
->n
; ++i
) {
1329 pw
->p
[i
].set
= isl_morph_set(isl_morph_copy(morph
), pw
->p
[i
].set
);
1332 pw
->p
[i
].FIELD
= FN(EL
,morph_domain
)(pw
->p
[i
].FIELD
,
1333 isl_morph_copy(morph
));
1334 if (!pw
->p
[i
].FIELD
)
1338 isl_morph_free(morph
);
1343 isl_morph_free(morph
);
1348 int FN(PW
,n_piece
)(__isl_keep PW
*pw
)
1350 return pw
? pw
->n
: 0;
1353 int FN(PW
,foreach_piece
)(__isl_keep PW
*pw
,
1354 int (*fn
)(__isl_take isl_set
*set
, __isl_take EL
*el
, void *user
),
1362 for (i
= 0; i
< pw
->n
; ++i
)
1363 if (fn(isl_set_copy(pw
->p
[i
].set
),
1364 FN(EL
,copy
)(pw
->p
[i
].FIELD
), user
) < 0)
1371 static int any_divs(__isl_keep isl_set
*set
)
1378 for (i
= 0; i
< set
->n
; ++i
)
1379 if (set
->p
[i
]->n_div
> 0)
1385 static int foreach_lifted_subset(__isl_take isl_set
*set
, __isl_take EL
*el
,
1386 int (*fn
)(__isl_take isl_set
*set
, __isl_take EL
*el
,
1387 void *user
), void *user
)
1394 for (i
= 0; i
< set
->n
; ++i
) {
1398 lift
= isl_set_from_basic_set(isl_basic_set_copy(set
->p
[i
]));
1399 lift
= isl_set_lift(lift
);
1401 copy
= FN(EL
,copy
)(el
);
1402 copy
= FN(EL
,lift
)(copy
, isl_set_get_space(lift
));
1404 if (fn(lift
, copy
, user
) < 0)
1418 int FN(PW
,foreach_lifted_piece
)(__isl_keep PW
*pw
,
1419 int (*fn
)(__isl_take isl_set
*set
, __isl_take EL
*el
,
1420 void *user
), void *user
)
1427 for (i
= 0; i
< pw
->n
; ++i
) {
1431 set
= isl_set_copy(pw
->p
[i
].set
);
1432 el
= FN(EL
,copy
)(pw
->p
[i
].FIELD
);
1433 if (!any_divs(set
)) {
1434 if (fn(set
, el
, user
) < 0)
1438 if (foreach_lifted_subset(set
, el
, fn
, user
) < 0)
1446 #ifndef NO_MOVE_DIMS
1447 __isl_give PW
*FN(PW
,move_dims
)(__isl_take PW
*pw
,
1448 enum isl_dim_type dst_type
, unsigned dst_pos
,
1449 enum isl_dim_type src_type
, unsigned src_pos
, unsigned n
)
1453 pw
= FN(PW
,cow
)(pw
);
1457 pw
->dim
= isl_space_move_dims(pw
->dim
, dst_type
, dst_pos
, src_type
, src_pos
, n
);
1461 for (i
= 0; i
< pw
->n
; ++i
) {
1462 pw
->p
[i
].FIELD
= FN(EL
,move_dims
)(pw
->p
[i
].FIELD
,
1463 dst_type
, dst_pos
, src_type
, src_pos
, n
);
1464 if (!pw
->p
[i
].FIELD
)
1468 if (dst_type
== isl_dim_in
)
1469 dst_type
= isl_dim_set
;
1470 if (src_type
== isl_dim_in
)
1471 src_type
= isl_dim_set
;
1473 for (i
= 0; i
< pw
->n
; ++i
) {
1474 pw
->p
[i
].set
= isl_set_move_dims(pw
->p
[i
].set
,
1476 src_type
, src_pos
, n
);
1488 __isl_give PW
*FN(PW
,mul_isl_int
)(__isl_take PW
*pw
, isl_int v
)
1492 if (isl_int_is_one(v
))
1494 if (pw
&& DEFAULT_IS_ZERO
&& isl_int_is_zero(v
)) {
1496 isl_space
*dim
= FN(PW
,get_space
)(pw
);
1498 zero
= FN(PW
,ZERO
)(dim
, pw
->type
);
1500 zero
= FN(PW
,ZERO
)(dim
);
1505 pw
= FN(PW
,cow
)(pw
);
1512 if (isl_int_is_neg(v
))
1513 pw
->type
= isl_fold_type_negate(pw
->type
);
1515 for (i
= 0; i
< pw
->n
; ++i
) {
1516 pw
->p
[i
].FIELD
= FN(EL
,scale
)(pw
->p
[i
].FIELD
, v
);
1517 if (!pw
->p
[i
].FIELD
)
1527 __isl_give PW
*FN(PW
,scale
)(__isl_take PW
*pw
, isl_int v
)
1529 return FN(PW
,mul_isl_int
)(pw
, v
);
1532 static int FN(PW
,qsort_set_cmp
)(const void *p1
, const void *p2
)
1534 isl_set
*set1
= *(isl_set
* const *)p1
;
1535 isl_set
*set2
= *(isl_set
* const *)p2
;
1537 return isl_set_plain_cmp(set1
, set2
);
1540 /* We normalize in place, but if anything goes wrong we need
1541 * to return NULL, so we need to make sure we don't change the
1542 * meaning of any possible other copies of map.
1544 __isl_give PW
*FN(PW
,normalize
)(__isl_take PW
*pw
)
1551 for (i
= 0; i
< pw
->n
; ++i
) {
1552 set
= isl_set_normalize(isl_set_copy(pw
->p
[i
].set
));
1554 return FN(PW
,free
)(pw
);
1555 isl_set_free(pw
->p
[i
].set
);
1558 qsort(pw
->p
, pw
->n
, sizeof(pw
->p
[0]), &FN(PW
,qsort_set_cmp
));
1559 for (i
= pw
->n
- 1; i
>= 1; --i
) {
1560 if (!isl_set_plain_is_equal(pw
->p
[i
- 1].set
, pw
->p
[i
].set
))
1562 if (!FN(EL
,plain_is_equal
)(pw
->p
[i
- 1].FIELD
, pw
->p
[i
].FIELD
))
1564 set
= isl_set_union(isl_set_copy(pw
->p
[i
- 1].set
),
1565 isl_set_copy(pw
->p
[i
].set
));
1567 return FN(PW
,free
)(pw
);
1568 isl_set_free(pw
->p
[i
].set
);
1569 FN(EL
,free
)(pw
->p
[i
].FIELD
);
1570 isl_set_free(pw
->p
[i
- 1].set
);
1571 pw
->p
[i
- 1].set
= set
;
1572 for (j
= i
+ 1; j
< pw
->n
; ++j
)
1573 pw
->p
[j
- 1] = pw
->p
[j
];
1580 /* Is pw1 obviously equal to pw2?
1581 * That is, do they have obviously identical cells and obviously identical
1582 * elements on each cell?
1584 int FN(PW
,plain_is_equal
)(__isl_keep PW
*pw1
, __isl_keep PW
*pw2
)
1594 if (!isl_space_is_equal(pw1
->dim
, pw2
->dim
))
1597 pw1
= FN(PW
,copy
)(pw1
);
1598 pw2
= FN(PW
,copy
)(pw2
);
1599 pw1
= FN(PW
,normalize
)(pw1
);
1600 pw2
= FN(PW
,normalize
)(pw2
);
1604 equal
= pw1
->n
== pw2
->n
;
1605 for (i
= 0; equal
&& i
< pw1
->n
; ++i
) {
1606 equal
= isl_set_plain_is_equal(pw1
->p
[i
].set
, pw2
->p
[i
].set
);
1611 equal
= FN(EL
,plain_is_equal
)(pw1
->p
[i
].FIELD
, pw2
->p
[i
].FIELD
);
1626 static __isl_give PW
*FN(PW
,align_params_pw_multi_aff_and
)(__isl_take PW
*pw
,
1627 __isl_take isl_multi_aff
*ma
,
1628 __isl_give PW
*(*fn
)(__isl_take PW
*pw
, __isl_take isl_multi_aff
*ma
))
1631 isl_space
*ma_space
;
1633 ma_space
= isl_multi_aff_get_space(ma
);
1634 if (!pw
|| !ma
|| !ma_space
)
1636 if (isl_space_match(pw
->dim
, isl_dim_param
, ma_space
, isl_dim_param
)) {
1637 isl_space_free(ma_space
);
1640 ctx
= FN(PW
,get_ctx
)(pw
);
1641 if (!isl_space_has_named_params(pw
->dim
) ||
1642 !isl_space_has_named_params(ma_space
))
1643 isl_die(ctx
, isl_error_invalid
,
1644 "unaligned unnamed parameters", goto error
);
1645 pw
= FN(PW
,align_params
)(pw
, ma_space
);
1646 ma
= isl_multi_aff_align_params(ma
, FN(PW
,get_space
)(pw
));
1649 isl_space_free(ma_space
);
1651 isl_multi_aff_free(ma
);
1655 static __isl_give PW
*FN(PW
,align_params_pw_pw_multi_aff_and
)(__isl_take PW
*pw
,
1656 __isl_take isl_pw_multi_aff
*pma
,
1657 __isl_give PW
*(*fn
)(__isl_take PW
*pw
,
1658 __isl_take isl_pw_multi_aff
*ma
))
1661 isl_space
*pma_space
;
1663 pma_space
= isl_pw_multi_aff_get_space(pma
);
1664 if (!pw
|| !pma
|| !pma_space
)
1666 if (isl_space_match(pw
->dim
, isl_dim_param
, pma_space
, isl_dim_param
)) {
1667 isl_space_free(pma_space
);
1670 ctx
= FN(PW
,get_ctx
)(pw
);
1671 if (!isl_space_has_named_params(pw
->dim
) ||
1672 !isl_space_has_named_params(pma_space
))
1673 isl_die(ctx
, isl_error_invalid
,
1674 "unaligned unnamed parameters", goto error
);
1675 pw
= FN(PW
,align_params
)(pw
, pma_space
);
1676 pma
= isl_pw_multi_aff_align_params(pma
, FN(PW
,get_space
)(pw
));
1679 isl_space_free(pma_space
);
1681 isl_pw_multi_aff_free(pma
);
1685 /* Compute the pullback of "pw" by the function represented by "ma".
1686 * In other words, plug in "ma" in "pw".
1688 static __isl_give PW
*FN(PW
,pullback_multi_aff_aligned
)(__isl_take PW
*pw
,
1689 __isl_take isl_multi_aff
*ma
)
1692 isl_space
*space
= NULL
;
1694 ma
= isl_multi_aff_align_divs(ma
);
1695 pw
= FN(PW
,cow
)(pw
);
1699 space
= isl_space_join(isl_multi_aff_get_space(ma
),
1700 FN(PW
,get_space
)(pw
));
1702 for (i
= 0; i
< pw
->n
; ++i
) {
1703 pw
->p
[i
].set
= isl_set_preimage_multi_aff(pw
->p
[i
].set
,
1704 isl_multi_aff_copy(ma
));
1707 pw
->p
[i
].FIELD
= FN(EL
,pullback_multi_aff
)(pw
->p
[i
].FIELD
,
1708 isl_multi_aff_copy(ma
));
1709 if (!pw
->p
[i
].FIELD
)
1713 pw
= FN(PW
,reset_space
)(pw
, space
);
1714 isl_multi_aff_free(ma
);
1717 isl_space_free(space
);
1718 isl_multi_aff_free(ma
);
1723 __isl_give PW
*FN(PW
,pullback_multi_aff
)(__isl_take PW
*pw
,
1724 __isl_take isl_multi_aff
*ma
)
1726 return FN(PW
,align_params_pw_multi_aff_and
)(pw
, ma
,
1727 &FN(PW
,pullback_multi_aff_aligned
));
1730 /* Compute the pullback of "pw" by the function represented by "pma".
1731 * In other words, plug in "pma" in "pw".
1733 static __isl_give PW
*FN(PW
,pullback_pw_multi_aff_aligned
)(__isl_take PW
*pw
,
1734 __isl_take isl_pw_multi_aff
*pma
)
1743 isl_pw_multi_aff_free(pma
);
1744 res
= FN(PW
,empty
)(FN(PW
,get_space
)(pw
));
1749 res
= FN(PW
,pullback_multi_aff
)(FN(PW
,copy
)(pw
),
1750 isl_multi_aff_copy(pma
->p
[0].maff
));
1751 res
= FN(PW
,intersect_domain
)(res
, isl_set_copy(pma
->p
[0].set
));
1753 for (i
= 1; i
< pma
->n
; ++i
) {
1756 res_i
= FN(PW
,pullback_multi_aff
)(FN(PW
,copy
)(pw
),
1757 isl_multi_aff_copy(pma
->p
[i
].maff
));
1758 res_i
= FN(PW
,intersect_domain
)(res_i
,
1759 isl_set_copy(pma
->p
[i
].set
));
1760 res
= FN(PW
,add_disjoint
)(res
, res_i
);
1763 isl_pw_multi_aff_free(pma
);
1767 isl_pw_multi_aff_free(pma
);
1772 __isl_give PW
*FN(PW
,pullback_pw_multi_aff
)(__isl_take PW
*pw
,
1773 __isl_take isl_pw_multi_aff
*pma
)
1775 return FN(PW
,align_params_pw_pw_multi_aff_and
)(pw
, pma
,
1776 &FN(PW
,pullback_pw_multi_aff_aligned
));