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
15 #include <isl_val_private.h>
17 #define xFN(TYPE,NAME) TYPE ## _ ## NAME
18 #define FN(TYPE,NAME) xFN(TYPE,NAME)
19 #define xS(TYPE,NAME) struct TYPE ## _ ## NAME
20 #define S(TYPE,NAME) xS(TYPE,NAME)
23 __isl_give PW
*FN(PW
,alloc_size
)(__isl_take isl_space
*dim
,
24 enum isl_fold type
, int n
)
26 __isl_give PW
*FN(PW
,alloc_size
)(__isl_take isl_space
*dim
, int n
)
34 ctx
= isl_space_get_ctx(dim
);
35 isl_assert(ctx
, n
>= 0, goto error
);
36 pw
= isl_alloc(ctx
, struct PW
,
37 sizeof(struct PW
) + (n
- 1) * sizeof(S(PW
,piece
)));
55 __isl_give PW
*FN(PW
,ZERO
)(__isl_take isl_space
*dim
, enum isl_fold type
)
57 return FN(PW
,alloc_size
)(dim
, type
, 0);
60 __isl_give PW
*FN(PW
,ZERO
)(__isl_take isl_space
*dim
)
62 return FN(PW
,alloc_size
)(dim
, 0);
66 __isl_give PW
*FN(PW
,add_piece
)(__isl_take PW
*pw
,
67 __isl_take isl_set
*set
, __isl_take EL
*el
)
70 isl_space
*el_dim
= NULL
;
72 if (!pw
|| !set
|| !el
)
75 if (isl_set_plain_is_empty(set
) || FN(EL
,EL_IS_ZERO
)(el
)) {
81 ctx
= isl_set_get_ctx(set
);
83 if (pw
->type
!= el
->type
)
84 isl_die(ctx
, isl_error_invalid
, "fold types don't match",
87 el_dim
= FN(EL
,get_space(el
));
88 isl_assert(ctx
, isl_space_is_equal(pw
->dim
, el_dim
), goto error
);
89 isl_assert(ctx
, pw
->n
< pw
->size
, goto error
);
91 pw
->p
[pw
->n
].set
= set
;
92 pw
->p
[pw
->n
].FIELD
= el
;
95 isl_space_free(el_dim
);
98 isl_space_free(el_dim
);
106 __isl_give PW
*FN(PW
,alloc
)(enum isl_fold type
,
107 __isl_take isl_set
*set
, __isl_take EL
*el
)
109 __isl_give PW
*FN(PW
,alloc
)(__isl_take isl_set
*set
, __isl_take EL
*el
)
118 pw
= FN(PW
,alloc_size
)(FN(EL
,get_space
)(el
), type
, 1);
120 pw
= FN(PW
,alloc_size
)(FN(EL
,get_space
)(el
), 1);
123 return FN(PW
,add_piece
)(pw
, set
, el
);
130 __isl_give PW
*FN(PW
,dup
)(__isl_keep PW
*pw
)
139 dup
= FN(PW
,alloc_size
)(isl_space_copy(pw
->dim
), pw
->type
, pw
->n
);
141 dup
= FN(PW
,alloc_size
)(isl_space_copy(pw
->dim
), pw
->n
);
146 for (i
= 0; i
< pw
->n
; ++i
)
147 dup
= FN(PW
,add_piece
)(dup
, isl_set_copy(pw
->p
[i
].set
),
148 FN(EL
,copy
)(pw
->p
[i
].FIELD
));
153 __isl_give PW
*FN(PW
,cow
)(__isl_take PW
*pw
)
161 return FN(PW
,dup
)(pw
);
164 __isl_give PW
*FN(PW
,copy
)(__isl_keep PW
*pw
)
173 __isl_null PW
*FN(PW
,free
)(__isl_take PW
*pw
)
182 for (i
= 0; i
< pw
->n
; ++i
) {
183 isl_set_free(pw
->p
[i
].set
);
184 FN(EL
,free
)(pw
->p
[i
].FIELD
);
186 isl_space_free(pw
->dim
);
192 const char *FN(PW
,get_dim_name
)(__isl_keep PW
*pw
, enum isl_dim_type type
,
195 return pw
? isl_space_get_dim_name(pw
->dim
, type
, pos
) : NULL
;
198 isl_bool
FN(PW
,has_dim_id
)(__isl_keep PW
*pw
, enum isl_dim_type type
,
201 return pw
? isl_space_has_dim_id(pw
->dim
, type
, pos
) : isl_bool_error
;
204 __isl_give isl_id
*FN(PW
,get_dim_id
)(__isl_keep PW
*pw
, enum isl_dim_type type
,
207 return pw
? isl_space_get_dim_id(pw
->dim
, type
, pos
) : NULL
;
210 isl_bool
FN(PW
,has_tuple_name
)(__isl_keep PW
*pw
, enum isl_dim_type type
)
212 return pw
? isl_space_has_tuple_name(pw
->dim
, type
) : isl_bool_error
;
215 const char *FN(PW
,get_tuple_name
)(__isl_keep PW
*pw
, enum isl_dim_type type
)
217 return pw
? isl_space_get_tuple_name(pw
->dim
, type
) : NULL
;
220 isl_bool
FN(PW
,has_tuple_id
)(__isl_keep PW
*pw
, enum isl_dim_type type
)
222 return pw
? isl_space_has_tuple_id(pw
->dim
, type
) : isl_bool_error
;
225 __isl_give isl_id
*FN(PW
,get_tuple_id
)(__isl_keep PW
*pw
, enum isl_dim_type type
)
227 return pw
? isl_space_get_tuple_id(pw
->dim
, type
) : NULL
;
230 isl_bool
FN(PW
,IS_ZERO
)(__isl_keep PW
*pw
)
233 return isl_bool_error
;
239 __isl_give PW
*FN(PW
,realign_domain
)(__isl_take PW
*pw
,
240 __isl_take isl_reordering
*exp
)
248 for (i
= 0; i
< pw
->n
; ++i
) {
249 pw
->p
[i
].set
= isl_set_realign(pw
->p
[i
].set
,
250 isl_reordering_copy(exp
));
253 pw
->p
[i
].FIELD
= FN(EL
,realign_domain
)(pw
->p
[i
].FIELD
,
254 isl_reordering_copy(exp
));
259 pw
= FN(PW
,reset_domain_space
)(pw
, isl_space_copy(exp
->dim
));
261 isl_reordering_free(exp
);
264 isl_reordering_free(exp
);
269 /* Align the parameters of "pw" to those of "model".
271 __isl_give PW
*FN(PW
,align_params
)(__isl_take PW
*pw
, __isl_take isl_space
*model
)
278 ctx
= isl_space_get_ctx(model
);
279 if (!isl_space_has_named_params(model
))
280 isl_die(ctx
, isl_error_invalid
,
281 "model has unnamed parameters", goto error
);
282 if (!isl_space_has_named_params(pw
->dim
))
283 isl_die(ctx
, isl_error_invalid
,
284 "input has unnamed parameters", goto error
);
285 if (!isl_space_match(pw
->dim
, isl_dim_param
, model
, isl_dim_param
)) {
288 model
= isl_space_drop_dims(model
, isl_dim_in
,
289 0, isl_space_dim(model
, isl_dim_in
));
290 model
= isl_space_drop_dims(model
, isl_dim_out
,
291 0, isl_space_dim(model
, isl_dim_out
));
292 exp
= isl_parameter_alignment_reordering(pw
->dim
, model
);
293 exp
= isl_reordering_extend_space(exp
,
294 FN(PW
,get_domain_space
)(pw
));
295 pw
= FN(PW
,realign_domain
)(pw
, exp
);
298 isl_space_free(model
);
301 isl_space_free(model
);
306 static __isl_give PW
*FN(PW
,align_params_pw_pw_and
)(__isl_take PW
*pw1
,
308 __isl_give PW
*(*fn
)(__isl_take PW
*pw1
, __isl_take PW
*pw2
))
314 if (isl_space_match(pw1
->dim
, isl_dim_param
, pw2
->dim
, isl_dim_param
))
316 ctx
= FN(PW
,get_ctx
)(pw1
);
317 if (!isl_space_has_named_params(pw1
->dim
) ||
318 !isl_space_has_named_params(pw2
->dim
))
319 isl_die(ctx
, isl_error_invalid
,
320 "unaligned unnamed parameters", goto error
);
321 pw1
= FN(PW
,align_params
)(pw1
, FN(PW
,get_space
)(pw2
));
322 pw2
= FN(PW
,align_params
)(pw2
, FN(PW
,get_space
)(pw1
));
330 static __isl_give PW
*FN(PW
,align_params_pw_set_and
)(__isl_take PW
*pw
,
331 __isl_take isl_set
*set
,
332 __isl_give PW
*(*fn
)(__isl_take PW
*pw
, __isl_take isl_set
*set
))
338 if (isl_space_match(pw
->dim
, isl_dim_param
, set
->dim
, isl_dim_param
))
340 ctx
= FN(PW
,get_ctx
)(pw
);
341 if (!isl_space_has_named_params(pw
->dim
) ||
342 !isl_space_has_named_params(set
->dim
))
343 isl_die(ctx
, isl_error_invalid
,
344 "unaligned unnamed parameters", goto error
);
345 pw
= FN(PW
,align_params
)(pw
, isl_set_get_space(set
));
346 set
= isl_set_align_params(set
, FN(PW
,get_space
)(pw
));
355 static __isl_give PW
*FN(PW
,union_add_aligned
)(__isl_take PW
*pw1
,
366 ctx
= isl_space_get_ctx(pw1
->dim
);
368 if (pw1
->type
!= pw2
->type
)
369 isl_die(ctx
, isl_error_invalid
,
370 "fold types don't match", goto error
);
372 isl_assert(ctx
, isl_space_is_equal(pw1
->dim
, pw2
->dim
), goto error
);
374 if (FN(PW
,IS_ZERO
)(pw1
)) {
379 if (FN(PW
,IS_ZERO
)(pw2
)) {
384 n
= (pw1
->n
+ 1) * (pw2
->n
+ 1);
386 res
= FN(PW
,alloc_size
)(isl_space_copy(pw1
->dim
), pw1
->type
, n
);
388 res
= FN(PW
,alloc_size
)(isl_space_copy(pw1
->dim
), n
);
391 for (i
= 0; i
< pw1
->n
; ++i
) {
392 set
= isl_set_copy(pw1
->p
[i
].set
);
393 for (j
= 0; j
< pw2
->n
; ++j
) {
394 struct isl_set
*common
;
396 common
= isl_set_intersect(isl_set_copy(pw1
->p
[i
].set
),
397 isl_set_copy(pw2
->p
[j
].set
));
398 if (isl_set_plain_is_empty(common
)) {
399 isl_set_free(common
);
402 set
= isl_set_subtract(set
,
403 isl_set_copy(pw2
->p
[j
].set
));
405 sum
= FN(EL
,add_on_domain
)(common
,
406 FN(EL
,copy
)(pw1
->p
[i
].FIELD
),
407 FN(EL
,copy
)(pw2
->p
[j
].FIELD
));
409 res
= FN(PW
,add_piece
)(res
, common
, sum
);
411 res
= FN(PW
,add_piece
)(res
, set
, FN(EL
,copy
)(pw1
->p
[i
].FIELD
));
414 for (j
= 0; j
< pw2
->n
; ++j
) {
415 set
= isl_set_copy(pw2
->p
[j
].set
);
416 for (i
= 0; i
< pw1
->n
; ++i
)
417 set
= isl_set_subtract(set
,
418 isl_set_copy(pw1
->p
[i
].set
));
419 res
= FN(PW
,add_piece
)(res
, set
, FN(EL
,copy
)(pw2
->p
[j
].FIELD
));
432 /* Private version of "union_add". For isl_pw_qpolynomial and
433 * isl_pw_qpolynomial_fold, we prefer to simply call it "add".
435 static __isl_give PW
*FN(PW
,union_add_
)(__isl_take PW
*pw1
, __isl_take PW
*pw2
)
437 return FN(PW
,align_params_pw_pw_and
)(pw1
, pw2
,
438 &FN(PW
,union_add_aligned
));
441 /* Make sure "pw" has room for at least "n" more pieces.
443 * If there is only one reference to pw, we extend it in place.
444 * Otherwise, we create a new PW and copy the pieces.
446 static __isl_give PW
*FN(PW
,grow
)(__isl_take PW
*pw
, int n
)
454 if (pw
->n
+ n
<= pw
->size
)
456 ctx
= FN(PW
,get_ctx
)(pw
);
459 res
= isl_realloc(ctx
, pw
, struct PW
,
460 sizeof(struct PW
) + (n
- 1) * sizeof(S(PW
,piece
)));
462 return FN(PW
,free
)(pw
);
467 res
= FN(PW
,alloc_size
)(isl_space_copy(pw
->dim
), pw
->type
, n
);
469 res
= FN(PW
,alloc_size
)(isl_space_copy(pw
->dim
), n
);
472 return FN(PW
,free
)(pw
);
473 for (i
= 0; i
< pw
->n
; ++i
)
474 res
= FN(PW
,add_piece
)(res
, isl_set_copy(pw
->p
[i
].set
),
475 FN(EL
,copy
)(pw
->p
[i
].FIELD
));
480 static __isl_give PW
*FN(PW
,add_disjoint_aligned
)(__isl_take PW
*pw1
,
489 if (pw1
->size
< pw1
->n
+ pw2
->n
&& pw1
->n
< pw2
->n
)
490 return FN(PW
,add_disjoint_aligned
)(pw2
, pw1
);
492 ctx
= isl_space_get_ctx(pw1
->dim
);
494 if (pw1
->type
!= pw2
->type
)
495 isl_die(ctx
, isl_error_invalid
,
496 "fold types don't match", goto error
);
498 isl_assert(ctx
, isl_space_is_equal(pw1
->dim
, pw2
->dim
), goto error
);
500 if (FN(PW
,IS_ZERO
)(pw1
)) {
505 if (FN(PW
,IS_ZERO
)(pw2
)) {
510 pw1
= FN(PW
,grow
)(pw1
, pw2
->n
);
514 for (i
= 0; i
< pw2
->n
; ++i
)
515 pw1
= FN(PW
,add_piece
)(pw1
,
516 isl_set_copy(pw2
->p
[i
].set
),
517 FN(EL
,copy
)(pw2
->p
[i
].FIELD
));
528 __isl_give PW
*FN(PW
,add_disjoint
)(__isl_take PW
*pw1
, __isl_take PW
*pw2
)
530 return FN(PW
,align_params_pw_pw_and
)(pw1
, pw2
,
531 &FN(PW
,add_disjoint_aligned
));
534 /* This function is currently only used from isl_aff.c
536 static __isl_give PW
*FN(PW
,on_shared_domain_in
)(__isl_take PW
*pw1
,
537 __isl_take PW
*pw2
, __isl_take isl_space
*space
,
538 __isl_give EL
*(*fn
)(__isl_take EL
*el1
, __isl_take EL
*el2
))
539 __attribute__ ((unused
));
541 /* Apply "fn" to pairs of elements from pw1 and pw2 on shared domains.
542 * The result of "fn" (and therefore also of this function) lives in "space".
544 static __isl_give PW
*FN(PW
,on_shared_domain_in
)(__isl_take PW
*pw1
,
545 __isl_take PW
*pw2
, __isl_take isl_space
*space
,
546 __isl_give EL
*(*fn
)(__isl_take EL
*el1
, __isl_take EL
*el2
))
556 res
= FN(PW
,alloc_size
)(isl_space_copy(space
), pw1
->type
, n
);
558 res
= FN(PW
,alloc_size
)(isl_space_copy(space
), n
);
561 for (i
= 0; i
< pw1
->n
; ++i
) {
562 for (j
= 0; j
< pw2
->n
; ++j
) {
567 common
= isl_set_intersect(
568 isl_set_copy(pw1
->p
[i
].set
),
569 isl_set_copy(pw2
->p
[j
].set
));
570 empty
= isl_set_plain_is_empty(common
);
571 if (empty
< 0 || empty
) {
572 isl_set_free(common
);
578 res_ij
= fn(FN(EL
,copy
)(pw1
->p
[i
].FIELD
),
579 FN(EL
,copy
)(pw2
->p
[j
].FIELD
));
580 res_ij
= FN(EL
,gist
)(res_ij
, isl_set_copy(common
));
582 res
= FN(PW
,add_piece
)(res
, common
, res_ij
);
586 isl_space_free(space
);
591 isl_space_free(space
);
598 /* This function is currently only used from isl_aff.c
600 static __isl_give PW
*FN(PW
,on_shared_domain
)(__isl_take PW
*pw1
,
602 __isl_give EL
*(*fn
)(__isl_take EL
*el1
, __isl_take EL
*el2
))
603 __attribute__ ((unused
));
605 /* Apply "fn" to pairs of elements from pw1 and pw2 on shared domains.
606 * The result of "fn" is assumed to live in the same space as "pw1" and "pw2".
608 static __isl_give PW
*FN(PW
,on_shared_domain
)(__isl_take PW
*pw1
,
610 __isl_give EL
*(*fn
)(__isl_take EL
*el1
, __isl_take EL
*el2
))
617 space
= isl_space_copy(pw1
->dim
);
618 return FN(PW
,on_shared_domain_in
)(pw1
, pw2
, space
, fn
);
626 __isl_give PW
*FN(PW
,neg
)(__isl_take PW
*pw
)
633 if (FN(PW
,IS_ZERO
)(pw
))
640 for (i
= 0; i
< pw
->n
; ++i
) {
641 pw
->p
[i
].FIELD
= FN(EL
,neg
)(pw
->p
[i
].FIELD
);
643 return FN(PW
,free
)(pw
);
651 __isl_give PW
*FN(PW
,sub
)(__isl_take PW
*pw1
, __isl_take PW
*pw2
)
653 return FN(PW
,add
)(pw1
, FN(PW
,neg
)(pw2
));
658 __isl_give isl_val
*FN(PW
,eval
)(__isl_take PW
*pw
, __isl_take isl_point
*pnt
)
663 isl_space
*pnt_dim
= NULL
;
668 ctx
= isl_point_get_ctx(pnt
);
669 pnt_dim
= isl_point_get_space(pnt
);
670 isl_assert(ctx
, isl_space_is_domain_internal(pnt_dim
, pw
->dim
),
673 for (i
= 0; i
< pw
->n
; ++i
) {
674 found
= isl_set_contains_point(pw
->p
[i
].set
, pnt
);
681 v
= FN(EL
,eval
)(FN(EL
,copy
)(pw
->p
[i
].FIELD
),
682 isl_point_copy(pnt
));
684 v
= isl_val_zero(ctx
);
686 isl_space_free(pnt_dim
);
691 isl_space_free(pnt_dim
);
697 /* Return the parameter domain of "pw".
699 __isl_give isl_set
*FN(PW
,params
)(__isl_take PW
*pw
)
701 return isl_set_params(FN(PW
,domain
)(pw
));
704 __isl_give isl_set
*FN(PW
,domain
)(__isl_take PW
*pw
)
712 dom
= isl_set_empty(FN(PW
,get_domain_space
)(pw
));
713 for (i
= 0; i
< pw
->n
; ++i
)
714 dom
= isl_set_union_disjoint(dom
, isl_set_copy(pw
->p
[i
].set
));
721 /* Exploit the equalities in the domain of piece "i" of "pw"
722 * to simplify the associated function.
723 * If the domain of piece "i" is empty, then remove it entirely,
724 * replacing it with the final piece.
726 static int FN(PW
,exploit_equalities_and_remove_if_empty
)(__isl_keep PW
*pw
,
730 int empty
= isl_set_plain_is_empty(pw
->p
[i
].set
);
735 isl_set_free(pw
->p
[i
].set
);
736 FN(EL
,free
)(pw
->p
[i
].FIELD
);
738 pw
->p
[i
] = pw
->p
[pw
->n
- 1];
744 aff
= isl_set_affine_hull(isl_set_copy(pw
->p
[i
].set
));
745 pw
->p
[i
].FIELD
= FN(EL
,substitute_equalities
)(pw
->p
[i
].FIELD
, aff
);
752 /* Convert a piecewise expression defined over a parameter domain
753 * into one that is defined over a zero-dimensional set.
755 __isl_give PW
*FN(PW
,from_range
)(__isl_take PW
*pw
)
761 if (!isl_space_is_set(pw
->dim
))
762 isl_die(FN(PW
,get_ctx
)(pw
), isl_error_invalid
,
763 "not living in a set space", return FN(PW
,free
)(pw
));
765 space
= FN(PW
,get_space
)(pw
);
766 space
= isl_space_from_range(space
);
767 pw
= FN(PW
,reset_space
)(pw
, space
);
772 /* Fix the value of the given parameter or domain dimension of "pw"
773 * to be equal to "value".
775 __isl_give PW
*FN(PW
,fix_si
)(__isl_take PW
*pw
, enum isl_dim_type type
,
776 unsigned pos
, int value
)
783 if (type
== isl_dim_out
)
784 isl_die(FN(PW
,get_ctx
)(pw
), isl_error_invalid
,
785 "cannot fix output dimension", return FN(PW
,free
)(pw
));
790 if (type
== isl_dim_in
)
795 return FN(PW
,free
)(pw
);
797 for (i
= pw
->n
- 1; i
>= 0; --i
) {
798 pw
->p
[i
].set
= isl_set_fix_si(pw
->p
[i
].set
, type
, pos
, value
);
799 if (FN(PW
,exploit_equalities_and_remove_if_empty
)(pw
, i
) < 0)
800 return FN(PW
,free
)(pw
);
806 /* Restrict the domain of "pw" by combining each cell
807 * with "set" through a call to "fn", where "fn" may be
808 * isl_set_intersect, isl_set_intersect_params or isl_set_subtract.
810 static __isl_give PW
*FN(PW
,restrict_domain_aligned
)(__isl_take PW
*pw
,
811 __isl_take isl_set
*set
,
812 __isl_give isl_set
*(*fn
)(__isl_take isl_set
*set1
,
813 __isl_take isl_set
*set2
))
829 for (i
= pw
->n
- 1; i
>= 0; --i
) {
830 pw
->p
[i
].set
= fn(pw
->p
[i
].set
, isl_set_copy(set
));
831 if (FN(PW
,exploit_equalities_and_remove_if_empty
)(pw
, i
) < 0)
843 static __isl_give PW
*FN(PW
,intersect_domain_aligned
)(__isl_take PW
*pw
,
844 __isl_take isl_set
*set
)
846 return FN(PW
,restrict_domain_aligned
)(pw
, set
, &isl_set_intersect
);
849 __isl_give PW
*FN(PW
,intersect_domain
)(__isl_take PW
*pw
,
850 __isl_take isl_set
*context
)
852 return FN(PW
,align_params_pw_set_and
)(pw
, context
,
853 &FN(PW
,intersect_domain_aligned
));
856 static __isl_give PW
*FN(PW
,intersect_params_aligned
)(__isl_take PW
*pw
,
857 __isl_take isl_set
*set
)
859 return FN(PW
,restrict_domain_aligned
)(pw
, set
,
860 &isl_set_intersect_params
);
863 /* Intersect the domain of "pw" with the parameter domain "context".
865 __isl_give PW
*FN(PW
,intersect_params
)(__isl_take PW
*pw
,
866 __isl_take isl_set
*context
)
868 return FN(PW
,align_params_pw_set_and
)(pw
, context
,
869 &FN(PW
,intersect_params_aligned
));
872 /* Subtract "domain' from the domain of "pw", assuming their
873 * parameters have been aligned.
875 static __isl_give PW
*FN(PW
,subtract_domain_aligned
)(__isl_take PW
*pw
,
876 __isl_take isl_set
*domain
)
878 return FN(PW
,restrict_domain_aligned
)(pw
, domain
, &isl_set_subtract
);
881 /* Subtract "domain' from the domain of "pw".
883 __isl_give PW
*FN(PW
,subtract_domain
)(__isl_take PW
*pw
,
884 __isl_take isl_set
*domain
)
886 return FN(PW
,align_params_pw_set_and
)(pw
, domain
,
887 &FN(PW
,subtract_domain_aligned
));
890 /* Compute the gist of "pw" with respect to the domain constraints
891 * of "context" for the case where the domain of the last element
892 * of "pw" is equal to "context".
893 * Call "fn_el" to compute the gist of this element, replace
894 * its domain by the universe and drop all other elements
895 * as their domains are necessarily disjoint from "context".
897 static __isl_give PW
*FN(PW
,gist_last
)(__isl_take PW
*pw
,
898 __isl_take isl_set
*context
,
899 __isl_give EL
*(*fn_el
)(__isl_take EL
*el
, __isl_take isl_set
*set
))
904 for (i
= 0; i
< pw
->n
- 1; ++i
) {
905 isl_set_free(pw
->p
[i
].set
);
906 FN(EL
,free
)(pw
->p
[i
].FIELD
);
908 pw
->p
[0].FIELD
= pw
->p
[pw
->n
- 1].FIELD
;
909 pw
->p
[0].set
= pw
->p
[pw
->n
- 1].set
;
912 space
= isl_set_get_space(context
);
913 pw
->p
[0].FIELD
= fn_el(pw
->p
[0].FIELD
, context
);
914 context
= isl_set_universe(space
);
915 isl_set_free(pw
->p
[0].set
);
916 pw
->p
[0].set
= context
;
918 if (!pw
->p
[0].FIELD
|| !pw
->p
[0].set
)
919 return FN(PW
,free
)(pw
);
924 /* Compute the gist of "pw" with respect to the domain constraints
925 * of "context". Call "fn_el" to compute the gist of the elements
926 * and "fn_dom" to compute the gist of the domains.
928 * If the piecewise expression is empty or the context is the universe,
929 * then nothing can be simplified.
931 static __isl_give PW
*FN(PW
,gist_aligned
)(__isl_take PW
*pw
,
932 __isl_take isl_set
*context
,
933 __isl_give EL
*(*fn_el
)(__isl_take EL
*el
,
934 __isl_take isl_set
*set
),
935 __isl_give isl_set
*(*fn_dom
)(__isl_take isl_set
*set
,
936 __isl_take isl_basic_set
*bset
))
940 isl_basic_set
*hull
= NULL
;
946 isl_set_free(context
);
950 is_universe
= isl_set_plain_is_universe(context
);
954 isl_set_free(context
);
958 if (!isl_space_match(pw
->dim
, isl_dim_param
,
959 context
->dim
, isl_dim_param
)) {
960 pw
= FN(PW
,align_params
)(pw
, isl_set_get_space(context
));
961 context
= isl_set_align_params(context
, FN(PW
,get_space
)(pw
));
971 equal
= isl_set_plain_is_equal(pw
->p
[0].set
, context
);
975 return FN(PW
,gist_last
)(pw
, context
, fn_el
);
978 context
= isl_set_compute_divs(context
);
979 hull
= isl_set_simple_hull(isl_set_copy(context
));
981 for (i
= pw
->n
- 1; i
>= 0; --i
) {
985 if (i
== pw
->n
- 1) {
987 equal
= isl_set_plain_is_equal(pw
->p
[i
].set
, context
);
991 isl_basic_set_free(hull
);
992 return FN(PW
,gist_last
)(pw
, context
, fn_el
);
995 set_i
= isl_set_intersect(isl_set_copy(pw
->p
[i
].set
),
996 isl_set_copy(context
));
997 empty
= isl_set_plain_is_empty(set_i
);
998 pw
->p
[i
].FIELD
= fn_el(pw
->p
[i
].FIELD
, set_i
);
999 pw
->p
[i
].set
= fn_dom(pw
->p
[i
].set
, isl_basic_set_copy(hull
));
1000 if (empty
< 0 || !pw
->p
[i
].FIELD
|| !pw
->p
[i
].set
)
1003 isl_set_free(pw
->p
[i
].set
);
1004 FN(EL
,free
)(pw
->p
[i
].FIELD
);
1006 pw
->p
[i
] = pw
->p
[pw
->n
- 1];
1011 isl_basic_set_free(hull
);
1012 isl_set_free(context
);
1017 isl_basic_set_free(hull
);
1018 isl_set_free(context
);
1022 static __isl_give PW
*FN(PW
,gist_domain_aligned
)(__isl_take PW
*pw
,
1023 __isl_take isl_set
*set
)
1025 return FN(PW
,gist_aligned
)(pw
, set
, &FN(EL
,gist
),
1026 &isl_set_gist_basic_set
);
1029 __isl_give PW
*FN(PW
,gist
)(__isl_take PW
*pw
, __isl_take isl_set
*context
)
1031 return FN(PW
,align_params_pw_set_and
)(pw
, context
,
1032 &FN(PW
,gist_domain_aligned
));
1035 static __isl_give PW
*FN(PW
,gist_params_aligned
)(__isl_take PW
*pw
,
1036 __isl_take isl_set
*set
)
1038 return FN(PW
,gist_aligned
)(pw
, set
, &FN(EL
,gist_params
),
1039 &isl_set_gist_params_basic_set
);
1042 __isl_give PW
*FN(PW
,gist_params
)(__isl_take PW
*pw
,
1043 __isl_take isl_set
*context
)
1045 return FN(PW
,align_params_pw_set_and
)(pw
, context
,
1046 &FN(PW
,gist_params_aligned
));
1049 __isl_give PW
*FN(PW
,coalesce
)(__isl_take PW
*pw
)
1058 for (i
= pw
->n
- 1; i
>= 0; --i
) {
1059 for (j
= i
- 1; j
>= 0; --j
) {
1060 if (!FN(EL
,plain_is_equal
)(pw
->p
[i
].FIELD
,
1063 pw
->p
[j
].set
= isl_set_union(pw
->p
[j
].set
,
1065 FN(EL
,free
)(pw
->p
[i
].FIELD
);
1067 pw
->p
[i
] = pw
->p
[pw
->n
- 1];
1073 pw
->p
[i
].set
= isl_set_coalesce(pw
->p
[i
].set
);
1084 isl_ctx
*FN(PW
,get_ctx
)(__isl_keep PW
*pw
)
1086 return pw
? isl_space_get_ctx(pw
->dim
) : NULL
;
1089 #ifndef NO_INVOLVES_DIMS
1090 isl_bool
FN(PW
,involves_dims
)(__isl_keep PW
*pw
, enum isl_dim_type type
,
1091 unsigned first
, unsigned n
)
1094 enum isl_dim_type set_type
;
1097 return isl_bool_error
;
1098 if (pw
->n
== 0 || n
== 0)
1099 return isl_bool_false
;
1101 set_type
= type
== isl_dim_in
? isl_dim_set
: type
;
1103 for (i
= 0; i
< pw
->n
; ++i
) {
1104 isl_bool involves
= FN(EL
,involves_dims
)(pw
->p
[i
].FIELD
,
1106 if (involves
< 0 || involves
)
1108 involves
= isl_set_involves_dims(pw
->p
[i
].set
,
1109 set_type
, first
, n
);
1110 if (involves
< 0 || involves
)
1113 return isl_bool_false
;
1117 __isl_give PW
*FN(PW
,set_dim_name
)(__isl_take PW
*pw
,
1118 enum isl_dim_type type
, unsigned pos
, const char *s
)
1121 enum isl_dim_type set_type
;
1123 pw
= FN(PW
,cow
)(pw
);
1127 set_type
= type
== isl_dim_in
? isl_dim_set
: type
;
1129 pw
->dim
= isl_space_set_dim_name(pw
->dim
, type
, pos
, s
);
1133 for (i
= 0; i
< pw
->n
; ++i
) {
1134 pw
->p
[i
].set
= isl_set_set_dim_name(pw
->p
[i
].set
,
1138 pw
->p
[i
].FIELD
= FN(EL
,set_dim_name
)(pw
->p
[i
].FIELD
, type
, pos
, s
);
1139 if (!pw
->p
[i
].FIELD
)
1149 #ifndef NO_DROP_DIMS
1150 __isl_give PW
*FN(PW
,drop_dims
)(__isl_take PW
*pw
,
1151 enum isl_dim_type type
, unsigned first
, unsigned n
)
1154 enum isl_dim_type set_type
;
1158 if (n
== 0 && !isl_space_get_tuple_name(pw
->dim
, type
))
1161 set_type
= type
== isl_dim_in
? isl_dim_set
: type
;
1163 pw
= FN(PW
,cow
)(pw
);
1166 pw
->dim
= isl_space_drop_dims(pw
->dim
, type
, first
, n
);
1169 for (i
= 0; i
< pw
->n
; ++i
) {
1170 pw
->p
[i
].FIELD
= FN(EL
,drop_dims
)(pw
->p
[i
].FIELD
, type
, first
, n
);
1171 if (!pw
->p
[i
].FIELD
)
1173 if (type
== isl_dim_out
)
1175 pw
->p
[i
].set
= isl_set_drop(pw
->p
[i
].set
, set_type
, first
, n
);
1186 /* This function is very similar to drop_dims.
1187 * The only difference is that the cells may still involve
1188 * the specified dimensions. They are removed using
1189 * isl_set_project_out instead of isl_set_drop.
1191 __isl_give PW
*FN(PW
,project_out
)(__isl_take PW
*pw
,
1192 enum isl_dim_type type
, unsigned first
, unsigned n
)
1195 enum isl_dim_type set_type
;
1199 if (n
== 0 && !isl_space_get_tuple_name(pw
->dim
, type
))
1202 set_type
= type
== isl_dim_in
? isl_dim_set
: type
;
1204 pw
= FN(PW
,cow
)(pw
);
1207 pw
->dim
= isl_space_drop_dims(pw
->dim
, type
, first
, n
);
1210 for (i
= 0; i
< pw
->n
; ++i
) {
1211 pw
->p
[i
].set
= isl_set_project_out(pw
->p
[i
].set
,
1212 set_type
, first
, n
);
1215 pw
->p
[i
].FIELD
= FN(EL
,drop_dims
)(pw
->p
[i
].FIELD
, type
, first
, n
);
1216 if (!pw
->p
[i
].FIELD
)
1226 /* Project the domain of pw onto its parameter space.
1228 __isl_give PW
*FN(PW
,project_domain_on_params
)(__isl_take PW
*pw
)
1233 n
= FN(PW
,dim
)(pw
, isl_dim_in
);
1234 pw
= FN(PW
,project_out
)(pw
, isl_dim_in
, 0, n
);
1235 space
= FN(PW
,get_domain_space
)(pw
);
1236 space
= isl_space_params(space
);
1237 pw
= FN(PW
,reset_domain_space
)(pw
, space
);
1242 #ifndef NO_INSERT_DIMS
1243 __isl_give PW
*FN(PW
,insert_dims
)(__isl_take PW
*pw
, enum isl_dim_type type
,
1244 unsigned first
, unsigned n
)
1247 enum isl_dim_type set_type
;
1251 if (n
== 0 && !isl_space_is_named_or_nested(pw
->dim
, type
))
1254 set_type
= type
== isl_dim_in
? isl_dim_set
: type
;
1256 pw
= FN(PW
,cow
)(pw
);
1260 pw
->dim
= isl_space_insert_dims(pw
->dim
, type
, first
, n
);
1264 for (i
= 0; i
< pw
->n
; ++i
) {
1265 pw
->p
[i
].set
= isl_set_insert_dims(pw
->p
[i
].set
,
1266 set_type
, first
, n
);
1269 pw
->p
[i
].FIELD
= FN(EL
,insert_dims
)(pw
->p
[i
].FIELD
,
1271 if (!pw
->p
[i
].FIELD
)
1282 __isl_give PW
*FN(PW
,fix_dim
)(__isl_take PW
*pw
,
1283 enum isl_dim_type type
, unsigned pos
, isl_int v
)
1290 if (type
== isl_dim_in
)
1293 pw
= FN(PW
,cow
)(pw
);
1296 for (i
= 0; i
< pw
->n
; ++i
) {
1297 pw
->p
[i
].set
= isl_set_fix(pw
->p
[i
].set
, type
, pos
, v
);
1298 if (FN(PW
,exploit_equalities_and_remove_if_empty
)(pw
, i
) < 0)
1299 return FN(PW
,free
)(pw
);
1305 /* Fix the value of the variable at position "pos" of type "type" of "pw"
1306 * to be equal to "v".
1308 __isl_give PW
*FN(PW
,fix_val
)(__isl_take PW
*pw
,
1309 enum isl_dim_type type
, unsigned pos
, __isl_take isl_val
*v
)
1312 return FN(PW
,free
)(pw
);
1313 if (!isl_val_is_int(v
))
1314 isl_die(FN(PW
,get_ctx
)(pw
), isl_error_invalid
,
1315 "expecting integer value", goto error
);
1317 pw
= FN(PW
,fix_dim
)(pw
, type
, pos
, v
->n
);
1323 return FN(PW
,free
)(pw
);
1326 unsigned FN(PW
,dim
)(__isl_keep PW
*pw
, enum isl_dim_type type
)
1328 return pw
? isl_space_dim(pw
->dim
, type
) : 0;
1331 __isl_give PW
*FN(PW
,split_dims
)(__isl_take PW
*pw
,
1332 enum isl_dim_type type
, unsigned first
, unsigned n
)
1341 if (type
== isl_dim_in
)
1344 pw
= FN(PW
,cow
)(pw
);
1349 for (i
= 0; i
< pw
->n
; ++i
) {
1350 pw
->p
[i
].set
= isl_set_split_dims(pw
->p
[i
].set
, type
, first
, n
);
1362 /* Compute the maximal value attained by the piecewise quasipolynomial
1363 * on its domain or zero if the domain is empty.
1364 * In the worst case, the domain is scanned completely,
1365 * so the domain is assumed to be bounded.
1367 __isl_give isl_val
*FN(PW
,opt
)(__isl_take PW
*pw
, int max
)
1376 opt
= isl_val_zero(FN(PW
,get_ctx
)(pw
));
1381 opt
= FN(EL
,opt_on_domain
)(FN(EL
,copy
)(pw
->p
[0].FIELD
),
1382 isl_set_copy(pw
->p
[0].set
), max
);
1383 for (i
= 1; i
< pw
->n
; ++i
) {
1385 opt_i
= FN(EL
,opt_on_domain
)(FN(EL
,copy
)(pw
->p
[i
].FIELD
),
1386 isl_set_copy(pw
->p
[i
].set
), max
);
1388 opt
= isl_val_max(opt
, opt_i
);
1390 opt
= isl_val_min(opt
, opt_i
);
1397 __isl_give isl_val
*FN(PW
,max
)(__isl_take PW
*pw
)
1399 return FN(PW
,opt
)(pw
, 1);
1402 __isl_give isl_val
*FN(PW
,min
)(__isl_take PW
*pw
)
1404 return FN(PW
,opt
)(pw
, 0);
1408 __isl_give isl_space
*FN(PW
,get_space
)(__isl_keep PW
*pw
)
1410 return pw
? isl_space_copy(pw
->dim
) : NULL
;
1413 __isl_give isl_space
*FN(PW
,get_domain_space
)(__isl_keep PW
*pw
)
1415 return pw
? isl_space_domain(isl_space_copy(pw
->dim
)) : NULL
;
1418 /* Return the position of the dimension of the given type and name
1420 * Return -1 if no such dimension can be found.
1422 int FN(PW
,find_dim_by_name
)(__isl_keep PW
*pw
,
1423 enum isl_dim_type type
, const char *name
)
1427 return isl_space_find_dim_by_name(pw
->dim
, type
, name
);
1430 #ifndef NO_RESET_DIM
1431 /* Reset the space of "pw". Since we don't know if the elements
1432 * represent the spaces themselves or their domains, we pass along
1433 * both when we call their reset_space_and_domain.
1435 static __isl_give PW
*FN(PW
,reset_space_and_domain
)(__isl_take PW
*pw
,
1436 __isl_take isl_space
*space
, __isl_take isl_space
*domain
)
1440 pw
= FN(PW
,cow
)(pw
);
1441 if (!pw
|| !space
|| !domain
)
1444 for (i
= 0; i
< pw
->n
; ++i
) {
1445 pw
->p
[i
].set
= isl_set_reset_space(pw
->p
[i
].set
,
1446 isl_space_copy(domain
));
1449 pw
->p
[i
].FIELD
= FN(EL
,reset_space_and_domain
)(pw
->p
[i
].FIELD
,
1450 isl_space_copy(space
), isl_space_copy(domain
));
1451 if (!pw
->p
[i
].FIELD
)
1455 isl_space_free(domain
);
1457 isl_space_free(pw
->dim
);
1462 isl_space_free(domain
);
1463 isl_space_free(space
);
1468 __isl_give PW
*FN(PW
,reset_domain_space
)(__isl_take PW
*pw
,
1469 __isl_take isl_space
*domain
)
1473 space
= isl_space_extend_domain_with_range(isl_space_copy(domain
),
1474 FN(PW
,get_space
)(pw
));
1475 return FN(PW
,reset_space_and_domain
)(pw
, space
, domain
);
1478 __isl_give PW
*FN(PW
,reset_space
)(__isl_take PW
*pw
, __isl_take isl_space
*dim
)
1482 domain
= isl_space_domain(isl_space_copy(dim
));
1483 return FN(PW
,reset_space_and_domain
)(pw
, dim
, domain
);
1486 __isl_give PW
*FN(PW
,set_tuple_id
)(__isl_take PW
*pw
, enum isl_dim_type type
,
1487 __isl_take isl_id
*id
)
1491 pw
= FN(PW
,cow
)(pw
);
1495 space
= FN(PW
,get_space
)(pw
);
1496 space
= isl_space_set_tuple_id(space
, type
, id
);
1498 return FN(PW
,reset_space
)(pw
, space
);
1501 return FN(PW
,free
)(pw
);
1504 /* Drop the id on the specified tuple.
1506 __isl_give PW
*FN(PW
,reset_tuple_id
)(__isl_take PW
*pw
, enum isl_dim_type type
)
1512 if (!FN(PW
,has_tuple_id
)(pw
, type
))
1515 pw
= FN(PW
,cow
)(pw
);
1519 space
= FN(PW
,get_space
)(pw
);
1520 space
= isl_space_reset_tuple_id(space
, type
);
1522 return FN(PW
,reset_space
)(pw
, space
);
1525 __isl_give PW
*FN(PW
,set_dim_id
)(__isl_take PW
*pw
,
1526 enum isl_dim_type type
, unsigned pos
, __isl_take isl_id
*id
)
1528 pw
= FN(PW
,cow
)(pw
);
1531 pw
->dim
= isl_space_set_dim_id(pw
->dim
, type
, pos
, id
);
1532 return FN(PW
,reset_space
)(pw
, isl_space_copy(pw
->dim
));
1535 return FN(PW
,free
)(pw
);
1539 /* Reset the user pointer on all identifiers of parameters and tuples
1540 * of the space of "pw".
1542 __isl_give PW
*FN(PW
,reset_user
)(__isl_take PW
*pw
)
1546 space
= FN(PW
,get_space
)(pw
);
1547 space
= isl_space_reset_user(space
);
1549 return FN(PW
,reset_space
)(pw
, space
);
1552 int FN(PW
,has_equal_space
)(__isl_keep PW
*pw1
, __isl_keep PW
*pw2
)
1557 return isl_space_is_equal(pw1
->dim
, pw2
->dim
);
1561 __isl_give PW
*FN(PW
,morph_domain
)(__isl_take PW
*pw
,
1562 __isl_take isl_morph
*morph
)
1570 ctx
= isl_space_get_ctx(pw
->dim
);
1571 isl_assert(ctx
, isl_space_is_domain_internal(morph
->dom
->dim
, pw
->dim
),
1574 pw
= FN(PW
,cow
)(pw
);
1577 pw
->dim
= isl_space_extend_domain_with_range(
1578 isl_space_copy(morph
->ran
->dim
), pw
->dim
);
1582 for (i
= 0; i
< pw
->n
; ++i
) {
1583 pw
->p
[i
].set
= isl_morph_set(isl_morph_copy(morph
), pw
->p
[i
].set
);
1586 pw
->p
[i
].FIELD
= FN(EL
,morph_domain
)(pw
->p
[i
].FIELD
,
1587 isl_morph_copy(morph
));
1588 if (!pw
->p
[i
].FIELD
)
1592 isl_morph_free(morph
);
1597 isl_morph_free(morph
);
1602 int FN(PW
,n_piece
)(__isl_keep PW
*pw
)
1604 return pw
? pw
->n
: 0;
1607 isl_stat
FN(PW
,foreach_piece
)(__isl_keep PW
*pw
,
1608 isl_stat (*fn
)(__isl_take isl_set
*set
, __isl_take EL
*el
, void *user
),
1614 return isl_stat_error
;
1616 for (i
= 0; i
< pw
->n
; ++i
)
1617 if (fn(isl_set_copy(pw
->p
[i
].set
),
1618 FN(EL
,copy
)(pw
->p
[i
].FIELD
), user
) < 0)
1619 return isl_stat_error
;
1625 static int any_divs(__isl_keep isl_set
*set
)
1632 for (i
= 0; i
< set
->n
; ++i
)
1633 if (set
->p
[i
]->n_div
> 0)
1639 static isl_stat
foreach_lifted_subset(__isl_take isl_set
*set
,
1641 isl_stat (*fn
)(__isl_take isl_set
*set
, __isl_take EL
*el
,
1642 void *user
), void *user
)
1649 for (i
= 0; i
< set
->n
; ++i
) {
1653 lift
= isl_set_from_basic_set(isl_basic_set_copy(set
->p
[i
]));
1654 lift
= isl_set_lift(lift
);
1656 copy
= FN(EL
,copy
)(el
);
1657 copy
= FN(EL
,lift
)(copy
, isl_set_get_space(lift
));
1659 if (fn(lift
, copy
, user
) < 0)
1670 return isl_stat_error
;
1673 isl_stat
FN(PW
,foreach_lifted_piece
)(__isl_keep PW
*pw
,
1674 isl_stat (*fn
)(__isl_take isl_set
*set
, __isl_take EL
*el
,
1675 void *user
), void *user
)
1680 return isl_stat_error
;
1682 for (i
= 0; i
< pw
->n
; ++i
) {
1686 set
= isl_set_copy(pw
->p
[i
].set
);
1687 el
= FN(EL
,copy
)(pw
->p
[i
].FIELD
);
1688 if (!any_divs(set
)) {
1689 if (fn(set
, el
, user
) < 0)
1690 return isl_stat_error
;
1693 if (foreach_lifted_subset(set
, el
, fn
, user
) < 0)
1694 return isl_stat_error
;
1701 #ifndef NO_MOVE_DIMS
1702 __isl_give PW
*FN(PW
,move_dims
)(__isl_take PW
*pw
,
1703 enum isl_dim_type dst_type
, unsigned dst_pos
,
1704 enum isl_dim_type src_type
, unsigned src_pos
, unsigned n
)
1708 pw
= FN(PW
,cow
)(pw
);
1712 pw
->dim
= isl_space_move_dims(pw
->dim
, dst_type
, dst_pos
, src_type
, src_pos
, n
);
1716 for (i
= 0; i
< pw
->n
; ++i
) {
1717 pw
->p
[i
].FIELD
= FN(EL
,move_dims
)(pw
->p
[i
].FIELD
,
1718 dst_type
, dst_pos
, src_type
, src_pos
, n
);
1719 if (!pw
->p
[i
].FIELD
)
1723 if (dst_type
== isl_dim_in
)
1724 dst_type
= isl_dim_set
;
1725 if (src_type
== isl_dim_in
)
1726 src_type
= isl_dim_set
;
1728 for (i
= 0; i
< pw
->n
; ++i
) {
1729 pw
->p
[i
].set
= isl_set_move_dims(pw
->p
[i
].set
,
1731 src_type
, src_pos
, n
);
1743 __isl_give PW
*FN(PW
,mul_isl_int
)(__isl_take PW
*pw
, isl_int v
)
1747 if (isl_int_is_one(v
))
1749 if (pw
&& DEFAULT_IS_ZERO
&& isl_int_is_zero(v
)) {
1751 isl_space
*dim
= FN(PW
,get_space
)(pw
);
1753 zero
= FN(PW
,ZERO
)(dim
, pw
->type
);
1755 zero
= FN(PW
,ZERO
)(dim
);
1760 pw
= FN(PW
,cow
)(pw
);
1767 if (isl_int_is_neg(v
))
1768 pw
->type
= isl_fold_type_negate(pw
->type
);
1770 for (i
= 0; i
< pw
->n
; ++i
) {
1771 pw
->p
[i
].FIELD
= FN(EL
,scale
)(pw
->p
[i
].FIELD
, v
);
1772 if (!pw
->p
[i
].FIELD
)
1782 /* Multiply the pieces of "pw" by "v" and return the result.
1784 __isl_give PW
*FN(PW
,scale_val
)(__isl_take PW
*pw
, __isl_take isl_val
*v
)
1791 if (isl_val_is_one(v
)) {
1795 if (pw
&& DEFAULT_IS_ZERO
&& isl_val_is_zero(v
)) {
1797 isl_space
*space
= FN(PW
,get_space
)(pw
);
1799 zero
= FN(PW
,ZERO
)(space
, pw
->type
);
1801 zero
= FN(PW
,ZERO
)(space
);
1811 pw
= FN(PW
,cow
)(pw
);
1816 if (isl_val_is_neg(v
))
1817 pw
->type
= isl_fold_type_negate(pw
->type
);
1819 for (i
= 0; i
< pw
->n
; ++i
) {
1820 pw
->p
[i
].FIELD
= FN(EL
,scale_val
)(pw
->p
[i
].FIELD
,
1822 if (!pw
->p
[i
].FIELD
)
1834 /* Divide the pieces of "pw" by "v" and return the result.
1836 __isl_give PW
*FN(PW
,scale_down_val
)(__isl_take PW
*pw
, __isl_take isl_val
*v
)
1843 if (isl_val_is_one(v
)) {
1848 if (!isl_val_is_rat(v
))
1849 isl_die(isl_val_get_ctx(v
), isl_error_invalid
,
1850 "expecting rational factor", goto error
);
1851 if (isl_val_is_zero(v
))
1852 isl_die(isl_val_get_ctx(v
), isl_error_invalid
,
1853 "cannot scale down by zero", goto error
);
1859 pw
= FN(PW
,cow
)(pw
);
1864 if (isl_val_is_neg(v
))
1865 pw
->type
= isl_fold_type_negate(pw
->type
);
1867 for (i
= 0; i
< pw
->n
; ++i
) {
1868 pw
->p
[i
].FIELD
= FN(EL
,scale_down_val
)(pw
->p
[i
].FIELD
,
1870 if (!pw
->p
[i
].FIELD
)
1882 __isl_give PW
*FN(PW
,scale
)(__isl_take PW
*pw
, isl_int v
)
1884 return FN(PW
,mul_isl_int
)(pw
, v
);
1887 static int FN(PW
,qsort_set_cmp
)(const void *p1
, const void *p2
)
1889 isl_set
*set1
= *(isl_set
* const *)p1
;
1890 isl_set
*set2
= *(isl_set
* const *)p2
;
1892 return isl_set_plain_cmp(set1
, set2
);
1895 /* We normalize in place, but if anything goes wrong we need
1896 * to return NULL, so we need to make sure we don't change the
1897 * meaning of any possible other copies of map.
1899 __isl_give PW
*FN(PW
,normalize
)(__isl_take PW
*pw
)
1906 for (i
= 0; i
< pw
->n
; ++i
) {
1907 set
= isl_set_normalize(isl_set_copy(pw
->p
[i
].set
));
1909 return FN(PW
,free
)(pw
);
1910 isl_set_free(pw
->p
[i
].set
);
1913 qsort(pw
->p
, pw
->n
, sizeof(pw
->p
[0]), &FN(PW
,qsort_set_cmp
));
1914 for (i
= pw
->n
- 1; i
>= 1; --i
) {
1915 if (!isl_set_plain_is_equal(pw
->p
[i
- 1].set
, pw
->p
[i
].set
))
1917 if (!FN(EL
,plain_is_equal
)(pw
->p
[i
- 1].FIELD
, pw
->p
[i
].FIELD
))
1919 set
= isl_set_union(isl_set_copy(pw
->p
[i
- 1].set
),
1920 isl_set_copy(pw
->p
[i
].set
));
1922 return FN(PW
,free
)(pw
);
1923 isl_set_free(pw
->p
[i
].set
);
1924 FN(EL
,free
)(pw
->p
[i
].FIELD
);
1925 isl_set_free(pw
->p
[i
- 1].set
);
1926 pw
->p
[i
- 1].set
= set
;
1927 for (j
= i
+ 1; j
< pw
->n
; ++j
)
1928 pw
->p
[j
- 1] = pw
->p
[j
];
1935 /* Is pw1 obviously equal to pw2?
1936 * That is, do they have obviously identical cells and obviously identical
1937 * elements on each cell?
1939 isl_bool
FN(PW
,plain_is_equal
)(__isl_keep PW
*pw1
, __isl_keep PW
*pw2
)
1945 return isl_bool_error
;
1948 return isl_bool_true
;
1949 if (!isl_space_is_equal(pw1
->dim
, pw2
->dim
))
1950 return isl_bool_false
;
1952 pw1
= FN(PW
,copy
)(pw1
);
1953 pw2
= FN(PW
,copy
)(pw2
);
1954 pw1
= FN(PW
,normalize
)(pw1
);
1955 pw2
= FN(PW
,normalize
)(pw2
);
1959 equal
= pw1
->n
== pw2
->n
;
1960 for (i
= 0; equal
&& i
< pw1
->n
; ++i
) {
1961 equal
= isl_set_plain_is_equal(pw1
->p
[i
].set
, pw2
->p
[i
].set
);
1966 equal
= FN(EL
,plain_is_equal
)(pw1
->p
[i
].FIELD
, pw2
->p
[i
].FIELD
);
1977 return isl_bool_error
;
1981 static __isl_give PW
*FN(PW
,align_params_pw_multi_aff_and
)(__isl_take PW
*pw
,
1982 __isl_take isl_multi_aff
*ma
,
1983 __isl_give PW
*(*fn
)(__isl_take PW
*pw
, __isl_take isl_multi_aff
*ma
))
1986 isl_space
*ma_space
;
1988 ma_space
= isl_multi_aff_get_space(ma
);
1989 if (!pw
|| !ma
|| !ma_space
)
1991 if (isl_space_match(pw
->dim
, isl_dim_param
, ma_space
, isl_dim_param
)) {
1992 isl_space_free(ma_space
);
1995 ctx
= FN(PW
,get_ctx
)(pw
);
1996 if (!isl_space_has_named_params(pw
->dim
) ||
1997 !isl_space_has_named_params(ma_space
))
1998 isl_die(ctx
, isl_error_invalid
,
1999 "unaligned unnamed parameters", goto error
);
2000 pw
= FN(PW
,align_params
)(pw
, ma_space
);
2001 ma
= isl_multi_aff_align_params(ma
, FN(PW
,get_space
)(pw
));
2004 isl_space_free(ma_space
);
2006 isl_multi_aff_free(ma
);
2010 static __isl_give PW
*FN(PW
,align_params_pw_pw_multi_aff_and
)(__isl_take PW
*pw
,
2011 __isl_take isl_pw_multi_aff
*pma
,
2012 __isl_give PW
*(*fn
)(__isl_take PW
*pw
,
2013 __isl_take isl_pw_multi_aff
*ma
))
2016 isl_space
*pma_space
;
2018 pma_space
= isl_pw_multi_aff_get_space(pma
);
2019 if (!pw
|| !pma
|| !pma_space
)
2021 if (isl_space_match(pw
->dim
, isl_dim_param
, pma_space
, isl_dim_param
)) {
2022 isl_space_free(pma_space
);
2025 ctx
= FN(PW
,get_ctx
)(pw
);
2026 if (!isl_space_has_named_params(pw
->dim
) ||
2027 !isl_space_has_named_params(pma_space
))
2028 isl_die(ctx
, isl_error_invalid
,
2029 "unaligned unnamed parameters", goto error
);
2030 pw
= FN(PW
,align_params
)(pw
, pma_space
);
2031 pma
= isl_pw_multi_aff_align_params(pma
, FN(PW
,get_space
)(pw
));
2034 isl_space_free(pma_space
);
2036 isl_pw_multi_aff_free(pma
);
2040 /* Compute the pullback of "pw" by the function represented by "ma".
2041 * In other words, plug in "ma" in "pw".
2043 static __isl_give PW
*FN(PW
,pullback_multi_aff_aligned
)(__isl_take PW
*pw
,
2044 __isl_take isl_multi_aff
*ma
)
2047 isl_space
*space
= NULL
;
2049 ma
= isl_multi_aff_align_divs(ma
);
2050 pw
= FN(PW
,cow
)(pw
);
2054 space
= isl_space_join(isl_multi_aff_get_space(ma
),
2055 FN(PW
,get_space
)(pw
));
2057 for (i
= 0; i
< pw
->n
; ++i
) {
2058 pw
->p
[i
].set
= isl_set_preimage_multi_aff(pw
->p
[i
].set
,
2059 isl_multi_aff_copy(ma
));
2062 pw
->p
[i
].FIELD
= FN(EL
,pullback_multi_aff
)(pw
->p
[i
].FIELD
,
2063 isl_multi_aff_copy(ma
));
2064 if (!pw
->p
[i
].FIELD
)
2068 pw
= FN(PW
,reset_space
)(pw
, space
);
2069 isl_multi_aff_free(ma
);
2072 isl_space_free(space
);
2073 isl_multi_aff_free(ma
);
2078 __isl_give PW
*FN(PW
,pullback_multi_aff
)(__isl_take PW
*pw
,
2079 __isl_take isl_multi_aff
*ma
)
2081 return FN(PW
,align_params_pw_multi_aff_and
)(pw
, ma
,
2082 &FN(PW
,pullback_multi_aff_aligned
));
2085 /* Compute the pullback of "pw" by the function represented by "pma".
2086 * In other words, plug in "pma" in "pw".
2088 static __isl_give PW
*FN(PW
,pullback_pw_multi_aff_aligned
)(__isl_take PW
*pw
,
2089 __isl_take isl_pw_multi_aff
*pma
)
2099 space
= isl_space_join(isl_pw_multi_aff_get_space(pma
),
2100 FN(PW
,get_space
)(pw
));
2101 isl_pw_multi_aff_free(pma
);
2102 res
= FN(PW
,empty
)(space
);
2107 res
= FN(PW
,pullback_multi_aff
)(FN(PW
,copy
)(pw
),
2108 isl_multi_aff_copy(pma
->p
[0].maff
));
2109 res
= FN(PW
,intersect_domain
)(res
, isl_set_copy(pma
->p
[0].set
));
2111 for (i
= 1; i
< pma
->n
; ++i
) {
2114 res_i
= FN(PW
,pullback_multi_aff
)(FN(PW
,copy
)(pw
),
2115 isl_multi_aff_copy(pma
->p
[i
].maff
));
2116 res_i
= FN(PW
,intersect_domain
)(res_i
,
2117 isl_set_copy(pma
->p
[i
].set
));
2118 res
= FN(PW
,add_disjoint
)(res
, res_i
);
2121 isl_pw_multi_aff_free(pma
);
2125 isl_pw_multi_aff_free(pma
);
2130 __isl_give PW
*FN(PW
,pullback_pw_multi_aff
)(__isl_take PW
*pw
,
2131 __isl_take isl_pw_multi_aff
*pma
)
2133 return FN(PW
,align_params_pw_pw_multi_aff_and
)(pw
, pma
,
2134 &FN(PW
,pullback_pw_multi_aff_aligned
));