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
16 #include <isl_val_private.h>
18 #include <isl_pw_macro.h>
21 __isl_give PW
*FN(PW
,alloc_size
)(__isl_take isl_space
*dim
,
22 enum isl_fold type
, int n
)
24 __isl_give PW
*FN(PW
,alloc_size
)(__isl_take isl_space
*dim
, int n
)
32 ctx
= isl_space_get_ctx(dim
);
33 isl_assert(ctx
, n
>= 0, goto error
);
34 pw
= isl_alloc(ctx
, struct PW
,
35 sizeof(struct PW
) + (n
- 1) * sizeof(S(PW
,piece
)));
53 __isl_give PW
*FN(PW
,ZERO
)(__isl_take isl_space
*dim
, enum isl_fold type
)
55 return FN(PW
,alloc_size
)(dim
, type
, 0);
58 __isl_give PW
*FN(PW
,ZERO
)(__isl_take isl_space
*dim
)
60 return FN(PW
,alloc_size
)(dim
, 0);
64 __isl_give PW
*FN(PW
,add_piece
)(__isl_take PW
*pw
,
65 __isl_take isl_set
*set
, __isl_take EL
*el
)
68 isl_space
*el_dim
= NULL
;
70 if (!pw
|| !set
|| !el
)
73 if (isl_set_plain_is_empty(set
) || FN(EL
,EL_IS_ZERO
)(el
)) {
79 ctx
= isl_set_get_ctx(set
);
81 if (pw
->type
!= el
->type
)
82 isl_die(ctx
, isl_error_invalid
, "fold types don't match",
85 el_dim
= FN(EL
,get_space(el
));
86 isl_assert(ctx
, isl_space_is_equal(pw
->dim
, el_dim
), goto error
);
87 isl_assert(ctx
, pw
->n
< pw
->size
, goto error
);
89 pw
->p
[pw
->n
].set
= set
;
90 pw
->p
[pw
->n
].FIELD
= el
;
93 isl_space_free(el_dim
);
96 isl_space_free(el_dim
);
104 __isl_give PW
*FN(PW
,alloc
)(enum isl_fold type
,
105 __isl_take isl_set
*set
, __isl_take EL
*el
)
107 __isl_give PW
*FN(PW
,alloc
)(__isl_take isl_set
*set
, __isl_take EL
*el
)
116 pw
= FN(PW
,alloc_size
)(FN(EL
,get_space
)(el
), type
, 1);
118 pw
= FN(PW
,alloc_size
)(FN(EL
,get_space
)(el
), 1);
121 return FN(PW
,add_piece
)(pw
, set
, el
);
128 __isl_give PW
*FN(PW
,dup
)(__isl_keep PW
*pw
)
137 dup
= FN(PW
,alloc_size
)(isl_space_copy(pw
->dim
), pw
->type
, pw
->n
);
139 dup
= FN(PW
,alloc_size
)(isl_space_copy(pw
->dim
), pw
->n
);
144 for (i
= 0; i
< pw
->n
; ++i
)
145 dup
= FN(PW
,add_piece
)(dup
, isl_set_copy(pw
->p
[i
].set
),
146 FN(EL
,copy
)(pw
->p
[i
].FIELD
));
151 __isl_give PW
*FN(PW
,cow
)(__isl_take PW
*pw
)
159 return FN(PW
,dup
)(pw
);
162 __isl_give PW
*FN(PW
,copy
)(__isl_keep PW
*pw
)
171 __isl_null PW
*FN(PW
,free
)(__isl_take PW
*pw
)
180 for (i
= 0; i
< pw
->n
; ++i
) {
181 isl_set_free(pw
->p
[i
].set
);
182 FN(EL
,free
)(pw
->p
[i
].FIELD
);
184 isl_space_free(pw
->dim
);
190 const char *FN(PW
,get_dim_name
)(__isl_keep PW
*pw
, enum isl_dim_type type
,
193 return pw
? isl_space_get_dim_name(pw
->dim
, type
, pos
) : NULL
;
196 isl_bool
FN(PW
,has_dim_id
)(__isl_keep PW
*pw
, enum isl_dim_type type
,
199 return pw
? isl_space_has_dim_id(pw
->dim
, type
, pos
) : isl_bool_error
;
202 __isl_give isl_id
*FN(PW
,get_dim_id
)(__isl_keep PW
*pw
, enum isl_dim_type type
,
205 return pw
? isl_space_get_dim_id(pw
->dim
, type
, pos
) : NULL
;
208 isl_bool
FN(PW
,has_tuple_name
)(__isl_keep PW
*pw
, enum isl_dim_type type
)
210 return pw
? isl_space_has_tuple_name(pw
->dim
, type
) : isl_bool_error
;
213 const char *FN(PW
,get_tuple_name
)(__isl_keep PW
*pw
, enum isl_dim_type type
)
215 return pw
? isl_space_get_tuple_name(pw
->dim
, type
) : NULL
;
218 isl_bool
FN(PW
,has_tuple_id
)(__isl_keep PW
*pw
, enum isl_dim_type type
)
220 return pw
? isl_space_has_tuple_id(pw
->dim
, type
) : isl_bool_error
;
223 __isl_give isl_id
*FN(PW
,get_tuple_id
)(__isl_keep PW
*pw
, enum isl_dim_type type
)
225 return pw
? isl_space_get_tuple_id(pw
->dim
, type
) : NULL
;
228 isl_bool
FN(PW
,IS_ZERO
)(__isl_keep PW
*pw
)
231 return isl_bool_error
;
237 __isl_give PW
*FN(PW
,realign_domain
)(__isl_take PW
*pw
,
238 __isl_take isl_reordering
*exp
)
246 for (i
= 0; i
< pw
->n
; ++i
) {
247 pw
->p
[i
].set
= isl_set_realign(pw
->p
[i
].set
,
248 isl_reordering_copy(exp
));
251 pw
->p
[i
].FIELD
= FN(EL
,realign_domain
)(pw
->p
[i
].FIELD
,
252 isl_reordering_copy(exp
));
257 pw
= FN(PW
,reset_domain_space
)(pw
, isl_space_copy(exp
->dim
));
259 isl_reordering_free(exp
);
262 isl_reordering_free(exp
);
267 /* Align the parameters of "pw" to those of "model".
269 __isl_give PW
*FN(PW
,align_params
)(__isl_take PW
*pw
, __isl_take isl_space
*model
)
272 isl_bool equal_params
;
277 ctx
= isl_space_get_ctx(model
);
278 if (!isl_space_has_named_params(model
))
279 isl_die(ctx
, isl_error_invalid
,
280 "model has unnamed parameters", goto error
);
281 if (!isl_space_has_named_params(pw
->dim
))
282 isl_die(ctx
, isl_error_invalid
,
283 "input has unnamed parameters", goto error
);
284 equal_params
= isl_space_has_equal_params(pw
->dim
, model
);
285 if (equal_params
< 0)
290 model
= isl_space_drop_dims(model
, isl_dim_in
,
291 0, isl_space_dim(model
, isl_dim_in
));
292 model
= isl_space_drop_dims(model
, isl_dim_out
,
293 0, isl_space_dim(model
, isl_dim_out
));
294 exp
= isl_parameter_alignment_reordering(pw
->dim
, model
);
295 exp
= isl_reordering_extend_space(exp
,
296 FN(PW
,get_domain_space
)(pw
));
297 pw
= FN(PW
,realign_domain
)(pw
, exp
);
300 isl_space_free(model
);
303 isl_space_free(model
);
308 static __isl_give PW
*FN(PW
,align_params_pw_pw_and
)(__isl_take PW
*pw1
,
310 __isl_give PW
*(*fn
)(__isl_take PW
*pw1
, __isl_take PW
*pw2
))
313 isl_bool equal_params
;
317 equal_params
= isl_space_has_equal_params(pw1
->dim
, pw2
->dim
);
318 if (equal_params
< 0)
322 ctx
= FN(PW
,get_ctx
)(pw1
);
323 if (!isl_space_has_named_params(pw1
->dim
) ||
324 !isl_space_has_named_params(pw2
->dim
))
325 isl_die(ctx
, isl_error_invalid
,
326 "unaligned unnamed parameters", goto error
);
327 pw1
= FN(PW
,align_params
)(pw1
, FN(PW
,get_space
)(pw2
));
328 pw2
= FN(PW
,align_params
)(pw2
, FN(PW
,get_space
)(pw1
));
336 static __isl_give PW
*FN(PW
,align_params_pw_set_and
)(__isl_take PW
*pw
,
337 __isl_take isl_set
*set
,
338 __isl_give PW
*(*fn
)(__isl_take PW
*pw
, __isl_take isl_set
*set
))
345 aligned
= isl_set_space_has_equal_params(set
, pw
->dim
);
350 ctx
= FN(PW
,get_ctx
)(pw
);
351 if (!isl_space_has_named_params(pw
->dim
) ||
352 !isl_space_has_named_params(set
->dim
))
353 isl_die(ctx
, isl_error_invalid
,
354 "unaligned unnamed parameters", goto error
);
355 pw
= FN(PW
,align_params
)(pw
, isl_set_get_space(set
));
356 set
= isl_set_align_params(set
, FN(PW
,get_space
)(pw
));
365 static __isl_give PW
*FN(PW
,union_add_aligned
)(__isl_take PW
*pw1
,
376 ctx
= isl_space_get_ctx(pw1
->dim
);
378 if (pw1
->type
!= pw2
->type
)
379 isl_die(ctx
, isl_error_invalid
,
380 "fold types don't match", goto error
);
382 isl_assert(ctx
, isl_space_is_equal(pw1
->dim
, pw2
->dim
), goto error
);
384 if (FN(PW
,IS_ZERO
)(pw1
)) {
389 if (FN(PW
,IS_ZERO
)(pw2
)) {
394 n
= (pw1
->n
+ 1) * (pw2
->n
+ 1);
396 res
= FN(PW
,alloc_size
)(isl_space_copy(pw1
->dim
), pw1
->type
, n
);
398 res
= FN(PW
,alloc_size
)(isl_space_copy(pw1
->dim
), n
);
401 for (i
= 0; i
< pw1
->n
; ++i
) {
402 set
= isl_set_copy(pw1
->p
[i
].set
);
403 for (j
= 0; j
< pw2
->n
; ++j
) {
404 struct isl_set
*common
;
406 common
= isl_set_intersect(isl_set_copy(pw1
->p
[i
].set
),
407 isl_set_copy(pw2
->p
[j
].set
));
408 if (isl_set_plain_is_empty(common
)) {
409 isl_set_free(common
);
412 set
= isl_set_subtract(set
,
413 isl_set_copy(pw2
->p
[j
].set
));
415 sum
= FN(EL
,add_on_domain
)(common
,
416 FN(EL
,copy
)(pw1
->p
[i
].FIELD
),
417 FN(EL
,copy
)(pw2
->p
[j
].FIELD
));
419 res
= FN(PW
,add_piece
)(res
, common
, sum
);
421 res
= FN(PW
,add_piece
)(res
, set
, FN(EL
,copy
)(pw1
->p
[i
].FIELD
));
424 for (j
= 0; j
< pw2
->n
; ++j
) {
425 set
= isl_set_copy(pw2
->p
[j
].set
);
426 for (i
= 0; i
< pw1
->n
; ++i
)
427 set
= isl_set_subtract(set
,
428 isl_set_copy(pw1
->p
[i
].set
));
429 res
= FN(PW
,add_piece
)(res
, set
, FN(EL
,copy
)(pw2
->p
[j
].FIELD
));
442 /* Private version of "union_add". For isl_pw_qpolynomial and
443 * isl_pw_qpolynomial_fold, we prefer to simply call it "add".
445 static __isl_give PW
*FN(PW
,union_add_
)(__isl_take PW
*pw1
, __isl_take PW
*pw2
)
447 return FN(PW
,align_params_pw_pw_and
)(pw1
, pw2
,
448 &FN(PW
,union_add_aligned
));
451 /* Make sure "pw" has room for at least "n" more pieces.
453 * If there is only one reference to pw, we extend it in place.
454 * Otherwise, we create a new PW and copy the pieces.
456 static __isl_give PW
*FN(PW
,grow
)(__isl_take PW
*pw
, int n
)
464 if (pw
->n
+ n
<= pw
->size
)
466 ctx
= FN(PW
,get_ctx
)(pw
);
469 res
= isl_realloc(ctx
, pw
, struct PW
,
470 sizeof(struct PW
) + (n
- 1) * sizeof(S(PW
,piece
)));
472 return FN(PW
,free
)(pw
);
477 res
= FN(PW
,alloc_size
)(isl_space_copy(pw
->dim
), pw
->type
, n
);
479 res
= FN(PW
,alloc_size
)(isl_space_copy(pw
->dim
), n
);
482 return FN(PW
,free
)(pw
);
483 for (i
= 0; i
< pw
->n
; ++i
)
484 res
= FN(PW
,add_piece
)(res
, isl_set_copy(pw
->p
[i
].set
),
485 FN(EL
,copy
)(pw
->p
[i
].FIELD
));
490 static __isl_give PW
*FN(PW
,add_disjoint_aligned
)(__isl_take PW
*pw1
,
499 if (pw1
->size
< pw1
->n
+ pw2
->n
&& pw1
->n
< pw2
->n
)
500 return FN(PW
,add_disjoint_aligned
)(pw2
, pw1
);
502 ctx
= isl_space_get_ctx(pw1
->dim
);
504 if (pw1
->type
!= pw2
->type
)
505 isl_die(ctx
, isl_error_invalid
,
506 "fold types don't match", goto error
);
508 isl_assert(ctx
, isl_space_is_equal(pw1
->dim
, pw2
->dim
), goto error
);
510 if (FN(PW
,IS_ZERO
)(pw1
)) {
515 if (FN(PW
,IS_ZERO
)(pw2
)) {
520 pw1
= FN(PW
,grow
)(pw1
, pw2
->n
);
524 for (i
= 0; i
< pw2
->n
; ++i
)
525 pw1
= FN(PW
,add_piece
)(pw1
,
526 isl_set_copy(pw2
->p
[i
].set
),
527 FN(EL
,copy
)(pw2
->p
[i
].FIELD
));
538 __isl_give PW
*FN(PW
,add_disjoint
)(__isl_take PW
*pw1
, __isl_take PW
*pw2
)
540 return FN(PW
,align_params_pw_pw_and
)(pw1
, pw2
,
541 &FN(PW
,add_disjoint_aligned
));
544 /* This function is currently only used from isl_aff.c
546 static __isl_give PW
*FN(PW
,on_shared_domain_in
)(__isl_take PW
*pw1
,
547 __isl_take PW
*pw2
, __isl_take isl_space
*space
,
548 __isl_give EL
*(*fn
)(__isl_take EL
*el1
, __isl_take EL
*el2
))
549 __attribute__ ((unused
));
551 /* Apply "fn" to pairs of elements from pw1 and pw2 on shared domains.
552 * The result of "fn" (and therefore also of this function) lives in "space".
554 static __isl_give PW
*FN(PW
,on_shared_domain_in
)(__isl_take PW
*pw1
,
555 __isl_take PW
*pw2
, __isl_take isl_space
*space
,
556 __isl_give EL
*(*fn
)(__isl_take EL
*el1
, __isl_take EL
*el2
))
566 res
= FN(PW
,alloc_size
)(isl_space_copy(space
), pw1
->type
, n
);
568 res
= FN(PW
,alloc_size
)(isl_space_copy(space
), n
);
571 for (i
= 0; i
< pw1
->n
; ++i
) {
572 for (j
= 0; j
< pw2
->n
; ++j
) {
577 common
= isl_set_intersect(
578 isl_set_copy(pw1
->p
[i
].set
),
579 isl_set_copy(pw2
->p
[j
].set
));
580 empty
= isl_set_plain_is_empty(common
);
581 if (empty
< 0 || empty
) {
582 isl_set_free(common
);
588 res_ij
= fn(FN(EL
,copy
)(pw1
->p
[i
].FIELD
),
589 FN(EL
,copy
)(pw2
->p
[j
].FIELD
));
590 res_ij
= FN(EL
,gist
)(res_ij
, isl_set_copy(common
));
592 res
= FN(PW
,add_piece
)(res
, common
, res_ij
);
596 isl_space_free(space
);
601 isl_space_free(space
);
608 /* This function is currently only used from isl_aff.c
610 static __isl_give PW
*FN(PW
,on_shared_domain
)(__isl_take PW
*pw1
,
612 __isl_give EL
*(*fn
)(__isl_take EL
*el1
, __isl_take EL
*el2
))
613 __attribute__ ((unused
));
615 /* Apply "fn" to pairs of elements from pw1 and pw2 on shared domains.
616 * The result of "fn" is assumed to live in the same space as "pw1" and "pw2".
618 static __isl_give PW
*FN(PW
,on_shared_domain
)(__isl_take PW
*pw1
,
620 __isl_give EL
*(*fn
)(__isl_take EL
*el1
, __isl_take EL
*el2
))
627 space
= isl_space_copy(pw1
->dim
);
628 return FN(PW
,on_shared_domain_in
)(pw1
, pw2
, space
, fn
);
636 __isl_give PW
*FN(PW
,neg
)(__isl_take PW
*pw
)
643 if (FN(PW
,IS_ZERO
)(pw
))
650 for (i
= 0; i
< pw
->n
; ++i
) {
651 pw
->p
[i
].FIELD
= FN(EL
,neg
)(pw
->p
[i
].FIELD
);
653 return FN(PW
,free
)(pw
);
661 __isl_give PW
*FN(PW
,sub
)(__isl_take PW
*pw1
, __isl_take PW
*pw2
)
663 return FN(PW
,add
)(pw1
, FN(PW
,neg
)(pw2
));
668 __isl_give isl_val
*FN(PW
,eval
)(__isl_take PW
*pw
, __isl_take isl_point
*pnt
)
673 isl_space
*pnt_dim
= NULL
;
678 ctx
= isl_point_get_ctx(pnt
);
679 pnt_dim
= isl_point_get_space(pnt
);
680 isl_assert(ctx
, isl_space_is_domain_internal(pnt_dim
, pw
->dim
),
683 for (i
= 0; i
< pw
->n
; ++i
) {
684 found
= isl_set_contains_point(pw
->p
[i
].set
, pnt
);
691 v
= FN(EL
,eval
)(FN(EL
,copy
)(pw
->p
[i
].FIELD
),
692 isl_point_copy(pnt
));
694 v
= isl_val_zero(ctx
);
696 isl_space_free(pnt_dim
);
701 isl_space_free(pnt_dim
);
707 /* Return the parameter domain of "pw".
709 __isl_give isl_set
*FN(PW
,params
)(__isl_take PW
*pw
)
711 return isl_set_params(FN(PW
,domain
)(pw
));
714 __isl_give isl_set
*FN(PW
,domain
)(__isl_take PW
*pw
)
722 dom
= isl_set_empty(FN(PW
,get_domain_space
)(pw
));
723 for (i
= 0; i
< pw
->n
; ++i
)
724 dom
= isl_set_union_disjoint(dom
, isl_set_copy(pw
->p
[i
].set
));
731 /* Exploit the equalities in the domain of piece "i" of "pw"
732 * to simplify the associated function.
733 * If the domain of piece "i" is empty, then remove it entirely,
734 * replacing it with the final piece.
736 static int FN(PW
,exploit_equalities_and_remove_if_empty
)(__isl_keep PW
*pw
,
740 int empty
= isl_set_plain_is_empty(pw
->p
[i
].set
);
745 isl_set_free(pw
->p
[i
].set
);
746 FN(EL
,free
)(pw
->p
[i
].FIELD
);
748 pw
->p
[i
] = pw
->p
[pw
->n
- 1];
754 aff
= isl_set_affine_hull(isl_set_copy(pw
->p
[i
].set
));
755 pw
->p
[i
].FIELD
= FN(EL
,substitute_equalities
)(pw
->p
[i
].FIELD
, aff
);
762 /* Convert a piecewise expression defined over a parameter domain
763 * into one that is defined over a zero-dimensional set.
765 __isl_give PW
*FN(PW
,from_range
)(__isl_take PW
*pw
)
771 if (!isl_space_is_set(pw
->dim
))
772 isl_die(FN(PW
,get_ctx
)(pw
), isl_error_invalid
,
773 "not living in a set space", return FN(PW
,free
)(pw
));
775 space
= FN(PW
,get_space
)(pw
);
776 space
= isl_space_from_range(space
);
777 pw
= FN(PW
,reset_space
)(pw
, space
);
782 /* Fix the value of the given parameter or domain dimension of "pw"
783 * to be equal to "value".
785 __isl_give PW
*FN(PW
,fix_si
)(__isl_take PW
*pw
, enum isl_dim_type type
,
786 unsigned pos
, int value
)
793 if (type
== isl_dim_out
)
794 isl_die(FN(PW
,get_ctx
)(pw
), isl_error_invalid
,
795 "cannot fix output dimension", return FN(PW
,free
)(pw
));
800 if (type
== isl_dim_in
)
805 return FN(PW
,free
)(pw
);
807 for (i
= pw
->n
- 1; i
>= 0; --i
) {
808 pw
->p
[i
].set
= isl_set_fix_si(pw
->p
[i
].set
, type
, pos
, value
);
809 if (FN(PW
,exploit_equalities_and_remove_if_empty
)(pw
, i
) < 0)
810 return FN(PW
,free
)(pw
);
816 /* Restrict the domain of "pw" by combining each cell
817 * with "set" through a call to "fn", where "fn" may be
818 * isl_set_intersect, isl_set_intersect_params or isl_set_subtract.
820 static __isl_give PW
*FN(PW
,restrict_domain_aligned
)(__isl_take PW
*pw
,
821 __isl_take isl_set
*set
,
822 __isl_give isl_set
*(*fn
)(__isl_take isl_set
*set1
,
823 __isl_take isl_set
*set2
))
839 for (i
= pw
->n
- 1; i
>= 0; --i
) {
840 pw
->p
[i
].set
= fn(pw
->p
[i
].set
, isl_set_copy(set
));
841 if (FN(PW
,exploit_equalities_and_remove_if_empty
)(pw
, i
) < 0)
853 static __isl_give PW
*FN(PW
,intersect_domain_aligned
)(__isl_take PW
*pw
,
854 __isl_take isl_set
*set
)
856 return FN(PW
,restrict_domain_aligned
)(pw
, set
, &isl_set_intersect
);
859 __isl_give PW
*FN(PW
,intersect_domain
)(__isl_take PW
*pw
,
860 __isl_take isl_set
*context
)
862 return FN(PW
,align_params_pw_set_and
)(pw
, context
,
863 &FN(PW
,intersect_domain_aligned
));
866 static __isl_give PW
*FN(PW
,intersect_params_aligned
)(__isl_take PW
*pw
,
867 __isl_take isl_set
*set
)
869 return FN(PW
,restrict_domain_aligned
)(pw
, set
,
870 &isl_set_intersect_params
);
873 /* Intersect the domain of "pw" with the parameter domain "context".
875 __isl_give PW
*FN(PW
,intersect_params
)(__isl_take PW
*pw
,
876 __isl_take isl_set
*context
)
878 return FN(PW
,align_params_pw_set_and
)(pw
, context
,
879 &FN(PW
,intersect_params_aligned
));
882 /* Subtract "domain' from the domain of "pw", assuming their
883 * parameters have been aligned.
885 static __isl_give PW
*FN(PW
,subtract_domain_aligned
)(__isl_take PW
*pw
,
886 __isl_take isl_set
*domain
)
888 return FN(PW
,restrict_domain_aligned
)(pw
, domain
, &isl_set_subtract
);
891 /* Subtract "domain' from the domain of "pw".
893 __isl_give PW
*FN(PW
,subtract_domain
)(__isl_take PW
*pw
,
894 __isl_take isl_set
*domain
)
896 return FN(PW
,align_params_pw_set_and
)(pw
, domain
,
897 &FN(PW
,subtract_domain_aligned
));
900 /* Compute the gist of "pw" with respect to the domain constraints
901 * of "context" for the case where the domain of the last element
902 * of "pw" is equal to "context".
903 * Call "fn_el" to compute the gist of this element, replace
904 * its domain by the universe and drop all other elements
905 * as their domains are necessarily disjoint from "context".
907 static __isl_give PW
*FN(PW
,gist_last
)(__isl_take PW
*pw
,
908 __isl_take isl_set
*context
,
909 __isl_give EL
*(*fn_el
)(__isl_take EL
*el
, __isl_take isl_set
*set
))
914 for (i
= 0; i
< pw
->n
- 1; ++i
) {
915 isl_set_free(pw
->p
[i
].set
);
916 FN(EL
,free
)(pw
->p
[i
].FIELD
);
918 pw
->p
[0].FIELD
= pw
->p
[pw
->n
- 1].FIELD
;
919 pw
->p
[0].set
= pw
->p
[pw
->n
- 1].set
;
922 space
= isl_set_get_space(context
);
923 pw
->p
[0].FIELD
= fn_el(pw
->p
[0].FIELD
, context
);
924 context
= isl_set_universe(space
);
925 isl_set_free(pw
->p
[0].set
);
926 pw
->p
[0].set
= context
;
928 if (!pw
->p
[0].FIELD
|| !pw
->p
[0].set
)
929 return FN(PW
,free
)(pw
);
934 /* Compute the gist of "pw" with respect to the domain constraints
935 * of "context". Call "fn_el" to compute the gist of the elements
936 * and "fn_dom" to compute the gist of the domains.
938 * If the piecewise expression is empty or the context is the universe,
939 * then nothing can be simplified.
941 static __isl_give PW
*FN(PW
,gist_aligned
)(__isl_take PW
*pw
,
942 __isl_take isl_set
*context
,
943 __isl_give EL
*(*fn_el
)(__isl_take EL
*el
,
944 __isl_take isl_set
*set
),
945 __isl_give isl_set
*(*fn_dom
)(__isl_take isl_set
*set
,
946 __isl_take isl_basic_set
*bset
))
951 isl_basic_set
*hull
= NULL
;
957 isl_set_free(context
);
961 is_universe
= isl_set_plain_is_universe(context
);
965 isl_set_free(context
);
969 aligned
= isl_set_space_has_equal_params(context
, pw
->dim
);
973 pw
= FN(PW
,align_params
)(pw
, isl_set_get_space(context
));
974 context
= isl_set_align_params(context
, FN(PW
,get_space
)(pw
));
984 equal
= isl_set_plain_is_equal(pw
->p
[0].set
, context
);
988 return FN(PW
,gist_last
)(pw
, context
, fn_el
);
991 context
= isl_set_compute_divs(context
);
992 hull
= isl_set_simple_hull(isl_set_copy(context
));
994 for (i
= pw
->n
- 1; i
>= 0; --i
) {
998 if (i
== pw
->n
- 1) {
1000 equal
= isl_set_plain_is_equal(pw
->p
[i
].set
, context
);
1004 isl_basic_set_free(hull
);
1005 return FN(PW
,gist_last
)(pw
, context
, fn_el
);
1008 set_i
= isl_set_intersect(isl_set_copy(pw
->p
[i
].set
),
1009 isl_set_copy(context
));
1010 empty
= isl_set_plain_is_empty(set_i
);
1011 pw
->p
[i
].FIELD
= fn_el(pw
->p
[i
].FIELD
, set_i
);
1012 pw
->p
[i
].set
= fn_dom(pw
->p
[i
].set
, isl_basic_set_copy(hull
));
1013 if (empty
< 0 || !pw
->p
[i
].FIELD
|| !pw
->p
[i
].set
)
1016 isl_set_free(pw
->p
[i
].set
);
1017 FN(EL
,free
)(pw
->p
[i
].FIELD
);
1019 pw
->p
[i
] = pw
->p
[pw
->n
- 1];
1024 isl_basic_set_free(hull
);
1025 isl_set_free(context
);
1030 isl_basic_set_free(hull
);
1031 isl_set_free(context
);
1035 static __isl_give PW
*FN(PW
,gist_domain_aligned
)(__isl_take PW
*pw
,
1036 __isl_take isl_set
*set
)
1038 return FN(PW
,gist_aligned
)(pw
, set
, &FN(EL
,gist
),
1039 &isl_set_gist_basic_set
);
1042 __isl_give PW
*FN(PW
,gist
)(__isl_take PW
*pw
, __isl_take isl_set
*context
)
1044 return FN(PW
,align_params_pw_set_and
)(pw
, context
,
1045 &FN(PW
,gist_domain_aligned
));
1048 static __isl_give PW
*FN(PW
,gist_params_aligned
)(__isl_take PW
*pw
,
1049 __isl_take isl_set
*set
)
1051 return FN(PW
,gist_aligned
)(pw
, set
, &FN(EL
,gist_params
),
1052 &isl_set_gist_params_basic_set
);
1055 __isl_give PW
*FN(PW
,gist_params
)(__isl_take PW
*pw
,
1056 __isl_take isl_set
*context
)
1058 return FN(PW
,align_params_pw_set_and
)(pw
, context
,
1059 &FN(PW
,gist_params_aligned
));
1062 /* Return -1 if the piece "p1" should be sorted before "p2"
1063 * and 1 if it should be sorted after "p2".
1064 * Return 0 if they do not need to be sorted in a specific order.
1066 * The two pieces are compared on the basis of their function value expressions.
1068 static int FN(PW
,sort_field_cmp
)(const void *p1
, const void *p2
, void *arg
)
1070 struct FN(PW
,piece
) const *pc1
= p1
;
1071 struct FN(PW
,piece
) const *pc2
= p2
;
1073 return FN(EL
,plain_cmp
)(pc1
->FIELD
, pc2
->FIELD
);
1076 /* Sort the pieces of "pw" according to their function value
1077 * expressions and then combine pairs of adjacent pieces with
1078 * the same such expression.
1080 * The sorting is performed in place because it does not
1081 * change the meaning of "pw", but care needs to be
1082 * taken not to change any possible other copies of "pw"
1083 * in case anything goes wrong.
1085 __isl_give PW
*FN(PW
,sort
)(__isl_take PW
*pw
)
1094 if (isl_sort(pw
->p
, pw
->n
, sizeof(pw
->p
[0]),
1095 &FN(PW
,sort_field_cmp
), NULL
) < 0)
1096 return FN(PW
,free
)(pw
);
1097 for (i
= pw
->n
- 1; i
>= 1; --i
) {
1098 if (!FN(EL
,plain_is_equal
)(pw
->p
[i
- 1].FIELD
, pw
->p
[i
].FIELD
))
1100 set
= isl_set_union(isl_set_copy(pw
->p
[i
- 1].set
),
1101 isl_set_copy(pw
->p
[i
].set
));
1103 return FN(PW
,free
)(pw
);
1104 isl_set_free(pw
->p
[i
].set
);
1105 FN(EL
,free
)(pw
->p
[i
].FIELD
);
1106 isl_set_free(pw
->p
[i
- 1].set
);
1107 pw
->p
[i
- 1].set
= set
;
1108 for (j
= i
+ 1; j
< pw
->n
; ++j
)
1109 pw
->p
[j
- 1] = pw
->p
[j
];
1116 /* Coalesce the domains of "pw".
1118 * Prior to the actual coalescing, first sort the pieces such that
1119 * pieces with the same function value expression are combined
1120 * into a single piece, the combined domain of which can then
1123 __isl_give PW
*FN(PW
,coalesce
)(__isl_take PW
*pw
)
1127 pw
= FN(PW
,sort
)(pw
);
1131 for (i
= 0; i
< pw
->n
; ++i
) {
1132 pw
->p
[i
].set
= isl_set_coalesce(pw
->p
[i
].set
);
1143 isl_ctx
*FN(PW
,get_ctx
)(__isl_keep PW
*pw
)
1145 return pw
? isl_space_get_ctx(pw
->dim
) : NULL
;
1148 #ifndef NO_INVOLVES_DIMS
1149 isl_bool
FN(PW
,involves_dims
)(__isl_keep PW
*pw
, enum isl_dim_type type
,
1150 unsigned first
, unsigned n
)
1153 enum isl_dim_type set_type
;
1156 return isl_bool_error
;
1157 if (pw
->n
== 0 || n
== 0)
1158 return isl_bool_false
;
1160 set_type
= type
== isl_dim_in
? isl_dim_set
: type
;
1162 for (i
= 0; i
< pw
->n
; ++i
) {
1163 isl_bool involves
= FN(EL
,involves_dims
)(pw
->p
[i
].FIELD
,
1165 if (involves
< 0 || involves
)
1167 involves
= isl_set_involves_dims(pw
->p
[i
].set
,
1168 set_type
, first
, n
);
1169 if (involves
< 0 || involves
)
1172 return isl_bool_false
;
1176 __isl_give PW
*FN(PW
,set_dim_name
)(__isl_take PW
*pw
,
1177 enum isl_dim_type type
, unsigned pos
, const char *s
)
1180 enum isl_dim_type set_type
;
1182 pw
= FN(PW
,cow
)(pw
);
1186 set_type
= type
== isl_dim_in
? isl_dim_set
: type
;
1188 pw
->dim
= isl_space_set_dim_name(pw
->dim
, type
, pos
, s
);
1192 for (i
= 0; i
< pw
->n
; ++i
) {
1193 pw
->p
[i
].set
= isl_set_set_dim_name(pw
->p
[i
].set
,
1197 pw
->p
[i
].FIELD
= FN(EL
,set_dim_name
)(pw
->p
[i
].FIELD
, type
, pos
, s
);
1198 if (!pw
->p
[i
].FIELD
)
1208 #ifndef NO_DROP_DIMS
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
);
1301 #ifndef NO_INSERT_DIMS
1302 __isl_give PW
*FN(PW
,insert_dims
)(__isl_take PW
*pw
, enum isl_dim_type type
,
1303 unsigned first
, unsigned n
)
1306 enum isl_dim_type set_type
;
1310 if (n
== 0 && !isl_space_is_named_or_nested(pw
->dim
, type
))
1313 set_type
= type
== isl_dim_in
? isl_dim_set
: type
;
1315 pw
= FN(PW
,cow
)(pw
);
1319 pw
->dim
= isl_space_insert_dims(pw
->dim
, type
, first
, n
);
1323 for (i
= 0; i
< pw
->n
; ++i
) {
1324 pw
->p
[i
].set
= isl_set_insert_dims(pw
->p
[i
].set
,
1325 set_type
, first
, n
);
1328 pw
->p
[i
].FIELD
= FN(EL
,insert_dims
)(pw
->p
[i
].FIELD
,
1330 if (!pw
->p
[i
].FIELD
)
1341 __isl_give PW
*FN(PW
,fix_dim
)(__isl_take PW
*pw
,
1342 enum isl_dim_type type
, unsigned pos
, isl_int v
)
1349 if (type
== isl_dim_in
)
1352 pw
= FN(PW
,cow
)(pw
);
1355 for (i
= 0; i
< pw
->n
; ++i
) {
1356 pw
->p
[i
].set
= isl_set_fix(pw
->p
[i
].set
, type
, pos
, v
);
1357 if (FN(PW
,exploit_equalities_and_remove_if_empty
)(pw
, i
) < 0)
1358 return FN(PW
,free
)(pw
);
1364 /* Fix the value of the variable at position "pos" of type "type" of "pw"
1365 * to be equal to "v".
1367 __isl_give PW
*FN(PW
,fix_val
)(__isl_take PW
*pw
,
1368 enum isl_dim_type type
, unsigned pos
, __isl_take isl_val
*v
)
1371 return FN(PW
,free
)(pw
);
1372 if (!isl_val_is_int(v
))
1373 isl_die(FN(PW
,get_ctx
)(pw
), isl_error_invalid
,
1374 "expecting integer value", goto error
);
1376 pw
= FN(PW
,fix_dim
)(pw
, type
, pos
, v
->n
);
1382 return FN(PW
,free
)(pw
);
1385 unsigned FN(PW
,dim
)(__isl_keep PW
*pw
, enum isl_dim_type type
)
1387 return pw
? isl_space_dim(pw
->dim
, type
) : 0;
1390 __isl_give PW
*FN(PW
,split_dims
)(__isl_take PW
*pw
,
1391 enum isl_dim_type type
, unsigned first
, unsigned n
)
1400 if (type
== isl_dim_in
)
1403 pw
= FN(PW
,cow
)(pw
);
1408 for (i
= 0; i
< pw
->n
; ++i
) {
1409 pw
->p
[i
].set
= isl_set_split_dims(pw
->p
[i
].set
, type
, first
, n
);
1421 /* Compute the maximal value attained by the piecewise quasipolynomial
1422 * on its domain or zero if the domain is empty.
1423 * In the worst case, the domain is scanned completely,
1424 * so the domain is assumed to be bounded.
1426 __isl_give isl_val
*FN(PW
,opt
)(__isl_take PW
*pw
, int max
)
1435 opt
= isl_val_zero(FN(PW
,get_ctx
)(pw
));
1440 opt
= FN(EL
,opt_on_domain
)(FN(EL
,copy
)(pw
->p
[0].FIELD
),
1441 isl_set_copy(pw
->p
[0].set
), max
);
1442 for (i
= 1; i
< pw
->n
; ++i
) {
1444 opt_i
= FN(EL
,opt_on_domain
)(FN(EL
,copy
)(pw
->p
[i
].FIELD
),
1445 isl_set_copy(pw
->p
[i
].set
), max
);
1447 opt
= isl_val_max(opt
, opt_i
);
1449 opt
= isl_val_min(opt
, opt_i
);
1456 __isl_give isl_val
*FN(PW
,max
)(__isl_take PW
*pw
)
1458 return FN(PW
,opt
)(pw
, 1);
1461 __isl_give isl_val
*FN(PW
,min
)(__isl_take PW
*pw
)
1463 return FN(PW
,opt
)(pw
, 0);
1467 __isl_give isl_space
*FN(PW
,get_space
)(__isl_keep PW
*pw
)
1469 return pw
? isl_space_copy(pw
->dim
) : NULL
;
1472 __isl_give isl_space
*FN(PW
,get_domain_space
)(__isl_keep PW
*pw
)
1474 return pw
? isl_space_domain(isl_space_copy(pw
->dim
)) : NULL
;
1477 /* Return the position of the dimension of the given type and name
1479 * Return -1 if no such dimension can be found.
1481 int FN(PW
,find_dim_by_name
)(__isl_keep PW
*pw
,
1482 enum isl_dim_type type
, const char *name
)
1486 return isl_space_find_dim_by_name(pw
->dim
, type
, name
);
1489 #ifndef NO_RESET_DIM
1490 /* Reset the space of "pw". Since we don't know if the elements
1491 * represent the spaces themselves or their domains, we pass along
1492 * both when we call their reset_space_and_domain.
1494 static __isl_give PW
*FN(PW
,reset_space_and_domain
)(__isl_take PW
*pw
,
1495 __isl_take isl_space
*space
, __isl_take isl_space
*domain
)
1499 pw
= FN(PW
,cow
)(pw
);
1500 if (!pw
|| !space
|| !domain
)
1503 for (i
= 0; i
< pw
->n
; ++i
) {
1504 pw
->p
[i
].set
= isl_set_reset_space(pw
->p
[i
].set
,
1505 isl_space_copy(domain
));
1508 pw
->p
[i
].FIELD
= FN(EL
,reset_space_and_domain
)(pw
->p
[i
].FIELD
,
1509 isl_space_copy(space
), isl_space_copy(domain
));
1510 if (!pw
->p
[i
].FIELD
)
1514 isl_space_free(domain
);
1516 isl_space_free(pw
->dim
);
1521 isl_space_free(domain
);
1522 isl_space_free(space
);
1527 __isl_give PW
*FN(PW
,reset_domain_space
)(__isl_take PW
*pw
,
1528 __isl_take isl_space
*domain
)
1532 space
= isl_space_extend_domain_with_range(isl_space_copy(domain
),
1533 FN(PW
,get_space
)(pw
));
1534 return FN(PW
,reset_space_and_domain
)(pw
, space
, domain
);
1537 __isl_give PW
*FN(PW
,reset_space
)(__isl_take PW
*pw
, __isl_take isl_space
*dim
)
1541 domain
= isl_space_domain(isl_space_copy(dim
));
1542 return FN(PW
,reset_space_and_domain
)(pw
, dim
, domain
);
1545 __isl_give PW
*FN(PW
,set_tuple_id
)(__isl_take PW
*pw
, enum isl_dim_type type
,
1546 __isl_take isl_id
*id
)
1550 pw
= FN(PW
,cow
)(pw
);
1554 space
= FN(PW
,get_space
)(pw
);
1555 space
= isl_space_set_tuple_id(space
, type
, id
);
1557 return FN(PW
,reset_space
)(pw
, space
);
1560 return FN(PW
,free
)(pw
);
1563 /* Drop the id on the specified tuple.
1565 __isl_give PW
*FN(PW
,reset_tuple_id
)(__isl_take PW
*pw
, enum isl_dim_type type
)
1571 if (!FN(PW
,has_tuple_id
)(pw
, type
))
1574 pw
= FN(PW
,cow
)(pw
);
1578 space
= FN(PW
,get_space
)(pw
);
1579 space
= isl_space_reset_tuple_id(space
, type
);
1581 return FN(PW
,reset_space
)(pw
, space
);
1584 __isl_give PW
*FN(PW
,set_dim_id
)(__isl_take PW
*pw
,
1585 enum isl_dim_type type
, unsigned pos
, __isl_take isl_id
*id
)
1587 pw
= FN(PW
,cow
)(pw
);
1590 pw
->dim
= isl_space_set_dim_id(pw
->dim
, type
, pos
, id
);
1591 return FN(PW
,reset_space
)(pw
, isl_space_copy(pw
->dim
));
1594 return FN(PW
,free
)(pw
);
1598 /* Reset the user pointer on all identifiers of parameters and tuples
1599 * of the space of "pw".
1601 __isl_give PW
*FN(PW
,reset_user
)(__isl_take PW
*pw
)
1605 space
= FN(PW
,get_space
)(pw
);
1606 space
= isl_space_reset_user(space
);
1608 return FN(PW
,reset_space
)(pw
, space
);
1611 isl_bool
FN(PW
,has_equal_space
)(__isl_keep PW
*pw1
, __isl_keep PW
*pw2
)
1614 return isl_bool_error
;
1616 return isl_space_is_equal(pw1
->dim
, pw2
->dim
);
1620 __isl_give PW
*FN(PW
,morph_domain
)(__isl_take PW
*pw
,
1621 __isl_take isl_morph
*morph
)
1629 ctx
= isl_space_get_ctx(pw
->dim
);
1630 isl_assert(ctx
, isl_space_is_domain_internal(morph
->dom
->dim
, pw
->dim
),
1633 pw
= FN(PW
,cow
)(pw
);
1636 pw
->dim
= isl_space_extend_domain_with_range(
1637 isl_space_copy(morph
->ran
->dim
), pw
->dim
);
1641 for (i
= 0; i
< pw
->n
; ++i
) {
1642 pw
->p
[i
].set
= isl_morph_set(isl_morph_copy(morph
), pw
->p
[i
].set
);
1645 pw
->p
[i
].FIELD
= FN(EL
,morph_domain
)(pw
->p
[i
].FIELD
,
1646 isl_morph_copy(morph
));
1647 if (!pw
->p
[i
].FIELD
)
1651 isl_morph_free(morph
);
1656 isl_morph_free(morph
);
1661 int FN(PW
,n_piece
)(__isl_keep PW
*pw
)
1663 return pw
? pw
->n
: 0;
1666 isl_stat
FN(PW
,foreach_piece
)(__isl_keep PW
*pw
,
1667 isl_stat (*fn
)(__isl_take isl_set
*set
, __isl_take EL
*el
, void *user
),
1673 return isl_stat_error
;
1675 for (i
= 0; i
< pw
->n
; ++i
)
1676 if (fn(isl_set_copy(pw
->p
[i
].set
),
1677 FN(EL
,copy
)(pw
->p
[i
].FIELD
), user
) < 0)
1678 return isl_stat_error
;
1684 static isl_bool
any_divs(__isl_keep isl_set
*set
)
1689 return isl_bool_error
;
1691 for (i
= 0; i
< set
->n
; ++i
)
1692 if (set
->p
[i
]->n_div
> 0)
1693 return isl_bool_true
;
1695 return isl_bool_false
;
1698 static isl_stat
foreach_lifted_subset(__isl_take isl_set
*set
,
1700 isl_stat (*fn
)(__isl_take isl_set
*set
, __isl_take EL
*el
,
1701 void *user
), void *user
)
1708 for (i
= 0; i
< set
->n
; ++i
) {
1712 lift
= isl_set_from_basic_set(isl_basic_set_copy(set
->p
[i
]));
1713 lift
= isl_set_lift(lift
);
1715 copy
= FN(EL
,copy
)(el
);
1716 copy
= FN(EL
,lift
)(copy
, isl_set_get_space(lift
));
1718 if (fn(lift
, copy
, user
) < 0)
1729 return isl_stat_error
;
1732 isl_stat
FN(PW
,foreach_lifted_piece
)(__isl_keep PW
*pw
,
1733 isl_stat (*fn
)(__isl_take isl_set
*set
, __isl_take EL
*el
,
1734 void *user
), void *user
)
1739 return isl_stat_error
;
1741 for (i
= 0; i
< pw
->n
; ++i
) {
1746 any
= any_divs(pw
->p
[i
].set
);
1748 return isl_stat_error
;
1749 set
= isl_set_copy(pw
->p
[i
].set
);
1750 el
= FN(EL
,copy
)(pw
->p
[i
].FIELD
);
1752 if (fn(set
, el
, user
) < 0)
1753 return isl_stat_error
;
1756 if (foreach_lifted_subset(set
, el
, fn
, user
) < 0)
1757 return isl_stat_error
;
1764 #ifndef NO_MOVE_DIMS
1765 __isl_give PW
*FN(PW
,move_dims
)(__isl_take PW
*pw
,
1766 enum isl_dim_type dst_type
, unsigned dst_pos
,
1767 enum isl_dim_type src_type
, unsigned src_pos
, unsigned n
)
1771 pw
= FN(PW
,cow
)(pw
);
1775 pw
->dim
= isl_space_move_dims(pw
->dim
, dst_type
, dst_pos
, src_type
, src_pos
, n
);
1779 for (i
= 0; i
< pw
->n
; ++i
) {
1780 pw
->p
[i
].FIELD
= FN(EL
,move_dims
)(pw
->p
[i
].FIELD
,
1781 dst_type
, dst_pos
, src_type
, src_pos
, n
);
1782 if (!pw
->p
[i
].FIELD
)
1786 if (dst_type
== isl_dim_in
)
1787 dst_type
= isl_dim_set
;
1788 if (src_type
== isl_dim_in
)
1789 src_type
= isl_dim_set
;
1791 for (i
= 0; i
< pw
->n
; ++i
) {
1792 pw
->p
[i
].set
= isl_set_move_dims(pw
->p
[i
].set
,
1794 src_type
, src_pos
, n
);
1806 __isl_give PW
*FN(PW
,mul_isl_int
)(__isl_take PW
*pw
, isl_int v
)
1810 if (isl_int_is_one(v
))
1812 if (pw
&& DEFAULT_IS_ZERO
&& isl_int_is_zero(v
)) {
1814 isl_space
*dim
= FN(PW
,get_space
)(pw
);
1816 zero
= FN(PW
,ZERO
)(dim
, pw
->type
);
1818 zero
= FN(PW
,ZERO
)(dim
);
1823 pw
= FN(PW
,cow
)(pw
);
1830 if (isl_int_is_neg(v
))
1831 pw
->type
= isl_fold_type_negate(pw
->type
);
1833 for (i
= 0; i
< pw
->n
; ++i
) {
1834 pw
->p
[i
].FIELD
= FN(EL
,scale
)(pw
->p
[i
].FIELD
, v
);
1835 if (!pw
->p
[i
].FIELD
)
1845 /* Multiply the pieces of "pw" by "v" and return the result.
1847 __isl_give PW
*FN(PW
,scale_val
)(__isl_take PW
*pw
, __isl_take isl_val
*v
)
1854 if (isl_val_is_one(v
)) {
1858 if (pw
&& DEFAULT_IS_ZERO
&& isl_val_is_zero(v
)) {
1860 isl_space
*space
= FN(PW
,get_space
)(pw
);
1862 zero
= FN(PW
,ZERO
)(space
, pw
->type
);
1864 zero
= FN(PW
,ZERO
)(space
);
1874 pw
= FN(PW
,cow
)(pw
);
1879 if (isl_val_is_neg(v
))
1880 pw
->type
= isl_fold_type_negate(pw
->type
);
1882 for (i
= 0; i
< pw
->n
; ++i
) {
1883 pw
->p
[i
].FIELD
= FN(EL
,scale_val
)(pw
->p
[i
].FIELD
,
1885 if (!pw
->p
[i
].FIELD
)
1897 /* Divide the pieces of "pw" by "v" and return the result.
1899 __isl_give PW
*FN(PW
,scale_down_val
)(__isl_take PW
*pw
, __isl_take isl_val
*v
)
1906 if (isl_val_is_one(v
)) {
1911 if (!isl_val_is_rat(v
))
1912 isl_die(isl_val_get_ctx(v
), isl_error_invalid
,
1913 "expecting rational factor", goto error
);
1914 if (isl_val_is_zero(v
))
1915 isl_die(isl_val_get_ctx(v
), isl_error_invalid
,
1916 "cannot scale down by zero", goto error
);
1922 pw
= FN(PW
,cow
)(pw
);
1927 if (isl_val_is_neg(v
))
1928 pw
->type
= isl_fold_type_negate(pw
->type
);
1930 for (i
= 0; i
< pw
->n
; ++i
) {
1931 pw
->p
[i
].FIELD
= FN(EL
,scale_down_val
)(pw
->p
[i
].FIELD
,
1933 if (!pw
->p
[i
].FIELD
)
1945 __isl_give PW
*FN(PW
,scale
)(__isl_take PW
*pw
, isl_int v
)
1947 return FN(PW
,mul_isl_int
)(pw
, v
);
1950 /* Apply some normalization to "pw".
1951 * In particular, sort the pieces according to their function value
1952 * expressions, combining pairs of adjacent pieces with
1953 * the same such expression, and then normalize the domains of the pieces.
1955 * We normalize in place, but if anything goes wrong we need
1956 * to return NULL, so we need to make sure we don't change the
1957 * meaning of any possible other copies of "pw".
1959 __isl_give PW
*FN(PW
,normalize
)(__isl_take PW
*pw
)
1964 pw
= FN(PW
,sort
)(pw
);
1967 for (i
= 0; i
< pw
->n
; ++i
) {
1968 set
= isl_set_normalize(isl_set_copy(pw
->p
[i
].set
));
1970 return FN(PW
,free
)(pw
);
1971 isl_set_free(pw
->p
[i
].set
);
1978 /* Is pw1 obviously equal to pw2?
1979 * That is, do they have obviously identical cells and obviously identical
1980 * elements on each cell?
1982 * If "pw1" or "pw2" contain any NaNs, then they are considered
1983 * not to be the same. A NaN is not equal to anything, not even
1986 isl_bool
FN(PW
,plain_is_equal
)(__isl_keep PW
*pw1
, __isl_keep PW
*pw2
)
1989 isl_bool equal
, has_nan
;
1992 return isl_bool_error
;
1994 has_nan
= FN(PW
,involves_nan
)(pw1
);
1995 if (has_nan
>= 0 && !has_nan
)
1996 has_nan
= FN(PW
,involves_nan
)(pw2
);
1997 if (has_nan
< 0 || has_nan
)
1998 return isl_bool_not(has_nan
);
2001 return isl_bool_true
;
2002 if (!isl_space_is_equal(pw1
->dim
, pw2
->dim
))
2003 return isl_bool_false
;
2005 pw1
= FN(PW
,copy
)(pw1
);
2006 pw2
= FN(PW
,copy
)(pw2
);
2007 pw1
= FN(PW
,normalize
)(pw1
);
2008 pw2
= FN(PW
,normalize
)(pw2
);
2012 equal
= pw1
->n
== pw2
->n
;
2013 for (i
= 0; equal
&& i
< pw1
->n
; ++i
) {
2014 equal
= isl_set_plain_is_equal(pw1
->p
[i
].set
, pw2
->p
[i
].set
);
2019 equal
= FN(EL
,plain_is_equal
)(pw1
->p
[i
].FIELD
, pw2
->p
[i
].FIELD
);
2030 return isl_bool_error
;
2033 /* Does "pw" involve any NaNs?
2035 isl_bool
FN(PW
,involves_nan
)(__isl_keep PW
*pw
)
2040 return isl_bool_error
;
2042 return isl_bool_false
;
2044 for (i
= 0; i
< pw
->n
; ++i
) {
2045 isl_bool has_nan
= FN(EL
,involves_nan
)(pw
->p
[i
].FIELD
);
2046 if (has_nan
< 0 || has_nan
)
2050 return isl_bool_false
;
2054 static __isl_give PW
*FN(PW
,align_params_pw_multi_aff_and
)(__isl_take PW
*pw
,
2055 __isl_take isl_multi_aff
*ma
,
2056 __isl_give PW
*(*fn
)(__isl_take PW
*pw
, __isl_take isl_multi_aff
*ma
))
2059 isl_bool equal_params
;
2060 isl_space
*ma_space
;
2062 ma_space
= isl_multi_aff_get_space(ma
);
2063 if (!pw
|| !ma
|| !ma_space
)
2065 equal_params
= isl_space_has_equal_params(pw
->dim
, ma_space
);
2066 if (equal_params
< 0)
2069 isl_space_free(ma_space
);
2072 ctx
= FN(PW
,get_ctx
)(pw
);
2073 if (!isl_space_has_named_params(pw
->dim
) ||
2074 !isl_space_has_named_params(ma_space
))
2075 isl_die(ctx
, isl_error_invalid
,
2076 "unaligned unnamed parameters", goto error
);
2077 pw
= FN(PW
,align_params
)(pw
, ma_space
);
2078 ma
= isl_multi_aff_align_params(ma
, FN(PW
,get_space
)(pw
));
2081 isl_space_free(ma_space
);
2083 isl_multi_aff_free(ma
);
2087 static __isl_give PW
*FN(PW
,align_params_pw_pw_multi_aff_and
)(__isl_take PW
*pw
,
2088 __isl_take isl_pw_multi_aff
*pma
,
2089 __isl_give PW
*(*fn
)(__isl_take PW
*pw
,
2090 __isl_take isl_pw_multi_aff
*ma
))
2093 isl_bool equal_params
;
2094 isl_space
*pma_space
;
2096 pma_space
= isl_pw_multi_aff_get_space(pma
);
2097 if (!pw
|| !pma
|| !pma_space
)
2099 equal_params
= isl_space_has_equal_params(pw
->dim
, pma_space
);
2100 if (equal_params
< 0)
2103 isl_space_free(pma_space
);
2106 ctx
= FN(PW
,get_ctx
)(pw
);
2107 if (!isl_space_has_named_params(pw
->dim
) ||
2108 !isl_space_has_named_params(pma_space
))
2109 isl_die(ctx
, isl_error_invalid
,
2110 "unaligned unnamed parameters", goto error
);
2111 pw
= FN(PW
,align_params
)(pw
, pma_space
);
2112 pma
= isl_pw_multi_aff_align_params(pma
, FN(PW
,get_space
)(pw
));
2115 isl_space_free(pma_space
);
2117 isl_pw_multi_aff_free(pma
);
2121 /* Compute the pullback of "pw" by the function represented by "ma".
2122 * In other words, plug in "ma" in "pw".
2124 static __isl_give PW
*FN(PW
,pullback_multi_aff_aligned
)(__isl_take PW
*pw
,
2125 __isl_take isl_multi_aff
*ma
)
2128 isl_space
*space
= NULL
;
2130 ma
= isl_multi_aff_align_divs(ma
);
2131 pw
= FN(PW
,cow
)(pw
);
2135 space
= isl_space_join(isl_multi_aff_get_space(ma
),
2136 FN(PW
,get_space
)(pw
));
2138 for (i
= 0; i
< pw
->n
; ++i
) {
2139 pw
->p
[i
].set
= isl_set_preimage_multi_aff(pw
->p
[i
].set
,
2140 isl_multi_aff_copy(ma
));
2143 pw
->p
[i
].FIELD
= FN(EL
,pullback_multi_aff
)(pw
->p
[i
].FIELD
,
2144 isl_multi_aff_copy(ma
));
2145 if (!pw
->p
[i
].FIELD
)
2149 pw
= FN(PW
,reset_space
)(pw
, space
);
2150 isl_multi_aff_free(ma
);
2153 isl_space_free(space
);
2154 isl_multi_aff_free(ma
);
2159 __isl_give PW
*FN(PW
,pullback_multi_aff
)(__isl_take PW
*pw
,
2160 __isl_take isl_multi_aff
*ma
)
2162 return FN(PW
,align_params_pw_multi_aff_and
)(pw
, ma
,
2163 &FN(PW
,pullback_multi_aff_aligned
));
2166 /* Compute the pullback of "pw" by the function represented by "pma".
2167 * In other words, plug in "pma" in "pw".
2169 static __isl_give PW
*FN(PW
,pullback_pw_multi_aff_aligned
)(__isl_take PW
*pw
,
2170 __isl_take isl_pw_multi_aff
*pma
)
2180 space
= isl_space_join(isl_pw_multi_aff_get_space(pma
),
2181 FN(PW
,get_space
)(pw
));
2182 isl_pw_multi_aff_free(pma
);
2183 res
= FN(PW
,empty
)(space
);
2188 res
= FN(PW
,pullback_multi_aff
)(FN(PW
,copy
)(pw
),
2189 isl_multi_aff_copy(pma
->p
[0].maff
));
2190 res
= FN(PW
,intersect_domain
)(res
, isl_set_copy(pma
->p
[0].set
));
2192 for (i
= 1; i
< pma
->n
; ++i
) {
2195 res_i
= FN(PW
,pullback_multi_aff
)(FN(PW
,copy
)(pw
),
2196 isl_multi_aff_copy(pma
->p
[i
].maff
));
2197 res_i
= FN(PW
,intersect_domain
)(res_i
,
2198 isl_set_copy(pma
->p
[i
].set
));
2199 res
= FN(PW
,add_disjoint
)(res
, res_i
);
2202 isl_pw_multi_aff_free(pma
);
2206 isl_pw_multi_aff_free(pma
);
2211 __isl_give PW
*FN(PW
,pullback_pw_multi_aff
)(__isl_take PW
*pw
,
2212 __isl_take isl_pw_multi_aff
*pma
)
2214 return FN(PW
,align_params_pw_pw_multi_aff_and
)(pw
, pma
,
2215 &FN(PW
,pullback_pw_multi_aff_aligned
));