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>
23 __isl_give PW
*FN(PW
,alloc_size
)(__isl_take isl_space
*space
24 OPT_TYPE_PARAM
, int n
)
31 ctx
= isl_space_get_ctx(space
);
32 isl_assert(ctx
, n
>= 0, goto error
);
33 pw
= isl_alloc(ctx
, struct PW
,
34 sizeof(struct PW
) + (n
- 1) * sizeof(S(PW
,piece
)));
39 OPT_SET_TYPE(pw
->, type
);
45 isl_space_free(space
);
49 __isl_give PW
*FN(PW
,ZERO
)(__isl_take isl_space
*space OPT_TYPE_PARAM
)
51 return FN(PW
,alloc_size
)(space
OPT_TYPE_ARG(NO_LOC
), 0);
54 /* Add a piece with domain "set" and base expression "el"
55 * to the piecewise expression "pw".
57 * Do this independently of the values of "set" and "el",
58 * such that this function can be used by isl_pw_*_dup.
60 __isl_give PW
*FN(PW
,add_dup_piece
)(__isl_take PW
*pw
,
61 __isl_take isl_set
*set
, __isl_take EL
*el
)
64 isl_space
*el_dim
= NULL
;
66 if (!pw
|| !set
|| !el
)
69 ctx
= isl_set_get_ctx(set
);
70 if (!OPT_EQUAL_TYPES(pw
->, el
->))
71 isl_die(ctx
, isl_error_invalid
, "fold types don't match",
73 el_dim
= FN(EL
,get_space(el
));
74 isl_assert(ctx
, isl_space_is_equal(pw
->dim
, el_dim
), goto error
);
75 isl_assert(ctx
, pw
->n
< pw
->size
, goto error
);
77 pw
->p
[pw
->n
].set
= set
;
78 pw
->p
[pw
->n
].FIELD
= el
;
81 isl_space_free(el_dim
);
84 isl_space_free(el_dim
);
91 /* Add a piece with domain "set" and base expression "el"
92 * to the piecewise expression "pw", provided the domain
93 * is not obviously empty and the base expression
94 * is not equal to the default value.
96 __isl_give PW
*FN(PW
,add_piece
)(__isl_take PW
*pw
,
97 __isl_take isl_set
*set
, __isl_take EL
*el
)
101 skip
= isl_set_plain_is_empty(set
);
102 if (skip
>= 0 && !skip
)
103 skip
= FN(EL
,EL_IS_ZERO
)(el
);
104 if (skip
>= 0 && !skip
)
105 return FN(PW
,add_dup_piece
)(pw
, set
, el
);
110 return FN(PW
,free
)(pw
);
114 /* Does the space of "set" correspond to that of the domain of "el".
116 static isl_bool
FN(PW
,compatible_domain
)(__isl_keep EL
*el
,
117 __isl_keep isl_set
*set
)
120 isl_space
*el_space
, *set_space
;
123 return isl_bool_error
;
124 set_space
= isl_set_get_space(set
);
125 el_space
= FN(EL
,get_space
)(el
);
126 ok
= isl_space_is_domain_internal(set_space
, el_space
);
127 isl_space_free(el_space
);
128 isl_space_free(set_space
);
132 /* Check that the space of "set" corresponds to that of the domain of "el".
134 static isl_stat
FN(PW
,check_compatible_domain
)(__isl_keep EL
*el
,
135 __isl_keep isl_set
*set
)
139 ok
= FN(PW
,compatible_domain
)(el
, set
);
141 return isl_stat_error
;
143 isl_die(isl_set_get_ctx(set
), isl_error_invalid
,
144 "incompatible spaces", return isl_stat_error
);
149 __isl_give PW
*FN(PW
,alloc
)(OPT_TYPE_PARAM_FIRST
150 __isl_take isl_set
*set
, __isl_take EL
*el
)
154 if (FN(PW
,check_compatible_domain
)(el
, set
) < 0)
157 pw
= FN(PW
,alloc_size
)(FN(EL
,get_space
)(el
) OPT_TYPE_ARG(NO_LOC
), 1);
159 return FN(PW
,add_piece
)(pw
, set
, el
);
166 __isl_give PW
*FN(PW
,dup
)(__isl_keep PW
*pw
)
174 dup
= FN(PW
,alloc_size
)(isl_space_copy(pw
->dim
)
175 OPT_TYPE_ARG(pw
->), pw
->n
);
179 for (i
= 0; i
< pw
->n
; ++i
)
180 dup
= FN(PW
,add_dup_piece
)(dup
, isl_set_copy(pw
->p
[i
].set
),
181 FN(EL
,copy
)(pw
->p
[i
].FIELD
));
186 __isl_give PW
*FN(PW
,cow
)(__isl_take PW
*pw
)
194 return FN(PW
,dup
)(pw
);
197 __isl_give PW
*FN(PW
,copy
)(__isl_keep PW
*pw
)
206 __isl_null PW
*FN(PW
,free
)(__isl_take PW
*pw
)
215 for (i
= 0; i
< pw
->n
; ++i
) {
216 isl_set_free(pw
->p
[i
].set
);
217 FN(EL
,free
)(pw
->p
[i
].FIELD
);
219 isl_space_free(pw
->dim
);
225 /* Create a piecewise expression with the given base expression on a universe
228 static __isl_give PW
*FN(FN(FN(PW
,from
),BASE
),type_base
)(__isl_take EL
*el
231 isl_set
*dom
= isl_set_universe(FN(EL
,get_domain_space
)(el
));
232 return FN(PW
,alloc
)(OPT_TYPE_ARG_FIRST(NO_LOC
) dom
, el
);
235 /* Create a piecewise expression with the given base expression on a universe
238 * If the default value of this piecewise type is zero and
239 * if "el" is effectively zero, then create an empty piecewise expression
242 static __isl_give PW
*FN(FN(FN(PW
,from
),BASE
),type
)(__isl_take EL
*el
248 if (!DEFAULT_IS_ZERO
)
249 return FN(FN(FN(PW
,from
),BASE
),type_base
)(el
250 OPT_TYPE_ARG(NO_LOC
));
251 is_zero
= FN(EL
,EL_IS_ZERO
)(el
);
255 return FN(FN(FN(PW
,from
),BASE
),type_base
)(el
256 OPT_TYPE_ARG(NO_LOC
));
257 space
= FN(EL
,get_space
)(el
);
259 return FN(PW
,ZERO
)(space
OPT_TYPE_ARG(NO_LOC
));
266 /* Create a piecewise expression with the given base expression on a universe
269 * Pass along the type as an extra argument for improved uniformity
270 * with piecewise types that do not have a fold type.
272 __isl_give PW
*FN(FN(PW
,from
),BASE
)(__isl_take EL
*el
)
274 enum isl_fold type
= FN(EL
,get_type
)(el
);
275 return FN(FN(FN(PW
,from
),BASE
),type
)(el
, type
);
278 __isl_give PW
*FN(FN(PW
,from
),BASE
)(__isl_take EL
*el
)
280 return FN(FN(FN(PW
,from
),BASE
),type
)(el
);
284 const char *FN(PW
,get_dim_name
)(__isl_keep PW
*pw
, enum isl_dim_type type
,
287 return pw
? isl_space_get_dim_name(pw
->dim
, type
, pos
) : NULL
;
290 isl_bool
FN(PW
,has_dim_id
)(__isl_keep PW
*pw
, enum isl_dim_type type
,
293 return pw
? isl_space_has_dim_id(pw
->dim
, type
, pos
) : isl_bool_error
;
296 __isl_give isl_id
*FN(PW
,get_dim_id
)(__isl_keep PW
*pw
, enum isl_dim_type type
,
299 return pw
? isl_space_get_dim_id(pw
->dim
, type
, pos
) : NULL
;
302 isl_bool
FN(PW
,has_tuple_name
)(__isl_keep PW
*pw
, enum isl_dim_type type
)
304 return pw
? isl_space_has_tuple_name(pw
->dim
, type
) : isl_bool_error
;
307 const char *FN(PW
,get_tuple_name
)(__isl_keep PW
*pw
, enum isl_dim_type type
)
309 return pw
? isl_space_get_tuple_name(pw
->dim
, type
) : NULL
;
312 isl_bool
FN(PW
,has_tuple_id
)(__isl_keep PW
*pw
, enum isl_dim_type type
)
314 return pw
? isl_space_has_tuple_id(pw
->dim
, type
) : isl_bool_error
;
317 __isl_give isl_id
*FN(PW
,get_tuple_id
)(__isl_keep PW
*pw
, enum isl_dim_type type
)
319 return pw
? isl_space_get_tuple_id(pw
->dim
, type
) : NULL
;
322 isl_bool
FN(PW
,IS_ZERO
)(__isl_keep PW
*pw
)
325 return isl_bool_error
;
327 return isl_bool_ok(pw
->n
== 0);
330 __isl_give PW
*FN(PW
,realign_domain
)(__isl_take PW
*pw
,
331 __isl_take isl_reordering
*exp
)
339 for (i
= 0; i
< pw
->n
; ++i
) {
340 pw
->p
[i
].set
= isl_set_realign(pw
->p
[i
].set
,
341 isl_reordering_copy(exp
));
344 pw
->p
[i
].FIELD
= FN(EL
,realign_domain
)(pw
->p
[i
].FIELD
,
345 isl_reordering_copy(exp
));
350 pw
= FN(PW
,reset_domain_space
)(pw
, isl_reordering_get_space(exp
));
352 isl_reordering_free(exp
);
355 isl_reordering_free(exp
);
363 #include "isl_check_named_params_templ.c"
365 /* Align the parameters of "pw" to those of "model".
367 __isl_give PW
*FN(PW
,align_params
)(__isl_take PW
*pw
, __isl_take isl_space
*model
)
370 isl_bool equal_params
;
375 ctx
= isl_space_get_ctx(model
);
376 if (!isl_space_has_named_params(model
))
377 isl_die(ctx
, isl_error_invalid
,
378 "model has unnamed parameters", goto error
);
379 if (FN(PW
,check_named_params
)(pw
) < 0)
381 equal_params
= isl_space_has_equal_params(pw
->dim
, model
);
382 if (equal_params
< 0)
387 exp
= isl_parameter_alignment_reordering(pw
->dim
, model
);
388 exp
= isl_reordering_extend_space(exp
,
389 FN(PW
,get_domain_space
)(pw
));
390 pw
= FN(PW
,realign_domain
)(pw
, exp
);
393 isl_space_free(model
);
396 isl_space_free(model
);
405 #include "isl_align_params_bin_templ.c"
415 #include "isl_align_params_templ.c"
420 #include "isl_type_has_equal_space_bin_templ.c"
421 #include "isl_type_check_equal_space_templ.c"
423 /* Private version of "union_add". For isl_pw_qpolynomial and
424 * isl_pw_qpolynomial_fold, we prefer to simply call it "add".
426 static __isl_give PW
*FN(PW
,union_add_
)(__isl_take PW
*pw1
, __isl_take PW
*pw2
)
433 if (FN(PW
,align_params_bin
)(&pw1
, &pw2
) < 0)
436 ctx
= isl_space_get_ctx(pw1
->dim
);
437 if (!OPT_EQUAL_TYPES(pw1
->, pw2
->))
438 isl_die(ctx
, isl_error_invalid
,
439 "fold types don't match", goto error
);
440 if (FN(PW
,check_equal_space
)(pw1
, pw2
) < 0)
443 if (FN(PW
,IS_ZERO
)(pw1
)) {
448 if (FN(PW
,IS_ZERO
)(pw2
)) {
453 n
= (pw1
->n
+ 1) * (pw2
->n
+ 1);
454 res
= FN(PW
,alloc_size
)(isl_space_copy(pw1
->dim
)
455 OPT_TYPE_ARG(pw1
->), n
);
457 for (i
= 0; i
< pw1
->n
; ++i
) {
458 set
= isl_set_copy(pw1
->p
[i
].set
);
459 for (j
= 0; j
< pw2
->n
; ++j
) {
460 struct isl_set
*common
;
462 common
= isl_set_intersect(isl_set_copy(pw1
->p
[i
].set
),
463 isl_set_copy(pw2
->p
[j
].set
));
464 if (isl_set_plain_is_empty(common
)) {
465 isl_set_free(common
);
468 set
= isl_set_subtract(set
,
469 isl_set_copy(pw2
->p
[j
].set
));
471 sum
= FN(EL
,add_on_domain
)(common
,
472 FN(EL
,copy
)(pw1
->p
[i
].FIELD
),
473 FN(EL
,copy
)(pw2
->p
[j
].FIELD
));
475 res
= FN(PW
,add_piece
)(res
, common
, sum
);
477 res
= FN(PW
,add_piece
)(res
, set
, FN(EL
,copy
)(pw1
->p
[i
].FIELD
));
480 for (j
= 0; j
< pw2
->n
; ++j
) {
481 set
= isl_set_copy(pw2
->p
[j
].set
);
482 for (i
= 0; i
< pw1
->n
; ++i
)
483 set
= isl_set_subtract(set
,
484 isl_set_copy(pw1
->p
[i
].set
));
485 res
= FN(PW
,add_piece
)(res
, set
, FN(EL
,copy
)(pw2
->p
[j
].FIELD
));
498 /* Make sure "pw" has room for at least "n" more pieces.
500 * If there is only one reference to pw, we extend it in place.
501 * Otherwise, we create a new PW and copy the pieces.
503 static __isl_give PW
*FN(PW
,grow
)(__isl_take PW
*pw
, int n
)
511 if (pw
->n
+ n
<= pw
->size
)
513 ctx
= FN(PW
,get_ctx
)(pw
);
516 res
= isl_realloc(ctx
, pw
, struct PW
,
517 sizeof(struct PW
) + (n
- 1) * sizeof(S(PW
,piece
)));
519 return FN(PW
,free
)(pw
);
523 res
= FN(PW
,alloc_size
)(isl_space_copy(pw
->dim
) OPT_TYPE_ARG(pw
->), 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 __isl_give PW
*FN(PW
,add_disjoint
)(__isl_take PW
*pw1
, __isl_take PW
*pw2
)
538 if (FN(PW
,align_params_bin
)(&pw1
, &pw2
) < 0)
541 if (pw1
->size
< pw1
->n
+ pw2
->n
&& pw1
->n
< pw2
->n
)
542 return FN(PW
,add_disjoint
)(pw2
, pw1
);
544 ctx
= isl_space_get_ctx(pw1
->dim
);
545 if (!OPT_EQUAL_TYPES(pw1
->, pw2
->))
546 isl_die(ctx
, isl_error_invalid
,
547 "fold types don't match", goto error
);
548 if (FN(PW
,check_equal_space
)(pw1
, pw2
) < 0)
551 if (FN(PW
,IS_ZERO
)(pw1
)) {
556 if (FN(PW
,IS_ZERO
)(pw2
)) {
561 pw1
= FN(PW
,grow
)(pw1
, pw2
->n
);
565 for (i
= 0; i
< pw2
->n
; ++i
)
566 pw1
= FN(PW
,add_piece
)(pw1
,
567 isl_set_copy(pw2
->p
[i
].set
),
568 FN(EL
,copy
)(pw2
->p
[i
].FIELD
));
579 /* This function is currently only used from isl_aff.c
581 static __isl_give PW
*FN(PW
,on_shared_domain_in
)(__isl_take PW
*pw1
,
582 __isl_take PW
*pw2
, __isl_take isl_space
*space
,
583 __isl_give EL
*(*fn
)(__isl_take EL
*el1
, __isl_take EL
*el2
))
584 __attribute__ ((unused
));
586 /* Apply "fn" to pairs of elements from pw1 and pw2 on shared domains.
587 * The result of "fn" (and therefore also of this function) lives in "space".
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
))
600 res
= FN(PW
,alloc_size
)(isl_space_copy(space
) OPT_TYPE_ARG(pw1
->), n
);
602 for (i
= 0; i
< pw1
->n
; ++i
) {
603 for (j
= 0; j
< pw2
->n
; ++j
) {
608 common
= isl_set_intersect(
609 isl_set_copy(pw1
->p
[i
].set
),
610 isl_set_copy(pw2
->p
[j
].set
));
611 empty
= isl_set_plain_is_empty(common
);
612 if (empty
< 0 || empty
) {
613 isl_set_free(common
);
619 res_ij
= fn(FN(EL
,copy
)(pw1
->p
[i
].FIELD
),
620 FN(EL
,copy
)(pw2
->p
[j
].FIELD
));
621 res_ij
= FN(EL
,gist
)(res_ij
, isl_set_copy(common
));
623 res
= FN(PW
,add_piece
)(res
, common
, res_ij
);
627 isl_space_free(space
);
632 isl_space_free(space
);
639 /* This function is currently only used from isl_aff.c
641 static __isl_give PW
*FN(PW
,on_shared_domain
)(__isl_take PW
*pw1
,
643 __isl_give EL
*(*fn
)(__isl_take EL
*el1
, __isl_take EL
*el2
))
644 __attribute__ ((unused
));
646 /* Apply "fn" to pairs of elements from pw1 and pw2 on shared domains.
647 * The result of "fn" is assumed to live in the same space as "pw1" and "pw2".
649 static __isl_give PW
*FN(PW
,on_shared_domain
)(__isl_take PW
*pw1
,
651 __isl_give EL
*(*fn
)(__isl_take EL
*el1
, __isl_take EL
*el2
))
655 if (FN(PW
,check_equal_space
)(pw1
, pw2
) < 0)
658 space
= isl_space_copy(pw1
->dim
);
659 return FN(PW
,on_shared_domain_in
)(pw1
, pw2
, space
, fn
);
666 /* Return the parameter domain of "pw".
668 __isl_give isl_set
*FN(PW
,params
)(__isl_take PW
*pw
)
670 return isl_set_params(FN(PW
,domain
)(pw
));
673 __isl_give isl_set
*FN(PW
,domain
)(__isl_take PW
*pw
)
681 dom
= isl_set_empty(FN(PW
,get_domain_space
)(pw
));
682 for (i
= 0; i
< pw
->n
; ++i
)
683 dom
= isl_set_union_disjoint(dom
, isl_set_copy(pw
->p
[i
].set
));
690 /* Exploit the equalities in the domain of piece "i" of "pw"
691 * to simplify the associated function.
692 * If the domain of piece "i" is empty, then remove it entirely,
693 * replacing it with the final piece.
695 static int FN(PW
,exploit_equalities_and_remove_if_empty
)(__isl_keep PW
*pw
,
699 int empty
= isl_set_plain_is_empty(pw
->p
[i
].set
);
704 isl_set_free(pw
->p
[i
].set
);
705 FN(EL
,free
)(pw
->p
[i
].FIELD
);
707 pw
->p
[i
] = pw
->p
[pw
->n
- 1];
713 aff
= isl_set_affine_hull(isl_set_copy(pw
->p
[i
].set
));
714 pw
->p
[i
].FIELD
= FN(EL
,substitute_equalities
)(pw
->p
[i
].FIELD
, aff
);
721 /* Convert a piecewise expression defined over a parameter domain
722 * into one that is defined over a zero-dimensional set.
724 __isl_give PW
*FN(PW
,from_range
)(__isl_take PW
*pw
)
730 if (!isl_space_is_set(pw
->dim
))
731 isl_die(FN(PW
,get_ctx
)(pw
), isl_error_invalid
,
732 "not living in a set space", return FN(PW
,free
)(pw
));
734 space
= FN(PW
,get_space
)(pw
);
735 space
= isl_space_from_range(space
);
736 pw
= FN(PW
,reset_space
)(pw
, space
);
741 /* Fix the value of the given parameter or domain dimension of "pw"
742 * to be equal to "value".
744 __isl_give PW
*FN(PW
,fix_si
)(__isl_take PW
*pw
, enum isl_dim_type type
,
745 unsigned pos
, int value
)
752 if (type
== isl_dim_out
)
753 isl_die(FN(PW
,get_ctx
)(pw
), isl_error_invalid
,
754 "cannot fix output dimension", return FN(PW
,free
)(pw
));
759 if (type
== isl_dim_in
)
764 return FN(PW
,free
)(pw
);
766 for (i
= pw
->n
- 1; i
>= 0; --i
) {
767 pw
->p
[i
].set
= isl_set_fix_si(pw
->p
[i
].set
, type
, pos
, value
);
768 if (FN(PW
,exploit_equalities_and_remove_if_empty
)(pw
, i
) < 0)
769 return FN(PW
,free
)(pw
);
775 /* Restrict the domain of "pw" by combining each cell
776 * with "set" through a call to "fn", where "fn" may be
777 * isl_set_intersect, isl_set_intersect_params, isl_set_intersect_factor_domain,
778 * isl_set_intersect_factor_range or isl_set_subtract.
780 static __isl_give PW
*FN(PW
,restrict_domain
)(__isl_take PW
*pw
,
781 __isl_take isl_set
*set
,
782 __isl_give isl_set
*(*fn
)(__isl_take isl_set
*set1
,
783 __isl_take isl_set
*set2
))
787 FN(PW
,align_params_set
)(&pw
, &set
);
800 for (i
= pw
->n
- 1; i
>= 0; --i
) {
801 pw
->p
[i
].set
= fn(pw
->p
[i
].set
, isl_set_copy(set
));
802 if (FN(PW
,exploit_equalities_and_remove_if_empty
)(pw
, i
) < 0)
814 __isl_give PW
*FN(PW
,intersect_domain
)(__isl_take PW
*pw
,
815 __isl_take isl_set
*context
)
817 return FN(PW
,restrict_domain
)(pw
, context
, &isl_set_intersect
);
820 /* Intersect the domain of "pw" with the parameter domain "context".
822 __isl_give PW
*FN(PW
,intersect_params
)(__isl_take PW
*pw
,
823 __isl_take isl_set
*context
)
825 return FN(PW
,restrict_domain
)(pw
, context
, &isl_set_intersect_params
);
828 /* Given a piecewise expression "pw" with domain in a space [A -> B] and
829 * a set in the space A, intersect the domain with the set.
831 __isl_give PW
*FN(PW
,intersect_domain_wrapped_domain
)(__isl_take PW
*pw
,
832 __isl_take isl_set
*set
)
834 return FN(PW
,restrict_domain
)(pw
, set
,
835 &isl_set_intersect_factor_domain
);
838 /* Given a piecewise expression "pw" with domain in a space [A -> B] and
839 * a set in the space B, intersect the domain with the set.
841 __isl_give PW
*FN(PW
,intersect_domain_wrapped_range
)(__isl_take PW
*pw
,
842 __isl_take isl_set
*set
)
844 return FN(PW
,restrict_domain
)(pw
, set
, &isl_set_intersect_factor_range
);
847 /* Subtract "domain' from the domain of "pw".
849 __isl_give PW
*FN(PW
,subtract_domain
)(__isl_take PW
*pw
,
850 __isl_take isl_set
*domain
)
852 return FN(PW
,restrict_domain
)(pw
, domain
, &isl_set_subtract
);
855 /* Return -1 if the piece "p1" should be sorted before "p2"
856 * and 1 if it should be sorted after "p2".
857 * Return 0 if they do not need to be sorted in a specific order.
859 * The two pieces are compared on the basis of their function value expressions.
861 static int FN(PW
,sort_field_cmp
)(const void *p1
, const void *p2
, void *arg
)
863 struct FN(PW
,piece
) const *pc1
= p1
;
864 struct FN(PW
,piece
) const *pc2
= p2
;
866 return FN(EL
,plain_cmp
)(pc1
->FIELD
, pc2
->FIELD
);
869 /* Sort the pieces of "pw" according to their function value
870 * expressions and then combine pairs of adjacent pieces with
871 * the same such expression.
873 * The sorting is performed in place because it does not
874 * change the meaning of "pw", but care needs to be
875 * taken not to change any possible other copies of "pw"
876 * in case anything goes wrong.
878 static __isl_give PW
*FN(PW
,sort_unique
)(__isl_take PW
*pw
)
887 if (isl_sort(pw
->p
, pw
->n
, sizeof(pw
->p
[0]),
888 &FN(PW
,sort_field_cmp
), NULL
) < 0)
889 return FN(PW
,free
)(pw
);
890 for (i
= pw
->n
- 1; i
>= 1; --i
) {
891 if (!FN(EL
,plain_is_equal
)(pw
->p
[i
- 1].FIELD
, pw
->p
[i
].FIELD
))
893 set
= isl_set_union(isl_set_copy(pw
->p
[i
- 1].set
),
894 isl_set_copy(pw
->p
[i
].set
));
896 return FN(PW
,free
)(pw
);
897 isl_set_free(pw
->p
[i
].set
);
898 FN(EL
,free
)(pw
->p
[i
].FIELD
);
899 isl_set_free(pw
->p
[i
- 1].set
);
900 pw
->p
[i
- 1].set
= set
;
901 for (j
= i
+ 1; j
< pw
->n
; ++j
)
902 pw
->p
[j
- 1] = pw
->p
[j
];
909 /* Compute the gist of "pw" with respect to the domain constraints
910 * of "context" for the case where the domain of the last element
911 * of "pw" is equal to "context".
912 * Call "fn_el" to compute the gist of this element, replace
913 * its domain by the universe and drop all other elements
914 * as their domains are necessarily disjoint from "context".
916 static __isl_give PW
*FN(PW
,gist_last
)(__isl_take PW
*pw
,
917 __isl_take isl_set
*context
,
918 __isl_give EL
*(*fn_el
)(__isl_take EL
*el
, __isl_take isl_set
*set
))
923 for (i
= 0; i
< pw
->n
- 1; ++i
) {
924 isl_set_free(pw
->p
[i
].set
);
925 FN(EL
,free
)(pw
->p
[i
].FIELD
);
927 pw
->p
[0].FIELD
= pw
->p
[pw
->n
- 1].FIELD
;
928 pw
->p
[0].set
= pw
->p
[pw
->n
- 1].set
;
931 space
= isl_set_get_space(context
);
932 pw
->p
[0].FIELD
= fn_el(pw
->p
[0].FIELD
, context
);
933 context
= isl_set_universe(space
);
934 isl_set_free(pw
->p
[0].set
);
935 pw
->p
[0].set
= context
;
937 if (!pw
->p
[0].FIELD
|| !pw
->p
[0].set
)
938 return FN(PW
,free
)(pw
);
943 /* Compute the gist of "pw" with respect to the domain constraints
944 * of "context". Call "fn_el" to compute the gist of the elements
945 * and "fn_dom" to compute the gist of the domains.
947 * If the piecewise expression is empty or the context is the universe,
948 * then nothing can be simplified.
949 * If "pw" has a single domain and it is equal to "context",
950 * then simply replace the domain by the universe.
951 * Combine duplicate function value expressions first
952 * to increase the chance of "pw" having a single domain.
954 static __isl_give PW
*FN(PW
,gist_fn
)(__isl_take PW
*pw
,
955 __isl_take isl_set
*context
,
956 __isl_give EL
*(*fn_el
)(__isl_take EL
*el
,
957 __isl_take isl_set
*set
),
958 __isl_give isl_set
*(*fn_dom
)(__isl_take isl_set
*set
,
959 __isl_take isl_basic_set
*bset
))
963 isl_basic_set
*hull
= NULL
;
965 pw
= FN(PW
,sort_unique
)(pw
);
970 isl_set_free(context
);
974 is_universe
= isl_set_plain_is_universe(context
);
978 isl_set_free(context
);
982 FN(PW
,align_params_set
)(&pw
, &context
);
991 equal
= isl_set_plain_is_equal(pw
->p
[0].set
, context
);
995 return FN(PW
,gist_last
)(pw
, context
, fn_el
);
998 context
= isl_set_compute_divs(context
);
999 hull
= isl_set_simple_hull(isl_set_copy(context
));
1001 for (i
= pw
->n
- 1; i
>= 0; --i
) {
1005 if (i
== pw
->n
- 1) {
1007 equal
= isl_set_plain_is_equal(pw
->p
[i
].set
, context
);
1011 isl_basic_set_free(hull
);
1012 return FN(PW
,gist_last
)(pw
, context
, fn_el
);
1015 set_i
= isl_set_intersect(isl_set_copy(pw
->p
[i
].set
),
1016 isl_set_copy(context
));
1017 empty
= isl_set_plain_is_empty(set_i
);
1018 pw
->p
[i
].FIELD
= fn_el(pw
->p
[i
].FIELD
, set_i
);
1019 pw
->p
[i
].set
= fn_dom(pw
->p
[i
].set
, isl_basic_set_copy(hull
));
1020 if (empty
< 0 || !pw
->p
[i
].FIELD
|| !pw
->p
[i
].set
)
1023 isl_set_free(pw
->p
[i
].set
);
1024 FN(EL
,free
)(pw
->p
[i
].FIELD
);
1026 pw
->p
[i
] = pw
->p
[pw
->n
- 1];
1031 isl_basic_set_free(hull
);
1032 isl_set_free(context
);
1037 isl_basic_set_free(hull
);
1038 isl_set_free(context
);
1042 __isl_give PW
*FN(PW
,gist
)(__isl_take PW
*pw
, __isl_take isl_set
*context
)
1044 return FN(PW
,gist_fn
)(pw
, context
, &FN(EL
,gist
),
1045 &isl_set_gist_basic_set
);
1048 __isl_give PW
*FN(PW
,gist_params
)(__isl_take PW
*pw
,
1049 __isl_take isl_set
*context
)
1051 return FN(PW
,gist_fn
)(pw
, context
, &FN(EL
,gist_params
),
1052 &isl_set_gist_params_basic_set
);
1055 /* Coalesce the domains of "pw".
1057 * Prior to the actual coalescing, first sort the pieces such that
1058 * pieces with the same function value expression are combined
1059 * into a single piece, the combined domain of which can then
1062 __isl_give PW
*FN(PW
,coalesce
)(__isl_take PW
*pw
)
1066 pw
= FN(PW
,sort_unique
)(pw
);
1070 for (i
= 0; i
< pw
->n
; ++i
) {
1071 pw
->p
[i
].set
= isl_set_coalesce(pw
->p
[i
].set
);
1082 isl_ctx
*FN(PW
,get_ctx
)(__isl_keep PW
*pw
)
1084 return pw
? isl_space_get_ctx(pw
->dim
) : NULL
;
1087 isl_bool
FN(PW
,involves_dims
)(__isl_keep PW
*pw
, enum isl_dim_type type
,
1088 unsigned first
, unsigned n
)
1091 enum isl_dim_type set_type
;
1094 return isl_bool_error
;
1095 if (pw
->n
== 0 || n
== 0)
1096 return isl_bool_false
;
1098 set_type
= type
== isl_dim_in
? isl_dim_set
: type
;
1100 for (i
= 0; i
< pw
->n
; ++i
) {
1101 isl_bool involves
= FN(EL
,involves_dims
)(pw
->p
[i
].FIELD
,
1103 if (involves
< 0 || involves
)
1105 involves
= isl_set_involves_dims(pw
->p
[i
].set
,
1106 set_type
, first
, n
);
1107 if (involves
< 0 || involves
)
1110 return isl_bool_false
;
1113 __isl_give PW
*FN(PW
,set_dim_name
)(__isl_take PW
*pw
,
1114 enum isl_dim_type type
, unsigned pos
, const char *s
)
1117 enum isl_dim_type set_type
;
1119 pw
= FN(PW
,cow
)(pw
);
1123 set_type
= type
== isl_dim_in
? isl_dim_set
: type
;
1125 pw
->dim
= isl_space_set_dim_name(pw
->dim
, type
, pos
, s
);
1129 for (i
= 0; i
< pw
->n
; ++i
) {
1130 pw
->p
[i
].set
= isl_set_set_dim_name(pw
->p
[i
].set
,
1134 pw
->p
[i
].FIELD
= FN(EL
,set_dim_name
)(pw
->p
[i
].FIELD
, type
, pos
, s
);
1135 if (!pw
->p
[i
].FIELD
)
1145 __isl_give PW
*FN(PW
,drop_dims
)(__isl_take PW
*pw
,
1146 enum isl_dim_type type
, unsigned first
, unsigned n
)
1149 enum isl_dim_type set_type
;
1153 if (n
== 0 && !isl_space_get_tuple_name(pw
->dim
, type
))
1156 set_type
= type
== isl_dim_in
? isl_dim_set
: type
;
1158 pw
= FN(PW
,cow
)(pw
);
1161 pw
->dim
= isl_space_drop_dims(pw
->dim
, type
, first
, n
);
1164 for (i
= 0; i
< pw
->n
; ++i
) {
1165 pw
->p
[i
].FIELD
= FN(EL
,drop_dims
)(pw
->p
[i
].FIELD
, type
, first
, n
);
1166 if (!pw
->p
[i
].FIELD
)
1168 if (type
== isl_dim_out
)
1170 pw
->p
[i
].set
= isl_set_drop(pw
->p
[i
].set
, set_type
, first
, n
);
1181 /* This function is very similar to drop_dims.
1182 * The only difference is that the cells may still involve
1183 * the specified dimensions. They are removed using
1184 * isl_set_project_out instead of isl_set_drop.
1186 __isl_give PW
*FN(PW
,project_out
)(__isl_take PW
*pw
,
1187 enum isl_dim_type type
, unsigned first
, unsigned n
)
1190 enum isl_dim_type set_type
;
1194 if (n
== 0 && !isl_space_get_tuple_name(pw
->dim
, type
))
1197 set_type
= type
== isl_dim_in
? isl_dim_set
: type
;
1199 pw
= FN(PW
,cow
)(pw
);
1202 pw
->dim
= isl_space_drop_dims(pw
->dim
, type
, first
, n
);
1205 for (i
= 0; i
< pw
->n
; ++i
) {
1206 pw
->p
[i
].set
= isl_set_project_out(pw
->p
[i
].set
,
1207 set_type
, first
, n
);
1210 pw
->p
[i
].FIELD
= FN(EL
,drop_dims
)(pw
->p
[i
].FIELD
, type
, first
, n
);
1211 if (!pw
->p
[i
].FIELD
)
1221 /* Project the domain of pw onto its parameter space.
1223 __isl_give PW
*FN(PW
,project_domain_on_params
)(__isl_take PW
*pw
)
1228 n
= FN(PW
,dim
)(pw
, isl_dim_in
);
1230 return FN(PW
,free
)(pw
);
1231 pw
= FN(PW
,project_out
)(pw
, isl_dim_in
, 0, n
);
1232 space
= FN(PW
,get_domain_space
)(pw
);
1233 space
= isl_space_params(space
);
1234 pw
= FN(PW
,reset_domain_space
)(pw
, space
);
1238 /* Drop all parameters not referenced by "pw".
1240 __isl_give PW
*FN(PW
,drop_unused_params
)(__isl_take PW
*pw
)
1245 if (FN(PW
,check_named_params
)(pw
) < 0)
1246 return FN(PW
,free
)(pw
);
1248 n
= FN(PW
,dim
)(pw
, isl_dim_param
);
1250 return FN(PW
,free
)(pw
);
1251 for (i
= n
- 1; i
>= 0; i
--) {
1254 involves
= FN(PW
,involves_dims
)(pw
, isl_dim_param
, i
, 1);
1256 return FN(PW
,free
)(pw
);
1258 pw
= FN(PW
,drop_dims
)(pw
, isl_dim_param
, i
, 1);
1264 __isl_give PW
*FN(PW
,fix_dim
)(__isl_take PW
*pw
,
1265 enum isl_dim_type type
, unsigned pos
, isl_int v
)
1272 if (type
== isl_dim_in
)
1275 pw
= FN(PW
,cow
)(pw
);
1278 for (i
= 0; i
< pw
->n
; ++i
) {
1279 pw
->p
[i
].set
= isl_set_fix(pw
->p
[i
].set
, type
, pos
, v
);
1280 if (FN(PW
,exploit_equalities_and_remove_if_empty
)(pw
, i
) < 0)
1281 return FN(PW
,free
)(pw
);
1287 /* Fix the value of the variable at position "pos" of type "type" of "pw"
1288 * to be equal to "v".
1290 __isl_give PW
*FN(PW
,fix_val
)(__isl_take PW
*pw
,
1291 enum isl_dim_type type
, unsigned pos
, __isl_take isl_val
*v
)
1294 return FN(PW
,free
)(pw
);
1295 if (!isl_val_is_int(v
))
1296 isl_die(FN(PW
,get_ctx
)(pw
), isl_error_invalid
,
1297 "expecting integer value", goto error
);
1299 pw
= FN(PW
,fix_dim
)(pw
, type
, pos
, v
->n
);
1305 return FN(PW
,free
)(pw
);
1308 isl_size
FN(PW
,dim
)(__isl_keep PW
*pw
, enum isl_dim_type type
)
1310 return isl_space_dim(FN(PW
,peek_space
)(pw
), type
);
1313 __isl_give PW
*FN(PW
,split_dims
)(__isl_take PW
*pw
,
1314 enum isl_dim_type type
, unsigned first
, unsigned n
)
1323 if (type
== isl_dim_in
)
1326 pw
= FN(PW
,cow
)(pw
);
1331 for (i
= 0; i
< pw
->n
; ++i
) {
1332 pw
->p
[i
].set
= isl_set_split_dims(pw
->p
[i
].set
, type
, first
, n
);
1343 /* Return the space of "pw".
1345 __isl_keep isl_space
*FN(PW
,peek_space
)(__isl_keep PW
*pw
)
1347 return pw
? pw
->dim
: NULL
;
1350 __isl_give isl_space
*FN(PW
,get_space
)(__isl_keep PW
*pw
)
1352 return isl_space_copy(FN(PW
,peek_space
)(pw
));
1355 /* Return the space of "pw".
1356 * This may be either a copy or the space itself
1357 * if there is only one reference to "pw".
1358 * This allows the space to be modified inplace
1359 * if both the piecewise expression and its space have only a single reference.
1360 * The caller is not allowed to modify "pw" between this call and
1361 * a subsequent call to isl_pw_*_restore_*.
1362 * The only exception is that isl_pw_*_free can be called instead.
1364 __isl_give isl_space
*FN(PW
,take_space
)(__isl_keep PW
*pw
)
1371 return FN(PW
,get_space
)(pw
);
1377 /* Set the space of "pw" to "space", where the space of "pw" may be missing
1378 * due to a preceding call to isl_pw_*_take_space.
1379 * However, in this case, "pw" only has a single reference and
1380 * then the call to isl_pw_*_cow has no effect.
1382 __isl_give PW
*FN(PW
,restore_space
)(__isl_take PW
*pw
,
1383 __isl_take isl_space
*space
)
1388 if (pw
->dim
== space
) {
1389 isl_space_free(space
);
1393 pw
= FN(PW
,cow
)(pw
);
1396 isl_space_free(pw
->dim
);
1402 isl_space_free(space
);
1406 /* Check that "pos" is a valid position for a cell in "pw".
1408 static isl_stat
FN(PW
,check_pos
)(__isl_keep PW
*pw
, int pos
)
1411 return isl_stat_error
;
1412 if (pos
< 0 || pos
>= pw
->n
)
1413 isl_die(FN(PW
,get_ctx
)(pw
), isl_error_internal
,
1414 "position out of bounds", return isl_stat_error
);
1418 /* Return the cell at position "pos" in "pw".
1420 static __isl_keep isl_set
*FN(PW
,peek_domain_at
)(__isl_keep PW
*pw
, int pos
)
1422 if (FN(PW
,check_pos
)(pw
, pos
) < 0)
1424 return pw
->p
[pos
].set
;
1427 /* Return a copy of the cell at position "pos" in "pw".
1429 __isl_give isl_set
*FN(PW
,get_domain_at
)(__isl_keep PW
*pw
, int pos
)
1431 return isl_set_copy(FN(PW
,peek_domain_at
)(pw
, pos
));
1434 /* Return the base expression associated to
1435 * the cell at position "pos" in "pw".
1437 static __isl_keep EL
*FN(PW
,peek_base_at
)(__isl_keep PW
*pw
, int pos
)
1439 if (FN(PW
,check_pos
)(pw
, pos
) < 0)
1441 return pw
->p
[pos
].FIELD
;
1444 /* Return a copy of the base expression associated to
1445 * the cell at position "pos" in "pw".
1447 __isl_give EL
*FN(PW
,get_base_at
)(__isl_keep PW
*pw
, int pos
)
1449 return FN(EL
,copy
)(FN(PW
,peek_base_at
)(pw
, pos
));
1452 /* Return the base expression associated to
1453 * the cell at position "pos" in "pw".
1454 * This may be either a copy or the base expression itself
1455 * if there is only one reference to "pw".
1456 * This allows the base expression to be modified inplace
1457 * if both the piecewise expression and this base expression
1458 * have only a single reference.
1459 * The caller is not allowed to modify "pw" between this call and
1460 * a subsequent call to isl_pw_*_restore_*.
1461 * The only exception is that isl_pw_*_free can be called instead.
1463 __isl_give EL
*FN(PW
,take_base_at
)(__isl_keep PW
*pw
, int pos
)
1470 return FN(PW
,get_base_at
)(pw
, pos
);
1471 if (FN(PW
,check_pos
)(pw
, pos
) < 0)
1473 el
= pw
->p
[pos
].FIELD
;
1474 pw
->p
[pos
].FIELD
= NULL
;
1478 /* Set the base expression associated to
1479 * the cell at position "pos" in "pw" to "el",
1480 * where this base expression may be missing
1481 * due to a preceding call to isl_pw_*_take_base_at.
1482 * However, in this case, "pw" only has a single reference and
1483 * then the call to isl_pw_*_cow has no effect.
1485 __isl_give PW
*FN(PW
,restore_base_at
)(__isl_take PW
*pw
, int pos
,
1488 if (FN(PW
,check_pos
)(pw
, pos
) < 0 || !el
)
1491 if (pw
->p
[pos
].FIELD
== el
) {
1496 pw
= FN(PW
,cow
)(pw
);
1499 FN(EL
,free
)(pw
->p
[pos
].FIELD
);
1500 pw
->p
[pos
].FIELD
= el
;
1509 __isl_give isl_space
*FN(PW
,get_domain_space
)(__isl_keep PW
*pw
)
1511 return pw
? isl_space_domain(isl_space_copy(pw
->dim
)) : NULL
;
1514 /* Return the position of the dimension of the given type and name
1516 * Return -1 if no such dimension can be found.
1518 int FN(PW
,find_dim_by_name
)(__isl_keep PW
*pw
,
1519 enum isl_dim_type type
, const char *name
)
1523 return isl_space_find_dim_by_name(pw
->dim
, type
, name
);
1526 /* Return the position of the dimension of the given type and identifier
1528 * Return -1 if no such dimension can be found.
1530 static int FN(PW
,find_dim_by_id
)(__isl_keep PW
*pw
,
1531 enum isl_dim_type type
, __isl_keep isl_id
*id
)
1535 space
= FN(PW
,peek_space
)(pw
);
1536 return isl_space_find_dim_by_id(space
, type
, id
);
1539 /* Does the piecewise expression "pw" depend in any way
1540 * on the parameter with identifier "id"?
1542 isl_bool
FN(PW
,involves_param_id
)(__isl_keep PW
*pw
, __isl_keep isl_id
*id
)
1547 return isl_bool_error
;
1549 return isl_bool_false
;
1551 pos
= FN(PW
,find_dim_by_id
)(pw
, isl_dim_param
, id
);
1553 return isl_bool_false
;
1554 return FN(PW
,involves_dims
)(pw
, isl_dim_param
, pos
, 1);
1557 /* Reset the space of "pw". Since we don't know if the elements
1558 * represent the spaces themselves or their domains, we pass along
1559 * both when we call their reset_space_and_domain.
1561 static __isl_give PW
*FN(PW
,reset_space_and_domain
)(__isl_take PW
*pw
,
1562 __isl_take isl_space
*space
, __isl_take isl_space
*domain
)
1566 pw
= FN(PW
,cow
)(pw
);
1567 if (!pw
|| !space
|| !domain
)
1570 for (i
= 0; i
< pw
->n
; ++i
) {
1571 pw
->p
[i
].set
= isl_set_reset_space(pw
->p
[i
].set
,
1572 isl_space_copy(domain
));
1575 pw
->p
[i
].FIELD
= FN(EL
,reset_space_and_domain
)(pw
->p
[i
].FIELD
,
1576 isl_space_copy(space
), isl_space_copy(domain
));
1577 if (!pw
->p
[i
].FIELD
)
1581 isl_space_free(domain
);
1583 isl_space_free(pw
->dim
);
1588 isl_space_free(domain
);
1589 isl_space_free(space
);
1594 __isl_give PW
*FN(PW
,reset_domain_space
)(__isl_take PW
*pw
,
1595 __isl_take isl_space
*domain
)
1599 space
= isl_space_extend_domain_with_range(isl_space_copy(domain
),
1600 FN(PW
,get_space
)(pw
));
1601 return FN(PW
,reset_space_and_domain
)(pw
, space
, domain
);
1604 __isl_give PW
*FN(PW
,reset_space
)(__isl_take PW
*pw
,
1605 __isl_take isl_space
*space
)
1609 domain
= isl_space_domain(isl_space_copy(space
));
1610 return FN(PW
,reset_space_and_domain
)(pw
, space
, domain
);
1613 __isl_give PW
*FN(PW
,set_tuple_id
)(__isl_take PW
*pw
, enum isl_dim_type type
,
1614 __isl_take isl_id
*id
)
1618 pw
= FN(PW
,cow
)(pw
);
1622 space
= FN(PW
,get_space
)(pw
);
1623 space
= isl_space_set_tuple_id(space
, type
, id
);
1625 return FN(PW
,reset_space
)(pw
, space
);
1628 return FN(PW
,free
)(pw
);
1631 /* Drop the id on the specified tuple.
1633 __isl_give PW
*FN(PW
,reset_tuple_id
)(__isl_take PW
*pw
, enum isl_dim_type type
)
1639 if (!FN(PW
,has_tuple_id
)(pw
, type
))
1642 pw
= FN(PW
,cow
)(pw
);
1646 space
= FN(PW
,get_space
)(pw
);
1647 space
= isl_space_reset_tuple_id(space
, type
);
1649 return FN(PW
,reset_space
)(pw
, space
);
1652 __isl_give PW
*FN(PW
,set_dim_id
)(__isl_take PW
*pw
,
1653 enum isl_dim_type type
, unsigned pos
, __isl_take isl_id
*id
)
1655 pw
= FN(PW
,cow
)(pw
);
1658 pw
->dim
= isl_space_set_dim_id(pw
->dim
, type
, pos
, id
);
1659 return FN(PW
,reset_space
)(pw
, isl_space_copy(pw
->dim
));
1662 return FN(PW
,free
)(pw
);
1665 /* Reset the user pointer on all identifiers of parameters and tuples
1666 * of the space of "pw".
1668 __isl_give PW
*FN(PW
,reset_user
)(__isl_take PW
*pw
)
1672 space
= FN(PW
,get_space
)(pw
);
1673 space
= isl_space_reset_user(space
);
1675 return FN(PW
,reset_space
)(pw
, space
);
1678 isl_size
FN(PW
,n_piece
)(__isl_keep PW
*pw
)
1680 return pw
? pw
->n
: isl_size_error
;
1683 isl_stat
FN(PW
,foreach_piece
)(__isl_keep PW
*pw
,
1684 isl_stat (*fn
)(__isl_take isl_set
*set
, __isl_take EL
*el
, void *user
),
1690 return isl_stat_error
;
1692 for (i
= 0; i
< pw
->n
; ++i
)
1693 if (fn(isl_set_copy(pw
->p
[i
].set
),
1694 FN(EL
,copy
)(pw
->p
[i
].FIELD
), user
) < 0)
1695 return isl_stat_error
;
1700 /* Does "test" succeed on every cell of "pw"?
1702 isl_bool
FN(PW
,every_piece
)(__isl_keep PW
*pw
,
1703 isl_bool (*test
)(__isl_keep isl_set
*set
,
1704 __isl_keep EL
*el
, void *user
), void *user
)
1709 return isl_bool_error
;
1711 for (i
= 0; i
< pw
->n
; ++i
) {
1714 r
= test(pw
->p
[i
].set
, pw
->p
[i
].FIELD
, user
);
1719 return isl_bool_true
;
1722 /* Is "pw" defined over a single universe domain?
1724 * If the default value of this piecewise type is zero,
1725 * then a "pw" with a zero number of cells is also accepted
1726 * as it represents the default zero value.
1728 isl_bool
FN(FN(PW
,isa
),BASE
)(__isl_keep PW
*pw
)
1732 n
= FN(PW
,n_piece
)(pw
);
1734 return isl_bool_error
;
1735 if (DEFAULT_IS_ZERO
&& n
== 0)
1736 return isl_bool_true
;
1738 return isl_bool_false
;
1739 return isl_set_plain_is_universe(FN(PW
,peek_domain_at
)(pw
, 0));
1742 /* Return a zero base expression in the same space (and of the same type)
1745 static __isl_give EL
*FN(EL
,zero_like_type
)(__isl_take PW
*pw OPT_TYPE_PARAM
)
1749 space
= FN(PW
,get_space
)(pw
);
1751 return FN(EL
,zero_in_space
)(space
OPT_TYPE_ARG(NO_LOC
));
1755 /* Return a zero base expression in the same space as "pw".
1757 static __isl_give EL
*FN(EL
,zero_like
)(__isl_take PW
*pw
)
1759 return FN(EL
,zero_like_type
)(pw
);
1762 /* Return a zero base expression in the same space and of the same type
1765 * Pass along the type as an explicit argument for uniform handling
1766 * in isl_*_zero_like_type.
1768 static __isl_give EL
*FN(EL
,zero_like
)(__isl_take PW
*pw
)
1772 type
= FN(PW
,get_type
)(pw
);
1775 return FN(EL
,zero_like_type
)(pw
, type
);
1782 /* Given that "pw" is defined over a single universe domain,
1783 * return the base expression associated to this domain.
1785 * If the number of cells is zero, then "pw" is of a piecewise type
1786 * with a default zero value and effectively represents zero.
1787 * In this case, create a zero base expression in the same space
1788 * (and with the same type).
1789 * Otherwise, simply extract the associated base expression.
1791 __isl_give EL
*FN(FN(PW
,as
),BASE
)(__isl_take PW
*pw
)
1797 is_total
= FN(FN(PW
,isa
),BASE
)(pw
);
1801 isl_die(FN(PW
,get_ctx
)(pw
), isl_error_invalid
,
1802 "expecting single total function", goto error
);
1803 n
= FN(PW
,n_piece
)(pw
);
1807 return FN(EL
,zero_like
)(pw
);
1808 el
= FN(PW
,take_base_at
)(pw
, 0);
1817 /* Negate the type of "pw".
1819 static __isl_give PW
*FN(PW
,negate_type
)(__isl_take PW
*pw
)
1821 pw
= FN(PW
,cow
)(pw
);
1824 pw
->type
= isl_fold_type_negate(pw
->type
);
1828 /* Negate the type of "pw".
1829 * Since "pw" does not have a type, do nothing.
1831 static __isl_give PW
*FN(PW
,negate_type
)(__isl_take PW
*pw
)
1837 __isl_give PW
*FN(PW
,mul_isl_int
)(__isl_take PW
*pw
, isl_int v
)
1841 if (isl_int_is_one(v
))
1843 if (pw
&& DEFAULT_IS_ZERO
&& isl_int_is_zero(v
)) {
1845 isl_space
*space
= FN(PW
,get_space
)(pw
);
1846 zero
= FN(PW
,ZERO
)(space
OPT_TYPE_ARG(pw
->));
1850 pw
= FN(PW
,cow
)(pw
);
1851 if (isl_int_is_neg(v
))
1852 pw
= FN(PW
,negate_type
)(pw
);
1858 for (i
= 0; i
< pw
->n
; ++i
) {
1859 pw
->p
[i
].FIELD
= FN(EL
,scale
)(pw
->p
[i
].FIELD
, v
);
1860 if (!pw
->p
[i
].FIELD
)
1870 /* Multiply the pieces of "pw" by "v" and return the result.
1872 __isl_give PW
*FN(PW
,scale_val
)(__isl_take PW
*pw
, __isl_take isl_val
*v
)
1879 if (isl_val_is_one(v
)) {
1883 if (pw
&& DEFAULT_IS_ZERO
&& isl_val_is_zero(v
)) {
1885 isl_space
*space
= FN(PW
,get_space
)(pw
);
1886 zero
= FN(PW
,ZERO
)(space
OPT_TYPE_ARG(pw
->));
1895 pw
= FN(PW
,cow
)(pw
);
1896 if (isl_val_is_neg(v
))
1897 pw
= FN(PW
,negate_type
)(pw
);
1901 for (i
= 0; i
< pw
->n
; ++i
) {
1902 pw
->p
[i
].FIELD
= FN(EL
,scale_val
)(pw
->p
[i
].FIELD
,
1904 if (!pw
->p
[i
].FIELD
)
1916 /* Divide the pieces of "pw" by "v" and return the result.
1918 __isl_give PW
*FN(PW
,scale_down_val
)(__isl_take PW
*pw
, __isl_take isl_val
*v
)
1925 if (isl_val_is_one(v
)) {
1930 if (!isl_val_is_rat(v
))
1931 isl_die(isl_val_get_ctx(v
), isl_error_invalid
,
1932 "expecting rational factor", goto error
);
1933 if (isl_val_is_zero(v
))
1934 isl_die(isl_val_get_ctx(v
), isl_error_invalid
,
1935 "cannot scale down by zero", goto error
);
1941 pw
= FN(PW
,cow
)(pw
);
1942 if (isl_val_is_neg(v
))
1943 pw
= FN(PW
,negate_type
)(pw
);
1947 for (i
= 0; i
< pw
->n
; ++i
) {
1948 pw
->p
[i
].FIELD
= FN(EL
,scale_down_val
)(pw
->p
[i
].FIELD
,
1950 if (!pw
->p
[i
].FIELD
)
1962 __isl_give PW
*FN(PW
,scale
)(__isl_take PW
*pw
, isl_int v
)
1964 return FN(PW
,mul_isl_int
)(pw
, v
);
1967 /* Apply some normalization to "pw".
1968 * In particular, sort the pieces according to their function value
1969 * expressions, combining pairs of adjacent pieces with
1970 * the same such expression, and then normalize the domains of the pieces.
1972 * We normalize in place, but if anything goes wrong we need
1973 * to return NULL, so we need to make sure we don't change the
1974 * meaning of any possible other copies of "pw".
1976 __isl_give PW
*FN(PW
,normalize
)(__isl_take PW
*pw
)
1981 pw
= FN(PW
,sort_unique
)(pw
);
1984 for (i
= 0; i
< pw
->n
; ++i
) {
1985 set
= isl_set_normalize(isl_set_copy(pw
->p
[i
].set
));
1987 return FN(PW
,free
)(pw
);
1988 isl_set_free(pw
->p
[i
].set
);
1995 /* Is pw1 obviously equal to pw2?
1996 * That is, do they have obviously identical cells and obviously identical
1997 * elements on each cell?
1999 * If "pw1" or "pw2" contain any NaNs, then they are considered
2000 * not to be the same. A NaN is not equal to anything, not even
2003 isl_bool
FN(PW
,plain_is_equal
)(__isl_keep PW
*pw1
, __isl_keep PW
*pw2
)
2006 isl_bool equal
, has_nan
;
2009 return isl_bool_error
;
2011 has_nan
= FN(PW
,involves_nan
)(pw1
);
2012 if (has_nan
>= 0 && !has_nan
)
2013 has_nan
= FN(PW
,involves_nan
)(pw2
);
2014 if (has_nan
< 0 || has_nan
)
2015 return isl_bool_not(has_nan
);
2018 return isl_bool_true
;
2019 equal
= FN(PW
,has_equal_space
)(pw1
, pw2
);
2020 if (equal
< 0 || !equal
)
2023 pw1
= FN(PW
,copy
)(pw1
);
2024 pw2
= FN(PW
,copy
)(pw2
);
2025 pw1
= FN(PW
,normalize
)(pw1
);
2026 pw2
= FN(PW
,normalize
)(pw2
);
2030 equal
= isl_bool_ok(pw1
->n
== pw2
->n
);
2031 for (i
= 0; equal
&& i
< pw1
->n
; ++i
) {
2032 equal
= isl_set_plain_is_equal(pw1
->p
[i
].set
, pw2
->p
[i
].set
);
2037 equal
= FN(EL
,plain_is_equal
)(pw1
->p
[i
].FIELD
, pw2
->p
[i
].FIELD
);
2048 return isl_bool_error
;
2051 /* Does "pw" involve any NaNs?
2053 isl_bool
FN(PW
,involves_nan
)(__isl_keep PW
*pw
)
2058 return isl_bool_error
;
2060 return isl_bool_false
;
2062 for (i
= 0; i
< pw
->n
; ++i
) {
2063 isl_bool has_nan
= FN(EL
,involves_nan
)(pw
->p
[i
].FIELD
);
2064 if (has_nan
< 0 || has_nan
)
2068 return isl_bool_false
;