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 int FN(PW
,IS_ZERO
)(__isl_keep PW
*pw
)
185 __isl_give PW
*FN(PW
,realign_domain
)(__isl_take PW
*pw
,
186 __isl_take isl_reordering
*exp
)
194 for (i
= 0; i
< pw
->n
; ++i
) {
195 pw
->p
[i
].set
= isl_set_realign(pw
->p
[i
].set
,
196 isl_reordering_copy(exp
));
199 pw
->p
[i
].FIELD
= FN(EL
,realign_domain
)(pw
->p
[i
].FIELD
,
200 isl_reordering_copy(exp
));
205 pw
= FN(PW
,reset_domain_space
)(pw
, isl_space_copy(exp
->dim
));
207 isl_reordering_free(exp
);
210 isl_reordering_free(exp
);
215 /* Align the parameters of "pw" to those of "model".
217 __isl_give PW
*FN(PW
,align_params
)(__isl_take PW
*pw
, __isl_take isl_space
*model
)
224 ctx
= isl_space_get_ctx(model
);
225 if (!isl_space_has_named_params(model
))
226 isl_die(ctx
, isl_error_invalid
,
227 "model has unnamed parameters", goto error
);
228 if (!isl_space_has_named_params(pw
->dim
))
229 isl_die(ctx
, isl_error_invalid
,
230 "input has unnamed parameters", goto error
);
231 if (!isl_space_match(pw
->dim
, isl_dim_param
, model
, isl_dim_param
)) {
234 model
= isl_space_drop_dims(model
, isl_dim_in
,
235 0, isl_space_dim(model
, isl_dim_in
));
236 model
= isl_space_drop_dims(model
, isl_dim_out
,
237 0, isl_space_dim(model
, isl_dim_out
));
238 exp
= isl_parameter_alignment_reordering(pw
->dim
, model
);
239 exp
= isl_reordering_extend_space(exp
,
240 FN(PW
,get_domain_space
)(pw
));
241 pw
= FN(PW
,realign_domain
)(pw
, exp
);
244 isl_space_free(model
);
247 isl_space_free(model
);
252 static __isl_give PW
*align_params_pw_pw_and(__isl_take PW
*pw1
,
254 __isl_give PW
*(*fn
)(__isl_take PW
*pw1
, __isl_take PW
*pw2
))
260 if (isl_space_match(pw1
->dim
, isl_dim_param
, pw2
->dim
, isl_dim_param
))
262 ctx
= FN(PW
,get_ctx
)(pw1
);
263 if (!isl_space_has_named_params(pw1
->dim
) ||
264 !isl_space_has_named_params(pw2
->dim
))
265 isl_die(ctx
, isl_error_invalid
,
266 "unaligned unnamed parameters", goto error
);
267 pw1
= FN(PW
,align_params
)(pw1
, FN(PW
,get_space
)(pw2
));
268 pw2
= FN(PW
,align_params
)(pw2
, FN(PW
,get_space
)(pw1
));
276 static __isl_give PW
*align_params_pw_set_and(__isl_take PW
*pw
,
277 __isl_take isl_set
*set
,
278 __isl_give PW
*(*fn
)(__isl_take PW
*pw
, __isl_take isl_set
*set
))
284 if (isl_space_match(pw
->dim
, isl_dim_param
, set
->dim
, isl_dim_param
))
286 ctx
= FN(PW
,get_ctx
)(pw
);
287 if (!isl_space_has_named_params(pw
->dim
) ||
288 !isl_space_has_named_params(set
->dim
))
289 isl_die(ctx
, isl_error_invalid
,
290 "unaligned unnamed parameters", goto error
);
291 pw
= FN(PW
,align_params
)(pw
, isl_set_get_space(set
));
292 set
= isl_set_align_params(set
, FN(PW
,get_space
)(pw
));
301 static __isl_give PW
*FN(PW
,add_aligned
)(__isl_take PW
*pw1
, __isl_take PW
*pw2
)
311 ctx
= isl_space_get_ctx(pw1
->dim
);
313 if (pw1
->type
!= pw2
->type
)
314 isl_die(ctx
, isl_error_invalid
,
315 "fold types don't match", goto error
);
317 isl_assert(ctx
, isl_space_is_equal(pw1
->dim
, pw2
->dim
), goto error
);
319 if (FN(PW
,IS_ZERO
)(pw1
)) {
324 if (FN(PW
,IS_ZERO
)(pw2
)) {
329 n
= (pw1
->n
+ 1) * (pw2
->n
+ 1);
331 res
= FN(PW
,alloc_size
)(isl_space_copy(pw1
->dim
), pw1
->type
, n
);
333 res
= FN(PW
,alloc_size
)(isl_space_copy(pw1
->dim
), n
);
336 for (i
= 0; i
< pw1
->n
; ++i
) {
337 set
= isl_set_copy(pw1
->p
[i
].set
);
338 for (j
= 0; j
< pw2
->n
; ++j
) {
339 struct isl_set
*common
;
341 set
= isl_set_subtract(set
,
342 isl_set_copy(pw2
->p
[j
].set
));
343 common
= isl_set_intersect(isl_set_copy(pw1
->p
[i
].set
),
344 isl_set_copy(pw2
->p
[j
].set
));
345 if (isl_set_plain_is_empty(common
)) {
346 isl_set_free(common
);
350 sum
= FN(EL
,add_on_domain
)(common
,
351 FN(EL
,copy
)(pw1
->p
[i
].FIELD
),
352 FN(EL
,copy
)(pw2
->p
[j
].FIELD
));
354 res
= FN(PW
,add_piece
)(res
, common
, sum
);
356 res
= FN(PW
,add_piece
)(res
, set
, FN(EL
,copy
)(pw1
->p
[i
].FIELD
));
359 for (j
= 0; j
< pw2
->n
; ++j
) {
360 set
= isl_set_copy(pw2
->p
[j
].set
);
361 for (i
= 0; i
< pw1
->n
; ++i
)
362 set
= isl_set_subtract(set
,
363 isl_set_copy(pw1
->p
[i
].set
));
364 res
= FN(PW
,add_piece
)(res
, set
, FN(EL
,copy
)(pw2
->p
[j
].FIELD
));
377 __isl_give PW
*FN(PW
,add
)(__isl_take PW
*pw1
, __isl_take PW
*pw2
)
379 return align_params_pw_pw_and(pw1
, pw2
, &FN(PW
,add_aligned
));
382 /* Make sure "pw" has room for at least "n" more pieces.
384 * If there is only one reference to pw, we extend it in place.
385 * Otherwise, we create a new PW and copy the pieces.
387 static __isl_give PW
*FN(PW
,grow
)(__isl_take PW
*pw
, int n
)
395 if (pw
->n
+ n
<= pw
->size
)
397 ctx
= FN(PW
,get_ctx
)(pw
);
400 res
= isl_realloc(ctx
, pw
, struct PW
,
401 sizeof(struct PW
) + (n
- 1) * sizeof(S(PW
,piece
)));
403 return FN(PW
,free
)(pw
);
408 res
= FN(PW
,alloc_size
)(isl_space_copy(pw
->dim
), pw
->type
, n
);
410 res
= FN(PW
,alloc_size
)(isl_space_copy(pw
->dim
), n
);
413 return FN(PW
,free
)(pw
);
414 for (i
= 0; i
< pw
->n
; ++i
)
415 res
= FN(PW
,add_piece
)(res
, isl_set_copy(pw
->p
[i
].set
),
416 FN(EL
,copy
)(pw
->p
[i
].FIELD
));
421 static __isl_give PW
*FN(PW
,add_disjoint_aligned
)(__isl_take PW
*pw1
,
430 if (pw1
->size
< pw1
->n
+ pw2
->n
&& pw1
->n
< pw2
->n
)
431 return FN(PW
,add_disjoint_aligned
)(pw2
, pw1
);
433 ctx
= isl_space_get_ctx(pw1
->dim
);
435 if (pw1
->type
!= pw2
->type
)
436 isl_die(ctx
, isl_error_invalid
,
437 "fold types don't match", goto error
);
439 isl_assert(ctx
, isl_space_is_equal(pw1
->dim
, pw2
->dim
), goto error
);
441 if (FN(PW
,IS_ZERO
)(pw1
)) {
446 if (FN(PW
,IS_ZERO
)(pw2
)) {
451 pw1
= FN(PW
,grow
)(pw1
, pw2
->n
);
455 for (i
= 0; i
< pw2
->n
; ++i
)
456 pw1
= FN(PW
,add_piece
)(pw1
,
457 isl_set_copy(pw2
->p
[i
].set
),
458 FN(EL
,copy
)(pw2
->p
[i
].FIELD
));
469 __isl_give PW
*FN(PW
,add_disjoint
)(__isl_take PW
*pw1
, __isl_take PW
*pw2
)
471 return align_params_pw_pw_and(pw1
, pw2
, &FN(PW
,add_disjoint_aligned
));
475 __isl_give PW
*FN(PW
,neg
)(__isl_take PW
*pw
)
482 if (FN(PW
,IS_ZERO
)(pw
))
489 for (i
= 0; i
< pw
->n
; ++i
) {
490 pw
->p
[i
].FIELD
= FN(EL
,neg
)(pw
->p
[i
].FIELD
);
492 return FN(PW
,free
)(pw
);
498 __isl_give PW
*FN(PW
,sub
)(__isl_take PW
*pw1
, __isl_take PW
*pw2
)
500 return FN(PW
,add
)(pw1
, FN(PW
,neg
)(pw2
));
505 __isl_give isl_qpolynomial
*FN(PW
,eval
)(__isl_take PW
*pw
,
506 __isl_take isl_point
*pnt
)
511 isl_space
*pnt_dim
= NULL
;
516 ctx
= isl_point_get_ctx(pnt
);
517 pnt_dim
= isl_point_get_space(pnt
);
518 isl_assert(ctx
, isl_space_is_domain(pnt_dim
, pw
->dim
), goto error
);
520 for (i
= 0; i
< pw
->n
; ++i
) {
521 found
= isl_set_contains_point(pw
->p
[i
].set
, pnt
);
528 qp
= FN(EL
,eval
)(FN(EL
,copy
)(pw
->p
[i
].FIELD
),
529 isl_point_copy(pnt
));
531 qp
= isl_qpolynomial_zero_on_domain(FN(PW
,get_domain_space
)(pw
));
533 isl_space_free(pnt_dim
);
538 isl_space_free(pnt_dim
);
544 __isl_give isl_set
*FN(PW
,domain
)(__isl_take PW
*pw
)
552 dom
= isl_set_empty(FN(PW
,get_domain_space
)(pw
));
553 for (i
= 0; i
< pw
->n
; ++i
)
554 dom
= isl_set_union_disjoint(dom
, isl_set_copy(pw
->p
[i
].set
));
561 static __isl_give PW
*FN(PW
,intersect_domain_aligned
)(__isl_take PW
*pw
,
562 __isl_take isl_set
*set
)
578 for (i
= pw
->n
- 1; i
>= 0; --i
) {
580 pw
->p
[i
].set
= isl_set_intersect(pw
->p
[i
].set
, isl_set_copy(set
));
583 aff
= isl_set_affine_hull(isl_set_copy(pw
->p
[i
].set
));
584 pw
->p
[i
].FIELD
= FN(EL
,substitute_equalities
)(pw
->p
[i
].FIELD
,
586 if (isl_set_plain_is_empty(pw
->p
[i
].set
)) {
587 isl_set_free(pw
->p
[i
].set
);
588 FN(EL
,free
)(pw
->p
[i
].FIELD
);
590 pw
->p
[i
] = pw
->p
[pw
->n
- 1];
603 __isl_give PW
*FN(PW
,intersect_domain
)(__isl_take PW
*pw
,
604 __isl_take isl_set
*context
)
606 return align_params_pw_set_and(pw
, context
,
607 &FN(PW
,intersect_domain_aligned
));
610 static __isl_give PW
*FN(PW
,gist_aligned
)(__isl_take PW
*pw
,
611 __isl_take isl_set
*context
)
614 isl_basic_set
*hull
= NULL
;
620 isl_set_free(context
);
624 if (!isl_space_match(pw
->dim
, isl_dim_param
,
625 context
->dim
, isl_dim_param
)) {
626 pw
= FN(PW
,align_params
)(pw
, isl_set_get_space(context
));
627 context
= isl_set_align_params(context
, FN(PW
,get_space
)(pw
));
630 context
= isl_set_compute_divs(context
);
631 hull
= isl_set_simple_hull(isl_set_copy(context
));
637 for (i
= pw
->n
- 1; i
>= 0; --i
) {
638 pw
->p
[i
].set
= isl_set_intersect(pw
->p
[i
].set
,
639 isl_set_copy(context
));
642 pw
->p
[i
].FIELD
= FN(EL
,gist
)(pw
->p
[i
].FIELD
,
643 isl_set_copy(pw
->p
[i
].set
));
644 pw
->p
[i
].set
= isl_set_gist_basic_set(pw
->p
[i
].set
,
645 isl_basic_set_copy(hull
));
648 if (isl_set_plain_is_empty(pw
->p
[i
].set
)) {
649 isl_set_free(pw
->p
[i
].set
);
650 FN(EL
,free
)(pw
->p
[i
].FIELD
);
652 pw
->p
[i
] = pw
->p
[pw
->n
- 1];
657 isl_basic_set_free(hull
);
658 isl_set_free(context
);
663 isl_basic_set_free(hull
);
664 isl_set_free(context
);
668 __isl_give PW
*FN(PW
,gist
)(__isl_take PW
*pw
, __isl_take isl_set
*context
)
670 return align_params_pw_set_and(pw
, context
, &FN(PW
,gist_aligned
));
673 __isl_give PW
*FN(PW
,coalesce
)(__isl_take PW
*pw
)
682 for (i
= pw
->n
- 1; i
>= 0; --i
) {
683 for (j
= i
- 1; j
>= 0; --j
) {
684 if (!FN(EL
,plain_is_equal
)(pw
->p
[i
].FIELD
,
687 pw
->p
[j
].set
= isl_set_union(pw
->p
[j
].set
,
689 FN(EL
,free
)(pw
->p
[i
].FIELD
);
691 pw
->p
[i
] = pw
->p
[pw
->n
- 1];
697 pw
->p
[i
].set
= isl_set_coalesce(pw
->p
[i
].set
);
708 isl_ctx
*FN(PW
,get_ctx
)(__isl_keep PW
*pw
)
710 return pw
? isl_space_get_ctx(pw
->dim
) : NULL
;
713 #ifndef NO_INVOLVES_DIMS
714 int FN(PW
,involves_dims
)(__isl_keep PW
*pw
, enum isl_dim_type type
,
715 unsigned first
, unsigned n
)
718 enum isl_dim_type set_type
;
722 if (pw
->n
== 0 || n
== 0)
725 set_type
= type
== isl_dim_in
? isl_dim_set
: type
;
727 for (i
= 0; i
< pw
->n
; ++i
) {
728 int involves
= FN(EL
,involves_dims
)(pw
->p
[i
].FIELD
,
730 if (involves
< 0 || involves
)
732 involves
= isl_set_involves_dims(pw
->p
[i
].set
,
734 if (involves
< 0 || involves
)
741 __isl_give PW
*FN(PW
,set_dim_name
)(__isl_take PW
*pw
,
742 enum isl_dim_type type
, unsigned pos
, const char *s
)
745 enum isl_dim_type set_type
;
751 set_type
= type
== isl_dim_in
? isl_dim_set
: type
;
753 pw
->dim
= isl_space_set_dim_name(pw
->dim
, type
, pos
, s
);
757 for (i
= 0; i
< pw
->n
; ++i
) {
758 pw
->p
[i
].set
= isl_set_set_dim_name(pw
->p
[i
].set
,
762 pw
->p
[i
].FIELD
= FN(EL
,set_dim_name
)(pw
->p
[i
].FIELD
, type
, pos
, s
);
774 __isl_give PW
*FN(PW
,drop_dims
)(__isl_take PW
*pw
,
775 enum isl_dim_type type
, unsigned first
, unsigned n
)
778 enum isl_dim_type set_type
;
782 if (n
== 0 && !isl_space_get_tuple_name(pw
->dim
, type
))
785 set_type
= type
== isl_dim_in
? isl_dim_set
: type
;
790 pw
->dim
= isl_space_drop_dims(pw
->dim
, type
, first
, n
);
793 for (i
= 0; i
< pw
->n
; ++i
) {
794 pw
->p
[i
].set
= isl_set_drop(pw
->p
[i
].set
, set_type
, first
, n
);
797 pw
->p
[i
].FIELD
= FN(EL
,drop_dims
)(pw
->p
[i
].FIELD
, type
, first
, n
);
808 /* This function is very similar to drop_dims.
809 * The only difference is that the cells may still involve
810 * the specified dimensions. They are removed using
811 * isl_set_project_out instead of isl_set_drop.
813 __isl_give PW
*FN(PW
,project_out
)(__isl_take PW
*pw
,
814 enum isl_dim_type type
, unsigned first
, unsigned n
)
817 enum isl_dim_type set_type
;
821 if (n
== 0 && !isl_space_get_tuple_name(pw
->dim
, type
))
824 set_type
= type
== isl_dim_in
? isl_dim_set
: type
;
829 pw
->dim
= isl_space_drop_dims(pw
->dim
, type
, first
, n
);
832 for (i
= 0; i
< pw
->n
; ++i
) {
833 pw
->p
[i
].set
= isl_set_project_out(pw
->p
[i
].set
,
837 pw
->p
[i
].FIELD
= FN(EL
,drop_dims
)(pw
->p
[i
].FIELD
, type
, first
, n
);
848 /* Project the domain of pw onto its parameter space.
850 __isl_give PW
*FN(PW
,project_domain_on_params
)(__isl_take PW
*pw
)
855 n
= FN(PW
,dim
)(pw
, isl_dim_in
);
856 pw
= FN(PW
,project_out
)(pw
, isl_dim_in
, 0, n
);
857 space
= FN(PW
,get_domain_space
)(pw
);
858 space
= isl_space_params(space
);
859 pw
= FN(PW
,reset_domain_space
)(pw
, space
);
864 #ifndef NO_INSERT_DIMS
865 __isl_give PW
*FN(PW
,insert_dims
)(__isl_take PW
*pw
, enum isl_dim_type type
,
866 unsigned first
, unsigned n
)
869 enum isl_dim_type set_type
;
873 if (n
== 0 && !isl_space_is_named_or_nested(pw
->dim
, type
))
876 set_type
= type
== isl_dim_in
? isl_dim_set
: type
;
882 pw
->dim
= isl_space_insert_dims(pw
->dim
, type
, first
, n
);
886 for (i
= 0; i
< pw
->n
; ++i
) {
887 pw
->p
[i
].set
= isl_set_insert_dims(pw
->p
[i
].set
,
891 pw
->p
[i
].FIELD
= FN(EL
,insert_dims
)(pw
->p
[i
].FIELD
,
904 __isl_give PW
*FN(PW
,fix_dim
)(__isl_take PW
*pw
,
905 enum isl_dim_type type
, unsigned pos
, isl_int v
)
912 if (type
== isl_dim_in
)
918 for (i
= 0; i
< pw
->n
; ++i
) {
919 pw
->p
[i
].set
= isl_set_fix(pw
->p
[i
].set
, type
, pos
, v
);
930 unsigned FN(PW
,dim
)(__isl_keep PW
*pw
, enum isl_dim_type type
)
932 return pw
? isl_space_dim(pw
->dim
, type
) : 0;
935 __isl_give PW
*FN(PW
,split_dims
)(__isl_take PW
*pw
,
936 enum isl_dim_type type
, unsigned first
, unsigned n
)
945 if (type
== isl_dim_in
)
953 for (i
= 0; i
< pw
->n
; ++i
) {
954 pw
->p
[i
].set
= isl_set_split_dims(pw
->p
[i
].set
, type
, first
, n
);
966 /* Compute the maximal value attained by the piecewise quasipolynomial
967 * on its domain or zero if the domain is empty.
968 * In the worst case, the domain is scanned completely,
969 * so the domain is assumed to be bounded.
971 __isl_give isl_qpolynomial
*FN(PW
,opt
)(__isl_take PW
*pw
, int max
)
974 isl_qpolynomial
*opt
;
980 isl_space
*dim
= isl_space_copy(pw
->dim
);
982 return isl_qpolynomial_zero_on_domain(dim
);
985 opt
= FN(EL
,opt_on_domain
)(FN(EL
,copy
)(pw
->p
[0].FIELD
),
986 isl_set_copy(pw
->p
[0].set
), max
);
987 for (i
= 1; i
< pw
->n
; ++i
) {
988 isl_qpolynomial
*opt_i
;
989 opt_i
= FN(EL
,opt_on_domain
)(FN(EL
,copy
)(pw
->p
[i
].FIELD
),
990 isl_set_copy(pw
->p
[i
].set
), max
);
992 opt
= isl_qpolynomial_max_cst(opt
, opt_i
);
994 opt
= isl_qpolynomial_min_cst(opt
, opt_i
);
1001 __isl_give isl_qpolynomial
*FN(PW
,max
)(__isl_take PW
*pw
)
1003 return FN(PW
,opt
)(pw
, 1);
1006 __isl_give isl_qpolynomial
*FN(PW
,min
)(__isl_take PW
*pw
)
1008 return FN(PW
,opt
)(pw
, 0);
1012 __isl_give isl_space
*FN(PW
,get_space
)(__isl_keep PW
*pw
)
1014 return pw
? isl_space_copy(pw
->dim
) : NULL
;
1017 __isl_give isl_space
*FN(PW
,get_domain_space
)(__isl_keep PW
*pw
)
1019 return pw
? isl_space_domain(isl_space_copy(pw
->dim
)) : NULL
;
1022 #ifndef NO_RESET_DIM
1023 /* Reset the space of "pw". Since we don't know if the elements
1024 * represent the spaces themselves or their domains, we pass along
1025 * both when we call their reset_space_and_domain.
1027 static __isl_give PW
*FN(PW
,reset_space_and_domain
)(__isl_take PW
*pw
,
1028 __isl_take isl_space
*space
, __isl_take isl_space
*domain
)
1032 pw
= FN(PW
,cow
)(pw
);
1033 if (!pw
|| !space
|| !domain
)
1036 for (i
= 0; i
< pw
->n
; ++i
) {
1037 pw
->p
[i
].set
= isl_set_reset_space(pw
->p
[i
].set
,
1038 isl_space_copy(domain
));
1041 pw
->p
[i
].FIELD
= FN(EL
,reset_space_and_domain
)(pw
->p
[i
].FIELD
,
1042 isl_space_copy(space
), isl_space_copy(domain
));
1043 if (!pw
->p
[i
].FIELD
)
1047 isl_space_free(domain
);
1049 isl_space_free(pw
->dim
);
1054 isl_space_free(domain
);
1055 isl_space_free(space
);
1060 __isl_give PW
*FN(PW
,reset_domain_space
)(__isl_take PW
*pw
,
1061 __isl_take isl_space
*domain
)
1065 space
= isl_space_extend_domain_with_range(isl_space_copy(domain
),
1066 FN(PW
,get_space
)(pw
));
1067 return FN(PW
,reset_space_and_domain
)(pw
, space
, domain
);
1070 __isl_give PW
*FN(PW
,reset_space
)(__isl_take PW
*pw
, __isl_take isl_space
*dim
)
1074 domain
= isl_space_domain(isl_space_copy(dim
));
1075 return FN(PW
,reset_space_and_domain
)(pw
, dim
, domain
);
1079 int FN(PW
,has_equal_space
)(__isl_keep PW
*pw1
, __isl_keep PW
*pw2
)
1084 return isl_space_is_equal(pw1
->dim
, pw2
->dim
);
1088 __isl_give PW
*FN(PW
,morph_domain
)(__isl_take PW
*pw
,
1089 __isl_take isl_morph
*morph
)
1097 ctx
= isl_space_get_ctx(pw
->dim
);
1098 isl_assert(ctx
, isl_space_is_domain(morph
->dom
->dim
, pw
->dim
),
1101 pw
= FN(PW
,cow
)(pw
);
1104 pw
->dim
= isl_space_extend_domain_with_range(
1105 isl_space_copy(morph
->ran
->dim
), pw
->dim
);
1109 for (i
= 0; i
< pw
->n
; ++i
) {
1110 pw
->p
[i
].set
= isl_morph_set(isl_morph_copy(morph
), pw
->p
[i
].set
);
1113 pw
->p
[i
].FIELD
= FN(EL
,morph_domain
)(pw
->p
[i
].FIELD
,
1114 isl_morph_copy(morph
));
1115 if (!pw
->p
[i
].FIELD
)
1119 isl_morph_free(morph
);
1124 isl_morph_free(morph
);
1129 int FN(PW
,foreach_piece
)(__isl_keep PW
*pw
,
1130 int (*fn
)(__isl_take isl_set
*set
, __isl_take EL
*el
, void *user
),
1138 for (i
= 0; i
< pw
->n
; ++i
)
1139 if (fn(isl_set_copy(pw
->p
[i
].set
),
1140 FN(EL
,copy
)(pw
->p
[i
].FIELD
), user
) < 0)
1147 static int any_divs(__isl_keep isl_set
*set
)
1154 for (i
= 0; i
< set
->n
; ++i
)
1155 if (set
->p
[i
]->n_div
> 0)
1161 static int foreach_lifted_subset(__isl_take isl_set
*set
, __isl_take EL
*el
,
1162 int (*fn
)(__isl_take isl_set
*set
, __isl_take EL
*el
,
1163 void *user
), void *user
)
1170 for (i
= 0; i
< set
->n
; ++i
) {
1174 lift
= isl_set_from_basic_set(isl_basic_set_copy(set
->p
[i
]));
1175 lift
= isl_set_lift(lift
);
1177 copy
= FN(EL
,copy
)(el
);
1178 copy
= FN(EL
,lift
)(copy
, isl_set_get_space(lift
));
1180 if (fn(lift
, copy
, user
) < 0)
1194 int FN(PW
,foreach_lifted_piece
)(__isl_keep PW
*pw
,
1195 int (*fn
)(__isl_take isl_set
*set
, __isl_take EL
*el
,
1196 void *user
), void *user
)
1203 for (i
= 0; i
< pw
->n
; ++i
) {
1207 set
= isl_set_copy(pw
->p
[i
].set
);
1208 el
= FN(EL
,copy
)(pw
->p
[i
].FIELD
);
1209 if (!any_divs(set
)) {
1210 if (fn(set
, el
, user
) < 0)
1214 if (foreach_lifted_subset(set
, el
, fn
, user
) < 0)
1222 #ifndef NO_MOVE_DIMS
1223 __isl_give PW
*FN(PW
,move_dims
)(__isl_take PW
*pw
,
1224 enum isl_dim_type dst_type
, unsigned dst_pos
,
1225 enum isl_dim_type src_type
, unsigned src_pos
, unsigned n
)
1229 pw
= FN(PW
,cow
)(pw
);
1233 pw
->dim
= isl_space_move_dims(pw
->dim
, dst_type
, dst_pos
, src_type
, src_pos
, n
);
1237 for (i
= 0; i
< pw
->n
; ++i
) {
1238 pw
->p
[i
].FIELD
= FN(EL
,move_dims
)(pw
->p
[i
].FIELD
,
1239 dst_type
, dst_pos
, src_type
, src_pos
, n
);
1240 if (!pw
->p
[i
].FIELD
)
1244 if (dst_type
== isl_dim_in
)
1245 dst_type
= isl_dim_set
;
1246 if (src_type
== isl_dim_in
)
1247 src_type
= isl_dim_set
;
1249 for (i
= 0; i
< pw
->n
; ++i
) {
1250 pw
->p
[i
].set
= isl_set_move_dims(pw
->p
[i
].set
,
1252 src_type
, src_pos
, n
);
1264 __isl_give PW
*FN(PW
,mul_isl_int
)(__isl_take PW
*pw
, isl_int v
)
1268 if (isl_int_is_one(v
))
1270 if (pw
&& isl_int_is_zero(v
)) {
1272 isl_space
*dim
= FN(PW
,get_space
)(pw
);
1274 zero
= FN(PW
,ZERO
)(dim
, pw
->type
);
1276 zero
= FN(PW
,ZERO
)(dim
);
1281 pw
= FN(PW
,cow
)(pw
);
1288 if (isl_int_is_neg(v
))
1289 pw
->type
= isl_fold_type_negate(pw
->type
);
1291 for (i
= 0; i
< pw
->n
; ++i
) {
1292 pw
->p
[i
].FIELD
= FN(EL
,scale
)(pw
->p
[i
].FIELD
, v
);
1293 if (!pw
->p
[i
].FIELD
)
1303 __isl_give PW
*FN(PW
,scale
)(__isl_take PW
*pw
, isl_int v
)
1305 return FN(PW
,mul_isl_int
)(pw
, v
);