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 int FN(PW
,has_dim_id
)(__isl_keep PW
*pw
, enum isl_dim_type type
, unsigned pos
)
200 return pw
? isl_space_has_dim_id(pw
->dim
, type
, pos
) : -1;
203 __isl_give isl_id
*FN(PW
,get_dim_id
)(__isl_keep PW
*pw
, enum isl_dim_type type
,
206 return pw
? isl_space_get_dim_id(pw
->dim
, type
, pos
) : NULL
;
209 int FN(PW
,has_tuple_name
)(__isl_keep PW
*pw
, enum isl_dim_type type
)
211 return pw
? isl_space_has_tuple_name(pw
->dim
, type
) : -1;
214 const char *FN(PW
,get_tuple_name
)(__isl_keep PW
*pw
, enum isl_dim_type type
)
216 return pw
? isl_space_get_tuple_name(pw
->dim
, type
) : NULL
;
219 int FN(PW
,has_tuple_id
)(__isl_keep PW
*pw
, enum isl_dim_type type
)
221 return pw
? isl_space_has_tuple_id(pw
->dim
, type
) : -1;
224 __isl_give isl_id
*FN(PW
,get_tuple_id
)(__isl_keep PW
*pw
, enum isl_dim_type type
)
226 return pw
? isl_space_get_tuple_id(pw
->dim
, type
) : NULL
;
229 int FN(PW
,IS_ZERO
)(__isl_keep PW
*pw
)
238 __isl_give PW
*FN(PW
,realign_domain
)(__isl_take PW
*pw
,
239 __isl_take isl_reordering
*exp
)
247 for (i
= 0; i
< pw
->n
; ++i
) {
248 pw
->p
[i
].set
= isl_set_realign(pw
->p
[i
].set
,
249 isl_reordering_copy(exp
));
252 pw
->p
[i
].FIELD
= FN(EL
,realign_domain
)(pw
->p
[i
].FIELD
,
253 isl_reordering_copy(exp
));
258 pw
= FN(PW
,reset_domain_space
)(pw
, isl_space_copy(exp
->dim
));
260 isl_reordering_free(exp
);
263 isl_reordering_free(exp
);
268 /* Align the parameters of "pw" to those of "model".
270 __isl_give PW
*FN(PW
,align_params
)(__isl_take PW
*pw
, __isl_take isl_space
*model
)
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 if (!isl_space_match(pw
->dim
, isl_dim_param
, model
, isl_dim_param
)) {
287 model
= isl_space_drop_dims(model
, isl_dim_in
,
288 0, isl_space_dim(model
, isl_dim_in
));
289 model
= isl_space_drop_dims(model
, isl_dim_out
,
290 0, isl_space_dim(model
, isl_dim_out
));
291 exp
= isl_parameter_alignment_reordering(pw
->dim
, model
);
292 exp
= isl_reordering_extend_space(exp
,
293 FN(PW
,get_domain_space
)(pw
));
294 pw
= FN(PW
,realign_domain
)(pw
, exp
);
297 isl_space_free(model
);
300 isl_space_free(model
);
305 static __isl_give PW
*FN(PW
,align_params_pw_pw_and
)(__isl_take PW
*pw1
,
307 __isl_give PW
*(*fn
)(__isl_take PW
*pw1
, __isl_take PW
*pw2
))
313 if (isl_space_match(pw1
->dim
, isl_dim_param
, pw2
->dim
, isl_dim_param
))
315 ctx
= FN(PW
,get_ctx
)(pw1
);
316 if (!isl_space_has_named_params(pw1
->dim
) ||
317 !isl_space_has_named_params(pw2
->dim
))
318 isl_die(ctx
, isl_error_invalid
,
319 "unaligned unnamed parameters", goto error
);
320 pw1
= FN(PW
,align_params
)(pw1
, FN(PW
,get_space
)(pw2
));
321 pw2
= FN(PW
,align_params
)(pw2
, FN(PW
,get_space
)(pw1
));
329 static __isl_give PW
*FN(PW
,align_params_pw_set_and
)(__isl_take PW
*pw
,
330 __isl_take isl_set
*set
,
331 __isl_give PW
*(*fn
)(__isl_take PW
*pw
, __isl_take isl_set
*set
))
337 if (isl_space_match(pw
->dim
, isl_dim_param
, set
->dim
, isl_dim_param
))
339 ctx
= FN(PW
,get_ctx
)(pw
);
340 if (!isl_space_has_named_params(pw
->dim
) ||
341 !isl_space_has_named_params(set
->dim
))
342 isl_die(ctx
, isl_error_invalid
,
343 "unaligned unnamed parameters", goto error
);
344 pw
= FN(PW
,align_params
)(pw
, isl_set_get_space(set
));
345 set
= isl_set_align_params(set
, FN(PW
,get_space
)(pw
));
354 static __isl_give PW
*FN(PW
,union_add_aligned
)(__isl_take PW
*pw1
,
365 ctx
= isl_space_get_ctx(pw1
->dim
);
367 if (pw1
->type
!= pw2
->type
)
368 isl_die(ctx
, isl_error_invalid
,
369 "fold types don't match", goto error
);
371 isl_assert(ctx
, isl_space_is_equal(pw1
->dim
, pw2
->dim
), goto error
);
373 if (FN(PW
,IS_ZERO
)(pw1
)) {
378 if (FN(PW
,IS_ZERO
)(pw2
)) {
383 n
= (pw1
->n
+ 1) * (pw2
->n
+ 1);
385 res
= FN(PW
,alloc_size
)(isl_space_copy(pw1
->dim
), pw1
->type
, n
);
387 res
= FN(PW
,alloc_size
)(isl_space_copy(pw1
->dim
), n
);
390 for (i
= 0; i
< pw1
->n
; ++i
) {
391 set
= isl_set_copy(pw1
->p
[i
].set
);
392 for (j
= 0; j
< pw2
->n
; ++j
) {
393 struct isl_set
*common
;
395 common
= isl_set_intersect(isl_set_copy(pw1
->p
[i
].set
),
396 isl_set_copy(pw2
->p
[j
].set
));
397 if (isl_set_plain_is_empty(common
)) {
398 isl_set_free(common
);
401 set
= isl_set_subtract(set
,
402 isl_set_copy(pw2
->p
[j
].set
));
404 sum
= FN(EL
,add_on_domain
)(common
,
405 FN(EL
,copy
)(pw1
->p
[i
].FIELD
),
406 FN(EL
,copy
)(pw2
->p
[j
].FIELD
));
408 res
= FN(PW
,add_piece
)(res
, common
, sum
);
410 res
= FN(PW
,add_piece
)(res
, set
, FN(EL
,copy
)(pw1
->p
[i
].FIELD
));
413 for (j
= 0; j
< pw2
->n
; ++j
) {
414 set
= isl_set_copy(pw2
->p
[j
].set
);
415 for (i
= 0; i
< pw1
->n
; ++i
)
416 set
= isl_set_subtract(set
,
417 isl_set_copy(pw1
->p
[i
].set
));
418 res
= FN(PW
,add_piece
)(res
, set
, FN(EL
,copy
)(pw2
->p
[j
].FIELD
));
431 /* Private version of "union_add". For isl_pw_qpolynomial and
432 * isl_pw_qpolynomial_fold, we prefer to simply call it "add".
434 static __isl_give PW
*FN(PW
,union_add_
)(__isl_take PW
*pw1
, __isl_take PW
*pw2
)
436 return FN(PW
,align_params_pw_pw_and
)(pw1
, pw2
,
437 &FN(PW
,union_add_aligned
));
440 /* Make sure "pw" has room for at least "n" more pieces.
442 * If there is only one reference to pw, we extend it in place.
443 * Otherwise, we create a new PW and copy the pieces.
445 static __isl_give PW
*FN(PW
,grow
)(__isl_take PW
*pw
, int n
)
453 if (pw
->n
+ n
<= pw
->size
)
455 ctx
= FN(PW
,get_ctx
)(pw
);
458 res
= isl_realloc(ctx
, pw
, struct PW
,
459 sizeof(struct PW
) + (n
- 1) * sizeof(S(PW
,piece
)));
461 return FN(PW
,free
)(pw
);
466 res
= FN(PW
,alloc_size
)(isl_space_copy(pw
->dim
), pw
->type
, n
);
468 res
= FN(PW
,alloc_size
)(isl_space_copy(pw
->dim
), n
);
471 return FN(PW
,free
)(pw
);
472 for (i
= 0; i
< pw
->n
; ++i
)
473 res
= FN(PW
,add_piece
)(res
, isl_set_copy(pw
->p
[i
].set
),
474 FN(EL
,copy
)(pw
->p
[i
].FIELD
));
479 static __isl_give PW
*FN(PW
,add_disjoint_aligned
)(__isl_take PW
*pw1
,
488 if (pw1
->size
< pw1
->n
+ pw2
->n
&& pw1
->n
< pw2
->n
)
489 return FN(PW
,add_disjoint_aligned
)(pw2
, pw1
);
491 ctx
= isl_space_get_ctx(pw1
->dim
);
493 if (pw1
->type
!= pw2
->type
)
494 isl_die(ctx
, isl_error_invalid
,
495 "fold types don't match", goto error
);
497 isl_assert(ctx
, isl_space_is_equal(pw1
->dim
, pw2
->dim
), goto error
);
499 if (FN(PW
,IS_ZERO
)(pw1
)) {
504 if (FN(PW
,IS_ZERO
)(pw2
)) {
509 pw1
= FN(PW
,grow
)(pw1
, pw2
->n
);
513 for (i
= 0; i
< pw2
->n
; ++i
)
514 pw1
= FN(PW
,add_piece
)(pw1
,
515 isl_set_copy(pw2
->p
[i
].set
),
516 FN(EL
,copy
)(pw2
->p
[i
].FIELD
));
527 __isl_give PW
*FN(PW
,add_disjoint
)(__isl_take PW
*pw1
, __isl_take PW
*pw2
)
529 return FN(PW
,align_params_pw_pw_and
)(pw1
, pw2
,
530 &FN(PW
,add_disjoint_aligned
));
533 /* This function is currently only used from isl_aff.c
535 static __isl_give PW
*FN(PW
,on_shared_domain_in
)(__isl_take PW
*pw1
,
536 __isl_take PW
*pw2
, __isl_take isl_space
*space
,
537 __isl_give EL
*(*fn
)(__isl_take EL
*el1
, __isl_take EL
*el2
))
538 __attribute__ ((unused
));
540 /* Apply "fn" to pairs of elements from pw1 and pw2 on shared domains.
541 * The result of "fn" (and therefore also of this function) lives in "space".
543 static __isl_give PW
*FN(PW
,on_shared_domain_in
)(__isl_take PW
*pw1
,
544 __isl_take PW
*pw2
, __isl_take isl_space
*space
,
545 __isl_give EL
*(*fn
)(__isl_take EL
*el1
, __isl_take EL
*el2
))
555 res
= FN(PW
,alloc_size
)(isl_space_copy(space
), pw1
->type
, n
);
557 res
= FN(PW
,alloc_size
)(isl_space_copy(space
), n
);
560 for (i
= 0; i
< pw1
->n
; ++i
) {
561 for (j
= 0; j
< pw2
->n
; ++j
) {
566 common
= isl_set_intersect(
567 isl_set_copy(pw1
->p
[i
].set
),
568 isl_set_copy(pw2
->p
[j
].set
));
569 empty
= isl_set_plain_is_empty(common
);
570 if (empty
< 0 || empty
) {
571 isl_set_free(common
);
577 res_ij
= fn(FN(EL
,copy
)(pw1
->p
[i
].FIELD
),
578 FN(EL
,copy
)(pw2
->p
[j
].FIELD
));
579 res_ij
= FN(EL
,gist
)(res_ij
, isl_set_copy(common
));
581 res
= FN(PW
,add_piece
)(res
, common
, res_ij
);
585 isl_space_free(space
);
590 isl_space_free(space
);
597 /* This function is currently only used from isl_aff.c
599 static __isl_give PW
*FN(PW
,on_shared_domain
)(__isl_take PW
*pw1
,
601 __isl_give EL
*(*fn
)(__isl_take EL
*el1
, __isl_take EL
*el2
))
602 __attribute__ ((unused
));
604 /* Apply "fn" to pairs of elements from pw1 and pw2 on shared domains.
605 * The result of "fn" is assumed to live in the same space as "pw1" and "pw2".
607 static __isl_give PW
*FN(PW
,on_shared_domain
)(__isl_take PW
*pw1
,
609 __isl_give EL
*(*fn
)(__isl_take EL
*el1
, __isl_take EL
*el2
))
616 space
= isl_space_copy(pw1
->dim
);
617 return FN(PW
,on_shared_domain_in
)(pw1
, pw2
, space
, fn
);
625 __isl_give PW
*FN(PW
,neg
)(__isl_take PW
*pw
)
632 if (FN(PW
,IS_ZERO
)(pw
))
639 for (i
= 0; i
< pw
->n
; ++i
) {
640 pw
->p
[i
].FIELD
= FN(EL
,neg
)(pw
->p
[i
].FIELD
);
642 return FN(PW
,free
)(pw
);
648 __isl_give PW
*FN(PW
,sub
)(__isl_take PW
*pw1
, __isl_take PW
*pw2
)
650 return FN(PW
,add
)(pw1
, FN(PW
,neg
)(pw2
));
655 __isl_give isl_val
*FN(PW
,eval
)(__isl_take PW
*pw
, __isl_take isl_point
*pnt
)
660 isl_space
*pnt_dim
= NULL
;
665 ctx
= isl_point_get_ctx(pnt
);
666 pnt_dim
= isl_point_get_space(pnt
);
667 isl_assert(ctx
, isl_space_is_domain_internal(pnt_dim
, pw
->dim
),
670 for (i
= 0; i
< pw
->n
; ++i
) {
671 found
= isl_set_contains_point(pw
->p
[i
].set
, pnt
);
678 v
= FN(EL
,eval
)(FN(EL
,copy
)(pw
->p
[i
].FIELD
),
679 isl_point_copy(pnt
));
681 v
= isl_val_zero(ctx
);
683 isl_space_free(pnt_dim
);
688 isl_space_free(pnt_dim
);
694 /* Return the parameter domain of "pw".
696 __isl_give isl_set
*FN(PW
,params
)(__isl_take PW
*pw
)
698 return isl_set_params(FN(PW
,domain
)(pw
));
701 __isl_give isl_set
*FN(PW
,domain
)(__isl_take PW
*pw
)
709 dom
= isl_set_empty(FN(PW
,get_domain_space
)(pw
));
710 for (i
= 0; i
< pw
->n
; ++i
)
711 dom
= isl_set_union_disjoint(dom
, isl_set_copy(pw
->p
[i
].set
));
718 /* Exploit the equalities in the domain of piece "i" of "pw"
719 * to simplify the associated function.
720 * If the domain of piece "i" is empty, then remove it entirely,
721 * replacing it with the final piece.
723 static int FN(PW
,exploit_equalities_and_remove_if_empty
)(__isl_keep PW
*pw
,
727 int empty
= isl_set_plain_is_empty(pw
->p
[i
].set
);
732 isl_set_free(pw
->p
[i
].set
);
733 FN(EL
,free
)(pw
->p
[i
].FIELD
);
735 pw
->p
[i
] = pw
->p
[pw
->n
- 1];
741 aff
= isl_set_affine_hull(isl_set_copy(pw
->p
[i
].set
));
742 pw
->p
[i
].FIELD
= FN(EL
,substitute_equalities
)(pw
->p
[i
].FIELD
, aff
);
749 /* Convert a piecewise expression defined over a parameter domain
750 * into one that is defined over a zero-dimensional set.
752 __isl_give PW
*FN(PW
,from_range
)(__isl_take PW
*pw
)
758 if (!isl_space_is_set(pw
->dim
))
759 isl_die(FN(PW
,get_ctx
)(pw
), isl_error_invalid
,
760 "not living in a set space", return FN(PW
,free
)(pw
));
762 space
= FN(PW
,get_space
)(pw
);
763 space
= isl_space_from_range(space
);
764 pw
= FN(PW
,reset_space
)(pw
, space
);
769 /* Fix the value of the given parameter or domain dimension of "pw"
770 * to be equal to "value".
772 __isl_give PW
*FN(PW
,fix_si
)(__isl_take PW
*pw
, enum isl_dim_type type
,
773 unsigned pos
, int value
)
780 if (type
== isl_dim_out
)
781 isl_die(FN(PW
,get_ctx
)(pw
), isl_error_invalid
,
782 "cannot fix output dimension", return FN(PW
,free
)(pw
));
787 if (type
== isl_dim_in
)
792 return FN(PW
,free
)(pw
);
794 for (i
= pw
->n
- 1; i
>= 0; --i
) {
795 pw
->p
[i
].set
= isl_set_fix_si(pw
->p
[i
].set
, type
, pos
, value
);
796 if (FN(PW
,exploit_equalities_and_remove_if_empty
)(pw
, i
) < 0)
797 return FN(PW
,free
)(pw
);
803 /* Restrict the domain of "pw" by combining each cell
804 * with "set" through a call to "fn", where "fn" may be
805 * isl_set_intersect, isl_set_intersect_params or isl_set_subtract.
807 static __isl_give PW
*FN(PW
,restrict_domain_aligned
)(__isl_take PW
*pw
,
808 __isl_take isl_set
*set
,
809 __isl_give isl_set
*(*fn
)(__isl_take isl_set
*set1
,
810 __isl_take isl_set
*set2
))
826 for (i
= pw
->n
- 1; i
>= 0; --i
) {
827 pw
->p
[i
].set
= fn(pw
->p
[i
].set
, isl_set_copy(set
));
828 if (FN(PW
,exploit_equalities_and_remove_if_empty
)(pw
, i
) < 0)
840 static __isl_give PW
*FN(PW
,intersect_domain_aligned
)(__isl_take PW
*pw
,
841 __isl_take isl_set
*set
)
843 return FN(PW
,restrict_domain_aligned
)(pw
, set
, &isl_set_intersect
);
846 __isl_give PW
*FN(PW
,intersect_domain
)(__isl_take PW
*pw
,
847 __isl_take isl_set
*context
)
849 return FN(PW
,align_params_pw_set_and
)(pw
, context
,
850 &FN(PW
,intersect_domain_aligned
));
853 static __isl_give PW
*FN(PW
,intersect_params_aligned
)(__isl_take PW
*pw
,
854 __isl_take isl_set
*set
)
856 return FN(PW
,restrict_domain_aligned
)(pw
, set
,
857 &isl_set_intersect_params
);
860 /* Intersect the domain of "pw" with the parameter domain "context".
862 __isl_give PW
*FN(PW
,intersect_params
)(__isl_take PW
*pw
,
863 __isl_take isl_set
*context
)
865 return FN(PW
,align_params_pw_set_and
)(pw
, context
,
866 &FN(PW
,intersect_params_aligned
));
869 /* Subtract "domain' from the domain of "pw", assuming their
870 * parameters have been aligned.
872 static __isl_give PW
*FN(PW
,subtract_domain_aligned
)(__isl_take PW
*pw
,
873 __isl_take isl_set
*domain
)
875 return FN(PW
,restrict_domain_aligned
)(pw
, domain
, &isl_set_subtract
);
878 /* Subtract "domain' from the domain of "pw".
880 __isl_give PW
*FN(PW
,subtract_domain
)(__isl_take PW
*pw
,
881 __isl_take isl_set
*domain
)
883 return FN(PW
,align_params_pw_set_and
)(pw
, domain
,
884 &FN(PW
,subtract_domain_aligned
));
887 /* Compute the gist of "pw" with respect to the domain constraints
888 * of "context" for the case where the domain of the last element
889 * of "pw" is equal to "context".
890 * Call "fn_el" to compute the gist of this element, replace
891 * its domain by the universe and drop all other elements
892 * as their domains are necessarily disjoint from "context".
894 static __isl_give PW
*FN(PW
,gist_last
)(__isl_take PW
*pw
,
895 __isl_take isl_set
*context
,
896 __isl_give EL
*(*fn_el
)(__isl_take EL
*el
, __isl_take isl_set
*set
))
901 for (i
= 0; i
< pw
->n
- 1; ++i
) {
902 isl_set_free(pw
->p
[i
].set
);
903 FN(EL
,free
)(pw
->p
[i
].FIELD
);
905 pw
->p
[0].FIELD
= pw
->p
[pw
->n
- 1].FIELD
;
906 pw
->p
[0].set
= pw
->p
[pw
->n
- 1].set
;
909 space
= isl_set_get_space(context
);
910 pw
->p
[0].FIELD
= fn_el(pw
->p
[0].FIELD
, context
);
911 context
= isl_set_universe(space
);
912 isl_set_free(pw
->p
[0].set
);
913 pw
->p
[0].set
= context
;
915 if (!pw
->p
[0].FIELD
|| !pw
->p
[0].set
)
916 return FN(PW
,free
)(pw
);
921 /* Compute the gist of "pw" with respect to the domain constraints
922 * of "context". Call "fn_el" to compute the gist of the elements
923 * and "fn_dom" to compute the gist of the domains.
925 * If the piecewise expression is empty or the context is the universe,
926 * then nothing can be simplified.
928 static __isl_give PW
*FN(PW
,gist_aligned
)(__isl_take PW
*pw
,
929 __isl_take isl_set
*context
,
930 __isl_give EL
*(*fn_el
)(__isl_take EL
*el
,
931 __isl_take isl_set
*set
),
932 __isl_give isl_set
*(*fn_dom
)(__isl_take isl_set
*set
,
933 __isl_take isl_basic_set
*bset
))
937 isl_basic_set
*hull
= NULL
;
943 isl_set_free(context
);
947 is_universe
= isl_set_plain_is_universe(context
);
951 isl_set_free(context
);
955 if (!isl_space_match(pw
->dim
, isl_dim_param
,
956 context
->dim
, isl_dim_param
)) {
957 pw
= FN(PW
,align_params
)(pw
, isl_set_get_space(context
));
958 context
= isl_set_align_params(context
, FN(PW
,get_space
)(pw
));
968 equal
= isl_set_plain_is_equal(pw
->p
[0].set
, context
);
972 return FN(PW
,gist_last
)(pw
, context
, fn_el
);
975 context
= isl_set_compute_divs(context
);
976 hull
= isl_set_simple_hull(isl_set_copy(context
));
978 for (i
= pw
->n
- 1; i
>= 0; --i
) {
982 if (i
== pw
->n
- 1) {
984 equal
= isl_set_plain_is_equal(pw
->p
[i
].set
, context
);
988 isl_basic_set_free(hull
);
989 return FN(PW
,gist_last
)(pw
, context
, fn_el
);
992 set_i
= isl_set_intersect(isl_set_copy(pw
->p
[i
].set
),
993 isl_set_copy(context
));
994 empty
= isl_set_plain_is_empty(set_i
);
995 pw
->p
[i
].FIELD
= fn_el(pw
->p
[i
].FIELD
, set_i
);
996 pw
->p
[i
].set
= fn_dom(pw
->p
[i
].set
, isl_basic_set_copy(hull
));
997 if (empty
< 0 || !pw
->p
[i
].FIELD
|| !pw
->p
[i
].set
)
1000 isl_set_free(pw
->p
[i
].set
);
1001 FN(EL
,free
)(pw
->p
[i
].FIELD
);
1003 pw
->p
[i
] = pw
->p
[pw
->n
- 1];
1008 isl_basic_set_free(hull
);
1009 isl_set_free(context
);
1014 isl_basic_set_free(hull
);
1015 isl_set_free(context
);
1019 static __isl_give PW
*FN(PW
,gist_domain_aligned
)(__isl_take PW
*pw
,
1020 __isl_take isl_set
*set
)
1022 return FN(PW
,gist_aligned
)(pw
, set
, &FN(EL
,gist
),
1023 &isl_set_gist_basic_set
);
1026 __isl_give PW
*FN(PW
,gist
)(__isl_take PW
*pw
, __isl_take isl_set
*context
)
1028 return FN(PW
,align_params_pw_set_and
)(pw
, context
,
1029 &FN(PW
,gist_domain_aligned
));
1032 static __isl_give PW
*FN(PW
,gist_params_aligned
)(__isl_take PW
*pw
,
1033 __isl_take isl_set
*set
)
1035 return FN(PW
,gist_aligned
)(pw
, set
, &FN(EL
,gist_params
),
1036 &isl_set_gist_params_basic_set
);
1039 __isl_give PW
*FN(PW
,gist_params
)(__isl_take PW
*pw
,
1040 __isl_take isl_set
*context
)
1042 return FN(PW
,align_params_pw_set_and
)(pw
, context
,
1043 &FN(PW
,gist_params_aligned
));
1046 __isl_give PW
*FN(PW
,coalesce
)(__isl_take PW
*pw
)
1055 for (i
= pw
->n
- 1; i
>= 0; --i
) {
1056 for (j
= i
- 1; j
>= 0; --j
) {
1057 if (!FN(EL
,plain_is_equal
)(pw
->p
[i
].FIELD
,
1060 pw
->p
[j
].set
= isl_set_union(pw
->p
[j
].set
,
1062 FN(EL
,free
)(pw
->p
[i
].FIELD
);
1064 pw
->p
[i
] = pw
->p
[pw
->n
- 1];
1070 pw
->p
[i
].set
= isl_set_coalesce(pw
->p
[i
].set
);
1081 isl_ctx
*FN(PW
,get_ctx
)(__isl_keep PW
*pw
)
1083 return pw
? isl_space_get_ctx(pw
->dim
) : NULL
;
1086 #ifndef NO_INVOLVES_DIMS
1087 int FN(PW
,involves_dims
)(__isl_keep PW
*pw
, enum isl_dim_type type
,
1088 unsigned first
, unsigned n
)
1091 enum isl_dim_type set_type
;
1095 if (pw
->n
== 0 || n
== 0)
1098 set_type
= type
== isl_dim_in
? isl_dim_set
: type
;
1100 for (i
= 0; i
< pw
->n
; ++i
) {
1101 int involves
= FN(EL
,involves_dims
)(pw
->p
[i
].FIELD
,
1103 if (involves
< 0 || involves
)
1105 involves
= isl_set_involves_dims(pw
->p
[i
].set
,
1106 set_type
, first
, n
);
1107 if (involves
< 0 || involves
)
1114 __isl_give PW
*FN(PW
,set_dim_name
)(__isl_take PW
*pw
,
1115 enum isl_dim_type type
, unsigned pos
, const char *s
)
1118 enum isl_dim_type set_type
;
1120 pw
= FN(PW
,cow
)(pw
);
1124 set_type
= type
== isl_dim_in
? isl_dim_set
: type
;
1126 pw
->dim
= isl_space_set_dim_name(pw
->dim
, type
, pos
, s
);
1130 for (i
= 0; i
< pw
->n
; ++i
) {
1131 pw
->p
[i
].set
= isl_set_set_dim_name(pw
->p
[i
].set
,
1135 pw
->p
[i
].FIELD
= FN(EL
,set_dim_name
)(pw
->p
[i
].FIELD
, type
, pos
, s
);
1136 if (!pw
->p
[i
].FIELD
)
1146 #ifndef NO_DROP_DIMS
1147 __isl_give PW
*FN(PW
,drop_dims
)(__isl_take PW
*pw
,
1148 enum isl_dim_type type
, unsigned first
, unsigned n
)
1151 enum isl_dim_type set_type
;
1155 if (n
== 0 && !isl_space_get_tuple_name(pw
->dim
, type
))
1158 set_type
= type
== isl_dim_in
? isl_dim_set
: type
;
1160 pw
= FN(PW
,cow
)(pw
);
1163 pw
->dim
= isl_space_drop_dims(pw
->dim
, type
, first
, n
);
1166 for (i
= 0; i
< pw
->n
; ++i
) {
1167 pw
->p
[i
].FIELD
= FN(EL
,drop_dims
)(pw
->p
[i
].FIELD
, type
, first
, n
);
1168 if (!pw
->p
[i
].FIELD
)
1170 if (type
== isl_dim_out
)
1172 pw
->p
[i
].set
= isl_set_drop(pw
->p
[i
].set
, set_type
, first
, n
);
1183 /* This function is very similar to drop_dims.
1184 * The only difference is that the cells may still involve
1185 * the specified dimensions. They are removed using
1186 * isl_set_project_out instead of isl_set_drop.
1188 __isl_give PW
*FN(PW
,project_out
)(__isl_take PW
*pw
,
1189 enum isl_dim_type type
, unsigned first
, unsigned n
)
1192 enum isl_dim_type set_type
;
1196 if (n
== 0 && !isl_space_get_tuple_name(pw
->dim
, type
))
1199 set_type
= type
== isl_dim_in
? isl_dim_set
: type
;
1201 pw
= FN(PW
,cow
)(pw
);
1204 pw
->dim
= isl_space_drop_dims(pw
->dim
, type
, first
, n
);
1207 for (i
= 0; i
< pw
->n
; ++i
) {
1208 pw
->p
[i
].set
= isl_set_project_out(pw
->p
[i
].set
,
1209 set_type
, first
, n
);
1212 pw
->p
[i
].FIELD
= FN(EL
,drop_dims
)(pw
->p
[i
].FIELD
, type
, first
, n
);
1213 if (!pw
->p
[i
].FIELD
)
1223 /* Project the domain of pw onto its parameter space.
1225 __isl_give PW
*FN(PW
,project_domain_on_params
)(__isl_take PW
*pw
)
1230 n
= FN(PW
,dim
)(pw
, isl_dim_in
);
1231 pw
= FN(PW
,project_out
)(pw
, isl_dim_in
, 0, n
);
1232 space
= FN(PW
,get_domain_space
)(pw
);
1233 space
= isl_space_params(space
);
1234 pw
= FN(PW
,reset_domain_space
)(pw
, space
);
1239 #ifndef NO_INSERT_DIMS
1240 __isl_give PW
*FN(PW
,insert_dims
)(__isl_take PW
*pw
, enum isl_dim_type type
,
1241 unsigned first
, unsigned n
)
1244 enum isl_dim_type set_type
;
1248 if (n
== 0 && !isl_space_is_named_or_nested(pw
->dim
, type
))
1251 set_type
= type
== isl_dim_in
? isl_dim_set
: type
;
1253 pw
= FN(PW
,cow
)(pw
);
1257 pw
->dim
= isl_space_insert_dims(pw
->dim
, type
, first
, n
);
1261 for (i
= 0; i
< pw
->n
; ++i
) {
1262 pw
->p
[i
].set
= isl_set_insert_dims(pw
->p
[i
].set
,
1263 set_type
, first
, n
);
1266 pw
->p
[i
].FIELD
= FN(EL
,insert_dims
)(pw
->p
[i
].FIELD
,
1268 if (!pw
->p
[i
].FIELD
)
1279 __isl_give PW
*FN(PW
,fix_dim
)(__isl_take PW
*pw
,
1280 enum isl_dim_type type
, unsigned pos
, isl_int v
)
1287 if (type
== isl_dim_in
)
1290 pw
= FN(PW
,cow
)(pw
);
1293 for (i
= 0; i
< pw
->n
; ++i
) {
1294 pw
->p
[i
].set
= isl_set_fix(pw
->p
[i
].set
, type
, pos
, v
);
1295 if (FN(PW
,exploit_equalities_and_remove_if_empty
)(pw
, i
) < 0)
1296 return FN(PW
,free
)(pw
);
1302 /* Fix the value of the variable at position "pos" of type "type" of "pw"
1303 * to be equal to "v".
1305 __isl_give PW
*FN(PW
,fix_val
)(__isl_take PW
*pw
,
1306 enum isl_dim_type type
, unsigned pos
, __isl_take isl_val
*v
)
1309 return FN(PW
,free
)(pw
);
1310 if (!isl_val_is_int(v
))
1311 isl_die(FN(PW
,get_ctx
)(pw
), isl_error_invalid
,
1312 "expecting integer value", goto error
);
1314 pw
= FN(PW
,fix_dim
)(pw
, type
, pos
, v
->n
);
1320 return FN(PW
,free
)(pw
);
1323 unsigned FN(PW
,dim
)(__isl_keep PW
*pw
, enum isl_dim_type type
)
1325 return pw
? isl_space_dim(pw
->dim
, type
) : 0;
1328 __isl_give PW
*FN(PW
,split_dims
)(__isl_take PW
*pw
,
1329 enum isl_dim_type type
, unsigned first
, unsigned n
)
1338 if (type
== isl_dim_in
)
1341 pw
= FN(PW
,cow
)(pw
);
1346 for (i
= 0; i
< pw
->n
; ++i
) {
1347 pw
->p
[i
].set
= isl_set_split_dims(pw
->p
[i
].set
, type
, first
, n
);
1359 /* Compute the maximal value attained by the piecewise quasipolynomial
1360 * on its domain or zero if the domain is empty.
1361 * In the worst case, the domain is scanned completely,
1362 * so the domain is assumed to be bounded.
1364 __isl_give isl_val
*FN(PW
,opt
)(__isl_take PW
*pw
, int max
)
1373 opt
= isl_val_zero(FN(PW
,get_ctx
)(pw
));
1378 opt
= FN(EL
,opt_on_domain
)(FN(EL
,copy
)(pw
->p
[0].FIELD
),
1379 isl_set_copy(pw
->p
[0].set
), max
);
1380 for (i
= 1; i
< pw
->n
; ++i
) {
1382 opt_i
= FN(EL
,opt_on_domain
)(FN(EL
,copy
)(pw
->p
[i
].FIELD
),
1383 isl_set_copy(pw
->p
[i
].set
), max
);
1385 opt
= isl_val_max(opt
, opt_i
);
1387 opt
= isl_val_min(opt
, opt_i
);
1394 __isl_give isl_val
*FN(PW
,max
)(__isl_take PW
*pw
)
1396 return FN(PW
,opt
)(pw
, 1);
1399 __isl_give isl_val
*FN(PW
,min
)(__isl_take PW
*pw
)
1401 return FN(PW
,opt
)(pw
, 0);
1405 __isl_give isl_space
*FN(PW
,get_space
)(__isl_keep PW
*pw
)
1407 return pw
? isl_space_copy(pw
->dim
) : NULL
;
1410 __isl_give isl_space
*FN(PW
,get_domain_space
)(__isl_keep PW
*pw
)
1412 return pw
? isl_space_domain(isl_space_copy(pw
->dim
)) : NULL
;
1415 /* Return the position of the dimension of the given type and name
1417 * Return -1 if no such dimension can be found.
1419 int FN(PW
,find_dim_by_name
)(__isl_keep PW
*pw
,
1420 enum isl_dim_type type
, const char *name
)
1424 return isl_space_find_dim_by_name(pw
->dim
, type
, name
);
1427 #ifndef NO_RESET_DIM
1428 /* Reset the space of "pw". Since we don't know if the elements
1429 * represent the spaces themselves or their domains, we pass along
1430 * both when we call their reset_space_and_domain.
1432 static __isl_give PW
*FN(PW
,reset_space_and_domain
)(__isl_take PW
*pw
,
1433 __isl_take isl_space
*space
, __isl_take isl_space
*domain
)
1437 pw
= FN(PW
,cow
)(pw
);
1438 if (!pw
|| !space
|| !domain
)
1441 for (i
= 0; i
< pw
->n
; ++i
) {
1442 pw
->p
[i
].set
= isl_set_reset_space(pw
->p
[i
].set
,
1443 isl_space_copy(domain
));
1446 pw
->p
[i
].FIELD
= FN(EL
,reset_space_and_domain
)(pw
->p
[i
].FIELD
,
1447 isl_space_copy(space
), isl_space_copy(domain
));
1448 if (!pw
->p
[i
].FIELD
)
1452 isl_space_free(domain
);
1454 isl_space_free(pw
->dim
);
1459 isl_space_free(domain
);
1460 isl_space_free(space
);
1465 __isl_give PW
*FN(PW
,reset_domain_space
)(__isl_take PW
*pw
,
1466 __isl_take isl_space
*domain
)
1470 space
= isl_space_extend_domain_with_range(isl_space_copy(domain
),
1471 FN(PW
,get_space
)(pw
));
1472 return FN(PW
,reset_space_and_domain
)(pw
, space
, domain
);
1475 __isl_give PW
*FN(PW
,reset_space
)(__isl_take PW
*pw
, __isl_take isl_space
*dim
)
1479 domain
= isl_space_domain(isl_space_copy(dim
));
1480 return FN(PW
,reset_space_and_domain
)(pw
, dim
, domain
);
1483 __isl_give PW
*FN(PW
,set_tuple_id
)(__isl_take PW
*pw
, enum isl_dim_type type
,
1484 __isl_take isl_id
*id
)
1488 pw
= FN(PW
,cow
)(pw
);
1492 space
= FN(PW
,get_space
)(pw
);
1493 space
= isl_space_set_tuple_id(space
, type
, id
);
1495 return FN(PW
,reset_space
)(pw
, space
);
1498 return FN(PW
,free
)(pw
);
1501 /* Drop the id on the specified tuple.
1503 __isl_give PW
*FN(PW
,reset_tuple_id
)(__isl_take PW
*pw
, enum isl_dim_type type
)
1509 if (!FN(PW
,has_tuple_id
)(pw
, type
))
1512 pw
= FN(PW
,cow
)(pw
);
1516 space
= FN(PW
,get_space
)(pw
);
1517 space
= isl_space_reset_tuple_id(space
, type
);
1519 return FN(PW
,reset_space
)(pw
, space
);
1522 __isl_give PW
*FN(PW
,set_dim_id
)(__isl_take PW
*pw
,
1523 enum isl_dim_type type
, unsigned pos
, __isl_take isl_id
*id
)
1525 pw
= FN(PW
,cow
)(pw
);
1528 pw
->dim
= isl_space_set_dim_id(pw
->dim
, type
, pos
, id
);
1529 return FN(PW
,reset_space
)(pw
, isl_space_copy(pw
->dim
));
1532 return FN(PW
,free
)(pw
);
1536 int FN(PW
,has_equal_space
)(__isl_keep PW
*pw1
, __isl_keep PW
*pw2
)
1541 return isl_space_is_equal(pw1
->dim
, pw2
->dim
);
1545 __isl_give PW
*FN(PW
,morph_domain
)(__isl_take PW
*pw
,
1546 __isl_take isl_morph
*morph
)
1554 ctx
= isl_space_get_ctx(pw
->dim
);
1555 isl_assert(ctx
, isl_space_is_domain_internal(morph
->dom
->dim
, pw
->dim
),
1558 pw
= FN(PW
,cow
)(pw
);
1561 pw
->dim
= isl_space_extend_domain_with_range(
1562 isl_space_copy(morph
->ran
->dim
), pw
->dim
);
1566 for (i
= 0; i
< pw
->n
; ++i
) {
1567 pw
->p
[i
].set
= isl_morph_set(isl_morph_copy(morph
), pw
->p
[i
].set
);
1570 pw
->p
[i
].FIELD
= FN(EL
,morph_domain
)(pw
->p
[i
].FIELD
,
1571 isl_morph_copy(morph
));
1572 if (!pw
->p
[i
].FIELD
)
1576 isl_morph_free(morph
);
1581 isl_morph_free(morph
);
1586 int FN(PW
,n_piece
)(__isl_keep PW
*pw
)
1588 return pw
? pw
->n
: 0;
1591 int FN(PW
,foreach_piece
)(__isl_keep PW
*pw
,
1592 int (*fn
)(__isl_take isl_set
*set
, __isl_take EL
*el
, void *user
),
1600 for (i
= 0; i
< pw
->n
; ++i
)
1601 if (fn(isl_set_copy(pw
->p
[i
].set
),
1602 FN(EL
,copy
)(pw
->p
[i
].FIELD
), user
) < 0)
1609 static int any_divs(__isl_keep isl_set
*set
)
1616 for (i
= 0; i
< set
->n
; ++i
)
1617 if (set
->p
[i
]->n_div
> 0)
1623 static int foreach_lifted_subset(__isl_take isl_set
*set
, __isl_take EL
*el
,
1624 int (*fn
)(__isl_take isl_set
*set
, __isl_take EL
*el
,
1625 void *user
), void *user
)
1632 for (i
= 0; i
< set
->n
; ++i
) {
1636 lift
= isl_set_from_basic_set(isl_basic_set_copy(set
->p
[i
]));
1637 lift
= isl_set_lift(lift
);
1639 copy
= FN(EL
,copy
)(el
);
1640 copy
= FN(EL
,lift
)(copy
, isl_set_get_space(lift
));
1642 if (fn(lift
, copy
, user
) < 0)
1656 int FN(PW
,foreach_lifted_piece
)(__isl_keep PW
*pw
,
1657 int (*fn
)(__isl_take isl_set
*set
, __isl_take EL
*el
,
1658 void *user
), void *user
)
1665 for (i
= 0; i
< pw
->n
; ++i
) {
1669 set
= isl_set_copy(pw
->p
[i
].set
);
1670 el
= FN(EL
,copy
)(pw
->p
[i
].FIELD
);
1671 if (!any_divs(set
)) {
1672 if (fn(set
, el
, user
) < 0)
1676 if (foreach_lifted_subset(set
, el
, fn
, user
) < 0)
1684 #ifndef NO_MOVE_DIMS
1685 __isl_give PW
*FN(PW
,move_dims
)(__isl_take PW
*pw
,
1686 enum isl_dim_type dst_type
, unsigned dst_pos
,
1687 enum isl_dim_type src_type
, unsigned src_pos
, unsigned n
)
1691 pw
= FN(PW
,cow
)(pw
);
1695 pw
->dim
= isl_space_move_dims(pw
->dim
, dst_type
, dst_pos
, src_type
, src_pos
, n
);
1699 for (i
= 0; i
< pw
->n
; ++i
) {
1700 pw
->p
[i
].FIELD
= FN(EL
,move_dims
)(pw
->p
[i
].FIELD
,
1701 dst_type
, dst_pos
, src_type
, src_pos
, n
);
1702 if (!pw
->p
[i
].FIELD
)
1706 if (dst_type
== isl_dim_in
)
1707 dst_type
= isl_dim_set
;
1708 if (src_type
== isl_dim_in
)
1709 src_type
= isl_dim_set
;
1711 for (i
= 0; i
< pw
->n
; ++i
) {
1712 pw
->p
[i
].set
= isl_set_move_dims(pw
->p
[i
].set
,
1714 src_type
, src_pos
, n
);
1726 __isl_give PW
*FN(PW
,mul_isl_int
)(__isl_take PW
*pw
, isl_int v
)
1730 if (isl_int_is_one(v
))
1732 if (pw
&& DEFAULT_IS_ZERO
&& isl_int_is_zero(v
)) {
1734 isl_space
*dim
= FN(PW
,get_space
)(pw
);
1736 zero
= FN(PW
,ZERO
)(dim
, pw
->type
);
1738 zero
= FN(PW
,ZERO
)(dim
);
1743 pw
= FN(PW
,cow
)(pw
);
1750 if (isl_int_is_neg(v
))
1751 pw
->type
= isl_fold_type_negate(pw
->type
);
1753 for (i
= 0; i
< pw
->n
; ++i
) {
1754 pw
->p
[i
].FIELD
= FN(EL
,scale
)(pw
->p
[i
].FIELD
, v
);
1755 if (!pw
->p
[i
].FIELD
)
1765 /* Multiply the pieces of "pw" by "v" and return the result.
1767 __isl_give PW
*FN(PW
,scale_val
)(__isl_take PW
*pw
, __isl_take isl_val
*v
)
1774 if (isl_val_is_one(v
)) {
1778 if (pw
&& DEFAULT_IS_ZERO
&& isl_val_is_zero(v
)) {
1780 isl_space
*space
= FN(PW
,get_space
)(pw
);
1782 zero
= FN(PW
,ZERO
)(space
, pw
->type
);
1784 zero
= FN(PW
,ZERO
)(space
);
1794 pw
= FN(PW
,cow
)(pw
);
1799 if (isl_val_is_neg(v
))
1800 pw
->type
= isl_fold_type_negate(pw
->type
);
1802 for (i
= 0; i
< pw
->n
; ++i
) {
1803 pw
->p
[i
].FIELD
= FN(EL
,scale_val
)(pw
->p
[i
].FIELD
,
1805 if (!pw
->p
[i
].FIELD
)
1817 /* Divide the pieces of "pw" by "v" and return the result.
1819 __isl_give PW
*FN(PW
,scale_down_val
)(__isl_take PW
*pw
, __isl_take isl_val
*v
)
1826 if (isl_val_is_one(v
)) {
1831 if (!isl_val_is_rat(v
))
1832 isl_die(isl_val_get_ctx(v
), isl_error_invalid
,
1833 "expecting rational factor", goto error
);
1834 if (isl_val_is_zero(v
))
1835 isl_die(isl_val_get_ctx(v
), isl_error_invalid
,
1836 "cannot scale down by zero", goto error
);
1842 pw
= FN(PW
,cow
)(pw
);
1847 if (isl_val_is_neg(v
))
1848 pw
->type
= isl_fold_type_negate(pw
->type
);
1850 for (i
= 0; i
< pw
->n
; ++i
) {
1851 pw
->p
[i
].FIELD
= FN(EL
,scale_down_val
)(pw
->p
[i
].FIELD
,
1853 if (!pw
->p
[i
].FIELD
)
1865 __isl_give PW
*FN(PW
,scale
)(__isl_take PW
*pw
, isl_int v
)
1867 return FN(PW
,mul_isl_int
)(pw
, v
);
1870 static int FN(PW
,qsort_set_cmp
)(const void *p1
, const void *p2
)
1872 isl_set
*set1
= *(isl_set
* const *)p1
;
1873 isl_set
*set2
= *(isl_set
* const *)p2
;
1875 return isl_set_plain_cmp(set1
, set2
);
1878 /* We normalize in place, but if anything goes wrong we need
1879 * to return NULL, so we need to make sure we don't change the
1880 * meaning of any possible other copies of map.
1882 __isl_give PW
*FN(PW
,normalize
)(__isl_take PW
*pw
)
1889 for (i
= 0; i
< pw
->n
; ++i
) {
1890 set
= isl_set_normalize(isl_set_copy(pw
->p
[i
].set
));
1892 return FN(PW
,free
)(pw
);
1893 isl_set_free(pw
->p
[i
].set
);
1896 qsort(pw
->p
, pw
->n
, sizeof(pw
->p
[0]), &FN(PW
,qsort_set_cmp
));
1897 for (i
= pw
->n
- 1; i
>= 1; --i
) {
1898 if (!isl_set_plain_is_equal(pw
->p
[i
- 1].set
, pw
->p
[i
].set
))
1900 if (!FN(EL
,plain_is_equal
)(pw
->p
[i
- 1].FIELD
, pw
->p
[i
].FIELD
))
1902 set
= isl_set_union(isl_set_copy(pw
->p
[i
- 1].set
),
1903 isl_set_copy(pw
->p
[i
].set
));
1905 return FN(PW
,free
)(pw
);
1906 isl_set_free(pw
->p
[i
].set
);
1907 FN(EL
,free
)(pw
->p
[i
].FIELD
);
1908 isl_set_free(pw
->p
[i
- 1].set
);
1909 pw
->p
[i
- 1].set
= set
;
1910 for (j
= i
+ 1; j
< pw
->n
; ++j
)
1911 pw
->p
[j
- 1] = pw
->p
[j
];
1918 /* Is pw1 obviously equal to pw2?
1919 * That is, do they have obviously identical cells and obviously identical
1920 * elements on each cell?
1922 int FN(PW
,plain_is_equal
)(__isl_keep PW
*pw1
, __isl_keep PW
*pw2
)
1932 if (!isl_space_is_equal(pw1
->dim
, pw2
->dim
))
1935 pw1
= FN(PW
,copy
)(pw1
);
1936 pw2
= FN(PW
,copy
)(pw2
);
1937 pw1
= FN(PW
,normalize
)(pw1
);
1938 pw2
= FN(PW
,normalize
)(pw2
);
1942 equal
= pw1
->n
== pw2
->n
;
1943 for (i
= 0; equal
&& i
< pw1
->n
; ++i
) {
1944 equal
= isl_set_plain_is_equal(pw1
->p
[i
].set
, pw2
->p
[i
].set
);
1949 equal
= FN(EL
,plain_is_equal
)(pw1
->p
[i
].FIELD
, pw2
->p
[i
].FIELD
);
1964 static __isl_give PW
*FN(PW
,align_params_pw_multi_aff_and
)(__isl_take PW
*pw
,
1965 __isl_take isl_multi_aff
*ma
,
1966 __isl_give PW
*(*fn
)(__isl_take PW
*pw
, __isl_take isl_multi_aff
*ma
))
1969 isl_space
*ma_space
;
1971 ma_space
= isl_multi_aff_get_space(ma
);
1972 if (!pw
|| !ma
|| !ma_space
)
1974 if (isl_space_match(pw
->dim
, isl_dim_param
, ma_space
, isl_dim_param
)) {
1975 isl_space_free(ma_space
);
1978 ctx
= FN(PW
,get_ctx
)(pw
);
1979 if (!isl_space_has_named_params(pw
->dim
) ||
1980 !isl_space_has_named_params(ma_space
))
1981 isl_die(ctx
, isl_error_invalid
,
1982 "unaligned unnamed parameters", goto error
);
1983 pw
= FN(PW
,align_params
)(pw
, ma_space
);
1984 ma
= isl_multi_aff_align_params(ma
, FN(PW
,get_space
)(pw
));
1987 isl_space_free(ma_space
);
1989 isl_multi_aff_free(ma
);
1993 static __isl_give PW
*FN(PW
,align_params_pw_pw_multi_aff_and
)(__isl_take PW
*pw
,
1994 __isl_take isl_pw_multi_aff
*pma
,
1995 __isl_give PW
*(*fn
)(__isl_take PW
*pw
,
1996 __isl_take isl_pw_multi_aff
*ma
))
1999 isl_space
*pma_space
;
2001 pma_space
= isl_pw_multi_aff_get_space(pma
);
2002 if (!pw
|| !pma
|| !pma_space
)
2004 if (isl_space_match(pw
->dim
, isl_dim_param
, pma_space
, isl_dim_param
)) {
2005 isl_space_free(pma_space
);
2008 ctx
= FN(PW
,get_ctx
)(pw
);
2009 if (!isl_space_has_named_params(pw
->dim
) ||
2010 !isl_space_has_named_params(pma_space
))
2011 isl_die(ctx
, isl_error_invalid
,
2012 "unaligned unnamed parameters", goto error
);
2013 pw
= FN(PW
,align_params
)(pw
, pma_space
);
2014 pma
= isl_pw_multi_aff_align_params(pma
, FN(PW
,get_space
)(pw
));
2017 isl_space_free(pma_space
);
2019 isl_pw_multi_aff_free(pma
);
2023 /* Compute the pullback of "pw" by the function represented by "ma".
2024 * In other words, plug in "ma" in "pw".
2026 static __isl_give PW
*FN(PW
,pullback_multi_aff_aligned
)(__isl_take PW
*pw
,
2027 __isl_take isl_multi_aff
*ma
)
2030 isl_space
*space
= NULL
;
2032 ma
= isl_multi_aff_align_divs(ma
);
2033 pw
= FN(PW
,cow
)(pw
);
2037 space
= isl_space_join(isl_multi_aff_get_space(ma
),
2038 FN(PW
,get_space
)(pw
));
2040 for (i
= 0; i
< pw
->n
; ++i
) {
2041 pw
->p
[i
].set
= isl_set_preimage_multi_aff(pw
->p
[i
].set
,
2042 isl_multi_aff_copy(ma
));
2045 pw
->p
[i
].FIELD
= FN(EL
,pullback_multi_aff
)(pw
->p
[i
].FIELD
,
2046 isl_multi_aff_copy(ma
));
2047 if (!pw
->p
[i
].FIELD
)
2051 pw
= FN(PW
,reset_space
)(pw
, space
);
2052 isl_multi_aff_free(ma
);
2055 isl_space_free(space
);
2056 isl_multi_aff_free(ma
);
2061 __isl_give PW
*FN(PW
,pullback_multi_aff
)(__isl_take PW
*pw
,
2062 __isl_take isl_multi_aff
*ma
)
2064 return FN(PW
,align_params_pw_multi_aff_and
)(pw
, ma
,
2065 &FN(PW
,pullback_multi_aff_aligned
));
2068 /* Compute the pullback of "pw" by the function represented by "pma".
2069 * In other words, plug in "pma" in "pw".
2071 static __isl_give PW
*FN(PW
,pullback_pw_multi_aff_aligned
)(__isl_take PW
*pw
,
2072 __isl_take isl_pw_multi_aff
*pma
)
2082 space
= isl_space_join(isl_pw_multi_aff_get_space(pma
),
2083 FN(PW
,get_space
)(pw
));
2084 isl_pw_multi_aff_free(pma
);
2085 res
= FN(PW
,empty
)(space
);
2090 res
= FN(PW
,pullback_multi_aff
)(FN(PW
,copy
)(pw
),
2091 isl_multi_aff_copy(pma
->p
[0].maff
));
2092 res
= FN(PW
,intersect_domain
)(res
, isl_set_copy(pma
->p
[0].set
));
2094 for (i
= 1; i
< pma
->n
; ++i
) {
2097 res_i
= FN(PW
,pullback_multi_aff
)(FN(PW
,copy
)(pw
),
2098 isl_multi_aff_copy(pma
->p
[i
].maff
));
2099 res_i
= FN(PW
,intersect_domain
)(res_i
,
2100 isl_set_copy(pma
->p
[i
].set
));
2101 res
= FN(PW
,add_disjoint
)(res
, res_i
);
2104 isl_pw_multi_aff_free(pma
);
2108 isl_pw_multi_aff_free(pma
);
2113 __isl_give PW
*FN(PW
,pullback_pw_multi_aff
)(__isl_take PW
*pw
,
2114 __isl_take isl_pw_multi_aff
*pma
)
2116 return FN(PW
,align_params_pw_pw_multi_aff_and
)(pw
, pma
,
2117 &FN(PW
,pullback_pw_multi_aff_aligned
));