1 #define xFN(TYPE,NAME) TYPE ## _ ## NAME
2 #define FN(TYPE,NAME) xFN(TYPE,NAME)
3 #define xS(TYPE,NAME) struct TYPE ## _ ## NAME
4 #define S(TYPE,NAME) xS(TYPE,NAME)
7 __isl_give PW
*FN(PW
,alloc_size
)(__isl_take isl_space
*dim
,
8 enum isl_fold type
, int n
)
10 __isl_give PW
*FN(PW
,alloc_size
)(__isl_take isl_space
*dim
, int n
)
18 ctx
= isl_space_get_ctx(dim
);
19 isl_assert(ctx
, n
>= 0, goto error
);
20 pw
= isl_alloc(ctx
, struct PW
,
21 sizeof(struct PW
) + (n
- 1) * sizeof(S(PW
,piece
)));
39 __isl_give PW
*FN(PW
,ZERO
)(__isl_take isl_space
*dim
, enum isl_fold type
)
41 return FN(PW
,alloc_size
)(dim
, type
, 0);
44 __isl_give PW
*FN(PW
,ZERO
)(__isl_take isl_space
*dim
)
46 return FN(PW
,alloc_size
)(dim
, 0);
50 __isl_give PW
*FN(PW
,add_piece
)(__isl_take PW
*pw
,
51 __isl_take isl_set
*set
, __isl_take EL
*el
)
54 isl_space
*el_dim
= NULL
;
56 if (!pw
|| !set
|| !el
)
59 if (isl_set_plain_is_empty(set
) || FN(EL
,EL_IS_ZERO
)(el
)) {
65 ctx
= isl_set_get_ctx(set
);
67 if (pw
->type
!= el
->type
)
68 isl_die(ctx
, isl_error_invalid
, "fold types don't match",
71 el_dim
= FN(EL
,get_space(el
));
72 isl_assert(ctx
, isl_space_is_equal(pw
->dim
, el_dim
), goto error
);
73 isl_assert(ctx
, pw
->n
< pw
->size
, goto error
);
75 pw
->p
[pw
->n
].set
= set
;
76 pw
->p
[pw
->n
].FIELD
= el
;
79 isl_space_free(el_dim
);
82 isl_space_free(el_dim
);
90 __isl_give PW
*FN(PW
,alloc
)(enum isl_fold type
,
91 __isl_take isl_set
*set
, __isl_take EL
*el
)
93 __isl_give PW
*FN(PW
,alloc
)(__isl_take isl_set
*set
, __isl_take EL
*el
)
102 pw
= FN(PW
,alloc_size
)(FN(EL
,get_space
)(el
), type
, 1);
104 pw
= FN(PW
,alloc_size
)(FN(EL
,get_space
)(el
), 1);
107 return FN(PW
,add_piece
)(pw
, set
, el
);
114 __isl_give PW
*FN(PW
,dup
)(__isl_keep PW
*pw
)
123 dup
= FN(PW
,alloc_size
)(isl_space_copy(pw
->dim
), pw
->type
, pw
->n
);
125 dup
= FN(PW
,alloc_size
)(isl_space_copy(pw
->dim
), pw
->n
);
130 for (i
= 0; i
< pw
->n
; ++i
)
131 dup
= FN(PW
,add_piece
)(dup
, isl_set_copy(pw
->p
[i
].set
),
132 FN(EL
,copy
)(pw
->p
[i
].FIELD
));
137 __isl_give PW
*FN(PW
,cow
)(__isl_take PW
*pw
)
145 return FN(PW
,dup
)(pw
);
148 __isl_give PW
*FN(PW
,copy
)(__isl_keep PW
*pw
)
157 void *FN(PW
,free
)(__isl_take PW
*pw
)
166 for (i
= 0; i
< pw
->n
; ++i
) {
167 isl_set_free(pw
->p
[i
].set
);
168 FN(EL
,free
)(pw
->p
[i
].FIELD
);
170 isl_space_free(pw
->dim
);
176 const char *FN(PW
,get_dim_name
)(__isl_keep PW
*pw
, enum isl_dim_type type
,
179 return pw
? isl_space_get_dim_name(pw
->dim
, type
, pos
) : NULL
;
182 int FN(PW
,has_dim_id
)(__isl_keep PW
*pw
, enum isl_dim_type type
, unsigned pos
)
184 return pw
? isl_space_has_dim_id(pw
->dim
, type
, pos
) : -1;
187 __isl_give isl_id
*FN(PW
,get_dim_id
)(__isl_keep PW
*pw
, enum isl_dim_type type
,
190 return pw
? isl_space_get_dim_id(pw
->dim
, type
, pos
) : NULL
;
193 int FN(PW
,has_tuple_name
)(__isl_keep PW
*pw
, enum isl_dim_type type
)
195 return pw
? isl_space_has_tuple_name(pw
->dim
, type
) : -1;
198 const char *FN(PW
,get_tuple_name
)(__isl_keep PW
*pw
, enum isl_dim_type type
)
200 return pw
? isl_space_get_tuple_name(pw
->dim
, type
) : NULL
;
203 int FN(PW
,has_tuple_id
)(__isl_keep PW
*pw
, enum isl_dim_type type
)
205 return pw
? isl_space_has_tuple_id(pw
->dim
, type
) : -1;
208 __isl_give isl_id
*FN(PW
,get_tuple_id
)(__isl_keep PW
*pw
, enum isl_dim_type type
)
210 return pw
? isl_space_get_tuple_id(pw
->dim
, type
) : NULL
;
213 int FN(PW
,IS_ZERO
)(__isl_keep PW
*pw
)
222 __isl_give PW
*FN(PW
,realign_domain
)(__isl_take PW
*pw
,
223 __isl_take isl_reordering
*exp
)
231 for (i
= 0; i
< pw
->n
; ++i
) {
232 pw
->p
[i
].set
= isl_set_realign(pw
->p
[i
].set
,
233 isl_reordering_copy(exp
));
236 pw
->p
[i
].FIELD
= FN(EL
,realign_domain
)(pw
->p
[i
].FIELD
,
237 isl_reordering_copy(exp
));
242 pw
= FN(PW
,reset_domain_space
)(pw
, isl_space_copy(exp
->dim
));
244 isl_reordering_free(exp
);
247 isl_reordering_free(exp
);
252 /* Align the parameters of "pw" to those of "model".
254 __isl_give PW
*FN(PW
,align_params
)(__isl_take PW
*pw
, __isl_take isl_space
*model
)
261 ctx
= isl_space_get_ctx(model
);
262 if (!isl_space_has_named_params(model
))
263 isl_die(ctx
, isl_error_invalid
,
264 "model has unnamed parameters", goto error
);
265 if (!isl_space_has_named_params(pw
->dim
))
266 isl_die(ctx
, isl_error_invalid
,
267 "input has unnamed parameters", goto error
);
268 if (!isl_space_match(pw
->dim
, isl_dim_param
, model
, isl_dim_param
)) {
271 model
= isl_space_drop_dims(model
, isl_dim_in
,
272 0, isl_space_dim(model
, isl_dim_in
));
273 model
= isl_space_drop_dims(model
, isl_dim_out
,
274 0, isl_space_dim(model
, isl_dim_out
));
275 exp
= isl_parameter_alignment_reordering(pw
->dim
, model
);
276 exp
= isl_reordering_extend_space(exp
,
277 FN(PW
,get_domain_space
)(pw
));
278 pw
= FN(PW
,realign_domain
)(pw
, exp
);
281 isl_space_free(model
);
284 isl_space_free(model
);
289 static __isl_give PW
*FN(PW
,align_params_pw_pw_and
)(__isl_take PW
*pw1
,
291 __isl_give PW
*(*fn
)(__isl_take PW
*pw1
, __isl_take PW
*pw2
))
297 if (isl_space_match(pw1
->dim
, isl_dim_param
, pw2
->dim
, isl_dim_param
))
299 ctx
= FN(PW
,get_ctx
)(pw1
);
300 if (!isl_space_has_named_params(pw1
->dim
) ||
301 !isl_space_has_named_params(pw2
->dim
))
302 isl_die(ctx
, isl_error_invalid
,
303 "unaligned unnamed parameters", goto error
);
304 pw1
= FN(PW
,align_params
)(pw1
, FN(PW
,get_space
)(pw2
));
305 pw2
= FN(PW
,align_params
)(pw2
, FN(PW
,get_space
)(pw1
));
313 static __isl_give PW
*FN(PW
,align_params_pw_set_and
)(__isl_take PW
*pw
,
314 __isl_take isl_set
*set
,
315 __isl_give PW
*(*fn
)(__isl_take PW
*pw
, __isl_take isl_set
*set
))
321 if (isl_space_match(pw
->dim
, isl_dim_param
, set
->dim
, isl_dim_param
))
323 ctx
= FN(PW
,get_ctx
)(pw
);
324 if (!isl_space_has_named_params(pw
->dim
) ||
325 !isl_space_has_named_params(set
->dim
))
326 isl_die(ctx
, isl_error_invalid
,
327 "unaligned unnamed parameters", goto error
);
328 pw
= FN(PW
,align_params
)(pw
, isl_set_get_space(set
));
329 set
= isl_set_align_params(set
, FN(PW
,get_space
)(pw
));
338 static __isl_give PW
*FN(PW
,union_add_aligned
)(__isl_take PW
*pw1
,
349 ctx
= isl_space_get_ctx(pw1
->dim
);
351 if (pw1
->type
!= pw2
->type
)
352 isl_die(ctx
, isl_error_invalid
,
353 "fold types don't match", goto error
);
355 isl_assert(ctx
, isl_space_is_equal(pw1
->dim
, pw2
->dim
), goto error
);
357 if (FN(PW
,IS_ZERO
)(pw1
)) {
362 if (FN(PW
,IS_ZERO
)(pw2
)) {
367 n
= (pw1
->n
+ 1) * (pw2
->n
+ 1);
369 res
= FN(PW
,alloc_size
)(isl_space_copy(pw1
->dim
), pw1
->type
, n
);
371 res
= FN(PW
,alloc_size
)(isl_space_copy(pw1
->dim
), n
);
374 for (i
= 0; i
< pw1
->n
; ++i
) {
375 set
= isl_set_copy(pw1
->p
[i
].set
);
376 for (j
= 0; j
< pw2
->n
; ++j
) {
377 struct isl_set
*common
;
379 common
= isl_set_intersect(isl_set_copy(pw1
->p
[i
].set
),
380 isl_set_copy(pw2
->p
[j
].set
));
381 if (isl_set_plain_is_empty(common
)) {
382 isl_set_free(common
);
385 set
= isl_set_subtract(set
,
386 isl_set_copy(pw2
->p
[j
].set
));
388 sum
= FN(EL
,add_on_domain
)(common
,
389 FN(EL
,copy
)(pw1
->p
[i
].FIELD
),
390 FN(EL
,copy
)(pw2
->p
[j
].FIELD
));
392 res
= FN(PW
,add_piece
)(res
, common
, sum
);
394 res
= FN(PW
,add_piece
)(res
, set
, FN(EL
,copy
)(pw1
->p
[i
].FIELD
));
397 for (j
= 0; j
< pw2
->n
; ++j
) {
398 set
= isl_set_copy(pw2
->p
[j
].set
);
399 for (i
= 0; i
< pw1
->n
; ++i
)
400 set
= isl_set_subtract(set
,
401 isl_set_copy(pw1
->p
[i
].set
));
402 res
= FN(PW
,add_piece
)(res
, set
, FN(EL
,copy
)(pw2
->p
[j
].FIELD
));
415 /* Private version of "union_add". For isl_pw_qpolynomial and
416 * isl_pw_qpolynomial_fold, we prefer to simply call it "add".
418 static __isl_give PW
*FN(PW
,union_add_
)(__isl_take PW
*pw1
, __isl_take PW
*pw2
)
420 return FN(PW
,align_params_pw_pw_and
)(pw1
, pw2
,
421 &FN(PW
,union_add_aligned
));
424 /* Make sure "pw" has room for at least "n" more pieces.
426 * If there is only one reference to pw, we extend it in place.
427 * Otherwise, we create a new PW and copy the pieces.
429 static __isl_give PW
*FN(PW
,grow
)(__isl_take PW
*pw
, int n
)
437 if (pw
->n
+ n
<= pw
->size
)
439 ctx
= FN(PW
,get_ctx
)(pw
);
442 res
= isl_realloc(ctx
, pw
, struct PW
,
443 sizeof(struct PW
) + (n
- 1) * sizeof(S(PW
,piece
)));
445 return FN(PW
,free
)(pw
);
450 res
= FN(PW
,alloc_size
)(isl_space_copy(pw
->dim
), pw
->type
, n
);
452 res
= FN(PW
,alloc_size
)(isl_space_copy(pw
->dim
), n
);
455 return FN(PW
,free
)(pw
);
456 for (i
= 0; i
< pw
->n
; ++i
)
457 res
= FN(PW
,add_piece
)(res
, isl_set_copy(pw
->p
[i
].set
),
458 FN(EL
,copy
)(pw
->p
[i
].FIELD
));
463 static __isl_give PW
*FN(PW
,add_disjoint_aligned
)(__isl_take PW
*pw1
,
472 if (pw1
->size
< pw1
->n
+ pw2
->n
&& pw1
->n
< pw2
->n
)
473 return FN(PW
,add_disjoint_aligned
)(pw2
, pw1
);
475 ctx
= isl_space_get_ctx(pw1
->dim
);
477 if (pw1
->type
!= pw2
->type
)
478 isl_die(ctx
, isl_error_invalid
,
479 "fold types don't match", goto error
);
481 isl_assert(ctx
, isl_space_is_equal(pw1
->dim
, pw2
->dim
), goto error
);
483 if (FN(PW
,IS_ZERO
)(pw1
)) {
488 if (FN(PW
,IS_ZERO
)(pw2
)) {
493 pw1
= FN(PW
,grow
)(pw1
, pw2
->n
);
497 for (i
= 0; i
< pw2
->n
; ++i
)
498 pw1
= FN(PW
,add_piece
)(pw1
,
499 isl_set_copy(pw2
->p
[i
].set
),
500 FN(EL
,copy
)(pw2
->p
[i
].FIELD
));
511 __isl_give PW
*FN(PW
,add_disjoint
)(__isl_take PW
*pw1
, __isl_take PW
*pw2
)
513 return FN(PW
,align_params_pw_pw_and
)(pw1
, pw2
,
514 &FN(PW
,add_disjoint_aligned
));
517 /* This function is currently only used from isl_aff.c
519 static __isl_give PW
*FN(PW
,on_shared_domain_in
)(__isl_take PW
*pw1
,
520 __isl_take PW
*pw2
, __isl_take isl_space
*space
,
521 __isl_give EL
*(*fn
)(__isl_take EL
*el1
, __isl_take EL
*el2
))
522 __attribute__ ((unused
));
524 /* Apply "fn" to pairs of elements from pw1 and pw2 on shared domains.
525 * The result of "fn" (and therefore also of this function) lives in "space".
527 static __isl_give PW
*FN(PW
,on_shared_domain_in
)(__isl_take PW
*pw1
,
528 __isl_take PW
*pw2
, __isl_take isl_space
*space
,
529 __isl_give EL
*(*fn
)(__isl_take EL
*el1
, __isl_take EL
*el2
))
539 res
= FN(PW
,alloc_size
)(space
, pw1
->type
, n
);
541 res
= FN(PW
,alloc_size
)(space
, n
);
544 for (i
= 0; i
< pw1
->n
; ++i
) {
545 for (j
= 0; j
< pw2
->n
; ++j
) {
550 common
= isl_set_intersect(
551 isl_set_copy(pw1
->p
[i
].set
),
552 isl_set_copy(pw2
->p
[j
].set
));
553 empty
= isl_set_plain_is_empty(common
);
554 if (empty
< 0 || empty
) {
555 isl_set_free(common
);
561 res_ij
= fn(FN(EL
,copy
)(pw1
->p
[i
].FIELD
),
562 FN(EL
,copy
)(pw2
->p
[j
].FIELD
));
563 res_ij
= FN(EL
,gist
)(res_ij
, isl_set_copy(common
));
565 res
= FN(PW
,add_piece
)(res
, common
, res_ij
);
573 isl_space_free(space
);
580 /* This function is currently only used from isl_aff.c
582 static __isl_give PW
*FN(PW
,on_shared_domain
)(__isl_take PW
*pw1
,
584 __isl_give EL
*(*fn
)(__isl_take EL
*el1
, __isl_take EL
*el2
))
585 __attribute__ ((unused
));
587 /* Apply "fn" to pairs of elements from pw1 and pw2 on shared domains.
588 * The result of "fn" is assumed to live in the same space as "pw1" and "pw2".
590 static __isl_give PW
*FN(PW
,on_shared_domain
)(__isl_take PW
*pw1
,
592 __isl_give EL
*(*fn
)(__isl_take EL
*el1
, __isl_take EL
*el2
))
599 space
= isl_space_copy(pw1
->dim
);
600 return FN(PW
,on_shared_domain_in
)(pw1
, pw2
, space
, fn
);
608 __isl_give PW
*FN(PW
,neg
)(__isl_take PW
*pw
)
615 if (FN(PW
,IS_ZERO
)(pw
))
622 for (i
= 0; i
< pw
->n
; ++i
) {
623 pw
->p
[i
].FIELD
= FN(EL
,neg
)(pw
->p
[i
].FIELD
);
625 return FN(PW
,free
)(pw
);
631 __isl_give PW
*FN(PW
,sub
)(__isl_take PW
*pw1
, __isl_take PW
*pw2
)
633 return FN(PW
,add
)(pw1
, FN(PW
,neg
)(pw2
));
638 __isl_give isl_qpolynomial
*FN(PW
,eval
)(__isl_take PW
*pw
,
639 __isl_take isl_point
*pnt
)
644 isl_space
*pnt_dim
= NULL
;
649 ctx
= isl_point_get_ctx(pnt
);
650 pnt_dim
= isl_point_get_space(pnt
);
651 isl_assert(ctx
, isl_space_is_domain_internal(pnt_dim
, pw
->dim
),
654 for (i
= 0; i
< pw
->n
; ++i
) {
655 found
= isl_set_contains_point(pw
->p
[i
].set
, pnt
);
662 qp
= FN(EL
,eval
)(FN(EL
,copy
)(pw
->p
[i
].FIELD
),
663 isl_point_copy(pnt
));
665 qp
= isl_qpolynomial_zero_on_domain(FN(PW
,get_domain_space
)(pw
));
667 isl_space_free(pnt_dim
);
672 isl_space_free(pnt_dim
);
678 __isl_give isl_set
*FN(PW
,domain
)(__isl_take PW
*pw
)
686 dom
= isl_set_empty(FN(PW
,get_domain_space
)(pw
));
687 for (i
= 0; i
< pw
->n
; ++i
)
688 dom
= isl_set_union_disjoint(dom
, isl_set_copy(pw
->p
[i
].set
));
695 /* Restrict the domain of "pw" by combining each cell
696 * with "set" through a call to "fn", where "fn" may be
697 * isl_set_intersect or isl_set_intersect_params.
699 static __isl_give PW
*FN(PW
,intersect_aligned
)(__isl_take PW
*pw
,
700 __isl_take isl_set
*set
,
701 __isl_give isl_set
*(*fn
)(__isl_take isl_set
*set1
,
702 __isl_take isl_set
*set2
))
718 for (i
= pw
->n
- 1; i
>= 0; --i
) {
720 pw
->p
[i
].set
= fn(pw
->p
[i
].set
, isl_set_copy(set
));
723 aff
= isl_set_affine_hull(isl_set_copy(pw
->p
[i
].set
));
724 pw
->p
[i
].FIELD
= FN(EL
,substitute_equalities
)(pw
->p
[i
].FIELD
,
728 if (isl_set_plain_is_empty(pw
->p
[i
].set
)) {
729 isl_set_free(pw
->p
[i
].set
);
730 FN(EL
,free
)(pw
->p
[i
].FIELD
);
732 pw
->p
[i
] = pw
->p
[pw
->n
- 1];
745 static __isl_give PW
*FN(PW
,intersect_domain_aligned
)(__isl_take PW
*pw
,
746 __isl_take isl_set
*set
)
748 return FN(PW
,intersect_aligned
)(pw
, set
, &isl_set_intersect
);
751 __isl_give PW
*FN(PW
,intersect_domain
)(__isl_take PW
*pw
,
752 __isl_take isl_set
*context
)
754 return FN(PW
,align_params_pw_set_and
)(pw
, context
,
755 &FN(PW
,intersect_domain_aligned
));
758 static __isl_give PW
*FN(PW
,intersect_params_aligned
)(__isl_take PW
*pw
,
759 __isl_take isl_set
*set
)
761 return FN(PW
,intersect_aligned
)(pw
, set
, &isl_set_intersect_params
);
764 /* Intersect the domain of "pw" with the parameter domain "context".
766 __isl_give PW
*FN(PW
,intersect_params
)(__isl_take PW
*pw
,
767 __isl_take isl_set
*context
)
769 return FN(PW
,align_params_pw_set_and
)(pw
, context
,
770 &FN(PW
,intersect_params_aligned
));
773 static __isl_give PW
*FN(PW
,gist_aligned
)(__isl_take PW
*pw
,
774 __isl_take isl_set
*context
,
775 __isl_give EL
*(*fn_el
)(__isl_take EL
*el
,
776 __isl_take isl_set
*set
),
777 __isl_give isl_set
*(*fn_dom
)(__isl_take isl_set
*set
,
778 __isl_take isl_basic_set
*bset
))
781 isl_basic_set
*hull
= NULL
;
787 isl_set_free(context
);
791 if (!isl_space_match(pw
->dim
, isl_dim_param
,
792 context
->dim
, isl_dim_param
)) {
793 pw
= FN(PW
,align_params
)(pw
, isl_set_get_space(context
));
794 context
= isl_set_align_params(context
, FN(PW
,get_space
)(pw
));
797 context
= isl_set_compute_divs(context
);
798 hull
= isl_set_simple_hull(isl_set_copy(context
));
804 for (i
= pw
->n
- 1; i
>= 0; --i
) {
808 set_i
= isl_set_intersect(isl_set_copy(pw
->p
[i
].set
),
809 isl_set_copy(context
));
810 empty
= isl_set_plain_is_empty(set_i
);
811 pw
->p
[i
].FIELD
= fn_el(pw
->p
[i
].FIELD
, set_i
);
812 pw
->p
[i
].set
= fn_dom(pw
->p
[i
].set
, isl_basic_set_copy(hull
));
813 if (!pw
->p
[i
].FIELD
|| !pw
->p
[i
].set
)
816 isl_set_free(pw
->p
[i
].set
);
817 FN(EL
,free
)(pw
->p
[i
].FIELD
);
819 pw
->p
[i
] = pw
->p
[pw
->n
- 1];
824 isl_basic_set_free(hull
);
825 isl_set_free(context
);
830 isl_basic_set_free(hull
);
831 isl_set_free(context
);
835 static __isl_give PW
*FN(PW
,gist_domain_aligned
)(__isl_take PW
*pw
,
836 __isl_take isl_set
*set
)
838 return FN(PW
,gist_aligned
)(pw
, set
, &FN(EL
,gist
),
839 &isl_set_gist_basic_set
);
842 __isl_give PW
*FN(PW
,gist
)(__isl_take PW
*pw
, __isl_take isl_set
*context
)
844 return FN(PW
,align_params_pw_set_and
)(pw
, context
,
845 &FN(PW
,gist_domain_aligned
));
848 static __isl_give PW
*FN(PW
,gist_params_aligned
)(__isl_take PW
*pw
,
849 __isl_take isl_set
*set
)
851 return FN(PW
,gist_aligned
)(pw
, set
, &FN(EL
,gist_params
),
852 &isl_set_gist_params_basic_set
);
855 __isl_give PW
*FN(PW
,gist_params
)(__isl_take PW
*pw
,
856 __isl_take isl_set
*context
)
858 return FN(PW
,align_params_pw_set_and
)(pw
, context
,
859 &FN(PW
,gist_params_aligned
));
862 __isl_give PW
*FN(PW
,coalesce
)(__isl_take PW
*pw
)
871 for (i
= pw
->n
- 1; i
>= 0; --i
) {
872 for (j
= i
- 1; j
>= 0; --j
) {
873 if (!FN(EL
,plain_is_equal
)(pw
->p
[i
].FIELD
,
876 pw
->p
[j
].set
= isl_set_union(pw
->p
[j
].set
,
878 FN(EL
,free
)(pw
->p
[i
].FIELD
);
880 pw
->p
[i
] = pw
->p
[pw
->n
- 1];
886 pw
->p
[i
].set
= isl_set_coalesce(pw
->p
[i
].set
);
897 isl_ctx
*FN(PW
,get_ctx
)(__isl_keep PW
*pw
)
899 return pw
? isl_space_get_ctx(pw
->dim
) : NULL
;
902 #ifndef NO_INVOLVES_DIMS
903 int FN(PW
,involves_dims
)(__isl_keep PW
*pw
, enum isl_dim_type type
,
904 unsigned first
, unsigned n
)
907 enum isl_dim_type set_type
;
911 if (pw
->n
== 0 || n
== 0)
914 set_type
= type
== isl_dim_in
? isl_dim_set
: type
;
916 for (i
= 0; i
< pw
->n
; ++i
) {
917 int involves
= FN(EL
,involves_dims
)(pw
->p
[i
].FIELD
,
919 if (involves
< 0 || involves
)
921 involves
= isl_set_involves_dims(pw
->p
[i
].set
,
923 if (involves
< 0 || involves
)
930 __isl_give PW
*FN(PW
,set_dim_name
)(__isl_take PW
*pw
,
931 enum isl_dim_type type
, unsigned pos
, const char *s
)
934 enum isl_dim_type set_type
;
940 set_type
= type
== isl_dim_in
? isl_dim_set
: type
;
942 pw
->dim
= isl_space_set_dim_name(pw
->dim
, type
, pos
, s
);
946 for (i
= 0; i
< pw
->n
; ++i
) {
947 pw
->p
[i
].set
= isl_set_set_dim_name(pw
->p
[i
].set
,
951 pw
->p
[i
].FIELD
= FN(EL
,set_dim_name
)(pw
->p
[i
].FIELD
, type
, pos
, s
);
963 __isl_give PW
*FN(PW
,drop_dims
)(__isl_take PW
*pw
,
964 enum isl_dim_type type
, unsigned first
, unsigned n
)
967 enum isl_dim_type set_type
;
971 if (n
== 0 && !isl_space_get_tuple_name(pw
->dim
, type
))
974 set_type
= type
== isl_dim_in
? isl_dim_set
: type
;
979 pw
->dim
= isl_space_drop_dims(pw
->dim
, type
, first
, n
);
982 for (i
= 0; i
< pw
->n
; ++i
) {
983 pw
->p
[i
].set
= isl_set_drop(pw
->p
[i
].set
, set_type
, first
, n
);
986 pw
->p
[i
].FIELD
= FN(EL
,drop_dims
)(pw
->p
[i
].FIELD
, type
, first
, n
);
997 /* This function is very similar to drop_dims.
998 * The only difference is that the cells may still involve
999 * the specified dimensions. They are removed using
1000 * isl_set_project_out instead of isl_set_drop.
1002 __isl_give PW
*FN(PW
,project_out
)(__isl_take PW
*pw
,
1003 enum isl_dim_type type
, unsigned first
, unsigned n
)
1006 enum isl_dim_type set_type
;
1010 if (n
== 0 && !isl_space_get_tuple_name(pw
->dim
, type
))
1013 set_type
= type
== isl_dim_in
? isl_dim_set
: type
;
1015 pw
= FN(PW
,cow
)(pw
);
1018 pw
->dim
= isl_space_drop_dims(pw
->dim
, type
, first
, n
);
1021 for (i
= 0; i
< pw
->n
; ++i
) {
1022 pw
->p
[i
].set
= isl_set_project_out(pw
->p
[i
].set
,
1023 set_type
, first
, n
);
1026 pw
->p
[i
].FIELD
= FN(EL
,drop_dims
)(pw
->p
[i
].FIELD
, type
, first
, n
);
1027 if (!pw
->p
[i
].FIELD
)
1037 /* Project the domain of pw onto its parameter space.
1039 __isl_give PW
*FN(PW
,project_domain_on_params
)(__isl_take PW
*pw
)
1044 n
= FN(PW
,dim
)(pw
, isl_dim_in
);
1045 pw
= FN(PW
,project_out
)(pw
, isl_dim_in
, 0, n
);
1046 space
= FN(PW
,get_domain_space
)(pw
);
1047 space
= isl_space_params(space
);
1048 pw
= FN(PW
,reset_domain_space
)(pw
, space
);
1053 #ifndef NO_INSERT_DIMS
1054 __isl_give PW
*FN(PW
,insert_dims
)(__isl_take PW
*pw
, enum isl_dim_type type
,
1055 unsigned first
, unsigned n
)
1058 enum isl_dim_type set_type
;
1062 if (n
== 0 && !isl_space_is_named_or_nested(pw
->dim
, type
))
1065 set_type
= type
== isl_dim_in
? isl_dim_set
: type
;
1067 pw
= FN(PW
,cow
)(pw
);
1071 pw
->dim
= isl_space_insert_dims(pw
->dim
, type
, first
, n
);
1075 for (i
= 0; i
< pw
->n
; ++i
) {
1076 pw
->p
[i
].set
= isl_set_insert_dims(pw
->p
[i
].set
,
1077 set_type
, first
, n
);
1080 pw
->p
[i
].FIELD
= FN(EL
,insert_dims
)(pw
->p
[i
].FIELD
,
1082 if (!pw
->p
[i
].FIELD
)
1093 __isl_give PW
*FN(PW
,fix_dim
)(__isl_take PW
*pw
,
1094 enum isl_dim_type type
, unsigned pos
, isl_int v
)
1101 if (type
== isl_dim_in
)
1104 pw
= FN(PW
,cow
)(pw
);
1107 for (i
= 0; i
< pw
->n
; ++i
) {
1108 pw
->p
[i
].set
= isl_set_fix(pw
->p
[i
].set
, type
, pos
, v
);
1119 unsigned FN(PW
,dim
)(__isl_keep PW
*pw
, enum isl_dim_type type
)
1121 return pw
? isl_space_dim(pw
->dim
, type
) : 0;
1124 __isl_give PW
*FN(PW
,split_dims
)(__isl_take PW
*pw
,
1125 enum isl_dim_type type
, unsigned first
, unsigned n
)
1134 if (type
== isl_dim_in
)
1137 pw
= FN(PW
,cow
)(pw
);
1142 for (i
= 0; i
< pw
->n
; ++i
) {
1143 pw
->p
[i
].set
= isl_set_split_dims(pw
->p
[i
].set
, type
, first
, n
);
1155 /* Compute the maximal value attained by the piecewise quasipolynomial
1156 * on its domain or zero if the domain is empty.
1157 * In the worst case, the domain is scanned completely,
1158 * so the domain is assumed to be bounded.
1160 __isl_give isl_qpolynomial
*FN(PW
,opt
)(__isl_take PW
*pw
, int max
)
1163 isl_qpolynomial
*opt
;
1169 isl_space
*dim
= isl_space_copy(pw
->dim
);
1171 return isl_qpolynomial_zero_on_domain(isl_space_domain(dim
));
1174 opt
= FN(EL
,opt_on_domain
)(FN(EL
,copy
)(pw
->p
[0].FIELD
),
1175 isl_set_copy(pw
->p
[0].set
), max
);
1176 for (i
= 1; i
< pw
->n
; ++i
) {
1177 isl_qpolynomial
*opt_i
;
1178 opt_i
= FN(EL
,opt_on_domain
)(FN(EL
,copy
)(pw
->p
[i
].FIELD
),
1179 isl_set_copy(pw
->p
[i
].set
), max
);
1181 opt
= isl_qpolynomial_max_cst(opt
, opt_i
);
1183 opt
= isl_qpolynomial_min_cst(opt
, opt_i
);
1190 __isl_give isl_qpolynomial
*FN(PW
,max
)(__isl_take PW
*pw
)
1192 return FN(PW
,opt
)(pw
, 1);
1195 __isl_give isl_qpolynomial
*FN(PW
,min
)(__isl_take PW
*pw
)
1197 return FN(PW
,opt
)(pw
, 0);
1201 __isl_give isl_space
*FN(PW
,get_space
)(__isl_keep PW
*pw
)
1203 return pw
? isl_space_copy(pw
->dim
) : NULL
;
1206 __isl_give isl_space
*FN(PW
,get_domain_space
)(__isl_keep PW
*pw
)
1208 return pw
? isl_space_domain(isl_space_copy(pw
->dim
)) : NULL
;
1211 #ifndef NO_RESET_DIM
1212 /* Reset the space of "pw". Since we don't know if the elements
1213 * represent the spaces themselves or their domains, we pass along
1214 * both when we call their reset_space_and_domain.
1216 static __isl_give PW
*FN(PW
,reset_space_and_domain
)(__isl_take PW
*pw
,
1217 __isl_take isl_space
*space
, __isl_take isl_space
*domain
)
1221 pw
= FN(PW
,cow
)(pw
);
1222 if (!pw
|| !space
|| !domain
)
1225 for (i
= 0; i
< pw
->n
; ++i
) {
1226 pw
->p
[i
].set
= isl_set_reset_space(pw
->p
[i
].set
,
1227 isl_space_copy(domain
));
1230 pw
->p
[i
].FIELD
= FN(EL
,reset_space_and_domain
)(pw
->p
[i
].FIELD
,
1231 isl_space_copy(space
), isl_space_copy(domain
));
1232 if (!pw
->p
[i
].FIELD
)
1236 isl_space_free(domain
);
1238 isl_space_free(pw
->dim
);
1243 isl_space_free(domain
);
1244 isl_space_free(space
);
1249 __isl_give PW
*FN(PW
,reset_domain_space
)(__isl_take PW
*pw
,
1250 __isl_take isl_space
*domain
)
1254 space
= isl_space_extend_domain_with_range(isl_space_copy(domain
),
1255 FN(PW
,get_space
)(pw
));
1256 return FN(PW
,reset_space_and_domain
)(pw
, space
, domain
);
1259 __isl_give PW
*FN(PW
,reset_space
)(__isl_take PW
*pw
, __isl_take isl_space
*dim
)
1263 domain
= isl_space_domain(isl_space_copy(dim
));
1264 return FN(PW
,reset_space_and_domain
)(pw
, dim
, domain
);
1267 __isl_give PW
*FN(PW
,set_tuple_id
)(__isl_keep PW
*pw
, enum isl_dim_type type
,
1268 __isl_take isl_id
*id
)
1272 pw
= FN(PW
,cow
)(pw
);
1274 return isl_id_free(id
);
1276 space
= FN(PW
,get_space
)(pw
);
1277 space
= isl_space_set_tuple_id(space
, type
, id
);
1279 return FN(PW
,reset_space
)(pw
, space
);
1282 __isl_give PW
*FN(PW
,set_dim_id
)(__isl_take PW
*pw
,
1283 enum isl_dim_type type
, unsigned pos
, __isl_take isl_id
*id
)
1285 pw
= FN(PW
,cow
)(pw
);
1287 return isl_id_free(id
);
1288 pw
->dim
= isl_space_set_dim_id(pw
->dim
, type
, pos
, id
);
1289 return FN(PW
,reset_space
)(pw
, isl_space_copy(pw
->dim
));
1293 int FN(PW
,has_equal_space
)(__isl_keep PW
*pw1
, __isl_keep PW
*pw2
)
1298 return isl_space_is_equal(pw1
->dim
, pw2
->dim
);
1302 __isl_give PW
*FN(PW
,morph_domain
)(__isl_take PW
*pw
,
1303 __isl_take isl_morph
*morph
)
1311 ctx
= isl_space_get_ctx(pw
->dim
);
1312 isl_assert(ctx
, isl_space_is_domain_internal(morph
->dom
->dim
, pw
->dim
),
1315 pw
= FN(PW
,cow
)(pw
);
1318 pw
->dim
= isl_space_extend_domain_with_range(
1319 isl_space_copy(morph
->ran
->dim
), pw
->dim
);
1323 for (i
= 0; i
< pw
->n
; ++i
) {
1324 pw
->p
[i
].set
= isl_morph_set(isl_morph_copy(morph
), pw
->p
[i
].set
);
1327 pw
->p
[i
].FIELD
= FN(EL
,morph_domain
)(pw
->p
[i
].FIELD
,
1328 isl_morph_copy(morph
));
1329 if (!pw
->p
[i
].FIELD
)
1333 isl_morph_free(morph
);
1338 isl_morph_free(morph
);
1343 int FN(PW
,n_piece
)(__isl_keep PW
*pw
)
1345 return pw
? pw
->n
: 0;
1348 int FN(PW
,foreach_piece
)(__isl_keep PW
*pw
,
1349 int (*fn
)(__isl_take isl_set
*set
, __isl_take EL
*el
, void *user
),
1357 for (i
= 0; i
< pw
->n
; ++i
)
1358 if (fn(isl_set_copy(pw
->p
[i
].set
),
1359 FN(EL
,copy
)(pw
->p
[i
].FIELD
), user
) < 0)
1366 static int any_divs(__isl_keep isl_set
*set
)
1373 for (i
= 0; i
< set
->n
; ++i
)
1374 if (set
->p
[i
]->n_div
> 0)
1380 static int foreach_lifted_subset(__isl_take isl_set
*set
, __isl_take EL
*el
,
1381 int (*fn
)(__isl_take isl_set
*set
, __isl_take EL
*el
,
1382 void *user
), void *user
)
1389 for (i
= 0; i
< set
->n
; ++i
) {
1393 lift
= isl_set_from_basic_set(isl_basic_set_copy(set
->p
[i
]));
1394 lift
= isl_set_lift(lift
);
1396 copy
= FN(EL
,copy
)(el
);
1397 copy
= FN(EL
,lift
)(copy
, isl_set_get_space(lift
));
1399 if (fn(lift
, copy
, user
) < 0)
1413 int FN(PW
,foreach_lifted_piece
)(__isl_keep PW
*pw
,
1414 int (*fn
)(__isl_take isl_set
*set
, __isl_take EL
*el
,
1415 void *user
), void *user
)
1422 for (i
= 0; i
< pw
->n
; ++i
) {
1426 set
= isl_set_copy(pw
->p
[i
].set
);
1427 el
= FN(EL
,copy
)(pw
->p
[i
].FIELD
);
1428 if (!any_divs(set
)) {
1429 if (fn(set
, el
, user
) < 0)
1433 if (foreach_lifted_subset(set
, el
, fn
, user
) < 0)
1441 #ifndef NO_MOVE_DIMS
1442 __isl_give PW
*FN(PW
,move_dims
)(__isl_take PW
*pw
,
1443 enum isl_dim_type dst_type
, unsigned dst_pos
,
1444 enum isl_dim_type src_type
, unsigned src_pos
, unsigned n
)
1448 pw
= FN(PW
,cow
)(pw
);
1452 pw
->dim
= isl_space_move_dims(pw
->dim
, dst_type
, dst_pos
, src_type
, src_pos
, n
);
1456 for (i
= 0; i
< pw
->n
; ++i
) {
1457 pw
->p
[i
].FIELD
= FN(EL
,move_dims
)(pw
->p
[i
].FIELD
,
1458 dst_type
, dst_pos
, src_type
, src_pos
, n
);
1459 if (!pw
->p
[i
].FIELD
)
1463 if (dst_type
== isl_dim_in
)
1464 dst_type
= isl_dim_set
;
1465 if (src_type
== isl_dim_in
)
1466 src_type
= isl_dim_set
;
1468 for (i
= 0; i
< pw
->n
; ++i
) {
1469 pw
->p
[i
].set
= isl_set_move_dims(pw
->p
[i
].set
,
1471 src_type
, src_pos
, n
);
1483 __isl_give PW
*FN(PW
,mul_isl_int
)(__isl_take PW
*pw
, isl_int v
)
1487 if (isl_int_is_one(v
))
1489 if (pw
&& DEFAULT_IS_ZERO
&& isl_int_is_zero(v
)) {
1491 isl_space
*dim
= FN(PW
,get_space
)(pw
);
1493 zero
= FN(PW
,ZERO
)(dim
, pw
->type
);
1495 zero
= FN(PW
,ZERO
)(dim
);
1500 pw
= FN(PW
,cow
)(pw
);
1507 if (isl_int_is_neg(v
))
1508 pw
->type
= isl_fold_type_negate(pw
->type
);
1510 for (i
= 0; i
< pw
->n
; ++i
) {
1511 pw
->p
[i
].FIELD
= FN(EL
,scale
)(pw
->p
[i
].FIELD
, v
);
1512 if (!pw
->p
[i
].FIELD
)
1522 __isl_give PW
*FN(PW
,scale
)(__isl_take PW
*pw
, isl_int v
)
1524 return FN(PW
,mul_isl_int
)(pw
, v
);
1527 static int FN(PW
,qsort_set_cmp
)(const void *p1
, const void *p2
)
1529 isl_set
*set1
= *(isl_set
* const *)p1
;
1530 isl_set
*set2
= *(isl_set
* const *)p2
;
1532 return isl_set_plain_cmp(set1
, set2
);
1535 /* We normalize in place, but if anything goes wrong we need
1536 * to return NULL, so we need to make sure we don't change the
1537 * meaning of any possible other copies of map.
1539 __isl_give PW
*FN(PW
,normalize
)(__isl_take PW
*pw
)
1546 for (i
= 0; i
< pw
->n
; ++i
) {
1547 set
= isl_set_normalize(isl_set_copy(pw
->p
[i
].set
));
1549 return FN(PW
,free
)(pw
);
1550 isl_set_free(pw
->p
[i
].set
);
1553 qsort(pw
->p
, pw
->n
, sizeof(pw
->p
[0]), &FN(PW
,qsort_set_cmp
));
1554 for (i
= pw
->n
- 1; i
>= 1; --i
) {
1555 if (!isl_set_plain_is_equal(pw
->p
[i
- 1].set
, pw
->p
[i
].set
))
1557 if (!FN(EL
,plain_is_equal
)(pw
->p
[i
- 1].FIELD
, pw
->p
[i
].FIELD
))
1559 set
= isl_set_union(isl_set_copy(pw
->p
[i
- 1].set
),
1560 isl_set_copy(pw
->p
[i
].set
));
1562 return FN(PW
,free
)(pw
);
1563 isl_set_free(pw
->p
[i
].set
);
1564 FN(EL
,free
)(pw
->p
[i
].FIELD
);
1565 isl_set_free(pw
->p
[i
- 1].set
);
1566 pw
->p
[i
- 1].set
= set
;
1567 for (j
= i
+ 1; j
< pw
->n
; ++j
)
1568 pw
->p
[j
- 1] = pw
->p
[j
];
1575 /* Is pw1 obviously equal to pw2?
1576 * That is, do they have obviously identical cells and obviously identical
1577 * elements on each cell?
1579 int FN(PW
,plain_is_equal
)(__isl_keep PW
*pw1
, __isl_keep PW
*pw2
)
1589 if (!isl_space_is_equal(pw1
->dim
, pw2
->dim
))
1592 pw1
= FN(PW
,copy
)(pw1
);
1593 pw2
= FN(PW
,copy
)(pw2
);
1594 pw1
= FN(PW
,normalize
)(pw1
);
1595 pw2
= FN(PW
,normalize
)(pw2
);
1599 equal
= pw1
->n
== pw2
->n
;
1600 for (i
= 0; equal
&& i
< pw1
->n
; ++i
) {
1601 equal
= isl_set_plain_is_equal(pw1
->p
[i
].set
, pw2
->p
[i
].set
);
1606 equal
= FN(EL
,plain_is_equal
)(pw1
->p
[i
].FIELD
, pw2
->p
[i
].FIELD
);