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 __isl_give isl_id
*FN(PW
,get_dim_id
)(__isl_keep PW
*pw
, enum isl_dim_type type
,
185 return pw
? isl_space_get_dim_id(pw
->dim
, type
, pos
) : NULL
;
188 const char *FN(PW
,get_tuple_name
)(__isl_keep PW
*pw
, enum isl_dim_type type
)
190 return pw
? isl_space_get_tuple_name(pw
->dim
, type
) : NULL
;
193 int FN(PW
,has_tuple_id
)(__isl_keep PW
*pw
, enum isl_dim_type type
)
195 return pw
? isl_space_has_tuple_id(pw
->dim
, type
) : -1;
198 __isl_give isl_id
*FN(PW
,get_tuple_id
)(__isl_keep PW
*pw
, enum isl_dim_type type
)
200 return pw
? isl_space_get_tuple_id(pw
->dim
, type
) : NULL
;
203 int FN(PW
,IS_ZERO
)(__isl_keep PW
*pw
)
212 __isl_give PW
*FN(PW
,realign_domain
)(__isl_take PW
*pw
,
213 __isl_take isl_reordering
*exp
)
221 for (i
= 0; i
< pw
->n
; ++i
) {
222 pw
->p
[i
].set
= isl_set_realign(pw
->p
[i
].set
,
223 isl_reordering_copy(exp
));
226 pw
->p
[i
].FIELD
= FN(EL
,realign_domain
)(pw
->p
[i
].FIELD
,
227 isl_reordering_copy(exp
));
232 pw
= FN(PW
,reset_domain_space
)(pw
, isl_space_copy(exp
->dim
));
234 isl_reordering_free(exp
);
237 isl_reordering_free(exp
);
242 /* Align the parameters of "pw" to those of "model".
244 __isl_give PW
*FN(PW
,align_params
)(__isl_take PW
*pw
, __isl_take isl_space
*model
)
251 ctx
= isl_space_get_ctx(model
);
252 if (!isl_space_has_named_params(model
))
253 isl_die(ctx
, isl_error_invalid
,
254 "model has unnamed parameters", goto error
);
255 if (!isl_space_has_named_params(pw
->dim
))
256 isl_die(ctx
, isl_error_invalid
,
257 "input has unnamed parameters", goto error
);
258 if (!isl_space_match(pw
->dim
, isl_dim_param
, model
, isl_dim_param
)) {
261 model
= isl_space_drop_dims(model
, isl_dim_in
,
262 0, isl_space_dim(model
, isl_dim_in
));
263 model
= isl_space_drop_dims(model
, isl_dim_out
,
264 0, isl_space_dim(model
, isl_dim_out
));
265 exp
= isl_parameter_alignment_reordering(pw
->dim
, model
);
266 exp
= isl_reordering_extend_space(exp
,
267 FN(PW
,get_domain_space
)(pw
));
268 pw
= FN(PW
,realign_domain
)(pw
, exp
);
271 isl_space_free(model
);
274 isl_space_free(model
);
279 static __isl_give PW
*FN(PW
,align_params_pw_pw_and
)(__isl_take PW
*pw1
,
281 __isl_give PW
*(*fn
)(__isl_take PW
*pw1
, __isl_take PW
*pw2
))
287 if (isl_space_match(pw1
->dim
, isl_dim_param
, pw2
->dim
, isl_dim_param
))
289 ctx
= FN(PW
,get_ctx
)(pw1
);
290 if (!isl_space_has_named_params(pw1
->dim
) ||
291 !isl_space_has_named_params(pw2
->dim
))
292 isl_die(ctx
, isl_error_invalid
,
293 "unaligned unnamed parameters", goto error
);
294 pw1
= FN(PW
,align_params
)(pw1
, FN(PW
,get_space
)(pw2
));
295 pw2
= FN(PW
,align_params
)(pw2
, FN(PW
,get_space
)(pw1
));
303 static __isl_give PW
*FN(PW
,align_params_pw_set_and
)(__isl_take PW
*pw
,
304 __isl_take isl_set
*set
,
305 __isl_give PW
*(*fn
)(__isl_take PW
*pw
, __isl_take isl_set
*set
))
311 if (isl_space_match(pw
->dim
, isl_dim_param
, set
->dim
, isl_dim_param
))
313 ctx
= FN(PW
,get_ctx
)(pw
);
314 if (!isl_space_has_named_params(pw
->dim
) ||
315 !isl_space_has_named_params(set
->dim
))
316 isl_die(ctx
, isl_error_invalid
,
317 "unaligned unnamed parameters", goto error
);
318 pw
= FN(PW
,align_params
)(pw
, isl_set_get_space(set
));
319 set
= isl_set_align_params(set
, FN(PW
,get_space
)(pw
));
328 static __isl_give PW
*FN(PW
,add_aligned
)(__isl_take PW
*pw1
, __isl_take PW
*pw2
)
338 ctx
= isl_space_get_ctx(pw1
->dim
);
340 if (pw1
->type
!= pw2
->type
)
341 isl_die(ctx
, isl_error_invalid
,
342 "fold types don't match", goto error
);
344 isl_assert(ctx
, isl_space_is_equal(pw1
->dim
, pw2
->dim
), goto error
);
346 if (FN(PW
,IS_ZERO
)(pw1
)) {
351 if (FN(PW
,IS_ZERO
)(pw2
)) {
356 n
= (pw1
->n
+ 1) * (pw2
->n
+ 1);
358 res
= FN(PW
,alloc_size
)(isl_space_copy(pw1
->dim
), pw1
->type
, n
);
360 res
= FN(PW
,alloc_size
)(isl_space_copy(pw1
->dim
), n
);
363 for (i
= 0; i
< pw1
->n
; ++i
) {
364 set
= isl_set_copy(pw1
->p
[i
].set
);
365 for (j
= 0; j
< pw2
->n
; ++j
) {
366 struct isl_set
*common
;
368 set
= isl_set_subtract(set
,
369 isl_set_copy(pw2
->p
[j
].set
));
370 common
= isl_set_intersect(isl_set_copy(pw1
->p
[i
].set
),
371 isl_set_copy(pw2
->p
[j
].set
));
372 if (isl_set_plain_is_empty(common
)) {
373 isl_set_free(common
);
377 sum
= FN(EL
,add_on_domain
)(common
,
378 FN(EL
,copy
)(pw1
->p
[i
].FIELD
),
379 FN(EL
,copy
)(pw2
->p
[j
].FIELD
));
381 res
= FN(PW
,add_piece
)(res
, common
, sum
);
383 res
= FN(PW
,add_piece
)(res
, set
, FN(EL
,copy
)(pw1
->p
[i
].FIELD
));
386 for (j
= 0; j
< pw2
->n
; ++j
) {
387 set
= isl_set_copy(pw2
->p
[j
].set
);
388 for (i
= 0; i
< pw1
->n
; ++i
)
389 set
= isl_set_subtract(set
,
390 isl_set_copy(pw1
->p
[i
].set
));
391 res
= FN(PW
,add_piece
)(res
, set
, FN(EL
,copy
)(pw2
->p
[j
].FIELD
));
404 __isl_give PW
*FN(PW
,add
)(__isl_take PW
*pw1
, __isl_take PW
*pw2
)
406 return FN(PW
,align_params_pw_pw_and
)(pw1
, pw2
, &FN(PW
,add_aligned
));
409 /* Make sure "pw" has room for at least "n" more pieces.
411 * If there is only one reference to pw, we extend it in place.
412 * Otherwise, we create a new PW and copy the pieces.
414 static __isl_give PW
*FN(PW
,grow
)(__isl_take PW
*pw
, int n
)
422 if (pw
->n
+ n
<= pw
->size
)
424 ctx
= FN(PW
,get_ctx
)(pw
);
427 res
= isl_realloc(ctx
, pw
, struct PW
,
428 sizeof(struct PW
) + (n
- 1) * sizeof(S(PW
,piece
)));
430 return FN(PW
,free
)(pw
);
435 res
= FN(PW
,alloc_size
)(isl_space_copy(pw
->dim
), pw
->type
, n
);
437 res
= FN(PW
,alloc_size
)(isl_space_copy(pw
->dim
), n
);
440 return FN(PW
,free
)(pw
);
441 for (i
= 0; i
< pw
->n
; ++i
)
442 res
= FN(PW
,add_piece
)(res
, isl_set_copy(pw
->p
[i
].set
),
443 FN(EL
,copy
)(pw
->p
[i
].FIELD
));
448 static __isl_give PW
*FN(PW
,add_disjoint_aligned
)(__isl_take PW
*pw1
,
457 if (pw1
->size
< pw1
->n
+ pw2
->n
&& pw1
->n
< pw2
->n
)
458 return FN(PW
,add_disjoint_aligned
)(pw2
, pw1
);
460 ctx
= isl_space_get_ctx(pw1
->dim
);
462 if (pw1
->type
!= pw2
->type
)
463 isl_die(ctx
, isl_error_invalid
,
464 "fold types don't match", goto error
);
466 isl_assert(ctx
, isl_space_is_equal(pw1
->dim
, pw2
->dim
), goto error
);
468 if (FN(PW
,IS_ZERO
)(pw1
)) {
473 if (FN(PW
,IS_ZERO
)(pw2
)) {
478 pw1
= FN(PW
,grow
)(pw1
, pw2
->n
);
482 for (i
= 0; i
< pw2
->n
; ++i
)
483 pw1
= FN(PW
,add_piece
)(pw1
,
484 isl_set_copy(pw2
->p
[i
].set
),
485 FN(EL
,copy
)(pw2
->p
[i
].FIELD
));
496 __isl_give PW
*FN(PW
,add_disjoint
)(__isl_take PW
*pw1
, __isl_take PW
*pw2
)
498 return FN(PW
,align_params_pw_pw_and
)(pw1
, pw2
,
499 &FN(PW
,add_disjoint_aligned
));
503 __isl_give PW
*FN(PW
,neg
)(__isl_take PW
*pw
)
510 if (FN(PW
,IS_ZERO
)(pw
))
517 for (i
= 0; i
< pw
->n
; ++i
) {
518 pw
->p
[i
].FIELD
= FN(EL
,neg
)(pw
->p
[i
].FIELD
);
520 return FN(PW
,free
)(pw
);
526 __isl_give PW
*FN(PW
,sub
)(__isl_take PW
*pw1
, __isl_take PW
*pw2
)
528 return FN(PW
,add
)(pw1
, FN(PW
,neg
)(pw2
));
533 __isl_give isl_qpolynomial
*FN(PW
,eval
)(__isl_take PW
*pw
,
534 __isl_take isl_point
*pnt
)
539 isl_space
*pnt_dim
= NULL
;
544 ctx
= isl_point_get_ctx(pnt
);
545 pnt_dim
= isl_point_get_space(pnt
);
546 isl_assert(ctx
, isl_space_is_domain(pnt_dim
, pw
->dim
), goto error
);
548 for (i
= 0; i
< pw
->n
; ++i
) {
549 found
= isl_set_contains_point(pw
->p
[i
].set
, pnt
);
556 qp
= FN(EL
,eval
)(FN(EL
,copy
)(pw
->p
[i
].FIELD
),
557 isl_point_copy(pnt
));
559 qp
= isl_qpolynomial_zero_on_domain(FN(PW
,get_domain_space
)(pw
));
561 isl_space_free(pnt_dim
);
566 isl_space_free(pnt_dim
);
572 __isl_give isl_set
*FN(PW
,domain
)(__isl_take PW
*pw
)
580 dom
= isl_set_empty(FN(PW
,get_domain_space
)(pw
));
581 for (i
= 0; i
< pw
->n
; ++i
)
582 dom
= isl_set_union_disjoint(dom
, isl_set_copy(pw
->p
[i
].set
));
589 static __isl_give PW
*FN(PW
,intersect_domain_aligned
)(__isl_take PW
*pw
,
590 __isl_take isl_set
*set
)
606 for (i
= pw
->n
- 1; i
>= 0; --i
) {
608 pw
->p
[i
].set
= isl_set_intersect(pw
->p
[i
].set
, isl_set_copy(set
));
611 aff
= isl_set_affine_hull(isl_set_copy(pw
->p
[i
].set
));
612 pw
->p
[i
].FIELD
= FN(EL
,substitute_equalities
)(pw
->p
[i
].FIELD
,
614 if (isl_set_plain_is_empty(pw
->p
[i
].set
)) {
615 isl_set_free(pw
->p
[i
].set
);
616 FN(EL
,free
)(pw
->p
[i
].FIELD
);
618 pw
->p
[i
] = pw
->p
[pw
->n
- 1];
631 __isl_give PW
*FN(PW
,intersect_domain
)(__isl_take PW
*pw
,
632 __isl_take isl_set
*context
)
634 return FN(PW
,align_params_pw_set_and
)(pw
, context
,
635 &FN(PW
,intersect_domain_aligned
));
638 static __isl_give PW
*FN(PW
,gist_aligned
)(__isl_take PW
*pw
,
639 __isl_take isl_set
*context
)
642 isl_basic_set
*hull
= NULL
;
648 isl_set_free(context
);
652 if (!isl_space_match(pw
->dim
, isl_dim_param
,
653 context
->dim
, isl_dim_param
)) {
654 pw
= FN(PW
,align_params
)(pw
, isl_set_get_space(context
));
655 context
= isl_set_align_params(context
, FN(PW
,get_space
)(pw
));
658 context
= isl_set_compute_divs(context
);
659 hull
= isl_set_simple_hull(isl_set_copy(context
));
665 for (i
= pw
->n
- 1; i
>= 0; --i
) {
666 pw
->p
[i
].set
= isl_set_intersect(pw
->p
[i
].set
,
667 isl_set_copy(context
));
670 pw
->p
[i
].FIELD
= FN(EL
,gist
)(pw
->p
[i
].FIELD
,
671 isl_set_copy(pw
->p
[i
].set
));
672 pw
->p
[i
].set
= isl_set_gist_basic_set(pw
->p
[i
].set
,
673 isl_basic_set_copy(hull
));
676 if (isl_set_plain_is_empty(pw
->p
[i
].set
)) {
677 isl_set_free(pw
->p
[i
].set
);
678 FN(EL
,free
)(pw
->p
[i
].FIELD
);
680 pw
->p
[i
] = pw
->p
[pw
->n
- 1];
685 isl_basic_set_free(hull
);
686 isl_set_free(context
);
691 isl_basic_set_free(hull
);
692 isl_set_free(context
);
696 __isl_give PW
*FN(PW
,gist
)(__isl_take PW
*pw
, __isl_take isl_set
*context
)
698 return FN(PW
,align_params_pw_set_and
)(pw
, context
, &FN(PW
,gist_aligned
));
701 __isl_give PW
*FN(PW
,coalesce
)(__isl_take PW
*pw
)
710 for (i
= pw
->n
- 1; i
>= 0; --i
) {
711 for (j
= i
- 1; j
>= 0; --j
) {
712 if (!FN(EL
,plain_is_equal
)(pw
->p
[i
].FIELD
,
715 pw
->p
[j
].set
= isl_set_union(pw
->p
[j
].set
,
717 FN(EL
,free
)(pw
->p
[i
].FIELD
);
719 pw
->p
[i
] = pw
->p
[pw
->n
- 1];
725 pw
->p
[i
].set
= isl_set_coalesce(pw
->p
[i
].set
);
736 isl_ctx
*FN(PW
,get_ctx
)(__isl_keep PW
*pw
)
738 return pw
? isl_space_get_ctx(pw
->dim
) : NULL
;
741 #ifndef NO_INVOLVES_DIMS
742 int FN(PW
,involves_dims
)(__isl_keep PW
*pw
, enum isl_dim_type type
,
743 unsigned first
, unsigned n
)
746 enum isl_dim_type set_type
;
750 if (pw
->n
== 0 || n
== 0)
753 set_type
= type
== isl_dim_in
? isl_dim_set
: type
;
755 for (i
= 0; i
< pw
->n
; ++i
) {
756 int involves
= FN(EL
,involves_dims
)(pw
->p
[i
].FIELD
,
758 if (involves
< 0 || involves
)
760 involves
= isl_set_involves_dims(pw
->p
[i
].set
,
762 if (involves
< 0 || involves
)
769 __isl_give PW
*FN(PW
,set_dim_name
)(__isl_take PW
*pw
,
770 enum isl_dim_type type
, unsigned pos
, const char *s
)
773 enum isl_dim_type set_type
;
779 set_type
= type
== isl_dim_in
? isl_dim_set
: type
;
781 pw
->dim
= isl_space_set_dim_name(pw
->dim
, type
, pos
, s
);
785 for (i
= 0; i
< pw
->n
; ++i
) {
786 pw
->p
[i
].set
= isl_set_set_dim_name(pw
->p
[i
].set
,
790 pw
->p
[i
].FIELD
= FN(EL
,set_dim_name
)(pw
->p
[i
].FIELD
, type
, pos
, s
);
802 __isl_give PW
*FN(PW
,drop_dims
)(__isl_take PW
*pw
,
803 enum isl_dim_type type
, unsigned first
, unsigned n
)
806 enum isl_dim_type set_type
;
810 if (n
== 0 && !isl_space_get_tuple_name(pw
->dim
, type
))
813 set_type
= type
== isl_dim_in
? isl_dim_set
: type
;
818 pw
->dim
= isl_space_drop_dims(pw
->dim
, type
, first
, n
);
821 for (i
= 0; i
< pw
->n
; ++i
) {
822 pw
->p
[i
].set
= isl_set_drop(pw
->p
[i
].set
, set_type
, first
, n
);
825 pw
->p
[i
].FIELD
= FN(EL
,drop_dims
)(pw
->p
[i
].FIELD
, type
, first
, n
);
836 /* This function is very similar to drop_dims.
837 * The only difference is that the cells may still involve
838 * the specified dimensions. They are removed using
839 * isl_set_project_out instead of isl_set_drop.
841 __isl_give PW
*FN(PW
,project_out
)(__isl_take PW
*pw
,
842 enum isl_dim_type type
, unsigned first
, unsigned n
)
845 enum isl_dim_type set_type
;
849 if (n
== 0 && !isl_space_get_tuple_name(pw
->dim
, type
))
852 set_type
= type
== isl_dim_in
? isl_dim_set
: type
;
857 pw
->dim
= isl_space_drop_dims(pw
->dim
, type
, first
, n
);
860 for (i
= 0; i
< pw
->n
; ++i
) {
861 pw
->p
[i
].set
= isl_set_project_out(pw
->p
[i
].set
,
865 pw
->p
[i
].FIELD
= FN(EL
,drop_dims
)(pw
->p
[i
].FIELD
, type
, first
, n
);
876 /* Project the domain of pw onto its parameter space.
878 __isl_give PW
*FN(PW
,project_domain_on_params
)(__isl_take PW
*pw
)
883 n
= FN(PW
,dim
)(pw
, isl_dim_in
);
884 pw
= FN(PW
,project_out
)(pw
, isl_dim_in
, 0, n
);
885 space
= FN(PW
,get_domain_space
)(pw
);
886 space
= isl_space_params(space
);
887 pw
= FN(PW
,reset_domain_space
)(pw
, space
);
892 #ifndef NO_INSERT_DIMS
893 __isl_give PW
*FN(PW
,insert_dims
)(__isl_take PW
*pw
, enum isl_dim_type type
,
894 unsigned first
, unsigned n
)
897 enum isl_dim_type set_type
;
901 if (n
== 0 && !isl_space_is_named_or_nested(pw
->dim
, type
))
904 set_type
= type
== isl_dim_in
? isl_dim_set
: type
;
910 pw
->dim
= isl_space_insert_dims(pw
->dim
, type
, first
, n
);
914 for (i
= 0; i
< pw
->n
; ++i
) {
915 pw
->p
[i
].set
= isl_set_insert_dims(pw
->p
[i
].set
,
919 pw
->p
[i
].FIELD
= FN(EL
,insert_dims
)(pw
->p
[i
].FIELD
,
932 __isl_give PW
*FN(PW
,fix_dim
)(__isl_take PW
*pw
,
933 enum isl_dim_type type
, unsigned pos
, isl_int v
)
940 if (type
== isl_dim_in
)
946 for (i
= 0; i
< pw
->n
; ++i
) {
947 pw
->p
[i
].set
= isl_set_fix(pw
->p
[i
].set
, type
, pos
, v
);
958 unsigned FN(PW
,dim
)(__isl_keep PW
*pw
, enum isl_dim_type type
)
960 return pw
? isl_space_dim(pw
->dim
, type
) : 0;
963 __isl_give PW
*FN(PW
,split_dims
)(__isl_take PW
*pw
,
964 enum isl_dim_type type
, unsigned first
, unsigned n
)
973 if (type
== isl_dim_in
)
981 for (i
= 0; i
< pw
->n
; ++i
) {
982 pw
->p
[i
].set
= isl_set_split_dims(pw
->p
[i
].set
, type
, first
, n
);
994 /* Compute the maximal value attained by the piecewise quasipolynomial
995 * on its domain or zero if the domain is empty.
996 * In the worst case, the domain is scanned completely,
997 * so the domain is assumed to be bounded.
999 __isl_give isl_qpolynomial
*FN(PW
,opt
)(__isl_take PW
*pw
, int max
)
1002 isl_qpolynomial
*opt
;
1008 isl_space
*dim
= isl_space_copy(pw
->dim
);
1010 return isl_qpolynomial_zero_on_domain(dim
);
1013 opt
= FN(EL
,opt_on_domain
)(FN(EL
,copy
)(pw
->p
[0].FIELD
),
1014 isl_set_copy(pw
->p
[0].set
), max
);
1015 for (i
= 1; i
< pw
->n
; ++i
) {
1016 isl_qpolynomial
*opt_i
;
1017 opt_i
= FN(EL
,opt_on_domain
)(FN(EL
,copy
)(pw
->p
[i
].FIELD
),
1018 isl_set_copy(pw
->p
[i
].set
), max
);
1020 opt
= isl_qpolynomial_max_cst(opt
, opt_i
);
1022 opt
= isl_qpolynomial_min_cst(opt
, opt_i
);
1029 __isl_give isl_qpolynomial
*FN(PW
,max
)(__isl_take PW
*pw
)
1031 return FN(PW
,opt
)(pw
, 1);
1034 __isl_give isl_qpolynomial
*FN(PW
,min
)(__isl_take PW
*pw
)
1036 return FN(PW
,opt
)(pw
, 0);
1040 __isl_give isl_space
*FN(PW
,get_space
)(__isl_keep PW
*pw
)
1042 return pw
? isl_space_copy(pw
->dim
) : NULL
;
1045 __isl_give isl_space
*FN(PW
,get_domain_space
)(__isl_keep PW
*pw
)
1047 return pw
? isl_space_domain(isl_space_copy(pw
->dim
)) : NULL
;
1050 #ifndef NO_RESET_DIM
1051 /* Reset the space of "pw". Since we don't know if the elements
1052 * represent the spaces themselves or their domains, we pass along
1053 * both when we call their reset_space_and_domain.
1055 static __isl_give PW
*FN(PW
,reset_space_and_domain
)(__isl_take PW
*pw
,
1056 __isl_take isl_space
*space
, __isl_take isl_space
*domain
)
1060 pw
= FN(PW
,cow
)(pw
);
1061 if (!pw
|| !space
|| !domain
)
1064 for (i
= 0; i
< pw
->n
; ++i
) {
1065 pw
->p
[i
].set
= isl_set_reset_space(pw
->p
[i
].set
,
1066 isl_space_copy(domain
));
1069 pw
->p
[i
].FIELD
= FN(EL
,reset_space_and_domain
)(pw
->p
[i
].FIELD
,
1070 isl_space_copy(space
), isl_space_copy(domain
));
1071 if (!pw
->p
[i
].FIELD
)
1075 isl_space_free(domain
);
1077 isl_space_free(pw
->dim
);
1082 isl_space_free(domain
);
1083 isl_space_free(space
);
1088 __isl_give PW
*FN(PW
,reset_domain_space
)(__isl_take PW
*pw
,
1089 __isl_take isl_space
*domain
)
1093 space
= isl_space_extend_domain_with_range(isl_space_copy(domain
),
1094 FN(PW
,get_space
)(pw
));
1095 return FN(PW
,reset_space_and_domain
)(pw
, space
, domain
);
1098 __isl_give PW
*FN(PW
,reset_space
)(__isl_take PW
*pw
, __isl_take isl_space
*dim
)
1102 domain
= isl_space_domain(isl_space_copy(dim
));
1103 return FN(PW
,reset_space_and_domain
)(pw
, dim
, domain
);
1106 __isl_give PW
*FN(PW
,set_tuple_id
)(__isl_keep PW
*pw
, enum isl_dim_type type
,
1107 __isl_take isl_id
*id
)
1111 pw
= FN(PW
,cow
)(pw
);
1113 return isl_id_free(id
);
1115 space
= FN(PW
,get_space
)(pw
);
1116 space
= isl_space_set_tuple_id(space
, type
, id
);
1118 return FN(PW
,reset_space
)(pw
, space
);
1121 __isl_give PW
*FN(PW
,set_dim_id
)(__isl_take PW
*pw
,
1122 enum isl_dim_type type
, unsigned pos
, __isl_take isl_id
*id
)
1124 pw
= FN(PW
,cow
)(pw
);
1126 return isl_id_free(id
);
1127 pw
->dim
= isl_space_set_dim_id(pw
->dim
, type
, pos
, id
);
1128 return FN(PW
,reset_space
)(pw
, isl_space_copy(pw
->dim
));
1132 int FN(PW
,has_equal_space
)(__isl_keep PW
*pw1
, __isl_keep PW
*pw2
)
1137 return isl_space_is_equal(pw1
->dim
, pw2
->dim
);
1141 __isl_give PW
*FN(PW
,morph_domain
)(__isl_take PW
*pw
,
1142 __isl_take isl_morph
*morph
)
1150 ctx
= isl_space_get_ctx(pw
->dim
);
1151 isl_assert(ctx
, isl_space_is_domain(morph
->dom
->dim
, pw
->dim
),
1154 pw
= FN(PW
,cow
)(pw
);
1157 pw
->dim
= isl_space_extend_domain_with_range(
1158 isl_space_copy(morph
->ran
->dim
), pw
->dim
);
1162 for (i
= 0; i
< pw
->n
; ++i
) {
1163 pw
->p
[i
].set
= isl_morph_set(isl_morph_copy(morph
), pw
->p
[i
].set
);
1166 pw
->p
[i
].FIELD
= FN(EL
,morph_domain
)(pw
->p
[i
].FIELD
,
1167 isl_morph_copy(morph
));
1168 if (!pw
->p
[i
].FIELD
)
1172 isl_morph_free(morph
);
1177 isl_morph_free(morph
);
1182 int FN(PW
,foreach_piece
)(__isl_keep PW
*pw
,
1183 int (*fn
)(__isl_take isl_set
*set
, __isl_take EL
*el
, void *user
),
1191 for (i
= 0; i
< pw
->n
; ++i
)
1192 if (fn(isl_set_copy(pw
->p
[i
].set
),
1193 FN(EL
,copy
)(pw
->p
[i
].FIELD
), user
) < 0)
1200 static int any_divs(__isl_keep isl_set
*set
)
1207 for (i
= 0; i
< set
->n
; ++i
)
1208 if (set
->p
[i
]->n_div
> 0)
1214 static int foreach_lifted_subset(__isl_take isl_set
*set
, __isl_take EL
*el
,
1215 int (*fn
)(__isl_take isl_set
*set
, __isl_take EL
*el
,
1216 void *user
), void *user
)
1223 for (i
= 0; i
< set
->n
; ++i
) {
1227 lift
= isl_set_from_basic_set(isl_basic_set_copy(set
->p
[i
]));
1228 lift
= isl_set_lift(lift
);
1230 copy
= FN(EL
,copy
)(el
);
1231 copy
= FN(EL
,lift
)(copy
, isl_set_get_space(lift
));
1233 if (fn(lift
, copy
, user
) < 0)
1247 int FN(PW
,foreach_lifted_piece
)(__isl_keep PW
*pw
,
1248 int (*fn
)(__isl_take isl_set
*set
, __isl_take EL
*el
,
1249 void *user
), void *user
)
1256 for (i
= 0; i
< pw
->n
; ++i
) {
1260 set
= isl_set_copy(pw
->p
[i
].set
);
1261 el
= FN(EL
,copy
)(pw
->p
[i
].FIELD
);
1262 if (!any_divs(set
)) {
1263 if (fn(set
, el
, user
) < 0)
1267 if (foreach_lifted_subset(set
, el
, fn
, user
) < 0)
1275 #ifndef NO_MOVE_DIMS
1276 __isl_give PW
*FN(PW
,move_dims
)(__isl_take PW
*pw
,
1277 enum isl_dim_type dst_type
, unsigned dst_pos
,
1278 enum isl_dim_type src_type
, unsigned src_pos
, unsigned n
)
1282 pw
= FN(PW
,cow
)(pw
);
1286 pw
->dim
= isl_space_move_dims(pw
->dim
, dst_type
, dst_pos
, src_type
, src_pos
, n
);
1290 for (i
= 0; i
< pw
->n
; ++i
) {
1291 pw
->p
[i
].FIELD
= FN(EL
,move_dims
)(pw
->p
[i
].FIELD
,
1292 dst_type
, dst_pos
, src_type
, src_pos
, n
);
1293 if (!pw
->p
[i
].FIELD
)
1297 if (dst_type
== isl_dim_in
)
1298 dst_type
= isl_dim_set
;
1299 if (src_type
== isl_dim_in
)
1300 src_type
= isl_dim_set
;
1302 for (i
= 0; i
< pw
->n
; ++i
) {
1303 pw
->p
[i
].set
= isl_set_move_dims(pw
->p
[i
].set
,
1305 src_type
, src_pos
, n
);
1317 __isl_give PW
*FN(PW
,mul_isl_int
)(__isl_take PW
*pw
, isl_int v
)
1321 if (isl_int_is_one(v
))
1323 if (pw
&& isl_int_is_zero(v
)) {
1325 isl_space
*dim
= FN(PW
,get_space
)(pw
);
1327 zero
= FN(PW
,ZERO
)(dim
, pw
->type
);
1329 zero
= FN(PW
,ZERO
)(dim
);
1334 pw
= FN(PW
,cow
)(pw
);
1341 if (isl_int_is_neg(v
))
1342 pw
->type
= isl_fold_type_negate(pw
->type
);
1344 for (i
= 0; i
< pw
->n
; ++i
) {
1345 pw
->p
[i
].FIELD
= FN(EL
,scale
)(pw
->p
[i
].FIELD
, v
);
1346 if (!pw
->p
[i
].FIELD
)
1356 __isl_give PW
*FN(PW
,scale
)(__isl_take PW
*pw
, isl_int v
)
1358 return FN(PW
,mul_isl_int
)(pw
, v
);
1361 static int FN(PW
,qsort_set_cmp
)(const void *p1
, const void *p2
)
1363 const isl_set
*set1
= *(const isl_set
**)p1
;
1364 const isl_set
*set2
= *(const isl_set
**)p2
;
1366 return isl_set_plain_cmp(set1
, set2
);
1369 /* We normalize in place, but if anything goes wrong we need
1370 * to return NULL, so we need to make sure we don't change the
1371 * meaning of any possible other copies of map.
1373 __isl_give PW
*FN(PW
,normalize
)(__isl_take PW
*pw
)
1380 for (i
= 0; i
< pw
->n
; ++i
) {
1381 set
= isl_set_normalize(isl_set_copy(pw
->p
[i
].set
));
1383 return FN(PW
,free
)(pw
);
1384 isl_set_free(pw
->p
[i
].set
);
1387 qsort(pw
->p
, pw
->n
, sizeof(pw
->p
[0]), &FN(PW
,qsort_set_cmp
));
1388 for (i
= pw
->n
- 1; i
>= 1; --i
) {
1389 if (!isl_set_plain_is_equal(pw
->p
[i
- 1].set
, pw
->p
[i
].set
))
1391 if (!FN(EL
,plain_is_equal
)(pw
->p
[i
- 1].FIELD
, pw
->p
[i
].FIELD
))
1393 set
= isl_set_union(isl_set_copy(pw
->p
[i
- 1].set
),
1394 isl_set_copy(pw
->p
[i
].set
));
1396 return FN(PW
,free
)(pw
);
1397 isl_set_free(pw
->p
[i
].set
);
1398 FN(EL
,free
)(pw
->p
[i
].FIELD
);
1399 isl_set_free(pw
->p
[i
- 1].set
);
1400 pw
->p
[i
- 1].set
= set
;
1401 for (j
= i
+ 1; j
< pw
->n
; ++j
)
1402 pw
->p
[j
- 1] = pw
->p
[j
];
1409 /* Is pw1 obviously equal to pw2?
1410 * That is, do they have obviously identical cells and obviously identical
1411 * elements on each cell?
1413 int FN(PW
,plain_is_equal
)(__isl_keep PW
*pw1
, __isl_keep PW
*pw2
)
1423 if (!isl_space_is_equal(pw1
->dim
, pw2
->dim
))
1426 pw1
= FN(PW
,copy
)(pw1
);
1427 pw2
= FN(PW
,copy
)(pw2
);
1428 pw1
= FN(PW
,normalize
)(pw1
);
1429 pw2
= FN(PW
,normalize
)(pw2
);
1433 equal
= pw1
->n
== pw2
->n
;
1434 for (i
= 0; equal
&& i
< pw1
->n
; ++i
) {
1435 equal
= isl_set_plain_is_equal(pw1
->p
[i
].set
, pw2
->p
[i
].set
);
1440 equal
= FN(EL
,plain_is_equal
)(pw1
->p
[i
].FIELD
, pw2
->p
[i
].FIELD
);