2 * Copyright 2010-2011 INRIA Saclay
3 * Copyright 2011 Sven Verdoolaege
4 * Copyright 2012-2014 Ecole Normale Superieure
6 * Use of this software is governed by the MIT license
8 * Written by Sven Verdoolaege, INRIA Saclay - Ile-de-France,
9 * Parc Club Orsay Universite, ZAC des vignes, 4 rue Jacques Monod,
11 * and Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France
17 #include <isl_val_private.h>
19 #include <isl_pw_macro.h>
22 __isl_give PW
*FN(PW
,alloc_size
)(__isl_take isl_space
*dim
,
23 enum isl_fold type
, int n
)
25 __isl_give PW
*FN(PW
,alloc_size
)(__isl_take isl_space
*dim
, int n
)
33 ctx
= isl_space_get_ctx(dim
);
34 isl_assert(ctx
, n
>= 0, goto error
);
35 pw
= isl_alloc(ctx
, struct PW
,
36 sizeof(struct PW
) + (n
- 1) * sizeof(S(PW
,piece
)));
54 __isl_give PW
*FN(PW
,ZERO
)(__isl_take isl_space
*dim
, enum isl_fold type
)
56 return FN(PW
,alloc_size
)(dim
, type
, 0);
59 __isl_give PW
*FN(PW
,ZERO
)(__isl_take isl_space
*dim
)
61 return FN(PW
,alloc_size
)(dim
, 0);
65 __isl_give PW
*FN(PW
,add_piece
)(__isl_take PW
*pw
,
66 __isl_take isl_set
*set
, __isl_take EL
*el
)
69 isl_space
*el_dim
= NULL
;
71 if (!pw
|| !set
|| !el
)
74 if (isl_set_plain_is_empty(set
) || FN(EL
,EL_IS_ZERO
)(el
)) {
80 ctx
= isl_set_get_ctx(set
);
82 if (pw
->type
!= el
->type
)
83 isl_die(ctx
, isl_error_invalid
, "fold types don't match",
86 el_dim
= FN(EL
,get_space(el
));
87 isl_assert(ctx
, isl_space_is_equal(pw
->dim
, el_dim
), goto error
);
88 isl_assert(ctx
, pw
->n
< pw
->size
, goto error
);
90 pw
->p
[pw
->n
].set
= set
;
91 pw
->p
[pw
->n
].FIELD
= el
;
94 isl_space_free(el_dim
);
97 isl_space_free(el_dim
);
104 /* Does the space of "set" correspond to that of the domain of "el".
106 static isl_bool
FN(PW
,compatible_domain
)(__isl_keep EL
*el
,
107 __isl_keep isl_set
*set
)
110 isl_space
*el_space
, *set_space
;
113 return isl_bool_error
;
114 set_space
= isl_set_get_space(set
);
115 el_space
= FN(EL
,get_space
)(el
);
116 ok
= isl_space_is_domain_internal(set_space
, el_space
);
117 isl_space_free(el_space
);
118 isl_space_free(set_space
);
122 /* Check that the space of "set" corresponds to that of the domain of "el".
124 static isl_stat
FN(PW
,check_compatible_domain
)(__isl_keep EL
*el
,
125 __isl_keep isl_set
*set
)
129 ok
= FN(PW
,compatible_domain
)(el
, set
);
131 return isl_stat_error
;
133 isl_die(isl_set_get_ctx(set
), isl_error_invalid
,
134 "incompatible spaces", return isl_stat_error
);
140 __isl_give PW
*FN(PW
,alloc
)(enum isl_fold type
,
141 __isl_take isl_set
*set
, __isl_take EL
*el
)
143 __isl_give PW
*FN(PW
,alloc
)(__isl_take isl_set
*set
, __isl_take EL
*el
)
148 if (FN(PW
,check_compatible_domain
)(el
, set
) < 0)
152 pw
= FN(PW
,alloc_size
)(FN(EL
,get_space
)(el
), type
, 1);
154 pw
= FN(PW
,alloc_size
)(FN(EL
,get_space
)(el
), 1);
157 return FN(PW
,add_piece
)(pw
, set
, el
);
164 __isl_give PW
*FN(PW
,dup
)(__isl_keep PW
*pw
)
173 dup
= FN(PW
,alloc_size
)(isl_space_copy(pw
->dim
), pw
->type
, pw
->n
);
175 dup
= FN(PW
,alloc_size
)(isl_space_copy(pw
->dim
), pw
->n
);
180 for (i
= 0; i
< pw
->n
; ++i
)
181 dup
= FN(PW
,add_piece
)(dup
, isl_set_copy(pw
->p
[i
].set
),
182 FN(EL
,copy
)(pw
->p
[i
].FIELD
));
187 __isl_give PW
*FN(PW
,cow
)(__isl_take PW
*pw
)
195 return FN(PW
,dup
)(pw
);
198 __isl_give PW
*FN(PW
,copy
)(__isl_keep PW
*pw
)
207 __isl_null PW
*FN(PW
,free
)(__isl_take PW
*pw
)
216 for (i
= 0; i
< pw
->n
; ++i
) {
217 isl_set_free(pw
->p
[i
].set
);
218 FN(EL
,free
)(pw
->p
[i
].FIELD
);
220 isl_space_free(pw
->dim
);
226 const char *FN(PW
,get_dim_name
)(__isl_keep PW
*pw
, enum isl_dim_type type
,
229 return pw
? isl_space_get_dim_name(pw
->dim
, type
, pos
) : NULL
;
232 isl_bool
FN(PW
,has_dim_id
)(__isl_keep PW
*pw
, enum isl_dim_type type
,
235 return pw
? isl_space_has_dim_id(pw
->dim
, type
, pos
) : isl_bool_error
;
238 __isl_give isl_id
*FN(PW
,get_dim_id
)(__isl_keep PW
*pw
, enum isl_dim_type type
,
241 return pw
? isl_space_get_dim_id(pw
->dim
, type
, pos
) : NULL
;
244 isl_bool
FN(PW
,has_tuple_name
)(__isl_keep PW
*pw
, enum isl_dim_type type
)
246 return pw
? isl_space_has_tuple_name(pw
->dim
, type
) : isl_bool_error
;
249 const char *FN(PW
,get_tuple_name
)(__isl_keep PW
*pw
, enum isl_dim_type type
)
251 return pw
? isl_space_get_tuple_name(pw
->dim
, type
) : NULL
;
254 isl_bool
FN(PW
,has_tuple_id
)(__isl_keep PW
*pw
, enum isl_dim_type type
)
256 return pw
? isl_space_has_tuple_id(pw
->dim
, type
) : isl_bool_error
;
259 __isl_give isl_id
*FN(PW
,get_tuple_id
)(__isl_keep PW
*pw
, enum isl_dim_type type
)
261 return pw
? isl_space_get_tuple_id(pw
->dim
, type
) : NULL
;
264 isl_bool
FN(PW
,IS_ZERO
)(__isl_keep PW
*pw
)
267 return isl_bool_error
;
273 __isl_give PW
*FN(PW
,realign_domain
)(__isl_take PW
*pw
,
274 __isl_take isl_reordering
*exp
)
282 for (i
= 0; i
< pw
->n
; ++i
) {
283 pw
->p
[i
].set
= isl_set_realign(pw
->p
[i
].set
,
284 isl_reordering_copy(exp
));
287 pw
->p
[i
].FIELD
= FN(EL
,realign_domain
)(pw
->p
[i
].FIELD
,
288 isl_reordering_copy(exp
));
293 pw
= FN(PW
,reset_domain_space
)(pw
, isl_reordering_get_space(exp
));
295 isl_reordering_free(exp
);
298 isl_reordering_free(exp
);
303 /* Check that "pw" has only named parameters, reporting an error
306 isl_stat
FN(PW
,check_named_params
)(__isl_keep PW
*pw
)
308 return isl_space_check_named_params(FN(PW
,peek_space
)(pw
));
311 /* Align the parameters of "pw" to those of "model".
313 __isl_give PW
*FN(PW
,align_params
)(__isl_take PW
*pw
, __isl_take isl_space
*model
)
316 isl_bool equal_params
;
321 ctx
= isl_space_get_ctx(model
);
322 if (!isl_space_has_named_params(model
))
323 isl_die(ctx
, isl_error_invalid
,
324 "model has unnamed parameters", goto error
);
325 if (FN(PW
,check_named_params
)(pw
) < 0)
327 equal_params
= isl_space_has_equal_params(pw
->dim
, model
);
328 if (equal_params
< 0)
333 model
= isl_space_drop_dims(model
, isl_dim_in
,
334 0, isl_space_dim(model
, isl_dim_in
));
335 model
= isl_space_drop_dims(model
, isl_dim_out
,
336 0, isl_space_dim(model
, isl_dim_out
));
337 exp
= isl_parameter_alignment_reordering(pw
->dim
, model
);
338 exp
= isl_reordering_extend_space(exp
,
339 FN(PW
,get_domain_space
)(pw
));
340 pw
= FN(PW
,realign_domain
)(pw
, exp
);
343 isl_space_free(model
);
346 isl_space_free(model
);
351 static __isl_give PW
*FN(PW
,align_params_pw_pw_and
)(__isl_take PW
*pw1
,
353 __isl_give PW
*(*fn
)(__isl_take PW
*pw1
, __isl_take PW
*pw2
))
356 isl_bool equal_params
;
360 equal_params
= isl_space_has_equal_params(pw1
->dim
, pw2
->dim
);
361 if (equal_params
< 0)
365 ctx
= FN(PW
,get_ctx
)(pw1
);
366 if (FN(PW
,check_named_params
)(pw1
) < 0 ||
367 FN(PW
,check_named_params
)(pw2
) < 0)
369 pw1
= FN(PW
,align_params
)(pw1
, FN(PW
,get_space
)(pw2
));
370 pw2
= FN(PW
,align_params
)(pw2
, FN(PW
,get_space
)(pw1
));
378 static __isl_give PW
*FN(PW
,align_params_pw_set_and
)(__isl_take PW
*pw
,
379 __isl_take isl_set
*set
,
380 __isl_give PW
*(*fn
)(__isl_take PW
*pw
, __isl_take isl_set
*set
))
387 aligned
= isl_set_space_has_equal_params(set
, pw
->dim
);
392 ctx
= FN(PW
,get_ctx
)(pw
);
393 if (FN(PW
,check_named_params
)(pw
) < 0)
395 if (!isl_space_has_named_params(set
->dim
))
396 isl_die(ctx
, isl_error_invalid
,
397 "unaligned unnamed parameters", goto error
);
398 pw
= FN(PW
,align_params
)(pw
, isl_set_get_space(set
));
399 set
= isl_set_align_params(set
, FN(PW
,get_space
)(pw
));
408 static __isl_give PW
*FN(PW
,union_add_aligned
)(__isl_take PW
*pw1
,
419 ctx
= isl_space_get_ctx(pw1
->dim
);
421 if (pw1
->type
!= pw2
->type
)
422 isl_die(ctx
, isl_error_invalid
,
423 "fold types don't match", goto error
);
425 isl_assert(ctx
, isl_space_is_equal(pw1
->dim
, pw2
->dim
), goto error
);
427 if (FN(PW
,IS_ZERO
)(pw1
)) {
432 if (FN(PW
,IS_ZERO
)(pw2
)) {
437 n
= (pw1
->n
+ 1) * (pw2
->n
+ 1);
439 res
= FN(PW
,alloc_size
)(isl_space_copy(pw1
->dim
), pw1
->type
, n
);
441 res
= FN(PW
,alloc_size
)(isl_space_copy(pw1
->dim
), n
);
444 for (i
= 0; i
< pw1
->n
; ++i
) {
445 set
= isl_set_copy(pw1
->p
[i
].set
);
446 for (j
= 0; j
< pw2
->n
; ++j
) {
447 struct isl_set
*common
;
449 common
= isl_set_intersect(isl_set_copy(pw1
->p
[i
].set
),
450 isl_set_copy(pw2
->p
[j
].set
));
451 if (isl_set_plain_is_empty(common
)) {
452 isl_set_free(common
);
455 set
= isl_set_subtract(set
,
456 isl_set_copy(pw2
->p
[j
].set
));
458 sum
= FN(EL
,add_on_domain
)(common
,
459 FN(EL
,copy
)(pw1
->p
[i
].FIELD
),
460 FN(EL
,copy
)(pw2
->p
[j
].FIELD
));
462 res
= FN(PW
,add_piece
)(res
, common
, sum
);
464 res
= FN(PW
,add_piece
)(res
, set
, FN(EL
,copy
)(pw1
->p
[i
].FIELD
));
467 for (j
= 0; j
< pw2
->n
; ++j
) {
468 set
= isl_set_copy(pw2
->p
[j
].set
);
469 for (i
= 0; i
< pw1
->n
; ++i
)
470 set
= isl_set_subtract(set
,
471 isl_set_copy(pw1
->p
[i
].set
));
472 res
= FN(PW
,add_piece
)(res
, set
, FN(EL
,copy
)(pw2
->p
[j
].FIELD
));
485 /* Private version of "union_add". For isl_pw_qpolynomial and
486 * isl_pw_qpolynomial_fold, we prefer to simply call it "add".
488 static __isl_give PW
*FN(PW
,union_add_
)(__isl_take PW
*pw1
, __isl_take PW
*pw2
)
490 return FN(PW
,align_params_pw_pw_and
)(pw1
, pw2
,
491 &FN(PW
,union_add_aligned
));
494 /* Make sure "pw" has room for at least "n" more pieces.
496 * If there is only one reference to pw, we extend it in place.
497 * Otherwise, we create a new PW and copy the pieces.
499 static __isl_give PW
*FN(PW
,grow
)(__isl_take PW
*pw
, int n
)
507 if (pw
->n
+ n
<= pw
->size
)
509 ctx
= FN(PW
,get_ctx
)(pw
);
512 res
= isl_realloc(ctx
, pw
, struct PW
,
513 sizeof(struct PW
) + (n
- 1) * sizeof(S(PW
,piece
)));
515 return FN(PW
,free
)(pw
);
520 res
= FN(PW
,alloc_size
)(isl_space_copy(pw
->dim
), pw
->type
, n
);
522 res
= FN(PW
,alloc_size
)(isl_space_copy(pw
->dim
), n
);
525 return FN(PW
,free
)(pw
);
526 for (i
= 0; i
< pw
->n
; ++i
)
527 res
= FN(PW
,add_piece
)(res
, isl_set_copy(pw
->p
[i
].set
),
528 FN(EL
,copy
)(pw
->p
[i
].FIELD
));
533 static __isl_give PW
*FN(PW
,add_disjoint_aligned
)(__isl_take PW
*pw1
,
542 if (pw1
->size
< pw1
->n
+ pw2
->n
&& pw1
->n
< pw2
->n
)
543 return FN(PW
,add_disjoint_aligned
)(pw2
, pw1
);
545 ctx
= isl_space_get_ctx(pw1
->dim
);
547 if (pw1
->type
!= pw2
->type
)
548 isl_die(ctx
, isl_error_invalid
,
549 "fold types don't match", goto error
);
551 isl_assert(ctx
, isl_space_is_equal(pw1
->dim
, pw2
->dim
), goto error
);
553 if (FN(PW
,IS_ZERO
)(pw1
)) {
558 if (FN(PW
,IS_ZERO
)(pw2
)) {
563 pw1
= FN(PW
,grow
)(pw1
, pw2
->n
);
567 for (i
= 0; i
< pw2
->n
; ++i
)
568 pw1
= FN(PW
,add_piece
)(pw1
,
569 isl_set_copy(pw2
->p
[i
].set
),
570 FN(EL
,copy
)(pw2
->p
[i
].FIELD
));
581 __isl_give PW
*FN(PW
,add_disjoint
)(__isl_take PW
*pw1
, __isl_take PW
*pw2
)
583 return FN(PW
,align_params_pw_pw_and
)(pw1
, pw2
,
584 &FN(PW
,add_disjoint_aligned
));
587 /* This function is currently only used from isl_aff.c
589 static __isl_give PW
*FN(PW
,on_shared_domain_in
)(__isl_take PW
*pw1
,
590 __isl_take PW
*pw2
, __isl_take isl_space
*space
,
591 __isl_give EL
*(*fn
)(__isl_take EL
*el1
, __isl_take EL
*el2
))
592 __attribute__ ((unused
));
594 /* Apply "fn" to pairs of elements from pw1 and pw2 on shared domains.
595 * The result of "fn" (and therefore also of this function) lives in "space".
597 static __isl_give PW
*FN(PW
,on_shared_domain_in
)(__isl_take PW
*pw1
,
598 __isl_take PW
*pw2
, __isl_take isl_space
*space
,
599 __isl_give EL
*(*fn
)(__isl_take EL
*el1
, __isl_take EL
*el2
))
609 res
= FN(PW
,alloc_size
)(isl_space_copy(space
), pw1
->type
, n
);
611 res
= FN(PW
,alloc_size
)(isl_space_copy(space
), n
);
614 for (i
= 0; i
< pw1
->n
; ++i
) {
615 for (j
= 0; j
< pw2
->n
; ++j
) {
620 common
= isl_set_intersect(
621 isl_set_copy(pw1
->p
[i
].set
),
622 isl_set_copy(pw2
->p
[j
].set
));
623 empty
= isl_set_plain_is_empty(common
);
624 if (empty
< 0 || empty
) {
625 isl_set_free(common
);
631 res_ij
= fn(FN(EL
,copy
)(pw1
->p
[i
].FIELD
),
632 FN(EL
,copy
)(pw2
->p
[j
].FIELD
));
633 res_ij
= FN(EL
,gist
)(res_ij
, isl_set_copy(common
));
635 res
= FN(PW
,add_piece
)(res
, common
, res_ij
);
639 isl_space_free(space
);
644 isl_space_free(space
);
651 /* This function is currently only used from isl_aff.c
653 static __isl_give PW
*FN(PW
,on_shared_domain
)(__isl_take PW
*pw1
,
655 __isl_give EL
*(*fn
)(__isl_take EL
*el1
, __isl_take EL
*el2
))
656 __attribute__ ((unused
));
658 /* Apply "fn" to pairs of elements from pw1 and pw2 on shared domains.
659 * The result of "fn" is assumed to live in the same space as "pw1" and "pw2".
661 static __isl_give PW
*FN(PW
,on_shared_domain
)(__isl_take PW
*pw1
,
663 __isl_give EL
*(*fn
)(__isl_take EL
*el1
, __isl_take EL
*el2
))
670 space
= isl_space_copy(pw1
->dim
);
671 return FN(PW
,on_shared_domain_in
)(pw1
, pw2
, space
, fn
);
679 __isl_give PW
*FN(PW
,neg
)(__isl_take PW
*pw
)
686 if (FN(PW
,IS_ZERO
)(pw
))
693 for (i
= 0; i
< pw
->n
; ++i
) {
694 pw
->p
[i
].FIELD
= FN(EL
,neg
)(pw
->p
[i
].FIELD
);
696 return FN(PW
,free
)(pw
);
704 __isl_give PW
*FN(PW
,sub
)(__isl_take PW
*pw1
, __isl_take PW
*pw2
)
706 return FN(PW
,add
)(pw1
, FN(PW
,neg
)(pw2
));
710 /* Return the parameter domain of "pw".
712 __isl_give isl_set
*FN(PW
,params
)(__isl_take PW
*pw
)
714 return isl_set_params(FN(PW
,domain
)(pw
));
717 __isl_give isl_set
*FN(PW
,domain
)(__isl_take PW
*pw
)
725 dom
= isl_set_empty(FN(PW
,get_domain_space
)(pw
));
726 for (i
= 0; i
< pw
->n
; ++i
)
727 dom
= isl_set_union_disjoint(dom
, isl_set_copy(pw
->p
[i
].set
));
734 /* Exploit the equalities in the domain of piece "i" of "pw"
735 * to simplify the associated function.
736 * If the domain of piece "i" is empty, then remove it entirely,
737 * replacing it with the final piece.
739 static int FN(PW
,exploit_equalities_and_remove_if_empty
)(__isl_keep PW
*pw
,
743 int empty
= isl_set_plain_is_empty(pw
->p
[i
].set
);
748 isl_set_free(pw
->p
[i
].set
);
749 FN(EL
,free
)(pw
->p
[i
].FIELD
);
751 pw
->p
[i
] = pw
->p
[pw
->n
- 1];
757 aff
= isl_set_affine_hull(isl_set_copy(pw
->p
[i
].set
));
758 pw
->p
[i
].FIELD
= FN(EL
,substitute_equalities
)(pw
->p
[i
].FIELD
, aff
);
765 /* Convert a piecewise expression defined over a parameter domain
766 * into one that is defined over a zero-dimensional set.
768 __isl_give PW
*FN(PW
,from_range
)(__isl_take PW
*pw
)
774 if (!isl_space_is_set(pw
->dim
))
775 isl_die(FN(PW
,get_ctx
)(pw
), isl_error_invalid
,
776 "not living in a set space", return FN(PW
,free
)(pw
));
778 space
= FN(PW
,get_space
)(pw
);
779 space
= isl_space_from_range(space
);
780 pw
= FN(PW
,reset_space
)(pw
, space
);
785 /* Fix the value of the given parameter or domain dimension of "pw"
786 * to be equal to "value".
788 __isl_give PW
*FN(PW
,fix_si
)(__isl_take PW
*pw
, enum isl_dim_type type
,
789 unsigned pos
, int value
)
796 if (type
== isl_dim_out
)
797 isl_die(FN(PW
,get_ctx
)(pw
), isl_error_invalid
,
798 "cannot fix output dimension", return FN(PW
,free
)(pw
));
803 if (type
== isl_dim_in
)
808 return FN(PW
,free
)(pw
);
810 for (i
= pw
->n
- 1; i
>= 0; --i
) {
811 pw
->p
[i
].set
= isl_set_fix_si(pw
->p
[i
].set
, type
, pos
, value
);
812 if (FN(PW
,exploit_equalities_and_remove_if_empty
)(pw
, i
) < 0)
813 return FN(PW
,free
)(pw
);
819 /* Restrict the domain of "pw" by combining each cell
820 * with "set" through a call to "fn", where "fn" may be
821 * isl_set_intersect, isl_set_intersect_params or isl_set_subtract.
823 static __isl_give PW
*FN(PW
,restrict_domain_aligned
)(__isl_take PW
*pw
,
824 __isl_take isl_set
*set
,
825 __isl_give isl_set
*(*fn
)(__isl_take isl_set
*set1
,
826 __isl_take isl_set
*set2
))
842 for (i
= pw
->n
- 1; i
>= 0; --i
) {
843 pw
->p
[i
].set
= fn(pw
->p
[i
].set
, isl_set_copy(set
));
844 if (FN(PW
,exploit_equalities_and_remove_if_empty
)(pw
, i
) < 0)
856 static __isl_give PW
*FN(PW
,intersect_domain_aligned
)(__isl_take PW
*pw
,
857 __isl_take isl_set
*set
)
859 return FN(PW
,restrict_domain_aligned
)(pw
, set
, &isl_set_intersect
);
862 __isl_give PW
*FN(PW
,intersect_domain
)(__isl_take PW
*pw
,
863 __isl_take isl_set
*context
)
865 return FN(PW
,align_params_pw_set_and
)(pw
, context
,
866 &FN(PW
,intersect_domain_aligned
));
869 static __isl_give PW
*FN(PW
,intersect_params_aligned
)(__isl_take PW
*pw
,
870 __isl_take isl_set
*set
)
872 return FN(PW
,restrict_domain_aligned
)(pw
, set
,
873 &isl_set_intersect_params
);
876 /* Intersect the domain of "pw" with the parameter domain "context".
878 __isl_give PW
*FN(PW
,intersect_params
)(__isl_take PW
*pw
,
879 __isl_take isl_set
*context
)
881 return FN(PW
,align_params_pw_set_and
)(pw
, context
,
882 &FN(PW
,intersect_params_aligned
));
885 /* Subtract "domain' from the domain of "pw", assuming their
886 * parameters have been aligned.
888 static __isl_give PW
*FN(PW
,subtract_domain_aligned
)(__isl_take PW
*pw
,
889 __isl_take isl_set
*domain
)
891 return FN(PW
,restrict_domain_aligned
)(pw
, domain
, &isl_set_subtract
);
894 /* Subtract "domain' from the domain of "pw".
896 __isl_give PW
*FN(PW
,subtract_domain
)(__isl_take PW
*pw
,
897 __isl_take isl_set
*domain
)
899 return FN(PW
,align_params_pw_set_and
)(pw
, domain
,
900 &FN(PW
,subtract_domain_aligned
));
903 /* Compute the gist of "pw" with respect to the domain constraints
904 * of "context" for the case where the domain of the last element
905 * of "pw" is equal to "context".
906 * Call "fn_el" to compute the gist of this element, replace
907 * its domain by the universe and drop all other elements
908 * as their domains are necessarily disjoint from "context".
910 static __isl_give PW
*FN(PW
,gist_last
)(__isl_take PW
*pw
,
911 __isl_take isl_set
*context
,
912 __isl_give EL
*(*fn_el
)(__isl_take EL
*el
, __isl_take isl_set
*set
))
917 for (i
= 0; i
< pw
->n
- 1; ++i
) {
918 isl_set_free(pw
->p
[i
].set
);
919 FN(EL
,free
)(pw
->p
[i
].FIELD
);
921 pw
->p
[0].FIELD
= pw
->p
[pw
->n
- 1].FIELD
;
922 pw
->p
[0].set
= pw
->p
[pw
->n
- 1].set
;
925 space
= isl_set_get_space(context
);
926 pw
->p
[0].FIELD
= fn_el(pw
->p
[0].FIELD
, context
);
927 context
= isl_set_universe(space
);
928 isl_set_free(pw
->p
[0].set
);
929 pw
->p
[0].set
= context
;
931 if (!pw
->p
[0].FIELD
|| !pw
->p
[0].set
)
932 return FN(PW
,free
)(pw
);
937 /* Compute the gist of "pw" with respect to the domain constraints
938 * of "context". Call "fn_el" to compute the gist of the elements
939 * and "fn_dom" to compute the gist of the domains.
941 * If the piecewise expression is empty or the context is the universe,
942 * then nothing can be simplified.
944 static __isl_give PW
*FN(PW
,gist_aligned
)(__isl_take PW
*pw
,
945 __isl_take isl_set
*context
,
946 __isl_give EL
*(*fn_el
)(__isl_take EL
*el
,
947 __isl_take isl_set
*set
),
948 __isl_give isl_set
*(*fn_dom
)(__isl_take isl_set
*set
,
949 __isl_take isl_basic_set
*bset
))
954 isl_basic_set
*hull
= NULL
;
960 isl_set_free(context
);
964 is_universe
= isl_set_plain_is_universe(context
);
968 isl_set_free(context
);
972 aligned
= isl_set_space_has_equal_params(context
, pw
->dim
);
976 pw
= FN(PW
,align_params
)(pw
, isl_set_get_space(context
));
977 context
= isl_set_align_params(context
, FN(PW
,get_space
)(pw
));
987 equal
= isl_set_plain_is_equal(pw
->p
[0].set
, context
);
991 return FN(PW
,gist_last
)(pw
, context
, fn_el
);
994 context
= isl_set_compute_divs(context
);
995 hull
= isl_set_simple_hull(isl_set_copy(context
));
997 for (i
= pw
->n
- 1; i
>= 0; --i
) {
1001 if (i
== pw
->n
- 1) {
1003 equal
= isl_set_plain_is_equal(pw
->p
[i
].set
, context
);
1007 isl_basic_set_free(hull
);
1008 return FN(PW
,gist_last
)(pw
, context
, fn_el
);
1011 set_i
= isl_set_intersect(isl_set_copy(pw
->p
[i
].set
),
1012 isl_set_copy(context
));
1013 empty
= isl_set_plain_is_empty(set_i
);
1014 pw
->p
[i
].FIELD
= fn_el(pw
->p
[i
].FIELD
, set_i
);
1015 pw
->p
[i
].set
= fn_dom(pw
->p
[i
].set
, isl_basic_set_copy(hull
));
1016 if (empty
< 0 || !pw
->p
[i
].FIELD
|| !pw
->p
[i
].set
)
1019 isl_set_free(pw
->p
[i
].set
);
1020 FN(EL
,free
)(pw
->p
[i
].FIELD
);
1022 pw
->p
[i
] = pw
->p
[pw
->n
- 1];
1027 isl_basic_set_free(hull
);
1028 isl_set_free(context
);
1033 isl_basic_set_free(hull
);
1034 isl_set_free(context
);
1038 static __isl_give PW
*FN(PW
,gist_domain_aligned
)(__isl_take PW
*pw
,
1039 __isl_take isl_set
*set
)
1041 return FN(PW
,gist_aligned
)(pw
, set
, &FN(EL
,gist
),
1042 &isl_set_gist_basic_set
);
1045 __isl_give PW
*FN(PW
,gist
)(__isl_take PW
*pw
, __isl_take isl_set
*context
)
1047 return FN(PW
,align_params_pw_set_and
)(pw
, context
,
1048 &FN(PW
,gist_domain_aligned
));
1051 static __isl_give PW
*FN(PW
,gist_params_aligned
)(__isl_take PW
*pw
,
1052 __isl_take isl_set
*set
)
1054 return FN(PW
,gist_aligned
)(pw
, set
, &FN(EL
,gist_params
),
1055 &isl_set_gist_params_basic_set
);
1058 __isl_give PW
*FN(PW
,gist_params
)(__isl_take PW
*pw
,
1059 __isl_take isl_set
*context
)
1061 return FN(PW
,align_params_pw_set_and
)(pw
, context
,
1062 &FN(PW
,gist_params_aligned
));
1065 /* Return -1 if the piece "p1" should be sorted before "p2"
1066 * and 1 if it should be sorted after "p2".
1067 * Return 0 if they do not need to be sorted in a specific order.
1069 * The two pieces are compared on the basis of their function value expressions.
1071 static int FN(PW
,sort_field_cmp
)(const void *p1
, const void *p2
, void *arg
)
1073 struct FN(PW
,piece
) const *pc1
= p1
;
1074 struct FN(PW
,piece
) const *pc2
= p2
;
1076 return FN(EL
,plain_cmp
)(pc1
->FIELD
, pc2
->FIELD
);
1079 /* Sort the pieces of "pw" according to their function value
1080 * expressions and then combine pairs of adjacent pieces with
1081 * the same such expression.
1083 * The sorting is performed in place because it does not
1084 * change the meaning of "pw", but care needs to be
1085 * taken not to change any possible other copies of "pw"
1086 * in case anything goes wrong.
1088 __isl_give PW
*FN(PW
,sort
)(__isl_take PW
*pw
)
1097 if (isl_sort(pw
->p
, pw
->n
, sizeof(pw
->p
[0]),
1098 &FN(PW
,sort_field_cmp
), NULL
) < 0)
1099 return FN(PW
,free
)(pw
);
1100 for (i
= pw
->n
- 1; i
>= 1; --i
) {
1101 if (!FN(EL
,plain_is_equal
)(pw
->p
[i
- 1].FIELD
, pw
->p
[i
].FIELD
))
1103 set
= isl_set_union(isl_set_copy(pw
->p
[i
- 1].set
),
1104 isl_set_copy(pw
->p
[i
].set
));
1106 return FN(PW
,free
)(pw
);
1107 isl_set_free(pw
->p
[i
].set
);
1108 FN(EL
,free
)(pw
->p
[i
].FIELD
);
1109 isl_set_free(pw
->p
[i
- 1].set
);
1110 pw
->p
[i
- 1].set
= set
;
1111 for (j
= i
+ 1; j
< pw
->n
; ++j
)
1112 pw
->p
[j
- 1] = pw
->p
[j
];
1119 /* Coalesce the domains of "pw".
1121 * Prior to the actual coalescing, first sort the pieces such that
1122 * pieces with the same function value expression are combined
1123 * into a single piece, the combined domain of which can then
1126 __isl_give PW
*FN(PW
,coalesce
)(__isl_take PW
*pw
)
1130 pw
= FN(PW
,sort
)(pw
);
1134 for (i
= 0; i
< pw
->n
; ++i
) {
1135 pw
->p
[i
].set
= isl_set_coalesce(pw
->p
[i
].set
);
1146 isl_ctx
*FN(PW
,get_ctx
)(__isl_keep PW
*pw
)
1148 return pw
? isl_space_get_ctx(pw
->dim
) : NULL
;
1151 isl_bool
FN(PW
,involves_dims
)(__isl_keep PW
*pw
, enum isl_dim_type type
,
1152 unsigned first
, unsigned n
)
1155 enum isl_dim_type set_type
;
1158 return isl_bool_error
;
1159 if (pw
->n
== 0 || n
== 0)
1160 return isl_bool_false
;
1162 set_type
= type
== isl_dim_in
? isl_dim_set
: type
;
1164 for (i
= 0; i
< pw
->n
; ++i
) {
1165 isl_bool involves
= FN(EL
,involves_dims
)(pw
->p
[i
].FIELD
,
1167 if (involves
< 0 || involves
)
1169 involves
= isl_set_involves_dims(pw
->p
[i
].set
,
1170 set_type
, first
, n
);
1171 if (involves
< 0 || involves
)
1174 return isl_bool_false
;
1177 __isl_give PW
*FN(PW
,set_dim_name
)(__isl_take PW
*pw
,
1178 enum isl_dim_type type
, unsigned pos
, const char *s
)
1181 enum isl_dim_type set_type
;
1183 pw
= FN(PW
,cow
)(pw
);
1187 set_type
= type
== isl_dim_in
? isl_dim_set
: type
;
1189 pw
->dim
= isl_space_set_dim_name(pw
->dim
, type
, pos
, s
);
1193 for (i
= 0; i
< pw
->n
; ++i
) {
1194 pw
->p
[i
].set
= isl_set_set_dim_name(pw
->p
[i
].set
,
1198 pw
->p
[i
].FIELD
= FN(EL
,set_dim_name
)(pw
->p
[i
].FIELD
, type
, pos
, s
);
1199 if (!pw
->p
[i
].FIELD
)
1209 __isl_give PW
*FN(PW
,drop_dims
)(__isl_take PW
*pw
,
1210 enum isl_dim_type type
, unsigned first
, unsigned n
)
1213 enum isl_dim_type set_type
;
1217 if (n
== 0 && !isl_space_get_tuple_name(pw
->dim
, type
))
1220 set_type
= type
== isl_dim_in
? isl_dim_set
: type
;
1222 pw
= FN(PW
,cow
)(pw
);
1225 pw
->dim
= isl_space_drop_dims(pw
->dim
, type
, first
, n
);
1228 for (i
= 0; i
< pw
->n
; ++i
) {
1229 pw
->p
[i
].FIELD
= FN(EL
,drop_dims
)(pw
->p
[i
].FIELD
, type
, first
, n
);
1230 if (!pw
->p
[i
].FIELD
)
1232 if (type
== isl_dim_out
)
1234 pw
->p
[i
].set
= isl_set_drop(pw
->p
[i
].set
, set_type
, first
, n
);
1245 /* This function is very similar to drop_dims.
1246 * The only difference is that the cells may still involve
1247 * the specified dimensions. They are removed using
1248 * isl_set_project_out instead of isl_set_drop.
1250 __isl_give PW
*FN(PW
,project_out
)(__isl_take PW
*pw
,
1251 enum isl_dim_type type
, unsigned first
, unsigned n
)
1254 enum isl_dim_type set_type
;
1258 if (n
== 0 && !isl_space_get_tuple_name(pw
->dim
, type
))
1261 set_type
= type
== isl_dim_in
? isl_dim_set
: type
;
1263 pw
= FN(PW
,cow
)(pw
);
1266 pw
->dim
= isl_space_drop_dims(pw
->dim
, type
, first
, n
);
1269 for (i
= 0; i
< pw
->n
; ++i
) {
1270 pw
->p
[i
].set
= isl_set_project_out(pw
->p
[i
].set
,
1271 set_type
, first
, n
);
1274 pw
->p
[i
].FIELD
= FN(EL
,drop_dims
)(pw
->p
[i
].FIELD
, type
, first
, n
);
1275 if (!pw
->p
[i
].FIELD
)
1285 /* Project the domain of pw onto its parameter space.
1287 __isl_give PW
*FN(PW
,project_domain_on_params
)(__isl_take PW
*pw
)
1292 n
= FN(PW
,dim
)(pw
, isl_dim_in
);
1293 pw
= FN(PW
,project_out
)(pw
, isl_dim_in
, 0, n
);
1294 space
= FN(PW
,get_domain_space
)(pw
);
1295 space
= isl_space_params(space
);
1296 pw
= FN(PW
,reset_domain_space
)(pw
, space
);
1300 /* Drop all parameters not referenced by "pw".
1302 __isl_give PW
*FN(PW
,drop_unused_params
)(__isl_take PW
*pw
)
1306 if (FN(PW
,check_named_params
)(pw
) < 0)
1307 return FN(PW
,free
)(pw
);
1309 for (i
= FN(PW
,dim
)(pw
, isl_dim_param
) - 1; i
>= 0; i
--) {
1312 involves
= FN(PW
,involves_dims
)(pw
, isl_dim_param
, i
, 1);
1314 return FN(PW
,free
)(pw
);
1316 pw
= FN(PW
,drop_dims
)(pw
, isl_dim_param
, i
, 1);
1322 #ifndef NO_INSERT_DIMS
1323 __isl_give PW
*FN(PW
,insert_dims
)(__isl_take PW
*pw
, enum isl_dim_type type
,
1324 unsigned first
, unsigned n
)
1327 enum isl_dim_type set_type
;
1331 if (n
== 0 && !isl_space_is_named_or_nested(pw
->dim
, type
))
1334 set_type
= type
== isl_dim_in
? isl_dim_set
: type
;
1336 pw
= FN(PW
,cow
)(pw
);
1340 pw
->dim
= isl_space_insert_dims(pw
->dim
, type
, first
, n
);
1344 for (i
= 0; i
< pw
->n
; ++i
) {
1345 pw
->p
[i
].set
= isl_set_insert_dims(pw
->p
[i
].set
,
1346 set_type
, first
, n
);
1349 pw
->p
[i
].FIELD
= FN(EL
,insert_dims
)(pw
->p
[i
].FIELD
,
1351 if (!pw
->p
[i
].FIELD
)
1362 __isl_give PW
*FN(PW
,fix_dim
)(__isl_take PW
*pw
,
1363 enum isl_dim_type type
, unsigned pos
, isl_int v
)
1370 if (type
== isl_dim_in
)
1373 pw
= FN(PW
,cow
)(pw
);
1376 for (i
= 0; i
< pw
->n
; ++i
) {
1377 pw
->p
[i
].set
= isl_set_fix(pw
->p
[i
].set
, type
, pos
, v
);
1378 if (FN(PW
,exploit_equalities_and_remove_if_empty
)(pw
, i
) < 0)
1379 return FN(PW
,free
)(pw
);
1385 /* Fix the value of the variable at position "pos" of type "type" of "pw"
1386 * to be equal to "v".
1388 __isl_give PW
*FN(PW
,fix_val
)(__isl_take PW
*pw
,
1389 enum isl_dim_type type
, unsigned pos
, __isl_take isl_val
*v
)
1392 return FN(PW
,free
)(pw
);
1393 if (!isl_val_is_int(v
))
1394 isl_die(FN(PW
,get_ctx
)(pw
), isl_error_invalid
,
1395 "expecting integer value", goto error
);
1397 pw
= FN(PW
,fix_dim
)(pw
, type
, pos
, v
->n
);
1403 return FN(PW
,free
)(pw
);
1406 unsigned FN(PW
,dim
)(__isl_keep PW
*pw
, enum isl_dim_type type
)
1408 return pw
? isl_space_dim(pw
->dim
, type
) : 0;
1411 __isl_give PW
*FN(PW
,split_dims
)(__isl_take PW
*pw
,
1412 enum isl_dim_type type
, unsigned first
, unsigned n
)
1421 if (type
== isl_dim_in
)
1424 pw
= FN(PW
,cow
)(pw
);
1429 for (i
= 0; i
< pw
->n
; ++i
) {
1430 pw
->p
[i
].set
= isl_set_split_dims(pw
->p
[i
].set
, type
, first
, n
);
1442 /* Compute the maximal value attained by the piecewise quasipolynomial
1443 * on its domain or zero if the domain is empty.
1444 * In the worst case, the domain is scanned completely,
1445 * so the domain is assumed to be bounded.
1447 __isl_give isl_val
*FN(PW
,opt
)(__isl_take PW
*pw
, int max
)
1456 opt
= isl_val_zero(FN(PW
,get_ctx
)(pw
));
1461 opt
= FN(EL
,opt_on_domain
)(FN(EL
,copy
)(pw
->p
[0].FIELD
),
1462 isl_set_copy(pw
->p
[0].set
), max
);
1463 for (i
= 1; i
< pw
->n
; ++i
) {
1465 opt_i
= FN(EL
,opt_on_domain
)(FN(EL
,copy
)(pw
->p
[i
].FIELD
),
1466 isl_set_copy(pw
->p
[i
].set
), max
);
1468 opt
= isl_val_max(opt
, opt_i
);
1470 opt
= isl_val_min(opt
, opt_i
);
1477 __isl_give isl_val
*FN(PW
,max
)(__isl_take PW
*pw
)
1479 return FN(PW
,opt
)(pw
, 1);
1482 __isl_give isl_val
*FN(PW
,min
)(__isl_take PW
*pw
)
1484 return FN(PW
,opt
)(pw
, 0);
1488 /* Return the space of "pw".
1490 __isl_keep isl_space
*FN(PW
,peek_space
)(__isl_keep PW
*pw
)
1492 return pw
? pw
->dim
: NULL
;
1495 __isl_give isl_space
*FN(PW
,get_space
)(__isl_keep PW
*pw
)
1497 return isl_space_copy(FN(PW
,peek_space
)(pw
));
1500 __isl_give isl_space
*FN(PW
,get_domain_space
)(__isl_keep PW
*pw
)
1502 return pw
? isl_space_domain(isl_space_copy(pw
->dim
)) : NULL
;
1505 /* Return the position of the dimension of the given type and name
1507 * Return -1 if no such dimension can be found.
1509 int FN(PW
,find_dim_by_name
)(__isl_keep PW
*pw
,
1510 enum isl_dim_type type
, const char *name
)
1514 return isl_space_find_dim_by_name(pw
->dim
, type
, name
);
1517 #ifndef NO_RESET_DIM
1518 /* Reset the space of "pw". Since we don't know if the elements
1519 * represent the spaces themselves or their domains, we pass along
1520 * both when we call their reset_space_and_domain.
1522 static __isl_give PW
*FN(PW
,reset_space_and_domain
)(__isl_take PW
*pw
,
1523 __isl_take isl_space
*space
, __isl_take isl_space
*domain
)
1527 pw
= FN(PW
,cow
)(pw
);
1528 if (!pw
|| !space
|| !domain
)
1531 for (i
= 0; i
< pw
->n
; ++i
) {
1532 pw
->p
[i
].set
= isl_set_reset_space(pw
->p
[i
].set
,
1533 isl_space_copy(domain
));
1536 pw
->p
[i
].FIELD
= FN(EL
,reset_space_and_domain
)(pw
->p
[i
].FIELD
,
1537 isl_space_copy(space
), isl_space_copy(domain
));
1538 if (!pw
->p
[i
].FIELD
)
1542 isl_space_free(domain
);
1544 isl_space_free(pw
->dim
);
1549 isl_space_free(domain
);
1550 isl_space_free(space
);
1555 __isl_give PW
*FN(PW
,reset_domain_space
)(__isl_take PW
*pw
,
1556 __isl_take isl_space
*domain
)
1560 space
= isl_space_extend_domain_with_range(isl_space_copy(domain
),
1561 FN(PW
,get_space
)(pw
));
1562 return FN(PW
,reset_space_and_domain
)(pw
, space
, domain
);
1565 __isl_give PW
*FN(PW
,reset_space
)(__isl_take PW
*pw
, __isl_take isl_space
*dim
)
1569 domain
= isl_space_domain(isl_space_copy(dim
));
1570 return FN(PW
,reset_space_and_domain
)(pw
, dim
, domain
);
1573 __isl_give PW
*FN(PW
,set_tuple_id
)(__isl_take PW
*pw
, enum isl_dim_type type
,
1574 __isl_take isl_id
*id
)
1578 pw
= FN(PW
,cow
)(pw
);
1582 space
= FN(PW
,get_space
)(pw
);
1583 space
= isl_space_set_tuple_id(space
, type
, id
);
1585 return FN(PW
,reset_space
)(pw
, space
);
1588 return FN(PW
,free
)(pw
);
1591 /* Drop the id on the specified tuple.
1593 __isl_give PW
*FN(PW
,reset_tuple_id
)(__isl_take PW
*pw
, enum isl_dim_type type
)
1599 if (!FN(PW
,has_tuple_id
)(pw
, type
))
1602 pw
= FN(PW
,cow
)(pw
);
1606 space
= FN(PW
,get_space
)(pw
);
1607 space
= isl_space_reset_tuple_id(space
, type
);
1609 return FN(PW
,reset_space
)(pw
, space
);
1612 __isl_give PW
*FN(PW
,set_dim_id
)(__isl_take PW
*pw
,
1613 enum isl_dim_type type
, unsigned pos
, __isl_take isl_id
*id
)
1615 pw
= FN(PW
,cow
)(pw
);
1618 pw
->dim
= isl_space_set_dim_id(pw
->dim
, type
, pos
, id
);
1619 return FN(PW
,reset_space
)(pw
, isl_space_copy(pw
->dim
));
1622 return FN(PW
,free
)(pw
);
1626 /* Reset the user pointer on all identifiers of parameters and tuples
1627 * of the space of "pw".
1629 __isl_give PW
*FN(PW
,reset_user
)(__isl_take PW
*pw
)
1633 space
= FN(PW
,get_space
)(pw
);
1634 space
= isl_space_reset_user(space
);
1636 return FN(PW
,reset_space
)(pw
, space
);
1639 isl_bool
FN(PW
,has_equal_space
)(__isl_keep PW
*pw1
, __isl_keep PW
*pw2
)
1642 return isl_bool_error
;
1644 return isl_space_is_equal(pw1
->dim
, pw2
->dim
);
1648 __isl_give PW
*FN(PW
,morph_domain
)(__isl_take PW
*pw
,
1649 __isl_take isl_morph
*morph
)
1657 ctx
= isl_space_get_ctx(pw
->dim
);
1658 isl_assert(ctx
, isl_space_is_domain_internal(morph
->dom
->dim
, pw
->dim
),
1661 pw
= FN(PW
,cow
)(pw
);
1664 pw
->dim
= isl_space_extend_domain_with_range(
1665 isl_space_copy(morph
->ran
->dim
), pw
->dim
);
1669 for (i
= 0; i
< pw
->n
; ++i
) {
1670 pw
->p
[i
].set
= isl_morph_set(isl_morph_copy(morph
), pw
->p
[i
].set
);
1673 pw
->p
[i
].FIELD
= FN(EL
,morph_domain
)(pw
->p
[i
].FIELD
,
1674 isl_morph_copy(morph
));
1675 if (!pw
->p
[i
].FIELD
)
1679 isl_morph_free(morph
);
1684 isl_morph_free(morph
);
1689 int FN(PW
,n_piece
)(__isl_keep PW
*pw
)
1691 return pw
? pw
->n
: 0;
1694 isl_stat
FN(PW
,foreach_piece
)(__isl_keep PW
*pw
,
1695 isl_stat (*fn
)(__isl_take isl_set
*set
, __isl_take EL
*el
, void *user
),
1701 return isl_stat_error
;
1703 for (i
= 0; i
< pw
->n
; ++i
)
1704 if (fn(isl_set_copy(pw
->p
[i
].set
),
1705 FN(EL
,copy
)(pw
->p
[i
].FIELD
), user
) < 0)
1706 return isl_stat_error
;
1712 static isl_bool
any_divs(__isl_keep isl_set
*set
)
1717 return isl_bool_error
;
1719 for (i
= 0; i
< set
->n
; ++i
)
1720 if (set
->p
[i
]->n_div
> 0)
1721 return isl_bool_true
;
1723 return isl_bool_false
;
1726 static isl_stat
foreach_lifted_subset(__isl_take isl_set
*set
,
1728 isl_stat (*fn
)(__isl_take isl_set
*set
, __isl_take EL
*el
,
1729 void *user
), void *user
)
1736 for (i
= 0; i
< set
->n
; ++i
) {
1740 lift
= isl_set_from_basic_set(isl_basic_set_copy(set
->p
[i
]));
1741 lift
= isl_set_lift(lift
);
1743 copy
= FN(EL
,copy
)(el
);
1744 copy
= FN(EL
,lift
)(copy
, isl_set_get_space(lift
));
1746 if (fn(lift
, copy
, user
) < 0)
1757 return isl_stat_error
;
1760 isl_stat
FN(PW
,foreach_lifted_piece
)(__isl_keep PW
*pw
,
1761 isl_stat (*fn
)(__isl_take isl_set
*set
, __isl_take EL
*el
,
1762 void *user
), void *user
)
1767 return isl_stat_error
;
1769 for (i
= 0; i
< pw
->n
; ++i
) {
1774 any
= any_divs(pw
->p
[i
].set
);
1776 return isl_stat_error
;
1777 set
= isl_set_copy(pw
->p
[i
].set
);
1778 el
= FN(EL
,copy
)(pw
->p
[i
].FIELD
);
1780 if (fn(set
, el
, user
) < 0)
1781 return isl_stat_error
;
1784 if (foreach_lifted_subset(set
, el
, fn
, user
) < 0)
1785 return isl_stat_error
;
1792 #ifndef NO_MOVE_DIMS
1793 __isl_give PW
*FN(PW
,move_dims
)(__isl_take PW
*pw
,
1794 enum isl_dim_type dst_type
, unsigned dst_pos
,
1795 enum isl_dim_type src_type
, unsigned src_pos
, unsigned n
)
1799 pw
= FN(PW
,cow
)(pw
);
1803 pw
->dim
= isl_space_move_dims(pw
->dim
, dst_type
, dst_pos
, src_type
, src_pos
, n
);
1807 for (i
= 0; i
< pw
->n
; ++i
) {
1808 pw
->p
[i
].FIELD
= FN(EL
,move_dims
)(pw
->p
[i
].FIELD
,
1809 dst_type
, dst_pos
, src_type
, src_pos
, n
);
1810 if (!pw
->p
[i
].FIELD
)
1814 if (dst_type
== isl_dim_in
)
1815 dst_type
= isl_dim_set
;
1816 if (src_type
== isl_dim_in
)
1817 src_type
= isl_dim_set
;
1819 for (i
= 0; i
< pw
->n
; ++i
) {
1820 pw
->p
[i
].set
= isl_set_move_dims(pw
->p
[i
].set
,
1822 src_type
, src_pos
, n
);
1834 __isl_give PW
*FN(PW
,mul_isl_int
)(__isl_take PW
*pw
, isl_int v
)
1838 if (isl_int_is_one(v
))
1840 if (pw
&& DEFAULT_IS_ZERO
&& isl_int_is_zero(v
)) {
1842 isl_space
*dim
= FN(PW
,get_space
)(pw
);
1844 zero
= FN(PW
,ZERO
)(dim
, pw
->type
);
1846 zero
= FN(PW
,ZERO
)(dim
);
1851 pw
= FN(PW
,cow
)(pw
);
1858 if (isl_int_is_neg(v
))
1859 pw
->type
= isl_fold_type_negate(pw
->type
);
1861 for (i
= 0; i
< pw
->n
; ++i
) {
1862 pw
->p
[i
].FIELD
= FN(EL
,scale
)(pw
->p
[i
].FIELD
, v
);
1863 if (!pw
->p
[i
].FIELD
)
1873 /* Multiply the pieces of "pw" by "v" and return the result.
1875 __isl_give PW
*FN(PW
,scale_val
)(__isl_take PW
*pw
, __isl_take isl_val
*v
)
1882 if (isl_val_is_one(v
)) {
1886 if (pw
&& DEFAULT_IS_ZERO
&& isl_val_is_zero(v
)) {
1888 isl_space
*space
= FN(PW
,get_space
)(pw
);
1890 zero
= FN(PW
,ZERO
)(space
, pw
->type
);
1892 zero
= FN(PW
,ZERO
)(space
);
1902 pw
= FN(PW
,cow
)(pw
);
1907 if (isl_val_is_neg(v
))
1908 pw
->type
= isl_fold_type_negate(pw
->type
);
1910 for (i
= 0; i
< pw
->n
; ++i
) {
1911 pw
->p
[i
].FIELD
= FN(EL
,scale_val
)(pw
->p
[i
].FIELD
,
1913 if (!pw
->p
[i
].FIELD
)
1925 /* Divide the pieces of "pw" by "v" and return the result.
1927 __isl_give PW
*FN(PW
,scale_down_val
)(__isl_take PW
*pw
, __isl_take isl_val
*v
)
1934 if (isl_val_is_one(v
)) {
1939 if (!isl_val_is_rat(v
))
1940 isl_die(isl_val_get_ctx(v
), isl_error_invalid
,
1941 "expecting rational factor", goto error
);
1942 if (isl_val_is_zero(v
))
1943 isl_die(isl_val_get_ctx(v
), isl_error_invalid
,
1944 "cannot scale down by zero", goto error
);
1950 pw
= FN(PW
,cow
)(pw
);
1955 if (isl_val_is_neg(v
))
1956 pw
->type
= isl_fold_type_negate(pw
->type
);
1958 for (i
= 0; i
< pw
->n
; ++i
) {
1959 pw
->p
[i
].FIELD
= FN(EL
,scale_down_val
)(pw
->p
[i
].FIELD
,
1961 if (!pw
->p
[i
].FIELD
)
1973 __isl_give PW
*FN(PW
,scale
)(__isl_take PW
*pw
, isl_int v
)
1975 return FN(PW
,mul_isl_int
)(pw
, v
);
1978 /* Apply some normalization to "pw".
1979 * In particular, sort the pieces according to their function value
1980 * expressions, combining pairs of adjacent pieces with
1981 * the same such expression, and then normalize the domains of the pieces.
1983 * We normalize in place, but if anything goes wrong we need
1984 * to return NULL, so we need to make sure we don't change the
1985 * meaning of any possible other copies of "pw".
1987 __isl_give PW
*FN(PW
,normalize
)(__isl_take PW
*pw
)
1992 pw
= FN(PW
,sort
)(pw
);
1995 for (i
= 0; i
< pw
->n
; ++i
) {
1996 set
= isl_set_normalize(isl_set_copy(pw
->p
[i
].set
));
1998 return FN(PW
,free
)(pw
);
1999 isl_set_free(pw
->p
[i
].set
);
2006 /* Is pw1 obviously equal to pw2?
2007 * That is, do they have obviously identical cells and obviously identical
2008 * elements on each cell?
2010 * If "pw1" or "pw2" contain any NaNs, then they are considered
2011 * not to be the same. A NaN is not equal to anything, not even
2014 isl_bool
FN(PW
,plain_is_equal
)(__isl_keep PW
*pw1
, __isl_keep PW
*pw2
)
2017 isl_bool equal
, has_nan
;
2020 return isl_bool_error
;
2022 has_nan
= FN(PW
,involves_nan
)(pw1
);
2023 if (has_nan
>= 0 && !has_nan
)
2024 has_nan
= FN(PW
,involves_nan
)(pw2
);
2025 if (has_nan
< 0 || has_nan
)
2026 return isl_bool_not(has_nan
);
2029 return isl_bool_true
;
2030 if (!isl_space_is_equal(pw1
->dim
, pw2
->dim
))
2031 return isl_bool_false
;
2033 pw1
= FN(PW
,copy
)(pw1
);
2034 pw2
= FN(PW
,copy
)(pw2
);
2035 pw1
= FN(PW
,normalize
)(pw1
);
2036 pw2
= FN(PW
,normalize
)(pw2
);
2040 equal
= pw1
->n
== pw2
->n
;
2041 for (i
= 0; equal
&& i
< pw1
->n
; ++i
) {
2042 equal
= isl_set_plain_is_equal(pw1
->p
[i
].set
, pw2
->p
[i
].set
);
2047 equal
= FN(EL
,plain_is_equal
)(pw1
->p
[i
].FIELD
, pw2
->p
[i
].FIELD
);
2058 return isl_bool_error
;
2061 /* Does "pw" involve any NaNs?
2063 isl_bool
FN(PW
,involves_nan
)(__isl_keep PW
*pw
)
2068 return isl_bool_error
;
2070 return isl_bool_false
;
2072 for (i
= 0; i
< pw
->n
; ++i
) {
2073 isl_bool has_nan
= FN(EL
,involves_nan
)(pw
->p
[i
].FIELD
);
2074 if (has_nan
< 0 || has_nan
)
2078 return isl_bool_false
;
2082 static __isl_give PW
*FN(PW
,align_params_pw_multi_aff_and
)(__isl_take PW
*pw
,
2083 __isl_take isl_multi_aff
*ma
,
2084 __isl_give PW
*(*fn
)(__isl_take PW
*pw
, __isl_take isl_multi_aff
*ma
))
2087 isl_bool equal_params
;
2088 isl_space
*ma_space
;
2090 ma_space
= isl_multi_aff_get_space(ma
);
2091 if (!pw
|| !ma
|| !ma_space
)
2093 equal_params
= isl_space_has_equal_params(pw
->dim
, ma_space
);
2094 if (equal_params
< 0)
2097 isl_space_free(ma_space
);
2100 ctx
= FN(PW
,get_ctx
)(pw
);
2101 if (FN(PW
,check_named_params
)(pw
) < 0)
2103 if (!isl_space_has_named_params(ma_space
))
2104 isl_die(ctx
, isl_error_invalid
,
2105 "unaligned unnamed parameters", goto error
);
2106 pw
= FN(PW
,align_params
)(pw
, ma_space
);
2107 ma
= isl_multi_aff_align_params(ma
, FN(PW
,get_space
)(pw
));
2110 isl_space_free(ma_space
);
2112 isl_multi_aff_free(ma
);
2116 static __isl_give PW
*FN(PW
,align_params_pw_pw_multi_aff_and
)(__isl_take PW
*pw
,
2117 __isl_take isl_pw_multi_aff
*pma
,
2118 __isl_give PW
*(*fn
)(__isl_take PW
*pw
,
2119 __isl_take isl_pw_multi_aff
*ma
))
2122 isl_bool equal_params
;
2123 isl_space
*pma_space
;
2125 pma_space
= isl_pw_multi_aff_get_space(pma
);
2126 if (!pw
|| !pma
|| !pma_space
)
2128 equal_params
= isl_space_has_equal_params(pw
->dim
, pma_space
);
2129 if (equal_params
< 0)
2132 isl_space_free(pma_space
);
2135 ctx
= FN(PW
,get_ctx
)(pw
);
2136 if (FN(PW
,check_named_params
)(pw
) < 0 ||
2137 isl_pw_multi_aff_check_named_params(pma
) < 0)
2139 pw
= FN(PW
,align_params
)(pw
, pma_space
);
2140 pma
= isl_pw_multi_aff_align_params(pma
, FN(PW
,get_space
)(pw
));
2143 isl_space_free(pma_space
);
2145 isl_pw_multi_aff_free(pma
);
2149 /* Compute the pullback of "pw" by the function represented by "ma".
2150 * In other words, plug in "ma" in "pw".
2152 static __isl_give PW
*FN(PW
,pullback_multi_aff_aligned
)(__isl_take PW
*pw
,
2153 __isl_take isl_multi_aff
*ma
)
2156 isl_space
*space
= NULL
;
2158 ma
= isl_multi_aff_align_divs(ma
);
2159 pw
= FN(PW
,cow
)(pw
);
2163 space
= isl_space_join(isl_multi_aff_get_space(ma
),
2164 FN(PW
,get_space
)(pw
));
2166 for (i
= 0; i
< pw
->n
; ++i
) {
2167 pw
->p
[i
].set
= isl_set_preimage_multi_aff(pw
->p
[i
].set
,
2168 isl_multi_aff_copy(ma
));
2171 pw
->p
[i
].FIELD
= FN(EL
,pullback_multi_aff
)(pw
->p
[i
].FIELD
,
2172 isl_multi_aff_copy(ma
));
2173 if (!pw
->p
[i
].FIELD
)
2177 pw
= FN(PW
,reset_space
)(pw
, space
);
2178 isl_multi_aff_free(ma
);
2181 isl_space_free(space
);
2182 isl_multi_aff_free(ma
);
2187 __isl_give PW
*FN(PW
,pullback_multi_aff
)(__isl_take PW
*pw
,
2188 __isl_take isl_multi_aff
*ma
)
2190 return FN(PW
,align_params_pw_multi_aff_and
)(pw
, ma
,
2191 &FN(PW
,pullback_multi_aff_aligned
));
2194 /* Compute the pullback of "pw" by the function represented by "pma".
2195 * In other words, plug in "pma" in "pw".
2197 static __isl_give PW
*FN(PW
,pullback_pw_multi_aff_aligned
)(__isl_take PW
*pw
,
2198 __isl_take isl_pw_multi_aff
*pma
)
2208 space
= isl_space_join(isl_pw_multi_aff_get_space(pma
),
2209 FN(PW
,get_space
)(pw
));
2210 isl_pw_multi_aff_free(pma
);
2211 res
= FN(PW
,empty
)(space
);
2216 res
= FN(PW
,pullback_multi_aff
)(FN(PW
,copy
)(pw
),
2217 isl_multi_aff_copy(pma
->p
[0].maff
));
2218 res
= FN(PW
,intersect_domain
)(res
, isl_set_copy(pma
->p
[0].set
));
2220 for (i
= 1; i
< pma
->n
; ++i
) {
2223 res_i
= FN(PW
,pullback_multi_aff
)(FN(PW
,copy
)(pw
),
2224 isl_multi_aff_copy(pma
->p
[i
].maff
));
2225 res_i
= FN(PW
,intersect_domain
)(res_i
,
2226 isl_set_copy(pma
->p
[i
].set
));
2227 res
= FN(PW
,add_disjoint
)(res
, res_i
);
2230 isl_pw_multi_aff_free(pma
);
2234 isl_pw_multi_aff_free(pma
);
2239 __isl_give PW
*FN(PW
,pullback_pw_multi_aff
)(__isl_take PW
*pw
,
2240 __isl_take isl_pw_multi_aff
*pma
)
2242 return FN(PW
,align_params_pw_pw_multi_aff_and
)(pw
, pma
,
2243 &FN(PW
,pullback_pw_multi_aff_aligned
));