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
)
276 ctx
= isl_space_get_ctx(model
);
277 if (!isl_space_has_named_params(model
))
278 isl_die(ctx
, isl_error_invalid
,
279 "model has unnamed parameters", goto error
);
280 if (!isl_space_has_named_params(pw
->dim
))
281 isl_die(ctx
, isl_error_invalid
,
282 "input has unnamed parameters", goto error
);
283 if (!isl_space_match(pw
->dim
, isl_dim_param
, model
, isl_dim_param
)) {
286 model
= isl_space_drop_dims(model
, isl_dim_in
,
287 0, isl_space_dim(model
, isl_dim_in
));
288 model
= isl_space_drop_dims(model
, isl_dim_out
,
289 0, isl_space_dim(model
, isl_dim_out
));
290 exp
= isl_parameter_alignment_reordering(pw
->dim
, model
);
291 exp
= isl_reordering_extend_space(exp
,
292 FN(PW
,get_domain_space
)(pw
));
293 pw
= FN(PW
,realign_domain
)(pw
, exp
);
296 isl_space_free(model
);
299 isl_space_free(model
);
304 static __isl_give PW
*FN(PW
,align_params_pw_pw_and
)(__isl_take PW
*pw1
,
306 __isl_give PW
*(*fn
)(__isl_take PW
*pw1
, __isl_take PW
*pw2
))
312 if (isl_space_match(pw1
->dim
, isl_dim_param
, pw2
->dim
, isl_dim_param
))
314 ctx
= FN(PW
,get_ctx
)(pw1
);
315 if (!isl_space_has_named_params(pw1
->dim
) ||
316 !isl_space_has_named_params(pw2
->dim
))
317 isl_die(ctx
, isl_error_invalid
,
318 "unaligned unnamed parameters", goto error
);
319 pw1
= FN(PW
,align_params
)(pw1
, FN(PW
,get_space
)(pw2
));
320 pw2
= FN(PW
,align_params
)(pw2
, FN(PW
,get_space
)(pw1
));
328 static __isl_give PW
*FN(PW
,align_params_pw_set_and
)(__isl_take PW
*pw
,
329 __isl_take isl_set
*set
,
330 __isl_give PW
*(*fn
)(__isl_take PW
*pw
, __isl_take isl_set
*set
))
336 if (isl_space_match(pw
->dim
, isl_dim_param
, set
->dim
, isl_dim_param
))
338 ctx
= FN(PW
,get_ctx
)(pw
);
339 if (!isl_space_has_named_params(pw
->dim
) ||
340 !isl_space_has_named_params(set
->dim
))
341 isl_die(ctx
, isl_error_invalid
,
342 "unaligned unnamed parameters", goto error
);
343 pw
= FN(PW
,align_params
)(pw
, isl_set_get_space(set
));
344 set
= isl_set_align_params(set
, FN(PW
,get_space
)(pw
));
353 static __isl_give PW
*FN(PW
,union_add_aligned
)(__isl_take PW
*pw1
,
364 ctx
= isl_space_get_ctx(pw1
->dim
);
366 if (pw1
->type
!= pw2
->type
)
367 isl_die(ctx
, isl_error_invalid
,
368 "fold types don't match", goto error
);
370 isl_assert(ctx
, isl_space_is_equal(pw1
->dim
, pw2
->dim
), goto error
);
372 if (FN(PW
,IS_ZERO
)(pw1
)) {
377 if (FN(PW
,IS_ZERO
)(pw2
)) {
382 n
= (pw1
->n
+ 1) * (pw2
->n
+ 1);
384 res
= FN(PW
,alloc_size
)(isl_space_copy(pw1
->dim
), pw1
->type
, n
);
386 res
= FN(PW
,alloc_size
)(isl_space_copy(pw1
->dim
), n
);
389 for (i
= 0; i
< pw1
->n
; ++i
) {
390 set
= isl_set_copy(pw1
->p
[i
].set
);
391 for (j
= 0; j
< pw2
->n
; ++j
) {
392 struct isl_set
*common
;
394 common
= isl_set_intersect(isl_set_copy(pw1
->p
[i
].set
),
395 isl_set_copy(pw2
->p
[j
].set
));
396 if (isl_set_plain_is_empty(common
)) {
397 isl_set_free(common
);
400 set
= isl_set_subtract(set
,
401 isl_set_copy(pw2
->p
[j
].set
));
403 sum
= FN(EL
,add_on_domain
)(common
,
404 FN(EL
,copy
)(pw1
->p
[i
].FIELD
),
405 FN(EL
,copy
)(pw2
->p
[j
].FIELD
));
407 res
= FN(PW
,add_piece
)(res
, common
, sum
);
409 res
= FN(PW
,add_piece
)(res
, set
, FN(EL
,copy
)(pw1
->p
[i
].FIELD
));
412 for (j
= 0; j
< pw2
->n
; ++j
) {
413 set
= isl_set_copy(pw2
->p
[j
].set
);
414 for (i
= 0; i
< pw1
->n
; ++i
)
415 set
= isl_set_subtract(set
,
416 isl_set_copy(pw1
->p
[i
].set
));
417 res
= FN(PW
,add_piece
)(res
, set
, FN(EL
,copy
)(pw2
->p
[j
].FIELD
));
430 /* Private version of "union_add". For isl_pw_qpolynomial and
431 * isl_pw_qpolynomial_fold, we prefer to simply call it "add".
433 static __isl_give PW
*FN(PW
,union_add_
)(__isl_take PW
*pw1
, __isl_take PW
*pw2
)
435 return FN(PW
,align_params_pw_pw_and
)(pw1
, pw2
,
436 &FN(PW
,union_add_aligned
));
439 /* Make sure "pw" has room for at least "n" more pieces.
441 * If there is only one reference to pw, we extend it in place.
442 * Otherwise, we create a new PW and copy the pieces.
444 static __isl_give PW
*FN(PW
,grow
)(__isl_take PW
*pw
, int n
)
452 if (pw
->n
+ n
<= pw
->size
)
454 ctx
= FN(PW
,get_ctx
)(pw
);
457 res
= isl_realloc(ctx
, pw
, struct PW
,
458 sizeof(struct PW
) + (n
- 1) * sizeof(S(PW
,piece
)));
460 return FN(PW
,free
)(pw
);
465 res
= FN(PW
,alloc_size
)(isl_space_copy(pw
->dim
), pw
->type
, n
);
467 res
= FN(PW
,alloc_size
)(isl_space_copy(pw
->dim
), n
);
470 return FN(PW
,free
)(pw
);
471 for (i
= 0; i
< pw
->n
; ++i
)
472 res
= FN(PW
,add_piece
)(res
, isl_set_copy(pw
->p
[i
].set
),
473 FN(EL
,copy
)(pw
->p
[i
].FIELD
));
478 static __isl_give PW
*FN(PW
,add_disjoint_aligned
)(__isl_take PW
*pw1
,
487 if (pw1
->size
< pw1
->n
+ pw2
->n
&& pw1
->n
< pw2
->n
)
488 return FN(PW
,add_disjoint_aligned
)(pw2
, pw1
);
490 ctx
= isl_space_get_ctx(pw1
->dim
);
492 if (pw1
->type
!= pw2
->type
)
493 isl_die(ctx
, isl_error_invalid
,
494 "fold types don't match", goto error
);
496 isl_assert(ctx
, isl_space_is_equal(pw1
->dim
, pw2
->dim
), goto error
);
498 if (FN(PW
,IS_ZERO
)(pw1
)) {
503 if (FN(PW
,IS_ZERO
)(pw2
)) {
508 pw1
= FN(PW
,grow
)(pw1
, pw2
->n
);
512 for (i
= 0; i
< pw2
->n
; ++i
)
513 pw1
= FN(PW
,add_piece
)(pw1
,
514 isl_set_copy(pw2
->p
[i
].set
),
515 FN(EL
,copy
)(pw2
->p
[i
].FIELD
));
526 __isl_give PW
*FN(PW
,add_disjoint
)(__isl_take PW
*pw1
, __isl_take PW
*pw2
)
528 return FN(PW
,align_params_pw_pw_and
)(pw1
, pw2
,
529 &FN(PW
,add_disjoint_aligned
));
532 /* This function is currently only used from isl_aff.c
534 static __isl_give PW
*FN(PW
,on_shared_domain_in
)(__isl_take PW
*pw1
,
535 __isl_take PW
*pw2
, __isl_take isl_space
*space
,
536 __isl_give EL
*(*fn
)(__isl_take EL
*el1
, __isl_take EL
*el2
))
537 __attribute__ ((unused
));
539 /* Apply "fn" to pairs of elements from pw1 and pw2 on shared domains.
540 * The result of "fn" (and therefore also of this function) lives in "space".
542 static __isl_give PW
*FN(PW
,on_shared_domain_in
)(__isl_take PW
*pw1
,
543 __isl_take PW
*pw2
, __isl_take isl_space
*space
,
544 __isl_give EL
*(*fn
)(__isl_take EL
*el1
, __isl_take EL
*el2
))
554 res
= FN(PW
,alloc_size
)(isl_space_copy(space
), pw1
->type
, n
);
556 res
= FN(PW
,alloc_size
)(isl_space_copy(space
), n
);
559 for (i
= 0; i
< pw1
->n
; ++i
) {
560 for (j
= 0; j
< pw2
->n
; ++j
) {
565 common
= isl_set_intersect(
566 isl_set_copy(pw1
->p
[i
].set
),
567 isl_set_copy(pw2
->p
[j
].set
));
568 empty
= isl_set_plain_is_empty(common
);
569 if (empty
< 0 || empty
) {
570 isl_set_free(common
);
576 res_ij
= fn(FN(EL
,copy
)(pw1
->p
[i
].FIELD
),
577 FN(EL
,copy
)(pw2
->p
[j
].FIELD
));
578 res_ij
= FN(EL
,gist
)(res_ij
, isl_set_copy(common
));
580 res
= FN(PW
,add_piece
)(res
, common
, res_ij
);
584 isl_space_free(space
);
589 isl_space_free(space
);
596 /* This function is currently only used from isl_aff.c
598 static __isl_give PW
*FN(PW
,on_shared_domain
)(__isl_take PW
*pw1
,
600 __isl_give EL
*(*fn
)(__isl_take EL
*el1
, __isl_take EL
*el2
))
601 __attribute__ ((unused
));
603 /* Apply "fn" to pairs of elements from pw1 and pw2 on shared domains.
604 * The result of "fn" is assumed to live in the same space as "pw1" and "pw2".
606 static __isl_give PW
*FN(PW
,on_shared_domain
)(__isl_take PW
*pw1
,
608 __isl_give EL
*(*fn
)(__isl_take EL
*el1
, __isl_take EL
*el2
))
615 space
= isl_space_copy(pw1
->dim
);
616 return FN(PW
,on_shared_domain_in
)(pw1
, pw2
, space
, fn
);
624 __isl_give PW
*FN(PW
,neg
)(__isl_take PW
*pw
)
631 if (FN(PW
,IS_ZERO
)(pw
))
638 for (i
= 0; i
< pw
->n
; ++i
) {
639 pw
->p
[i
].FIELD
= FN(EL
,neg
)(pw
->p
[i
].FIELD
);
641 return FN(PW
,free
)(pw
);
649 __isl_give PW
*FN(PW
,sub
)(__isl_take PW
*pw1
, __isl_take PW
*pw2
)
651 return FN(PW
,add
)(pw1
, FN(PW
,neg
)(pw2
));
656 __isl_give isl_val
*FN(PW
,eval
)(__isl_take PW
*pw
, __isl_take isl_point
*pnt
)
661 isl_space
*pnt_dim
= NULL
;
666 ctx
= isl_point_get_ctx(pnt
);
667 pnt_dim
= isl_point_get_space(pnt
);
668 isl_assert(ctx
, isl_space_is_domain_internal(pnt_dim
, pw
->dim
),
671 for (i
= 0; i
< pw
->n
; ++i
) {
672 found
= isl_set_contains_point(pw
->p
[i
].set
, pnt
);
679 v
= FN(EL
,eval
)(FN(EL
,copy
)(pw
->p
[i
].FIELD
),
680 isl_point_copy(pnt
));
682 v
= isl_val_zero(ctx
);
684 isl_space_free(pnt_dim
);
689 isl_space_free(pnt_dim
);
695 /* Return the parameter domain of "pw".
697 __isl_give isl_set
*FN(PW
,params
)(__isl_take PW
*pw
)
699 return isl_set_params(FN(PW
,domain
)(pw
));
702 __isl_give isl_set
*FN(PW
,domain
)(__isl_take PW
*pw
)
710 dom
= isl_set_empty(FN(PW
,get_domain_space
)(pw
));
711 for (i
= 0; i
< pw
->n
; ++i
)
712 dom
= isl_set_union_disjoint(dom
, isl_set_copy(pw
->p
[i
].set
));
719 /* Exploit the equalities in the domain of piece "i" of "pw"
720 * to simplify the associated function.
721 * If the domain of piece "i" is empty, then remove it entirely,
722 * replacing it with the final piece.
724 static int FN(PW
,exploit_equalities_and_remove_if_empty
)(__isl_keep PW
*pw
,
728 int empty
= isl_set_plain_is_empty(pw
->p
[i
].set
);
733 isl_set_free(pw
->p
[i
].set
);
734 FN(EL
,free
)(pw
->p
[i
].FIELD
);
736 pw
->p
[i
] = pw
->p
[pw
->n
- 1];
742 aff
= isl_set_affine_hull(isl_set_copy(pw
->p
[i
].set
));
743 pw
->p
[i
].FIELD
= FN(EL
,substitute_equalities
)(pw
->p
[i
].FIELD
, aff
);
750 /* Convert a piecewise expression defined over a parameter domain
751 * into one that is defined over a zero-dimensional set.
753 __isl_give PW
*FN(PW
,from_range
)(__isl_take PW
*pw
)
759 if (!isl_space_is_set(pw
->dim
))
760 isl_die(FN(PW
,get_ctx
)(pw
), isl_error_invalid
,
761 "not living in a set space", return FN(PW
,free
)(pw
));
763 space
= FN(PW
,get_space
)(pw
);
764 space
= isl_space_from_range(space
);
765 pw
= FN(PW
,reset_space
)(pw
, space
);
770 /* Fix the value of the given parameter or domain dimension of "pw"
771 * to be equal to "value".
773 __isl_give PW
*FN(PW
,fix_si
)(__isl_take PW
*pw
, enum isl_dim_type type
,
774 unsigned pos
, int value
)
781 if (type
== isl_dim_out
)
782 isl_die(FN(PW
,get_ctx
)(pw
), isl_error_invalid
,
783 "cannot fix output dimension", return FN(PW
,free
)(pw
));
788 if (type
== isl_dim_in
)
793 return FN(PW
,free
)(pw
);
795 for (i
= pw
->n
- 1; i
>= 0; --i
) {
796 pw
->p
[i
].set
= isl_set_fix_si(pw
->p
[i
].set
, type
, pos
, value
);
797 if (FN(PW
,exploit_equalities_and_remove_if_empty
)(pw
, i
) < 0)
798 return FN(PW
,free
)(pw
);
804 /* Restrict the domain of "pw" by combining each cell
805 * with "set" through a call to "fn", where "fn" may be
806 * isl_set_intersect, isl_set_intersect_params or isl_set_subtract.
808 static __isl_give PW
*FN(PW
,restrict_domain_aligned
)(__isl_take PW
*pw
,
809 __isl_take isl_set
*set
,
810 __isl_give isl_set
*(*fn
)(__isl_take isl_set
*set1
,
811 __isl_take isl_set
*set2
))
827 for (i
= pw
->n
- 1; i
>= 0; --i
) {
828 pw
->p
[i
].set
= fn(pw
->p
[i
].set
, isl_set_copy(set
));
829 if (FN(PW
,exploit_equalities_and_remove_if_empty
)(pw
, i
) < 0)
841 static __isl_give PW
*FN(PW
,intersect_domain_aligned
)(__isl_take PW
*pw
,
842 __isl_take isl_set
*set
)
844 return FN(PW
,restrict_domain_aligned
)(pw
, set
, &isl_set_intersect
);
847 __isl_give PW
*FN(PW
,intersect_domain
)(__isl_take PW
*pw
,
848 __isl_take isl_set
*context
)
850 return FN(PW
,align_params_pw_set_and
)(pw
, context
,
851 &FN(PW
,intersect_domain_aligned
));
854 static __isl_give PW
*FN(PW
,intersect_params_aligned
)(__isl_take PW
*pw
,
855 __isl_take isl_set
*set
)
857 return FN(PW
,restrict_domain_aligned
)(pw
, set
,
858 &isl_set_intersect_params
);
861 /* Intersect the domain of "pw" with the parameter domain "context".
863 __isl_give PW
*FN(PW
,intersect_params
)(__isl_take PW
*pw
,
864 __isl_take isl_set
*context
)
866 return FN(PW
,align_params_pw_set_and
)(pw
, context
,
867 &FN(PW
,intersect_params_aligned
));
870 /* Subtract "domain' from the domain of "pw", assuming their
871 * parameters have been aligned.
873 static __isl_give PW
*FN(PW
,subtract_domain_aligned
)(__isl_take PW
*pw
,
874 __isl_take isl_set
*domain
)
876 return FN(PW
,restrict_domain_aligned
)(pw
, domain
, &isl_set_subtract
);
879 /* Subtract "domain' from the domain of "pw".
881 __isl_give PW
*FN(PW
,subtract_domain
)(__isl_take PW
*pw
,
882 __isl_take isl_set
*domain
)
884 return FN(PW
,align_params_pw_set_and
)(pw
, domain
,
885 &FN(PW
,subtract_domain_aligned
));
888 /* Compute the gist of "pw" with respect to the domain constraints
889 * of "context" for the case where the domain of the last element
890 * of "pw" is equal to "context".
891 * Call "fn_el" to compute the gist of this element, replace
892 * its domain by the universe and drop all other elements
893 * as their domains are necessarily disjoint from "context".
895 static __isl_give PW
*FN(PW
,gist_last
)(__isl_take PW
*pw
,
896 __isl_take isl_set
*context
,
897 __isl_give EL
*(*fn_el
)(__isl_take EL
*el
, __isl_take isl_set
*set
))
902 for (i
= 0; i
< pw
->n
- 1; ++i
) {
903 isl_set_free(pw
->p
[i
].set
);
904 FN(EL
,free
)(pw
->p
[i
].FIELD
);
906 pw
->p
[0].FIELD
= pw
->p
[pw
->n
- 1].FIELD
;
907 pw
->p
[0].set
= pw
->p
[pw
->n
- 1].set
;
910 space
= isl_set_get_space(context
);
911 pw
->p
[0].FIELD
= fn_el(pw
->p
[0].FIELD
, context
);
912 context
= isl_set_universe(space
);
913 isl_set_free(pw
->p
[0].set
);
914 pw
->p
[0].set
= context
;
916 if (!pw
->p
[0].FIELD
|| !pw
->p
[0].set
)
917 return FN(PW
,free
)(pw
);
922 /* Compute the gist of "pw" with respect to the domain constraints
923 * of "context". Call "fn_el" to compute the gist of the elements
924 * and "fn_dom" to compute the gist of the domains.
926 * If the piecewise expression is empty or the context is the universe,
927 * then nothing can be simplified.
929 static __isl_give PW
*FN(PW
,gist_aligned
)(__isl_take PW
*pw
,
930 __isl_take isl_set
*context
,
931 __isl_give EL
*(*fn_el
)(__isl_take EL
*el
,
932 __isl_take isl_set
*set
),
933 __isl_give isl_set
*(*fn_dom
)(__isl_take isl_set
*set
,
934 __isl_take isl_basic_set
*bset
))
938 isl_basic_set
*hull
= NULL
;
944 isl_set_free(context
);
948 is_universe
= isl_set_plain_is_universe(context
);
952 isl_set_free(context
);
956 if (!isl_space_match(pw
->dim
, isl_dim_param
,
957 context
->dim
, isl_dim_param
)) {
958 pw
= FN(PW
,align_params
)(pw
, isl_set_get_space(context
));
959 context
= isl_set_align_params(context
, FN(PW
,get_space
)(pw
));
969 equal
= isl_set_plain_is_equal(pw
->p
[0].set
, context
);
973 return FN(PW
,gist_last
)(pw
, context
, fn_el
);
976 context
= isl_set_compute_divs(context
);
977 hull
= isl_set_simple_hull(isl_set_copy(context
));
979 for (i
= pw
->n
- 1; i
>= 0; --i
) {
983 if (i
== pw
->n
- 1) {
985 equal
= isl_set_plain_is_equal(pw
->p
[i
].set
, context
);
989 isl_basic_set_free(hull
);
990 return FN(PW
,gist_last
)(pw
, context
, fn_el
);
993 set_i
= isl_set_intersect(isl_set_copy(pw
->p
[i
].set
),
994 isl_set_copy(context
));
995 empty
= isl_set_plain_is_empty(set_i
);
996 pw
->p
[i
].FIELD
= fn_el(pw
->p
[i
].FIELD
, set_i
);
997 pw
->p
[i
].set
= fn_dom(pw
->p
[i
].set
, isl_basic_set_copy(hull
));
998 if (empty
< 0 || !pw
->p
[i
].FIELD
|| !pw
->p
[i
].set
)
1001 isl_set_free(pw
->p
[i
].set
);
1002 FN(EL
,free
)(pw
->p
[i
].FIELD
);
1004 pw
->p
[i
] = pw
->p
[pw
->n
- 1];
1009 isl_basic_set_free(hull
);
1010 isl_set_free(context
);
1015 isl_basic_set_free(hull
);
1016 isl_set_free(context
);
1020 static __isl_give PW
*FN(PW
,gist_domain_aligned
)(__isl_take PW
*pw
,
1021 __isl_take isl_set
*set
)
1023 return FN(PW
,gist_aligned
)(pw
, set
, &FN(EL
,gist
),
1024 &isl_set_gist_basic_set
);
1027 __isl_give PW
*FN(PW
,gist
)(__isl_take PW
*pw
, __isl_take isl_set
*context
)
1029 return FN(PW
,align_params_pw_set_and
)(pw
, context
,
1030 &FN(PW
,gist_domain_aligned
));
1033 static __isl_give PW
*FN(PW
,gist_params_aligned
)(__isl_take PW
*pw
,
1034 __isl_take isl_set
*set
)
1036 return FN(PW
,gist_aligned
)(pw
, set
, &FN(EL
,gist_params
),
1037 &isl_set_gist_params_basic_set
);
1040 __isl_give PW
*FN(PW
,gist_params
)(__isl_take PW
*pw
,
1041 __isl_take isl_set
*context
)
1043 return FN(PW
,align_params_pw_set_and
)(pw
, context
,
1044 &FN(PW
,gist_params_aligned
));
1047 /* Return -1 if the piece "p1" should be sorted before "p2"
1048 * and 1 if it should be sorted after "p2".
1049 * Return 0 if they do not need to be sorted in a specific order.
1051 * The two pieces are compared on the basis of their function value expressions.
1053 static int FN(PW
,sort_field_cmp
)(const void *p1
, const void *p2
, void *arg
)
1055 struct FN(PW
,piece
) const *pc1
= p1
;
1056 struct FN(PW
,piece
) const *pc2
= p2
;
1058 return FN(EL
,plain_cmp
)(pc1
->FIELD
, pc2
->FIELD
);
1061 /* Sort the pieces of "pw" according to their function value
1062 * expressions and then combine pairs of adjacent pieces with
1063 * the same such expression.
1065 * The sorting is performed in place because it does not
1066 * change the meaning of "pw", but care needs to be
1067 * taken not to change any possible other copies of "pw"
1068 * in case anything goes wrong.
1070 __isl_give PW
*FN(PW
,sort
)(__isl_take PW
*pw
)
1079 if (isl_sort(pw
->p
, pw
->n
, sizeof(pw
->p
[0]),
1080 &FN(PW
,sort_field_cmp
), NULL
) < 0)
1081 return FN(PW
,free
)(pw
);
1082 for (i
= pw
->n
- 1; i
>= 1; --i
) {
1083 if (!FN(EL
,plain_is_equal
)(pw
->p
[i
- 1].FIELD
, pw
->p
[i
].FIELD
))
1085 set
= isl_set_union(isl_set_copy(pw
->p
[i
- 1].set
),
1086 isl_set_copy(pw
->p
[i
].set
));
1088 return FN(PW
,free
)(pw
);
1089 isl_set_free(pw
->p
[i
].set
);
1090 FN(EL
,free
)(pw
->p
[i
].FIELD
);
1091 isl_set_free(pw
->p
[i
- 1].set
);
1092 pw
->p
[i
- 1].set
= set
;
1093 for (j
= i
+ 1; j
< pw
->n
; ++j
)
1094 pw
->p
[j
- 1] = pw
->p
[j
];
1101 /* Coalesce the domains of "pw".
1103 * Prior to the actual coalescing, first sort the pieces such that
1104 * pieces with the same function value expression are combined
1105 * into a single piece, the combined domain of which can then
1108 __isl_give PW
*FN(PW
,coalesce
)(__isl_take PW
*pw
)
1112 pw
= FN(PW
,sort
)(pw
);
1116 for (i
= 0; i
< pw
->n
; ++i
) {
1117 pw
->p
[i
].set
= isl_set_coalesce(pw
->p
[i
].set
);
1128 isl_ctx
*FN(PW
,get_ctx
)(__isl_keep PW
*pw
)
1130 return pw
? isl_space_get_ctx(pw
->dim
) : NULL
;
1133 #ifndef NO_INVOLVES_DIMS
1134 isl_bool
FN(PW
,involves_dims
)(__isl_keep PW
*pw
, enum isl_dim_type type
,
1135 unsigned first
, unsigned n
)
1138 enum isl_dim_type set_type
;
1141 return isl_bool_error
;
1142 if (pw
->n
== 0 || n
== 0)
1143 return isl_bool_false
;
1145 set_type
= type
== isl_dim_in
? isl_dim_set
: type
;
1147 for (i
= 0; i
< pw
->n
; ++i
) {
1148 isl_bool involves
= FN(EL
,involves_dims
)(pw
->p
[i
].FIELD
,
1150 if (involves
< 0 || involves
)
1152 involves
= isl_set_involves_dims(pw
->p
[i
].set
,
1153 set_type
, first
, n
);
1154 if (involves
< 0 || involves
)
1157 return isl_bool_false
;
1161 __isl_give PW
*FN(PW
,set_dim_name
)(__isl_take PW
*pw
,
1162 enum isl_dim_type type
, unsigned pos
, const char *s
)
1165 enum isl_dim_type set_type
;
1167 pw
= FN(PW
,cow
)(pw
);
1171 set_type
= type
== isl_dim_in
? isl_dim_set
: type
;
1173 pw
->dim
= isl_space_set_dim_name(pw
->dim
, type
, pos
, s
);
1177 for (i
= 0; i
< pw
->n
; ++i
) {
1178 pw
->p
[i
].set
= isl_set_set_dim_name(pw
->p
[i
].set
,
1182 pw
->p
[i
].FIELD
= FN(EL
,set_dim_name
)(pw
->p
[i
].FIELD
, type
, pos
, s
);
1183 if (!pw
->p
[i
].FIELD
)
1193 #ifndef NO_DROP_DIMS
1194 __isl_give PW
*FN(PW
,drop_dims
)(__isl_take PW
*pw
,
1195 enum isl_dim_type type
, unsigned first
, unsigned n
)
1198 enum isl_dim_type set_type
;
1202 if (n
== 0 && !isl_space_get_tuple_name(pw
->dim
, type
))
1205 set_type
= type
== isl_dim_in
? isl_dim_set
: type
;
1207 pw
= FN(PW
,cow
)(pw
);
1210 pw
->dim
= isl_space_drop_dims(pw
->dim
, type
, first
, n
);
1213 for (i
= 0; i
< pw
->n
; ++i
) {
1214 pw
->p
[i
].FIELD
= FN(EL
,drop_dims
)(pw
->p
[i
].FIELD
, type
, first
, n
);
1215 if (!pw
->p
[i
].FIELD
)
1217 if (type
== isl_dim_out
)
1219 pw
->p
[i
].set
= isl_set_drop(pw
->p
[i
].set
, set_type
, first
, n
);
1230 /* This function is very similar to drop_dims.
1231 * The only difference is that the cells may still involve
1232 * the specified dimensions. They are removed using
1233 * isl_set_project_out instead of isl_set_drop.
1235 __isl_give PW
*FN(PW
,project_out
)(__isl_take PW
*pw
,
1236 enum isl_dim_type type
, unsigned first
, unsigned n
)
1239 enum isl_dim_type set_type
;
1243 if (n
== 0 && !isl_space_get_tuple_name(pw
->dim
, type
))
1246 set_type
= type
== isl_dim_in
? isl_dim_set
: type
;
1248 pw
= FN(PW
,cow
)(pw
);
1251 pw
->dim
= isl_space_drop_dims(pw
->dim
, type
, first
, n
);
1254 for (i
= 0; i
< pw
->n
; ++i
) {
1255 pw
->p
[i
].set
= isl_set_project_out(pw
->p
[i
].set
,
1256 set_type
, first
, n
);
1259 pw
->p
[i
].FIELD
= FN(EL
,drop_dims
)(pw
->p
[i
].FIELD
, type
, first
, n
);
1260 if (!pw
->p
[i
].FIELD
)
1270 /* Project the domain of pw onto its parameter space.
1272 __isl_give PW
*FN(PW
,project_domain_on_params
)(__isl_take PW
*pw
)
1277 n
= FN(PW
,dim
)(pw
, isl_dim_in
);
1278 pw
= FN(PW
,project_out
)(pw
, isl_dim_in
, 0, n
);
1279 space
= FN(PW
,get_domain_space
)(pw
);
1280 space
= isl_space_params(space
);
1281 pw
= FN(PW
,reset_domain_space
)(pw
, space
);
1286 #ifndef NO_INSERT_DIMS
1287 __isl_give PW
*FN(PW
,insert_dims
)(__isl_take PW
*pw
, enum isl_dim_type type
,
1288 unsigned first
, unsigned n
)
1291 enum isl_dim_type set_type
;
1295 if (n
== 0 && !isl_space_is_named_or_nested(pw
->dim
, type
))
1298 set_type
= type
== isl_dim_in
? isl_dim_set
: type
;
1300 pw
= FN(PW
,cow
)(pw
);
1304 pw
->dim
= isl_space_insert_dims(pw
->dim
, type
, first
, n
);
1308 for (i
= 0; i
< pw
->n
; ++i
) {
1309 pw
->p
[i
].set
= isl_set_insert_dims(pw
->p
[i
].set
,
1310 set_type
, first
, n
);
1313 pw
->p
[i
].FIELD
= FN(EL
,insert_dims
)(pw
->p
[i
].FIELD
,
1315 if (!pw
->p
[i
].FIELD
)
1326 __isl_give PW
*FN(PW
,fix_dim
)(__isl_take PW
*pw
,
1327 enum isl_dim_type type
, unsigned pos
, isl_int v
)
1334 if (type
== isl_dim_in
)
1337 pw
= FN(PW
,cow
)(pw
);
1340 for (i
= 0; i
< pw
->n
; ++i
) {
1341 pw
->p
[i
].set
= isl_set_fix(pw
->p
[i
].set
, type
, pos
, v
);
1342 if (FN(PW
,exploit_equalities_and_remove_if_empty
)(pw
, i
) < 0)
1343 return FN(PW
,free
)(pw
);
1349 /* Fix the value of the variable at position "pos" of type "type" of "pw"
1350 * to be equal to "v".
1352 __isl_give PW
*FN(PW
,fix_val
)(__isl_take PW
*pw
,
1353 enum isl_dim_type type
, unsigned pos
, __isl_take isl_val
*v
)
1356 return FN(PW
,free
)(pw
);
1357 if (!isl_val_is_int(v
))
1358 isl_die(FN(PW
,get_ctx
)(pw
), isl_error_invalid
,
1359 "expecting integer value", goto error
);
1361 pw
= FN(PW
,fix_dim
)(pw
, type
, pos
, v
->n
);
1367 return FN(PW
,free
)(pw
);
1370 unsigned FN(PW
,dim
)(__isl_keep PW
*pw
, enum isl_dim_type type
)
1372 return pw
? isl_space_dim(pw
->dim
, type
) : 0;
1375 __isl_give PW
*FN(PW
,split_dims
)(__isl_take PW
*pw
,
1376 enum isl_dim_type type
, unsigned first
, unsigned n
)
1385 if (type
== isl_dim_in
)
1388 pw
= FN(PW
,cow
)(pw
);
1393 for (i
= 0; i
< pw
->n
; ++i
) {
1394 pw
->p
[i
].set
= isl_set_split_dims(pw
->p
[i
].set
, type
, first
, n
);
1406 /* Compute the maximal value attained by the piecewise quasipolynomial
1407 * on its domain or zero if the domain is empty.
1408 * In the worst case, the domain is scanned completely,
1409 * so the domain is assumed to be bounded.
1411 __isl_give isl_val
*FN(PW
,opt
)(__isl_take PW
*pw
, int max
)
1420 opt
= isl_val_zero(FN(PW
,get_ctx
)(pw
));
1425 opt
= FN(EL
,opt_on_domain
)(FN(EL
,copy
)(pw
->p
[0].FIELD
),
1426 isl_set_copy(pw
->p
[0].set
), max
);
1427 for (i
= 1; i
< pw
->n
; ++i
) {
1429 opt_i
= FN(EL
,opt_on_domain
)(FN(EL
,copy
)(pw
->p
[i
].FIELD
),
1430 isl_set_copy(pw
->p
[i
].set
), max
);
1432 opt
= isl_val_max(opt
, opt_i
);
1434 opt
= isl_val_min(opt
, opt_i
);
1441 __isl_give isl_val
*FN(PW
,max
)(__isl_take PW
*pw
)
1443 return FN(PW
,opt
)(pw
, 1);
1446 __isl_give isl_val
*FN(PW
,min
)(__isl_take PW
*pw
)
1448 return FN(PW
,opt
)(pw
, 0);
1452 __isl_give isl_space
*FN(PW
,get_space
)(__isl_keep PW
*pw
)
1454 return pw
? isl_space_copy(pw
->dim
) : NULL
;
1457 __isl_give isl_space
*FN(PW
,get_domain_space
)(__isl_keep PW
*pw
)
1459 return pw
? isl_space_domain(isl_space_copy(pw
->dim
)) : NULL
;
1462 /* Return the position of the dimension of the given type and name
1464 * Return -1 if no such dimension can be found.
1466 int FN(PW
,find_dim_by_name
)(__isl_keep PW
*pw
,
1467 enum isl_dim_type type
, const char *name
)
1471 return isl_space_find_dim_by_name(pw
->dim
, type
, name
);
1474 #ifndef NO_RESET_DIM
1475 /* Reset the space of "pw". Since we don't know if the elements
1476 * represent the spaces themselves or their domains, we pass along
1477 * both when we call their reset_space_and_domain.
1479 static __isl_give PW
*FN(PW
,reset_space_and_domain
)(__isl_take PW
*pw
,
1480 __isl_take isl_space
*space
, __isl_take isl_space
*domain
)
1484 pw
= FN(PW
,cow
)(pw
);
1485 if (!pw
|| !space
|| !domain
)
1488 for (i
= 0; i
< pw
->n
; ++i
) {
1489 pw
->p
[i
].set
= isl_set_reset_space(pw
->p
[i
].set
,
1490 isl_space_copy(domain
));
1493 pw
->p
[i
].FIELD
= FN(EL
,reset_space_and_domain
)(pw
->p
[i
].FIELD
,
1494 isl_space_copy(space
), isl_space_copy(domain
));
1495 if (!pw
->p
[i
].FIELD
)
1499 isl_space_free(domain
);
1501 isl_space_free(pw
->dim
);
1506 isl_space_free(domain
);
1507 isl_space_free(space
);
1512 __isl_give PW
*FN(PW
,reset_domain_space
)(__isl_take PW
*pw
,
1513 __isl_take isl_space
*domain
)
1517 space
= isl_space_extend_domain_with_range(isl_space_copy(domain
),
1518 FN(PW
,get_space
)(pw
));
1519 return FN(PW
,reset_space_and_domain
)(pw
, space
, domain
);
1522 __isl_give PW
*FN(PW
,reset_space
)(__isl_take PW
*pw
, __isl_take isl_space
*dim
)
1526 domain
= isl_space_domain(isl_space_copy(dim
));
1527 return FN(PW
,reset_space_and_domain
)(pw
, dim
, domain
);
1530 __isl_give PW
*FN(PW
,set_tuple_id
)(__isl_take PW
*pw
, enum isl_dim_type type
,
1531 __isl_take isl_id
*id
)
1535 pw
= FN(PW
,cow
)(pw
);
1539 space
= FN(PW
,get_space
)(pw
);
1540 space
= isl_space_set_tuple_id(space
, type
, id
);
1542 return FN(PW
,reset_space
)(pw
, space
);
1545 return FN(PW
,free
)(pw
);
1548 /* Drop the id on the specified tuple.
1550 __isl_give PW
*FN(PW
,reset_tuple_id
)(__isl_take PW
*pw
, enum isl_dim_type type
)
1556 if (!FN(PW
,has_tuple_id
)(pw
, type
))
1559 pw
= FN(PW
,cow
)(pw
);
1563 space
= FN(PW
,get_space
)(pw
);
1564 space
= isl_space_reset_tuple_id(space
, type
);
1566 return FN(PW
,reset_space
)(pw
, space
);
1569 __isl_give PW
*FN(PW
,set_dim_id
)(__isl_take PW
*pw
,
1570 enum isl_dim_type type
, unsigned pos
, __isl_take isl_id
*id
)
1572 pw
= FN(PW
,cow
)(pw
);
1575 pw
->dim
= isl_space_set_dim_id(pw
->dim
, type
, pos
, id
);
1576 return FN(PW
,reset_space
)(pw
, isl_space_copy(pw
->dim
));
1579 return FN(PW
,free
)(pw
);
1583 /* Reset the user pointer on all identifiers of parameters and tuples
1584 * of the space of "pw".
1586 __isl_give PW
*FN(PW
,reset_user
)(__isl_take PW
*pw
)
1590 space
= FN(PW
,get_space
)(pw
);
1591 space
= isl_space_reset_user(space
);
1593 return FN(PW
,reset_space
)(pw
, space
);
1596 int FN(PW
,has_equal_space
)(__isl_keep PW
*pw1
, __isl_keep PW
*pw2
)
1601 return isl_space_is_equal(pw1
->dim
, pw2
->dim
);
1605 __isl_give PW
*FN(PW
,morph_domain
)(__isl_take PW
*pw
,
1606 __isl_take isl_morph
*morph
)
1614 ctx
= isl_space_get_ctx(pw
->dim
);
1615 isl_assert(ctx
, isl_space_is_domain_internal(morph
->dom
->dim
, pw
->dim
),
1618 pw
= FN(PW
,cow
)(pw
);
1621 pw
->dim
= isl_space_extend_domain_with_range(
1622 isl_space_copy(morph
->ran
->dim
), pw
->dim
);
1626 for (i
= 0; i
< pw
->n
; ++i
) {
1627 pw
->p
[i
].set
= isl_morph_set(isl_morph_copy(morph
), pw
->p
[i
].set
);
1630 pw
->p
[i
].FIELD
= FN(EL
,morph_domain
)(pw
->p
[i
].FIELD
,
1631 isl_morph_copy(morph
));
1632 if (!pw
->p
[i
].FIELD
)
1636 isl_morph_free(morph
);
1641 isl_morph_free(morph
);
1646 int FN(PW
,n_piece
)(__isl_keep PW
*pw
)
1648 return pw
? pw
->n
: 0;
1651 isl_stat
FN(PW
,foreach_piece
)(__isl_keep PW
*pw
,
1652 isl_stat (*fn
)(__isl_take isl_set
*set
, __isl_take EL
*el
, void *user
),
1658 return isl_stat_error
;
1660 for (i
= 0; i
< pw
->n
; ++i
)
1661 if (fn(isl_set_copy(pw
->p
[i
].set
),
1662 FN(EL
,copy
)(pw
->p
[i
].FIELD
), user
) < 0)
1663 return isl_stat_error
;
1669 static int any_divs(__isl_keep isl_set
*set
)
1676 for (i
= 0; i
< set
->n
; ++i
)
1677 if (set
->p
[i
]->n_div
> 0)
1683 static isl_stat
foreach_lifted_subset(__isl_take isl_set
*set
,
1685 isl_stat (*fn
)(__isl_take isl_set
*set
, __isl_take EL
*el
,
1686 void *user
), void *user
)
1693 for (i
= 0; i
< set
->n
; ++i
) {
1697 lift
= isl_set_from_basic_set(isl_basic_set_copy(set
->p
[i
]));
1698 lift
= isl_set_lift(lift
);
1700 copy
= FN(EL
,copy
)(el
);
1701 copy
= FN(EL
,lift
)(copy
, isl_set_get_space(lift
));
1703 if (fn(lift
, copy
, user
) < 0)
1714 return isl_stat_error
;
1717 isl_stat
FN(PW
,foreach_lifted_piece
)(__isl_keep PW
*pw
,
1718 isl_stat (*fn
)(__isl_take isl_set
*set
, __isl_take EL
*el
,
1719 void *user
), void *user
)
1724 return isl_stat_error
;
1726 for (i
= 0; i
< pw
->n
; ++i
) {
1730 set
= isl_set_copy(pw
->p
[i
].set
);
1731 el
= FN(EL
,copy
)(pw
->p
[i
].FIELD
);
1732 if (!any_divs(set
)) {
1733 if (fn(set
, el
, user
) < 0)
1734 return isl_stat_error
;
1737 if (foreach_lifted_subset(set
, el
, fn
, user
) < 0)
1738 return isl_stat_error
;
1745 #ifndef NO_MOVE_DIMS
1746 __isl_give PW
*FN(PW
,move_dims
)(__isl_take PW
*pw
,
1747 enum isl_dim_type dst_type
, unsigned dst_pos
,
1748 enum isl_dim_type src_type
, unsigned src_pos
, unsigned n
)
1752 pw
= FN(PW
,cow
)(pw
);
1756 pw
->dim
= isl_space_move_dims(pw
->dim
, dst_type
, dst_pos
, src_type
, src_pos
, n
);
1760 for (i
= 0; i
< pw
->n
; ++i
) {
1761 pw
->p
[i
].FIELD
= FN(EL
,move_dims
)(pw
->p
[i
].FIELD
,
1762 dst_type
, dst_pos
, src_type
, src_pos
, n
);
1763 if (!pw
->p
[i
].FIELD
)
1767 if (dst_type
== isl_dim_in
)
1768 dst_type
= isl_dim_set
;
1769 if (src_type
== isl_dim_in
)
1770 src_type
= isl_dim_set
;
1772 for (i
= 0; i
< pw
->n
; ++i
) {
1773 pw
->p
[i
].set
= isl_set_move_dims(pw
->p
[i
].set
,
1775 src_type
, src_pos
, n
);
1787 __isl_give PW
*FN(PW
,mul_isl_int
)(__isl_take PW
*pw
, isl_int v
)
1791 if (isl_int_is_one(v
))
1793 if (pw
&& DEFAULT_IS_ZERO
&& isl_int_is_zero(v
)) {
1795 isl_space
*dim
= FN(PW
,get_space
)(pw
);
1797 zero
= FN(PW
,ZERO
)(dim
, pw
->type
);
1799 zero
= FN(PW
,ZERO
)(dim
);
1804 pw
= FN(PW
,cow
)(pw
);
1811 if (isl_int_is_neg(v
))
1812 pw
->type
= isl_fold_type_negate(pw
->type
);
1814 for (i
= 0; i
< pw
->n
; ++i
) {
1815 pw
->p
[i
].FIELD
= FN(EL
,scale
)(pw
->p
[i
].FIELD
, v
);
1816 if (!pw
->p
[i
].FIELD
)
1826 /* Multiply the pieces of "pw" by "v" and return the result.
1828 __isl_give PW
*FN(PW
,scale_val
)(__isl_take PW
*pw
, __isl_take isl_val
*v
)
1835 if (isl_val_is_one(v
)) {
1839 if (pw
&& DEFAULT_IS_ZERO
&& isl_val_is_zero(v
)) {
1841 isl_space
*space
= FN(PW
,get_space
)(pw
);
1843 zero
= FN(PW
,ZERO
)(space
, pw
->type
);
1845 zero
= FN(PW
,ZERO
)(space
);
1855 pw
= FN(PW
,cow
)(pw
);
1860 if (isl_val_is_neg(v
))
1861 pw
->type
= isl_fold_type_negate(pw
->type
);
1863 for (i
= 0; i
< pw
->n
; ++i
) {
1864 pw
->p
[i
].FIELD
= FN(EL
,scale_val
)(pw
->p
[i
].FIELD
,
1866 if (!pw
->p
[i
].FIELD
)
1878 /* Divide the pieces of "pw" by "v" and return the result.
1880 __isl_give PW
*FN(PW
,scale_down_val
)(__isl_take PW
*pw
, __isl_take isl_val
*v
)
1887 if (isl_val_is_one(v
)) {
1892 if (!isl_val_is_rat(v
))
1893 isl_die(isl_val_get_ctx(v
), isl_error_invalid
,
1894 "expecting rational factor", goto error
);
1895 if (isl_val_is_zero(v
))
1896 isl_die(isl_val_get_ctx(v
), isl_error_invalid
,
1897 "cannot scale down by zero", goto error
);
1903 pw
= FN(PW
,cow
)(pw
);
1908 if (isl_val_is_neg(v
))
1909 pw
->type
= isl_fold_type_negate(pw
->type
);
1911 for (i
= 0; i
< pw
->n
; ++i
) {
1912 pw
->p
[i
].FIELD
= FN(EL
,scale_down_val
)(pw
->p
[i
].FIELD
,
1914 if (!pw
->p
[i
].FIELD
)
1926 __isl_give PW
*FN(PW
,scale
)(__isl_take PW
*pw
, isl_int v
)
1928 return FN(PW
,mul_isl_int
)(pw
, v
);
1931 /* Apply some normalization to "pw".
1932 * In particular, sort the pieces according to their function value
1933 * expressions, combining pairs of adjacent pieces with
1934 * the same such expression, and then normalize the domains of the pieces.
1936 * We normalize in place, but if anything goes wrong we need
1937 * to return NULL, so we need to make sure we don't change the
1938 * meaning of any possible other copies of "pw".
1940 __isl_give PW
*FN(PW
,normalize
)(__isl_take PW
*pw
)
1945 pw
= FN(PW
,sort
)(pw
);
1948 for (i
= 0; i
< pw
->n
; ++i
) {
1949 set
= isl_set_normalize(isl_set_copy(pw
->p
[i
].set
));
1951 return FN(PW
,free
)(pw
);
1952 isl_set_free(pw
->p
[i
].set
);
1959 /* Is pw1 obviously equal to pw2?
1960 * That is, do they have obviously identical cells and obviously identical
1961 * elements on each cell?
1963 isl_bool
FN(PW
,plain_is_equal
)(__isl_keep PW
*pw1
, __isl_keep PW
*pw2
)
1969 return isl_bool_error
;
1972 return isl_bool_true
;
1973 if (!isl_space_is_equal(pw1
->dim
, pw2
->dim
))
1974 return isl_bool_false
;
1976 pw1
= FN(PW
,copy
)(pw1
);
1977 pw2
= FN(PW
,copy
)(pw2
);
1978 pw1
= FN(PW
,normalize
)(pw1
);
1979 pw2
= FN(PW
,normalize
)(pw2
);
1983 equal
= pw1
->n
== pw2
->n
;
1984 for (i
= 0; equal
&& i
< pw1
->n
; ++i
) {
1985 equal
= isl_set_plain_is_equal(pw1
->p
[i
].set
, pw2
->p
[i
].set
);
1990 equal
= FN(EL
,plain_is_equal
)(pw1
->p
[i
].FIELD
, pw2
->p
[i
].FIELD
);
2001 return isl_bool_error
;
2005 static __isl_give PW
*FN(PW
,align_params_pw_multi_aff_and
)(__isl_take PW
*pw
,
2006 __isl_take isl_multi_aff
*ma
,
2007 __isl_give PW
*(*fn
)(__isl_take PW
*pw
, __isl_take isl_multi_aff
*ma
))
2010 isl_space
*ma_space
;
2012 ma_space
= isl_multi_aff_get_space(ma
);
2013 if (!pw
|| !ma
|| !ma_space
)
2015 if (isl_space_match(pw
->dim
, isl_dim_param
, ma_space
, isl_dim_param
)) {
2016 isl_space_free(ma_space
);
2019 ctx
= FN(PW
,get_ctx
)(pw
);
2020 if (!isl_space_has_named_params(pw
->dim
) ||
2021 !isl_space_has_named_params(ma_space
))
2022 isl_die(ctx
, isl_error_invalid
,
2023 "unaligned unnamed parameters", goto error
);
2024 pw
= FN(PW
,align_params
)(pw
, ma_space
);
2025 ma
= isl_multi_aff_align_params(ma
, FN(PW
,get_space
)(pw
));
2028 isl_space_free(ma_space
);
2030 isl_multi_aff_free(ma
);
2034 static __isl_give PW
*FN(PW
,align_params_pw_pw_multi_aff_and
)(__isl_take PW
*pw
,
2035 __isl_take isl_pw_multi_aff
*pma
,
2036 __isl_give PW
*(*fn
)(__isl_take PW
*pw
,
2037 __isl_take isl_pw_multi_aff
*ma
))
2040 isl_space
*pma_space
;
2042 pma_space
= isl_pw_multi_aff_get_space(pma
);
2043 if (!pw
|| !pma
|| !pma_space
)
2045 if (isl_space_match(pw
->dim
, isl_dim_param
, pma_space
, isl_dim_param
)) {
2046 isl_space_free(pma_space
);
2049 ctx
= FN(PW
,get_ctx
)(pw
);
2050 if (!isl_space_has_named_params(pw
->dim
) ||
2051 !isl_space_has_named_params(pma_space
))
2052 isl_die(ctx
, isl_error_invalid
,
2053 "unaligned unnamed parameters", goto error
);
2054 pw
= FN(PW
,align_params
)(pw
, pma_space
);
2055 pma
= isl_pw_multi_aff_align_params(pma
, FN(PW
,get_space
)(pw
));
2058 isl_space_free(pma_space
);
2060 isl_pw_multi_aff_free(pma
);
2064 /* Compute the pullback of "pw" by the function represented by "ma".
2065 * In other words, plug in "ma" in "pw".
2067 static __isl_give PW
*FN(PW
,pullback_multi_aff_aligned
)(__isl_take PW
*pw
,
2068 __isl_take isl_multi_aff
*ma
)
2071 isl_space
*space
= NULL
;
2073 ma
= isl_multi_aff_align_divs(ma
);
2074 pw
= FN(PW
,cow
)(pw
);
2078 space
= isl_space_join(isl_multi_aff_get_space(ma
),
2079 FN(PW
,get_space
)(pw
));
2081 for (i
= 0; i
< pw
->n
; ++i
) {
2082 pw
->p
[i
].set
= isl_set_preimage_multi_aff(pw
->p
[i
].set
,
2083 isl_multi_aff_copy(ma
));
2086 pw
->p
[i
].FIELD
= FN(EL
,pullback_multi_aff
)(pw
->p
[i
].FIELD
,
2087 isl_multi_aff_copy(ma
));
2088 if (!pw
->p
[i
].FIELD
)
2092 pw
= FN(PW
,reset_space
)(pw
, space
);
2093 isl_multi_aff_free(ma
);
2096 isl_space_free(space
);
2097 isl_multi_aff_free(ma
);
2102 __isl_give PW
*FN(PW
,pullback_multi_aff
)(__isl_take PW
*pw
,
2103 __isl_take isl_multi_aff
*ma
)
2105 return FN(PW
,align_params_pw_multi_aff_and
)(pw
, ma
,
2106 &FN(PW
,pullback_multi_aff_aligned
));
2109 /* Compute the pullback of "pw" by the function represented by "pma".
2110 * In other words, plug in "pma" in "pw".
2112 static __isl_give PW
*FN(PW
,pullback_pw_multi_aff_aligned
)(__isl_take PW
*pw
,
2113 __isl_take isl_pw_multi_aff
*pma
)
2123 space
= isl_space_join(isl_pw_multi_aff_get_space(pma
),
2124 FN(PW
,get_space
)(pw
));
2125 isl_pw_multi_aff_free(pma
);
2126 res
= FN(PW
,empty
)(space
);
2131 res
= FN(PW
,pullback_multi_aff
)(FN(PW
,copy
)(pw
),
2132 isl_multi_aff_copy(pma
->p
[0].maff
));
2133 res
= FN(PW
,intersect_domain
)(res
, isl_set_copy(pma
->p
[0].set
));
2135 for (i
= 1; i
< pma
->n
; ++i
) {
2138 res_i
= FN(PW
,pullback_multi_aff
)(FN(PW
,copy
)(pw
),
2139 isl_multi_aff_copy(pma
->p
[i
].maff
));
2140 res_i
= FN(PW
,intersect_domain
)(res_i
,
2141 isl_set_copy(pma
->p
[i
].set
));
2142 res
= FN(PW
,add_disjoint
)(res
, res_i
);
2145 isl_pw_multi_aff_free(pma
);
2149 isl_pw_multi_aff_free(pma
);
2154 __isl_give PW
*FN(PW
,pullback_pw_multi_aff
)(__isl_take PW
*pw
,
2155 __isl_take isl_pw_multi_aff
*pma
)
2157 return FN(PW
,align_params_pw_pw_multi_aff_and
)(pw
, pma
,
2158 &FN(PW
,pullback_pw_multi_aff_aligned
));