isl_schedule_node.c: is_disjoint_extension: return isl_bool
[isl.git] / isl_pw_templ.c
blobebd222955fd4c275a66d9b03945487033acd8670
1 /*
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,
10 * 91893 Orsay, France
11 * and Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France
14 #include <isl/id.h>
15 #include <isl/aff.h>
16 #include <isl_sort.h>
17 #include <isl_val_private.h>
19 #include <isl_pw_macro.h>
21 #include "opt_type.h"
23 __isl_give PW *FN(PW,alloc_size)(__isl_take isl_space *space
24 OPT_TYPE_PARAM, int n)
26 isl_ctx *ctx;
27 struct PW *pw;
29 if (!space)
30 return NULL;
31 ctx = isl_space_get_ctx(space);
32 isl_assert(ctx, n >= 0, goto error);
33 pw = isl_alloc(ctx, struct PW,
34 sizeof(struct PW) + (n - 1) * sizeof(S(PW,piece)));
35 if (!pw)
36 goto error;
38 pw->ref = 1;
39 OPT_SET_TYPE(pw->, type);
40 pw->size = n;
41 pw->n = 0;
42 pw->dim = space;
43 return pw;
44 error:
45 isl_space_free(space);
46 return NULL;
49 __isl_give PW *FN(PW,ZERO)(__isl_take isl_space *space OPT_TYPE_PARAM)
51 return FN(PW,alloc_size)(space OPT_TYPE_ARG(NO_LOC), 0);
54 /* Add a piece with domain "set" and base expression "el"
55 * to the piecewise expression "pw".
57 * Do this independently of the values of "set" and "el",
58 * such that this function can be used by isl_pw_*_dup.
60 __isl_give PW *FN(PW,add_dup_piece)(__isl_take PW *pw,
61 __isl_take isl_set *set, __isl_take EL *el)
63 isl_ctx *ctx;
64 isl_space *el_dim = NULL;
66 if (!pw || !set || !el)
67 goto error;
69 ctx = isl_set_get_ctx(set);
70 if (!OPT_EQUAL_TYPES(pw->, el->))
71 isl_die(ctx, isl_error_invalid, "fold types don't match",
72 goto error);
73 el_dim = FN(EL,get_space(el));
74 isl_assert(ctx, isl_space_is_equal(pw->dim, el_dim), goto error);
75 isl_assert(ctx, pw->n < pw->size, goto error);
77 pw->p[pw->n].set = set;
78 pw->p[pw->n].FIELD = el;
79 pw->n++;
81 isl_space_free(el_dim);
82 return pw;
83 error:
84 isl_space_free(el_dim);
85 FN(PW,free)(pw);
86 isl_set_free(set);
87 FN(EL,free)(el);
88 return NULL;
91 /* Add a piece with domain "set" and base expression "el"
92 * to the piecewise expression "pw", provided the domain
93 * is not obviously empty and the base expression
94 * is not equal to the default value.
96 __isl_give PW *FN(PW,add_piece)(__isl_take PW *pw,
97 __isl_take isl_set *set, __isl_take EL *el)
99 isl_bool skip;
101 skip = isl_set_plain_is_empty(set);
102 if (skip >= 0 && !skip)
103 skip = FN(EL,EL_IS_ZERO)(el);
104 if (skip >= 0 && !skip)
105 return FN(PW,add_dup_piece)(pw, set, el);
107 isl_set_free(set);
108 FN(EL,free)(el);
109 if (skip < 0)
110 return FN(PW,free)(pw);
111 return pw;
114 /* Does the space of "set" correspond to that of the domain of "el".
116 static isl_bool FN(PW,compatible_domain)(__isl_keep EL *el,
117 __isl_keep isl_set *set)
119 isl_bool ok;
120 isl_space *el_space, *set_space;
122 if (!set || !el)
123 return isl_bool_error;
124 set_space = isl_set_get_space(set);
125 el_space = FN(EL,get_space)(el);
126 ok = isl_space_is_domain_internal(set_space, el_space);
127 isl_space_free(el_space);
128 isl_space_free(set_space);
129 return ok;
132 /* Check that the space of "set" corresponds to that of the domain of "el".
134 static isl_stat FN(PW,check_compatible_domain)(__isl_keep EL *el,
135 __isl_keep isl_set *set)
137 isl_bool ok;
139 ok = FN(PW,compatible_domain)(el, set);
140 if (ok < 0)
141 return isl_stat_error;
142 if (!ok)
143 isl_die(isl_set_get_ctx(set), isl_error_invalid,
144 "incompatible spaces", return isl_stat_error);
146 return isl_stat_ok;
149 __isl_give PW *FN(PW,alloc)(OPT_TYPE_PARAM_FIRST
150 __isl_take isl_set *set, __isl_take EL *el)
152 PW *pw;
154 if (FN(PW,check_compatible_domain)(el, set) < 0)
155 goto error;
157 pw = FN(PW,alloc_size)(FN(EL,get_space)(el) OPT_TYPE_ARG(NO_LOC), 1);
159 return FN(PW,add_piece)(pw, set, el);
160 error:
161 isl_set_free(set);
162 FN(EL,free)(el);
163 return NULL;
166 __isl_give PW *FN(PW,dup)(__isl_keep PW *pw)
168 int i;
169 PW *dup;
171 if (!pw)
172 return NULL;
174 dup = FN(PW,alloc_size)(isl_space_copy(pw->dim)
175 OPT_TYPE_ARG(pw->), pw->n);
176 if (!dup)
177 return NULL;
179 for (i = 0; i < pw->n; ++i)
180 dup = FN(PW,add_dup_piece)(dup, isl_set_copy(pw->p[i].set),
181 FN(EL,copy)(pw->p[i].FIELD));
183 return dup;
186 __isl_give PW *FN(PW,cow)(__isl_take PW *pw)
188 if (!pw)
189 return NULL;
191 if (pw->ref == 1)
192 return pw;
193 pw->ref--;
194 return FN(PW,dup)(pw);
197 __isl_give PW *FN(PW,copy)(__isl_keep PW *pw)
199 if (!pw)
200 return NULL;
202 pw->ref++;
203 return pw;
206 __isl_null PW *FN(PW,free)(__isl_take PW *pw)
208 int i;
210 if (!pw)
211 return NULL;
212 if (--pw->ref > 0)
213 return NULL;
215 for (i = 0; i < pw->n; ++i) {
216 isl_set_free(pw->p[i].set);
217 FN(EL,free)(pw->p[i].FIELD);
219 isl_space_free(pw->dim);
220 free(pw);
222 return NULL;
225 /* Return the space of "pw".
227 __isl_keep isl_space *FN(PW,peek_space)(__isl_keep PW *pw)
229 return pw ? pw->dim : NULL;
232 __isl_give isl_space *FN(PW,get_space)(__isl_keep PW *pw)
234 return isl_space_copy(FN(PW,peek_space)(pw));
237 /* Return the space of "pw".
238 * This may be either a copy or the space itself
239 * if there is only one reference to "pw".
240 * This allows the space to be modified inplace
241 * if both the piecewise expression and its space have only a single reference.
242 * The caller is not allowed to modify "pw" between this call and
243 * a subsequent call to isl_pw_*_restore_*.
244 * The only exception is that isl_pw_*_free can be called instead.
246 __isl_give isl_space *FN(PW,take_space)(__isl_keep PW *pw)
248 isl_space *space;
250 if (!pw)
251 return NULL;
252 if (pw->ref != 1)
253 return FN(PW,get_space)(pw);
254 space = pw->dim;
255 pw->dim = NULL;
256 return space;
259 /* Set the space of "pw" to "space", where the space of "pw" may be missing
260 * due to a preceding call to isl_pw_*_take_space.
261 * However, in this case, "pw" only has a single reference and
262 * then the call to isl_pw_*_cow has no effect.
264 __isl_give PW *FN(PW,restore_space)(__isl_take PW *pw,
265 __isl_take isl_space *space)
267 if (!pw || !space)
268 goto error;
270 if (pw->dim == space) {
271 isl_space_free(space);
272 return pw;
275 pw = FN(PW,cow)(pw);
276 if (!pw)
277 goto error;
278 isl_space_free(pw->dim);
279 pw->dim = space;
281 return pw;
282 error:
283 FN(PW,free)(pw);
284 isl_space_free(space);
285 return NULL;
288 /* Check that "pos" is a valid position for a cell in "pw".
290 static isl_stat FN(PW,check_pos)(__isl_keep PW *pw, int pos)
292 if (!pw)
293 return isl_stat_error;
294 if (pos < 0 || pos >= pw->n)
295 isl_die(FN(PW,get_ctx)(pw), isl_error_internal,
296 "position out of bounds", return isl_stat_error);
297 return isl_stat_ok;
300 /* Return the cell at position "pos" in "pw".
302 static __isl_keep isl_set *FN(PW,peek_domain_at)(__isl_keep PW *pw, int pos)
304 if (FN(PW,check_pos)(pw, pos) < 0)
305 return NULL;
306 return pw->p[pos].set;
309 /* Return a copy of the cell at position "pos" in "pw".
311 __isl_give isl_set *FN(PW,get_domain_at)(__isl_keep PW *pw, int pos)
313 return isl_set_copy(FN(PW,peek_domain_at)(pw, pos));
316 /* Return the cell at position "pos" in "pw".
317 * This may be either a copy or the cell itself
318 * if there is only one reference to "pw".
319 * This allows the cell to be modified inplace
320 * if both the piecewise expression and this cell
321 * have only a single reference.
322 * The caller is not allowed to modify "pw" between this call and
323 * the subsequent call to isl_pw_*_restore_domain_at.
324 * The only exception is that isl_pw_*_free can be called instead.
326 static __isl_give isl_set *FN(PW,take_domain_at)(__isl_keep PW *pw, int pos)
328 isl_set *domain;
330 if (!pw)
331 return NULL;
332 if (pw->ref != 1)
333 return FN(PW,get_domain_at)(pw, pos);
334 if (FN(PW,check_pos)(pw, pos) < 0)
335 return NULL;
336 domain = pw->p[pos].set;
337 pw->p[pos].set = NULL;
338 return domain;
341 /* Set the cell at position "pos" in "pw" to "el",
342 * where this cell may be missing
343 * due to a preceding call to isl_pw_*_take_domain_at.
344 * However, in this case, "pw" only has a single reference and
345 * then the call to isl_pw_*_cow has no effect.
347 static __isl_give PW *FN(PW,restore_domain_at)(__isl_take PW *pw, int pos,
348 __isl_take isl_set *domain)
350 if (FN(PW,check_pos)(pw, pos) < 0 || !domain)
351 goto error;
353 if (pw->p[pos].set == domain) {
354 isl_set_free(domain);
355 return pw;
358 pw = FN(PW,cow)(pw);
359 if (!pw)
360 goto error;
361 isl_set_free(pw->p[pos].set);
362 pw->p[pos].set = domain;
364 return pw;
365 error:
366 FN(PW,free)(pw);
367 isl_set_free(domain);
368 return NULL;
371 /* Return the base expression associated to
372 * the cell at position "pos" in "pw".
374 static __isl_keep EL *FN(PW,peek_base_at)(__isl_keep PW *pw, int pos)
376 if (FN(PW,check_pos)(pw, pos) < 0)
377 return NULL;
378 return pw->p[pos].FIELD;
381 /* Return a copy of the base expression associated to
382 * the cell at position "pos" in "pw".
384 __isl_give EL *FN(PW,get_base_at)(__isl_keep PW *pw, int pos)
386 return FN(EL,copy)(FN(PW,peek_base_at)(pw, pos));
389 /* Return the base expression associated to
390 * the cell at position "pos" in "pw".
391 * This may be either a copy or the base expression itself
392 * if there is only one reference to "pw".
393 * This allows the base expression to be modified inplace
394 * if both the piecewise expression and this base expression
395 * have only a single reference.
396 * The caller is not allowed to modify "pw" between this call and
397 * a subsequent call to isl_pw_*_restore_*.
398 * The only exception is that isl_pw_*_free can be called instead.
400 __isl_give EL *FN(PW,take_base_at)(__isl_keep PW *pw, int pos)
402 EL *el;
404 if (!pw)
405 return NULL;
406 if (pw->ref != 1)
407 return FN(PW,get_base_at)(pw, pos);
408 if (FN(PW,check_pos)(pw, pos) < 0)
409 return NULL;
410 el = pw->p[pos].FIELD;
411 pw->p[pos].FIELD = NULL;
412 return el;
415 /* Set the base expression associated to
416 * the cell at position "pos" in "pw" to "el",
417 * where this base expression may be missing
418 * due to a preceding call to isl_pw_*_take_base_at.
419 * However, in this case, "pw" only has a single reference and
420 * then the call to isl_pw_*_cow has no effect.
421 * If "inplace" is set, then replacing the base expression by "el"
422 * is known not to change the meaning of "pw". It can therefore be replaced
423 * in all references to "pw".
425 static __isl_give PW *FN(PW,restore_base_at_)(__isl_take PW *pw, int pos,
426 __isl_take EL *el, int inplace)
428 if (FN(PW,check_pos)(pw, pos) < 0 || !el)
429 goto error;
431 if (pw->p[pos].FIELD == el) {
432 FN(EL,free)(el);
433 return pw;
436 if (!inplace)
437 pw = FN(PW,cow)(pw);
438 if (!pw)
439 goto error;
440 FN(EL,free)(pw->p[pos].FIELD);
441 pw->p[pos].FIELD = el;
443 return pw;
444 error:
445 FN(PW,free)(pw);
446 FN(EL,free)(el);
447 return NULL;
450 /* Set the base expression associated to
451 * the cell at position "pos" in "pw" to "el",
452 * where this base expression may be missing
453 * due to a preceding call to isl_pw_*_take_base_at.
455 __isl_give PW *FN(PW,restore_base_at)(__isl_take PW *pw, int pos,
456 __isl_take EL *el)
458 return FN(PW,restore_base_at_)(pw, pos, el, 0);
461 /* Set the base expression associated to
462 * the cell at position "pos" in "pw" to "el",
463 * where this base expression may be missing
464 * due to a preceding call to isl_pw_*_take_base_at.
465 * Furthermore, replacing the base expression by "el"
466 * is known not to change the meaning of "pw".
468 static __isl_give PW *FN(PW,restore_base_at_inplace)(__isl_take PW *pw, int pos,
469 __isl_take EL *el)
471 return FN(PW,restore_base_at_)(pw, pos, el, 1);
474 /* Create a piecewise expression with the given base expression on a universe
475 * domain.
477 static __isl_give PW *FN(FN(FN(PW,from),BASE),type_base)(__isl_take EL *el
478 OPT_TYPE_PARAM)
480 isl_set *dom = isl_set_universe(FN(EL,get_domain_space)(el));
481 return FN(PW,alloc)(OPT_TYPE_ARG_FIRST(NO_LOC) dom, el);
484 /* Create a piecewise expression with the given base expression on a universe
485 * domain.
487 * If the default value of this piecewise type is zero and
488 * if "el" is effectively zero, then create an empty piecewise expression
489 * instead.
491 static __isl_give PW *FN(FN(FN(PW,from),BASE),type)(__isl_take EL *el
492 OPT_TYPE_PARAM)
494 isl_bool is_zero;
495 isl_space *space;
497 if (!DEFAULT_IS_ZERO)
498 return FN(FN(FN(PW,from),BASE),type_base)(el
499 OPT_TYPE_ARG(NO_LOC));
500 is_zero = FN(EL,EL_IS_ZERO)(el);
501 if (is_zero < 0)
502 goto error;
503 if (!is_zero)
504 return FN(FN(FN(PW,from),BASE),type_base)(el
505 OPT_TYPE_ARG(NO_LOC));
506 space = FN(EL,get_space)(el);
507 FN(EL,free)(el);
508 return FN(PW,ZERO)(space OPT_TYPE_ARG(NO_LOC));
509 error:
510 FN(EL,free)(el);
511 return NULL;
514 #ifdef HAS_TYPE
515 /* Create a piecewise expression with the given base expression on a universe
516 * domain.
518 * Pass along the type as an extra argument for improved uniformity
519 * with piecewise types that do not have a fold type.
521 __isl_give PW *FN(FN(PW,from),BASE)(__isl_take EL *el)
523 enum isl_fold type = FN(EL,get_type)(el);
524 return FN(FN(FN(PW,from),BASE),type)(el, type);
526 #else
527 __isl_give PW *FN(FN(PW,from),BASE)(__isl_take EL *el)
529 return FN(FN(FN(PW,from),BASE),type)(el);
531 #endif
533 const char *FN(PW,get_dim_name)(__isl_keep PW *pw, enum isl_dim_type type,
534 unsigned pos)
536 return pw ? isl_space_get_dim_name(pw->dim, type, pos) : NULL;
539 isl_bool FN(PW,has_dim_id)(__isl_keep PW *pw, enum isl_dim_type type,
540 unsigned pos)
542 return pw ? isl_space_has_dim_id(pw->dim, type, pos) : isl_bool_error;
545 __isl_give isl_id *FN(PW,get_dim_id)(__isl_keep PW *pw, enum isl_dim_type type,
546 unsigned pos)
548 return pw ? isl_space_get_dim_id(pw->dim, type, pos) : NULL;
551 isl_bool FN(PW,has_tuple_name)(__isl_keep PW *pw, enum isl_dim_type type)
553 return pw ? isl_space_has_tuple_name(pw->dim, type) : isl_bool_error;
556 const char *FN(PW,get_tuple_name)(__isl_keep PW *pw, enum isl_dim_type type)
558 return pw ? isl_space_get_tuple_name(pw->dim, type) : NULL;
561 isl_bool FN(PW,has_tuple_id)(__isl_keep PW *pw, enum isl_dim_type type)
563 return pw ? isl_space_has_tuple_id(pw->dim, type) : isl_bool_error;
566 __isl_give isl_id *FN(PW,get_tuple_id)(__isl_keep PW *pw, enum isl_dim_type type)
568 return pw ? isl_space_get_tuple_id(pw->dim, type) : NULL;
571 isl_bool FN(PW,IS_ZERO)(__isl_keep PW *pw)
573 if (!pw)
574 return isl_bool_error;
576 return isl_bool_ok(pw->n == 0);
579 __isl_give PW *FN(PW,realign_domain)(__isl_take PW *pw,
580 __isl_take isl_reordering *exp)
582 int i;
583 isl_size n;
585 n = FN(PW,n_piece)(pw);
586 if (n < 0 || !exp)
587 goto error;
589 for (i = 0; i < n; ++i) {
590 isl_set *domain;
591 EL *el;
593 domain = FN(PW,take_domain_at)(pw, i);
594 domain = isl_set_realign(domain, isl_reordering_copy(exp));
595 pw = FN(PW,restore_domain_at)(pw, i, domain);
597 el = FN(PW,take_base_at)(pw, i);
598 el = FN(EL,realign_domain)(el, isl_reordering_copy(exp));
599 pw = FN(PW,restore_base_at)(pw, i, el);
602 pw = FN(PW,reset_domain_space)(pw, isl_reordering_get_space(exp));
604 isl_reordering_free(exp);
605 return pw;
606 error:
607 isl_reordering_free(exp);
608 FN(PW,free)(pw);
609 return NULL;
612 #undef TYPE
613 #define TYPE PW
615 #include "isl_check_named_params_templ.c"
617 /* Align the parameters of "pw" to those of "model".
619 __isl_give PW *FN(PW,align_params)(__isl_take PW *pw, __isl_take isl_space *model)
621 isl_ctx *ctx;
622 isl_bool equal_params;
624 if (!pw || !model)
625 goto error;
627 ctx = isl_space_get_ctx(model);
628 if (!isl_space_has_named_params(model))
629 isl_die(ctx, isl_error_invalid,
630 "model has unnamed parameters", goto error);
631 if (FN(PW,check_named_params)(pw) < 0)
632 goto error;
633 equal_params = isl_space_has_equal_params(pw->dim, model);
634 if (equal_params < 0)
635 goto error;
636 if (!equal_params) {
637 isl_reordering *exp;
639 exp = isl_parameter_alignment_reordering(pw->dim, model);
640 exp = isl_reordering_extend_space(exp,
641 FN(PW,get_domain_space)(pw));
642 pw = FN(PW,realign_domain)(pw, exp);
645 isl_space_free(model);
646 return pw;
647 error:
648 isl_space_free(model);
649 FN(PW,free)(pw);
650 return NULL;
653 #undef TYPE
654 #define TYPE PW
656 static
657 #include "isl_align_params_bin_templ.c"
659 #undef SUFFIX
660 #define SUFFIX set
661 #undef ARG1
662 #define ARG1 PW
663 #undef ARG2
664 #define ARG2 isl_set
666 static
667 #include "isl_align_params_templ.c"
669 #undef TYPE
670 #define TYPE PW
672 #include "isl_type_has_equal_space_bin_templ.c"
673 #include "isl_type_check_equal_space_templ.c"
675 /* Private version of "union_add". For isl_pw_qpolynomial and
676 * isl_pw_qpolynomial_fold, we prefer to simply call it "add".
678 static __isl_give PW *FN(PW,union_add_)(__isl_take PW *pw1, __isl_take PW *pw2)
680 int i, j, n;
681 struct PW *res;
682 isl_ctx *ctx;
683 isl_set *set;
685 if (FN(PW,align_params_bin)(&pw1, &pw2) < 0)
686 goto error;
688 ctx = isl_space_get_ctx(pw1->dim);
689 if (!OPT_EQUAL_TYPES(pw1->, pw2->))
690 isl_die(ctx, isl_error_invalid,
691 "fold types don't match", goto error);
692 if (FN(PW,check_equal_space)(pw1, pw2) < 0)
693 goto error;
695 if (FN(PW,IS_ZERO)(pw1)) {
696 FN(PW,free)(pw1);
697 return pw2;
700 if (FN(PW,IS_ZERO)(pw2)) {
701 FN(PW,free)(pw2);
702 return pw1;
705 n = (pw1->n + 1) * (pw2->n + 1);
706 res = FN(PW,alloc_size)(isl_space_copy(pw1->dim)
707 OPT_TYPE_ARG(pw1->), n);
709 for (i = 0; i < pw1->n; ++i) {
710 set = isl_set_copy(pw1->p[i].set);
711 for (j = 0; j < pw2->n; ++j) {
712 struct isl_set *common;
713 EL *sum;
714 common = isl_set_intersect(isl_set_copy(pw1->p[i].set),
715 isl_set_copy(pw2->p[j].set));
716 if (isl_set_plain_is_empty(common)) {
717 isl_set_free(common);
718 continue;
720 set = isl_set_subtract(set,
721 isl_set_copy(pw2->p[j].set));
723 sum = FN(EL,add_on_domain)(common,
724 FN(EL,copy)(pw1->p[i].FIELD),
725 FN(EL,copy)(pw2->p[j].FIELD));
727 res = FN(PW,add_piece)(res, common, sum);
729 res = FN(PW,add_piece)(res, set, FN(EL,copy)(pw1->p[i].FIELD));
732 for (j = 0; j < pw2->n; ++j) {
733 set = isl_set_copy(pw2->p[j].set);
734 for (i = 0; i < pw1->n; ++i)
735 set = isl_set_subtract(set,
736 isl_set_copy(pw1->p[i].set));
737 res = FN(PW,add_piece)(res, set, FN(EL,copy)(pw2->p[j].FIELD));
740 FN(PW,free)(pw1);
741 FN(PW,free)(pw2);
743 return res;
744 error:
745 FN(PW,free)(pw1);
746 FN(PW,free)(pw2);
747 return NULL;
750 /* Make sure "pw" has room for at least "n" more pieces.
752 * If there is only one reference to pw, we extend it in place.
753 * Otherwise, we create a new PW and copy the pieces.
755 static __isl_give PW *FN(PW,grow)(__isl_take PW *pw, int n)
757 int i;
758 isl_ctx *ctx;
759 PW *res;
761 if (!pw)
762 return NULL;
763 if (pw->n + n <= pw->size)
764 return pw;
765 ctx = FN(PW,get_ctx)(pw);
766 n += pw->n;
767 if (pw->ref == 1) {
768 res = isl_realloc(ctx, pw, struct PW,
769 sizeof(struct PW) + (n - 1) * sizeof(S(PW,piece)));
770 if (!res)
771 return FN(PW,free)(pw);
772 res->size = n;
773 return res;
775 res = FN(PW,alloc_size)(isl_space_copy(pw->dim) OPT_TYPE_ARG(pw->), n);
776 if (!res)
777 return FN(PW,free)(pw);
778 for (i = 0; i < pw->n; ++i)
779 res = FN(PW,add_piece)(res, isl_set_copy(pw->p[i].set),
780 FN(EL,copy)(pw->p[i].FIELD));
781 FN(PW,free)(pw);
782 return res;
785 __isl_give PW *FN(PW,add_disjoint)(__isl_take PW *pw1, __isl_take PW *pw2)
787 int i;
788 isl_ctx *ctx;
790 if (FN(PW,align_params_bin)(&pw1, &pw2) < 0)
791 goto error;
793 if (pw1->size < pw1->n + pw2->n && pw1->n < pw2->n)
794 return FN(PW,add_disjoint)(pw2, pw1);
796 ctx = isl_space_get_ctx(pw1->dim);
797 if (!OPT_EQUAL_TYPES(pw1->, pw2->))
798 isl_die(ctx, isl_error_invalid,
799 "fold types don't match", goto error);
800 if (FN(PW,check_equal_space)(pw1, pw2) < 0)
801 goto error;
803 if (FN(PW,IS_ZERO)(pw1)) {
804 FN(PW,free)(pw1);
805 return pw2;
808 if (FN(PW,IS_ZERO)(pw2)) {
809 FN(PW,free)(pw2);
810 return pw1;
813 pw1 = FN(PW,grow)(pw1, pw2->n);
814 if (!pw1)
815 goto error;
817 for (i = 0; i < pw2->n; ++i)
818 pw1 = FN(PW,add_piece)(pw1,
819 isl_set_copy(pw2->p[i].set),
820 FN(EL,copy)(pw2->p[i].FIELD));
822 FN(PW,free)(pw2);
824 return pw1;
825 error:
826 FN(PW,free)(pw1);
827 FN(PW,free)(pw2);
828 return NULL;
831 /* This function is currently only used from isl_aff.c
833 static __isl_give PW *FN(PW,on_shared_domain_in)(__isl_take PW *pw1,
834 __isl_take PW *pw2, __isl_take isl_space *space,
835 __isl_give EL *(*fn)(__isl_take EL *el1, __isl_take EL *el2))
836 __attribute__ ((unused));
838 /* Apply "fn" to pairs of elements from pw1 and pw2 on shared domains.
839 * The result of "fn" (and therefore also of this function) lives in "space".
841 static __isl_give PW *FN(PW,on_shared_domain_in)(__isl_take PW *pw1,
842 __isl_take PW *pw2, __isl_take isl_space *space,
843 __isl_give EL *(*fn)(__isl_take EL *el1, __isl_take EL *el2))
845 int i, j, n;
846 PW *res = NULL;
848 if (!pw1 || !pw2)
849 goto error;
851 n = pw1->n * pw2->n;
852 res = FN(PW,alloc_size)(isl_space_copy(space) OPT_TYPE_ARG(pw1->), n);
854 for (i = 0; i < pw1->n; ++i) {
855 for (j = 0; j < pw2->n; ++j) {
856 isl_set *common;
857 EL *res_ij;
858 int empty;
860 common = isl_set_intersect(
861 isl_set_copy(pw1->p[i].set),
862 isl_set_copy(pw2->p[j].set));
863 empty = isl_set_plain_is_empty(common);
864 if (empty < 0 || empty) {
865 isl_set_free(common);
866 if (empty < 0)
867 goto error;
868 continue;
871 res_ij = fn(FN(EL,copy)(pw1->p[i].FIELD),
872 FN(EL,copy)(pw2->p[j].FIELD));
873 res_ij = FN(EL,gist)(res_ij, isl_set_copy(common));
875 res = FN(PW,add_piece)(res, common, res_ij);
879 isl_space_free(space);
880 FN(PW,free)(pw1);
881 FN(PW,free)(pw2);
882 return res;
883 error:
884 isl_space_free(space);
885 FN(PW,free)(pw1);
886 FN(PW,free)(pw2);
887 FN(PW,free)(res);
888 return NULL;
891 /* This function is currently only used from isl_aff.c
893 static __isl_give PW *FN(PW,on_shared_domain)(__isl_take PW *pw1,
894 __isl_take PW *pw2,
895 __isl_give EL *(*fn)(__isl_take EL *el1, __isl_take EL *el2))
896 __attribute__ ((unused));
898 /* Apply "fn" to pairs of elements from pw1 and pw2 on shared domains.
899 * The result of "fn" is assumed to live in the same space as "pw1" and "pw2".
901 static __isl_give PW *FN(PW,on_shared_domain)(__isl_take PW *pw1,
902 __isl_take PW *pw2,
903 __isl_give EL *(*fn)(__isl_take EL *el1, __isl_take EL *el2))
905 isl_space *space;
907 if (FN(PW,check_equal_space)(pw1, pw2) < 0)
908 goto error;
910 space = isl_space_copy(pw1->dim);
911 return FN(PW,on_shared_domain_in)(pw1, pw2, space, fn);
912 error:
913 FN(PW,free)(pw1);
914 FN(PW,free)(pw2);
915 return NULL;
918 /* Return the parameter domain of "pw".
920 __isl_give isl_set *FN(PW,params)(__isl_take PW *pw)
922 return isl_set_params(FN(PW,domain)(pw));
925 __isl_give isl_set *FN(PW,domain)(__isl_take PW *pw)
927 int i;
928 isl_set *dom;
930 if (!pw)
931 return NULL;
933 dom = isl_set_empty(FN(PW,get_domain_space)(pw));
934 for (i = 0; i < pw->n; ++i)
935 dom = isl_set_union_disjoint(dom, isl_set_copy(pw->p[i].set));
937 FN(PW,free)(pw);
939 return dom;
942 /* Exploit the equalities in the domain of piece "i" of "pw"
943 * to simplify the associated function.
944 * If the domain of piece "i" is empty, then remove it entirely,
945 * replacing it with the final piece.
947 static __isl_give PW *FN(PW,exploit_equalities_and_remove_if_empty)(
948 __isl_take PW *pw, int i)
950 EL *el;
951 isl_basic_set *aff;
952 int empty = isl_set_plain_is_empty(pw->p[i].set);
954 if (empty < 0)
955 return FN(PW,free)(pw);
956 if (empty) {
957 isl_set_free(pw->p[i].set);
958 FN(EL,free)(pw->p[i].FIELD);
959 if (i != pw->n - 1)
960 pw->p[i] = pw->p[pw->n - 1];
961 pw->n--;
963 return pw;
966 aff = isl_set_affine_hull(FN(PW,get_domain_at)(pw, i));
967 el = FN(PW,take_base_at)(pw, i);
968 el = FN(EL,substitute_equalities)(el, aff);
969 pw = FN(PW,restore_base_at_inplace)(pw, i, el);
971 return pw;
974 /* Convert a piecewise expression defined over a parameter domain
975 * into one that is defined over a zero-dimensional set.
977 __isl_give PW *FN(PW,from_range)(__isl_take PW *pw)
979 isl_space *space;
981 if (!pw)
982 return NULL;
983 if (!isl_space_is_set(pw->dim))
984 isl_die(FN(PW,get_ctx)(pw), isl_error_invalid,
985 "not living in a set space", return FN(PW,free)(pw));
987 space = FN(PW,get_space)(pw);
988 space = isl_space_from_range(space);
989 pw = FN(PW,reset_space)(pw, space);
991 return pw;
994 /* Fix the value of the given parameter or domain dimension of "pw"
995 * to be equal to "value".
997 __isl_give PW *FN(PW,fix_si)(__isl_take PW *pw, enum isl_dim_type type,
998 unsigned pos, int value)
1000 int i;
1001 isl_size n;
1003 n = FN(PW,n_piece)(pw);
1004 if (n < 0)
1005 return FN(PW,free)(pw);
1007 if (type == isl_dim_out)
1008 isl_die(FN(PW,get_ctx)(pw), isl_error_invalid,
1009 "cannot fix output dimension", return FN(PW,free)(pw));
1011 if (type == isl_dim_in)
1012 type = isl_dim_set;
1014 for (i = n - 1; i >= 0; --i) {
1015 isl_set *domain;
1017 domain = FN(PW,take_domain_at)(pw, i);
1018 domain = isl_set_fix_si(domain, type, pos, value);
1019 pw = FN(PW,restore_domain_at)(pw, i, domain);
1020 pw = FN(PW,exploit_equalities_and_remove_if_empty)(pw, i);
1023 return pw;
1026 /* Restrict the domain of "pw" by combining each cell
1027 * with "set" through a call to "fn", where "fn" may be
1028 * isl_set_intersect, isl_set_intersect_params, isl_set_intersect_factor_domain,
1029 * isl_set_intersect_factor_range or isl_set_subtract.
1031 static __isl_give PW *FN(PW,restrict_domain)(__isl_take PW *pw,
1032 __isl_take isl_set *set,
1033 __isl_give isl_set *(*fn)(__isl_take isl_set *set1,
1034 __isl_take isl_set *set2))
1036 int i;
1037 isl_size n;
1039 FN(PW,align_params_set)(&pw, &set);
1040 n = FN(PW,n_piece)(pw);
1041 if (n < 0 || !set)
1042 goto error;
1044 for (i = n - 1; i >= 0; --i) {
1045 isl_set *domain;
1047 domain = FN(PW,take_domain_at)(pw, i);
1048 domain = fn(domain, isl_set_copy(set));
1049 pw = FN(PW,restore_domain_at)(pw, i, domain);
1050 pw = FN(PW,exploit_equalities_and_remove_if_empty)(pw, i);
1053 isl_set_free(set);
1054 return pw;
1055 error:
1056 isl_set_free(set);
1057 FN(PW,free)(pw);
1058 return NULL;
1061 __isl_give PW *FN(PW,intersect_domain)(__isl_take PW *pw,
1062 __isl_take isl_set *context)
1064 return FN(PW,restrict_domain)(pw, context, &isl_set_intersect);
1067 /* Intersect the domain of "pw" with the parameter domain "context".
1069 __isl_give PW *FN(PW,intersect_params)(__isl_take PW *pw,
1070 __isl_take isl_set *context)
1072 return FN(PW,restrict_domain)(pw, context, &isl_set_intersect_params);
1075 /* Given a piecewise expression "pw" with domain in a space [A -> B] and
1076 * a set in the space A, intersect the domain with the set.
1078 __isl_give PW *FN(PW,intersect_domain_wrapped_domain)(__isl_take PW *pw,
1079 __isl_take isl_set *set)
1081 return FN(PW,restrict_domain)(pw, set,
1082 &isl_set_intersect_factor_domain);
1085 /* Given a piecewise expression "pw" with domain in a space [A -> B] and
1086 * a set in the space B, intersect the domain with the set.
1088 __isl_give PW *FN(PW,intersect_domain_wrapped_range)(__isl_take PW *pw,
1089 __isl_take isl_set *set)
1091 return FN(PW,restrict_domain)(pw, set, &isl_set_intersect_factor_range);
1094 /* Subtract "domain' from the domain of "pw".
1096 __isl_give PW *FN(PW,subtract_domain)(__isl_take PW *pw,
1097 __isl_take isl_set *domain)
1099 return FN(PW,restrict_domain)(pw, domain, &isl_set_subtract);
1102 /* Return -1 if the piece "p1" should be sorted before "p2"
1103 * and 1 if it should be sorted after "p2".
1104 * Return 0 if they do not need to be sorted in a specific order.
1106 * The two pieces are compared on the basis of their function value expressions.
1108 static int FN(PW,sort_field_cmp)(const void *p1, const void *p2, void *arg)
1110 struct FN(PW,piece) const *pc1 = p1;
1111 struct FN(PW,piece) const *pc2 = p2;
1113 return FN(EL,plain_cmp)(pc1->FIELD, pc2->FIELD);
1116 /* Sort the pieces of "pw" according to their function value
1117 * expressions and then combine pairs of adjacent pieces with
1118 * the same such expression.
1120 * The sorting is performed in place because it does not
1121 * change the meaning of "pw", but care needs to be
1122 * taken not to change any possible other copies of "pw"
1123 * in case anything goes wrong.
1125 static __isl_give PW *FN(PW,sort_unique)(__isl_take PW *pw)
1127 int i, j;
1128 isl_set *set;
1130 if (!pw)
1131 return NULL;
1132 if (pw->n <= 1)
1133 return pw;
1134 if (isl_sort(pw->p, pw->n, sizeof(pw->p[0]),
1135 &FN(PW,sort_field_cmp), NULL) < 0)
1136 return FN(PW,free)(pw);
1137 for (i = pw->n - 1; i >= 1; --i) {
1138 isl_bool equal;
1139 EL *el, *el_prev;
1140 isl_set *set_prev;
1142 el = FN(PW,peek_base_at)(pw, i);
1143 el_prev = FN(PW,peek_base_at)(pw, i - 1);
1144 equal = FN(EL,plain_is_equal)(el, el_prev);
1145 if (equal < 0)
1146 return FN(PW,free)(pw);
1147 if (!equal)
1148 continue;
1149 set = FN(PW,get_domain_at)(pw, i);
1150 set_prev = FN(PW,get_domain_at)(pw, i - 1);
1151 set = isl_set_union(set_prev, set);
1152 if (!set)
1153 return FN(PW,free)(pw);
1154 isl_set_free(pw->p[i].set);
1155 FN(EL,free)(pw->p[i].FIELD);
1156 isl_set_free(pw->p[i - 1].set);
1157 pw->p[i - 1].set = set;
1158 for (j = i + 1; j < pw->n; ++j)
1159 pw->p[j - 1] = pw->p[j];
1160 pw->n--;
1163 return pw;
1166 /* Compute the gist of "pw" with respect to the domain constraints
1167 * of "context" for the case where the domain of the last element
1168 * of "pw" is equal to "context".
1169 * Call "fn_el" to compute the gist of this element, replace
1170 * its domain by the universe and drop all other elements
1171 * as their domains are necessarily disjoint from "context".
1173 static __isl_give PW *FN(PW,gist_last)(__isl_take PW *pw,
1174 __isl_take isl_set *context,
1175 __isl_give EL *(*fn_el)(__isl_take EL *el, __isl_take isl_set *set))
1177 int i;
1178 isl_space *space;
1179 EL *el;
1181 for (i = 0; i < pw->n - 1; ++i) {
1182 isl_set_free(pw->p[i].set);
1183 FN(EL,free)(pw->p[i].FIELD);
1185 pw->p[0].FIELD = pw->p[pw->n - 1].FIELD;
1186 pw->p[0].set = pw->p[pw->n - 1].set;
1187 pw->n = 1;
1189 space = isl_set_get_space(context);
1190 el = FN(PW,take_base_at)(pw, 0);
1191 el = fn_el(el, context);
1192 pw = FN(PW,restore_base_at)(pw, 0, el);
1193 context = isl_set_universe(space);
1194 pw = FN(PW,restore_domain_at)(pw, 0, context);
1196 return pw;
1199 /* Compute the gist of "pw" with respect to the domain constraints
1200 * of "context". Call "fn_el" to compute the gist of the elements
1201 * and "fn_dom" to compute the gist of the domains.
1203 * If the piecewise expression is empty or the context is the universe,
1204 * then nothing can be simplified.
1205 * If "pw" has a single domain and it is equal to "context",
1206 * then simply replace the domain by the universe.
1207 * Combine duplicate function value expressions first
1208 * to increase the chance of "pw" having a single domain.
1210 static __isl_give PW *FN(PW,gist_fn)(__isl_take PW *pw,
1211 __isl_take isl_set *context,
1212 __isl_give EL *(*fn_el)(__isl_take EL *el,
1213 __isl_take isl_set *set),
1214 __isl_give isl_set *(*fn_dom)(__isl_take isl_set *set,
1215 __isl_take isl_basic_set *bset))
1217 int i;
1218 int is_universe;
1219 isl_basic_set *hull = NULL;
1221 pw = FN(PW,sort_unique)(pw);
1222 if (!pw || !context)
1223 goto error;
1225 if (pw->n == 0) {
1226 isl_set_free(context);
1227 return pw;
1230 is_universe = isl_set_plain_is_universe(context);
1231 if (is_universe < 0)
1232 goto error;
1233 if (is_universe) {
1234 isl_set_free(context);
1235 return pw;
1238 FN(PW,align_params_set)(&pw, &context);
1240 pw = FN(PW,cow)(pw);
1241 if (!pw)
1242 goto error;
1244 if (pw->n == 1) {
1245 int equal;
1247 equal = isl_set_plain_is_equal(pw->p[0].set, context);
1248 if (equal < 0)
1249 goto error;
1250 if (equal)
1251 return FN(PW,gist_last)(pw, context, fn_el);
1254 context = isl_set_compute_divs(context);
1255 hull = isl_set_simple_hull(isl_set_copy(context));
1257 for (i = pw->n - 1; i >= 0; --i) {
1258 isl_set *set_i;
1259 EL *el;
1260 int empty;
1262 if (i == pw->n - 1) {
1263 int equal;
1264 equal = isl_set_plain_is_equal(pw->p[i].set, context);
1265 if (equal < 0)
1266 goto error;
1267 if (equal) {
1268 isl_basic_set_free(hull);
1269 return FN(PW,gist_last)(pw, context, fn_el);
1272 set_i = FN(PW,get_domain_at)(pw, i);
1273 set_i = isl_set_intersect(set_i, isl_set_copy(context));
1274 empty = isl_set_plain_is_empty(set_i);
1275 el = FN(PW,take_base_at)(pw, i);
1276 el = fn_el(el, set_i);
1277 pw = FN(PW,restore_base_at)(pw, i, el);
1278 set_i = FN(PW,take_domain_at)(pw, i);
1279 set_i = fn_dom(set_i, isl_basic_set_copy(hull));
1280 pw = FN(PW,restore_domain_at)(pw, i, set_i);
1281 if (empty < 0 || !pw)
1282 goto error;
1283 if (empty) {
1284 isl_set_free(pw->p[i].set);
1285 FN(EL,free)(pw->p[i].FIELD);
1286 if (i != pw->n - 1)
1287 pw->p[i] = pw->p[pw->n - 1];
1288 pw->n--;
1292 isl_basic_set_free(hull);
1293 isl_set_free(context);
1295 return pw;
1296 error:
1297 FN(PW,free)(pw);
1298 isl_basic_set_free(hull);
1299 isl_set_free(context);
1300 return NULL;
1303 __isl_give PW *FN(PW,gist)(__isl_take PW *pw, __isl_take isl_set *context)
1305 return FN(PW,gist_fn)(pw, context, &FN(EL,gist),
1306 &isl_set_gist_basic_set);
1309 __isl_give PW *FN(PW,gist_params)(__isl_take PW *pw,
1310 __isl_take isl_set *context)
1312 return FN(PW,gist_fn)(pw, context, &FN(EL,gist_params),
1313 &isl_set_gist_params_basic_set);
1316 /* Coalesce the domains of "pw".
1318 * Prior to the actual coalescing, first sort the pieces such that
1319 * pieces with the same function value expression are combined
1320 * into a single piece, the combined domain of which can then
1321 * be coalesced.
1323 __isl_give PW *FN(PW,coalesce)(__isl_take PW *pw)
1325 int i;
1326 isl_size n;
1328 pw = FN(PW,sort_unique)(pw);
1329 n = FN(PW,n_piece)(pw);
1330 if (n < 0)
1331 return FN(PW,free)(pw);
1333 for (i = 0; i < n; ++i) {
1334 pw->p[i].set = isl_set_coalesce(pw->p[i].set);
1335 if (!pw->p[i].set)
1336 goto error;
1339 return pw;
1340 error:
1341 FN(PW,free)(pw);
1342 return NULL;
1345 isl_ctx *FN(PW,get_ctx)(__isl_keep PW *pw)
1347 return pw ? isl_space_get_ctx(pw->dim) : NULL;
1350 isl_bool FN(PW,involves_dims)(__isl_keep PW *pw, enum isl_dim_type type,
1351 unsigned first, unsigned n)
1353 int i;
1354 enum isl_dim_type set_type;
1356 if (!pw)
1357 return isl_bool_error;
1358 if (pw->n == 0 || n == 0)
1359 return isl_bool_false;
1361 set_type = type == isl_dim_in ? isl_dim_set : type;
1363 for (i = 0; i < pw->n; ++i) {
1364 isl_bool involves = FN(EL,involves_dims)(pw->p[i].FIELD,
1365 type, first, n);
1366 if (involves < 0 || involves)
1367 return involves;
1368 involves = isl_set_involves_dims(pw->p[i].set,
1369 set_type, first, n);
1370 if (involves < 0 || involves)
1371 return involves;
1373 return isl_bool_false;
1376 __isl_give PW *FN(PW,set_dim_name)(__isl_take PW *pw,
1377 enum isl_dim_type type, unsigned pos, const char *s)
1379 isl_space *space;
1381 space = FN(PW,get_space)(pw);
1382 space = isl_space_set_dim_name(space, type, pos, s);
1383 return FN(PW,reset_space)(pw, space);
1386 __isl_give PW *FN(PW,drop_dims)(__isl_take PW *pw,
1387 enum isl_dim_type type, unsigned first, unsigned n)
1389 int i;
1390 isl_size n_piece;
1391 enum isl_dim_type set_type;
1392 isl_space *space;
1394 n_piece = FN(PW,n_piece)(pw);
1395 if (n_piece < 0)
1396 return FN(PW,free)(pw);
1397 if (n == 0 && !isl_space_get_tuple_name(pw->dim, type))
1398 return pw;
1400 set_type = type == isl_dim_in ? isl_dim_set : type;
1402 space = FN(PW,take_space)(pw);
1403 space = isl_space_drop_dims(space, type, first, n);
1404 pw = FN(PW,restore_space)(pw, space);
1405 for (i = 0; i < n_piece; ++i) {
1406 isl_set *domain;
1407 EL *el;
1409 el = FN(PW,take_base_at)(pw, i);
1410 el = FN(EL,drop_dims)(el, type, first, n);
1411 pw = FN(PW,restore_base_at)(pw, i, el);
1412 if (type == isl_dim_out)
1413 continue;
1414 domain = FN(PW,take_domain_at)(pw, i);
1415 domain = isl_set_drop(domain, set_type, first, n);
1416 pw = FN(PW,restore_domain_at)(pw, i, domain);
1419 return pw;
1422 /* This function is very similar to drop_dims.
1423 * The only difference is that the cells may still involve
1424 * the specified dimensions. They are removed using
1425 * isl_set_project_out instead of isl_set_drop.
1427 __isl_give PW *FN(PW,project_out)(__isl_take PW *pw,
1428 enum isl_dim_type type, unsigned first, unsigned n)
1430 int i;
1431 isl_size n_piece;
1432 enum isl_dim_type set_type;
1433 isl_space *space;
1435 n_piece = FN(PW,n_piece)(pw);
1436 if (n_piece < 0)
1437 return FN(PW,free)(pw);
1438 if (n == 0 && !isl_space_get_tuple_name(pw->dim, type))
1439 return pw;
1441 set_type = type == isl_dim_in ? isl_dim_set : type;
1443 space = FN(PW,take_space)(pw);
1444 space = isl_space_drop_dims(space, type, first, n);
1445 pw = FN(PW,restore_space)(pw, space);
1446 for (i = 0; i < n_piece; ++i) {
1447 isl_set *domain;
1448 EL *el;
1450 domain = FN(PW,take_domain_at)(pw, i);
1451 domain = isl_set_project_out(domain, set_type, first, n);
1452 pw = FN(PW,restore_domain_at)(pw, i, domain);
1453 el = FN(PW,take_base_at)(pw, i);
1454 el = FN(EL,drop_dims)(el, type, first, n);
1455 pw = FN(PW,restore_base_at)(pw, i, el);
1458 return pw;
1461 /* Project the domain of pw onto its parameter space.
1463 __isl_give PW *FN(PW,project_domain_on_params)(__isl_take PW *pw)
1465 isl_space *space;
1466 isl_size n;
1468 n = FN(PW,dim)(pw, isl_dim_in);
1469 if (n < 0)
1470 return FN(PW,free)(pw);
1471 pw = FN(PW,project_out)(pw, isl_dim_in, 0, n);
1472 space = FN(PW,get_domain_space)(pw);
1473 space = isl_space_params(space);
1474 pw = FN(PW,reset_domain_space)(pw, space);
1475 return pw;
1478 /* Drop all parameters not referenced by "pw".
1480 __isl_give PW *FN(PW,drop_unused_params)(__isl_take PW *pw)
1482 isl_size n;
1483 int i;
1485 if (FN(PW,check_named_params)(pw) < 0)
1486 return FN(PW,free)(pw);
1488 n = FN(PW,dim)(pw, isl_dim_param);
1489 if (n < 0)
1490 return FN(PW,free)(pw);
1491 for (i = n - 1; i >= 0; i--) {
1492 isl_bool involves;
1494 involves = FN(PW,involves_dims)(pw, isl_dim_param, i, 1);
1495 if (involves < 0)
1496 return FN(PW,free)(pw);
1497 if (!involves)
1498 pw = FN(PW,drop_dims)(pw, isl_dim_param, i, 1);
1501 return pw;
1504 __isl_give PW *FN(PW,fix_dim)(__isl_take PW *pw,
1505 enum isl_dim_type type, unsigned pos, isl_int v)
1507 int i;
1508 isl_size n;
1510 n = FN(PW,n_piece)(pw);
1511 if (n < 0)
1512 return FN(PW,free)(pw);
1514 if (type == isl_dim_in)
1515 type = isl_dim_set;
1517 for (i = 0; i < n; ++i) {
1518 isl_set *domain;
1520 domain = FN(PW,take_domain_at)(pw, i);
1521 domain = isl_set_fix(domain, type, pos, v);
1522 pw = FN(PW,restore_domain_at)(pw, i, domain);
1523 pw = FN(PW,exploit_equalities_and_remove_if_empty)(pw, i);
1526 return pw;
1529 /* Fix the value of the variable at position "pos" of type "type" of "pw"
1530 * to be equal to "v".
1532 __isl_give PW *FN(PW,fix_val)(__isl_take PW *pw,
1533 enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
1535 if (!v)
1536 return FN(PW,free)(pw);
1537 if (!isl_val_is_int(v))
1538 isl_die(FN(PW,get_ctx)(pw), isl_error_invalid,
1539 "expecting integer value", goto error);
1541 pw = FN(PW,fix_dim)(pw, type, pos, v->n);
1542 isl_val_free(v);
1544 return pw;
1545 error:
1546 isl_val_free(v);
1547 return FN(PW,free)(pw);
1550 isl_size FN(PW,dim)(__isl_keep PW *pw, enum isl_dim_type type)
1552 return isl_space_dim(FN(PW,peek_space)(pw), type);
1555 __isl_give PW *FN(PW,split_dims)(__isl_take PW *pw,
1556 enum isl_dim_type type, unsigned first, unsigned n)
1558 int i;
1559 isl_size n_piece;
1561 n_piece = FN(PW,n_piece)(pw);
1562 if (n_piece < 0)
1563 return FN(PW,free)(pw);
1564 if (n == 0)
1565 return pw;
1567 if (type == isl_dim_in)
1568 type = isl_dim_set;
1570 for (i = 0; i < n; ++i) {
1571 isl_set *domain;
1573 domain = FN(PW,take_domain_at)(pw, i);
1574 domain = isl_set_split_dims(domain, type, first, n);
1575 pw = FN(PW,restore_domain_at)(pw, i, domain);
1578 return pw;
1581 __isl_give isl_space *FN(PW,get_domain_space)(__isl_keep PW *pw)
1583 return pw ? isl_space_domain(isl_space_copy(pw->dim)) : NULL;
1586 /* Return the position of the dimension of the given type and name
1587 * in "pw".
1588 * Return -1 if no such dimension can be found.
1590 int FN(PW,find_dim_by_name)(__isl_keep PW *pw,
1591 enum isl_dim_type type, const char *name)
1593 if (!pw)
1594 return -1;
1595 return isl_space_find_dim_by_name(pw->dim, type, name);
1598 /* Return the position of the dimension of the given type and identifier
1599 * in "pw".
1600 * Return -1 if no such dimension can be found.
1602 static int FN(PW,find_dim_by_id)(__isl_keep PW *pw,
1603 enum isl_dim_type type, __isl_keep isl_id *id)
1605 isl_space *space;
1607 space = FN(PW,peek_space)(pw);
1608 return isl_space_find_dim_by_id(space, type, id);
1611 /* Does the piecewise expression "pw" depend in any way
1612 * on the parameter with identifier "id"?
1614 isl_bool FN(PW,involves_param_id)(__isl_keep PW *pw, __isl_keep isl_id *id)
1616 int pos;
1618 if (!pw || !id)
1619 return isl_bool_error;
1620 if (pw->n == 0)
1621 return isl_bool_false;
1623 pos = FN(PW,find_dim_by_id)(pw, isl_dim_param, id);
1624 if (pos < 0)
1625 return isl_bool_false;
1626 return FN(PW,involves_dims)(pw, isl_dim_param, pos, 1);
1629 /* Reset the space of "pw". Since we don't know if the elements
1630 * represent the spaces themselves or their domains, we pass along
1631 * both when we call their reset_space_and_domain.
1633 static __isl_give PW *FN(PW,reset_space_and_domain)(__isl_take PW *pw,
1634 __isl_take isl_space *space, __isl_take isl_space *domain)
1636 int i;
1637 isl_size n;
1639 n = FN(PW,n_piece)(pw);
1640 if (n < 0 || !space || !domain)
1641 goto error;
1643 for (i = 0; i < n; ++i) {
1644 isl_set *set;
1645 EL *el;
1647 set = FN(PW,take_domain_at)(pw, i);
1648 set = isl_set_reset_space(set, isl_space_copy(domain));
1649 pw = FN(PW,restore_domain_at)(pw, i, set);
1650 el = FN(PW,take_base_at)(pw, i);
1651 el = FN(EL,reset_space_and_domain)(el,
1652 isl_space_copy(space), isl_space_copy(domain));
1653 pw = FN(PW,restore_base_at)(pw, i, el);
1656 isl_space_free(domain);
1658 pw = FN(PW,restore_space)(pw, space);
1660 return pw;
1661 error:
1662 isl_space_free(domain);
1663 isl_space_free(space);
1664 FN(PW,free)(pw);
1665 return NULL;
1668 __isl_give PW *FN(PW,reset_domain_space)(__isl_take PW *pw,
1669 __isl_take isl_space *domain)
1671 isl_space *space;
1673 space = isl_space_extend_domain_with_range(isl_space_copy(domain),
1674 FN(PW,get_space)(pw));
1675 return FN(PW,reset_space_and_domain)(pw, space, domain);
1678 __isl_give PW *FN(PW,reset_space)(__isl_take PW *pw,
1679 __isl_take isl_space *space)
1681 isl_space *domain;
1683 domain = isl_space_domain(isl_space_copy(space));
1684 return FN(PW,reset_space_and_domain)(pw, space, domain);
1687 __isl_give PW *FN(PW,set_tuple_id)(__isl_take PW *pw, enum isl_dim_type type,
1688 __isl_take isl_id *id)
1690 isl_space *space;
1692 pw = FN(PW,cow)(pw);
1693 if (!pw)
1694 goto error;
1696 space = FN(PW,get_space)(pw);
1697 space = isl_space_set_tuple_id(space, type, id);
1699 return FN(PW,reset_space)(pw, space);
1700 error:
1701 isl_id_free(id);
1702 return FN(PW,free)(pw);
1705 /* Drop the id on the specified tuple.
1707 __isl_give PW *FN(PW,reset_tuple_id)(__isl_take PW *pw, enum isl_dim_type type)
1709 isl_space *space;
1711 if (!pw)
1712 return NULL;
1713 if (!FN(PW,has_tuple_id)(pw, type))
1714 return pw;
1716 pw = FN(PW,cow)(pw);
1717 if (!pw)
1718 return NULL;
1720 space = FN(PW,get_space)(pw);
1721 space = isl_space_reset_tuple_id(space, type);
1723 return FN(PW,reset_space)(pw, space);
1726 __isl_give PW *FN(PW,set_dim_id)(__isl_take PW *pw,
1727 enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)
1729 isl_space *space;
1731 space = FN(PW,get_space)(pw);
1732 space = isl_space_set_dim_id(space, type, pos, id);
1733 return FN(PW,reset_space)(pw, space);
1736 /* Reset the user pointer on all identifiers of parameters and tuples
1737 * of the space of "pw".
1739 __isl_give PW *FN(PW,reset_user)(__isl_take PW *pw)
1741 isl_space *space;
1743 space = FN(PW,get_space)(pw);
1744 space = isl_space_reset_user(space);
1746 return FN(PW,reset_space)(pw, space);
1749 isl_size FN(PW,n_piece)(__isl_keep PW *pw)
1751 return pw ? pw->n : isl_size_error;
1754 isl_stat FN(PW,foreach_piece)(__isl_keep PW *pw,
1755 isl_stat (*fn)(__isl_take isl_set *set, __isl_take EL *el, void *user),
1756 void *user)
1758 int i;
1760 if (!pw)
1761 return isl_stat_error;
1763 for (i = 0; i < pw->n; ++i)
1764 if (fn(isl_set_copy(pw->p[i].set),
1765 FN(EL,copy)(pw->p[i].FIELD), user) < 0)
1766 return isl_stat_error;
1768 return isl_stat_ok;
1771 /* Does "test" succeed on every cell of "pw"?
1773 isl_bool FN(PW,every_piece)(__isl_keep PW *pw,
1774 isl_bool (*test)(__isl_keep isl_set *set,
1775 __isl_keep EL *el, void *user), void *user)
1777 int i;
1779 if (!pw)
1780 return isl_bool_error;
1782 for (i = 0; i < pw->n; ++i) {
1783 isl_bool r;
1785 r = test(pw->p[i].set, pw->p[i].FIELD, user);
1786 if (r < 0 || !r)
1787 return r;
1790 return isl_bool_true;
1793 /* Is "pw" defined over a single universe domain?
1795 * If the default value of this piecewise type is zero,
1796 * then a "pw" with a zero number of cells is also accepted
1797 * as it represents the default zero value.
1799 isl_bool FN(FN(PW,isa),BASE)(__isl_keep PW *pw)
1801 isl_size n;
1803 n = FN(PW,n_piece)(pw);
1804 if (n < 0)
1805 return isl_bool_error;
1806 if (DEFAULT_IS_ZERO && n == 0)
1807 return isl_bool_true;
1808 if (n != 1)
1809 return isl_bool_false;
1810 return isl_set_plain_is_universe(FN(PW,peek_domain_at)(pw, 0));
1813 /* Return a zero base expression in the same space (and of the same type)
1814 * as "pw".
1816 static __isl_give EL *FN(EL,zero_like_type)(__isl_take PW *pw OPT_TYPE_PARAM)
1818 isl_space *space;
1820 space = FN(PW,get_space)(pw);
1821 FN(PW,free)(pw);
1822 return FN(EL,zero_in_space)(space OPT_TYPE_ARG(NO_LOC));
1825 #ifndef HAS_TYPE
1826 /* Return a zero base expression in the same space as "pw".
1828 static __isl_give EL *FN(EL,zero_like)(__isl_take PW *pw)
1830 return FN(EL,zero_like_type)(pw);
1832 #else
1833 /* Return a zero base expression in the same space and of the same type
1834 * as "pw".
1836 * Pass along the type as an explicit argument for uniform handling
1837 * in isl_*_zero_like_type.
1839 static __isl_give EL *FN(EL,zero_like)(__isl_take PW *pw)
1841 enum isl_fold type;
1843 type = FN(PW,get_type)(pw);
1844 if (type < 0)
1845 goto error;
1846 return FN(EL,zero_like_type)(pw, type);
1847 error:
1848 FN(PW,free)(pw);
1849 return NULL;
1851 #endif
1853 /* Given that "pw" is defined over a single universe domain,
1854 * return the base expression associated to this domain.
1856 * If the number of cells is zero, then "pw" is of a piecewise type
1857 * with a default zero value and effectively represents zero.
1858 * In this case, create a zero base expression in the same space
1859 * (and with the same type).
1860 * Otherwise, simply extract the associated base expression.
1862 __isl_give EL *FN(FN(PW,as),BASE)(__isl_take PW *pw)
1864 isl_bool is_total;
1865 isl_size n;
1866 EL *el;
1868 is_total = FN(FN(PW,isa),BASE)(pw);
1869 if (is_total < 0)
1870 goto error;
1871 if (!is_total)
1872 isl_die(FN(PW,get_ctx)(pw), isl_error_invalid,
1873 "expecting single total function", goto error);
1874 n = FN(PW,n_piece)(pw);
1875 if (n < 0)
1876 goto error;
1877 if (n == 0)
1878 return FN(EL,zero_like)(pw);
1879 el = FN(PW,take_base_at)(pw, 0);
1880 FN(PW,free)(pw);
1881 return el;
1882 error:
1883 FN(PW,free)(pw);
1884 return NULL;
1887 #ifdef HAS_TYPE
1888 /* Negate the type of "pw".
1890 static __isl_give PW *FN(PW,negate_type)(__isl_take PW *pw)
1892 pw = FN(PW,cow)(pw);
1893 if (!pw)
1894 return NULL;
1895 pw->type = isl_fold_type_negate(pw->type);
1896 return pw;
1898 #else
1899 /* Negate the type of "pw".
1900 * Since "pw" does not have a type, do nothing.
1902 static __isl_give PW *FN(PW,negate_type)(__isl_take PW *pw)
1904 return pw;
1906 #endif
1908 __isl_give PW *FN(PW,mul_isl_int)(__isl_take PW *pw, isl_int v)
1910 int i;
1911 isl_size n;
1913 if (isl_int_is_one(v))
1914 return pw;
1915 if (pw && DEFAULT_IS_ZERO && isl_int_is_zero(v)) {
1916 PW *zero;
1917 isl_space *space = FN(PW,get_space)(pw);
1918 zero = FN(PW,ZERO)(space OPT_TYPE_ARG(pw->));
1919 FN(PW,free)(pw);
1920 return zero;
1922 if (isl_int_is_neg(v))
1923 pw = FN(PW,negate_type)(pw);
1925 n = FN(PW,n_piece)(pw);
1926 if (n < 0)
1927 return FN(PW,free)(pw);
1928 for (i = 0; i < n; ++i) {
1929 EL *el;
1931 el = FN(PW,take_base_at)(pw, i);
1932 el = FN(EL,scale)(el, v);
1933 pw = FN(PW,restore_base_at)(pw, i, el);
1936 return pw;
1939 /* Multiply the pieces of "pw" by "v" and return the result.
1941 __isl_give PW *FN(PW,scale_val)(__isl_take PW *pw, __isl_take isl_val *v)
1943 int i;
1944 isl_size n;
1946 if (!pw || !v)
1947 goto error;
1949 if (isl_val_is_one(v)) {
1950 isl_val_free(v);
1951 return pw;
1953 if (pw && DEFAULT_IS_ZERO && isl_val_is_zero(v)) {
1954 PW *zero;
1955 isl_space *space = FN(PW,get_space)(pw);
1956 zero = FN(PW,ZERO)(space OPT_TYPE_ARG(pw->));
1957 FN(PW,free)(pw);
1958 isl_val_free(v);
1959 return zero;
1961 if (isl_val_is_neg(v))
1962 pw = FN(PW,negate_type)(pw);
1963 n = FN(PW,n_piece)(pw);
1964 if (n < 0)
1965 goto error;
1967 for (i = 0; i < n; ++i) {
1968 EL *el;
1970 el = FN(PW,take_base_at)(pw, i);
1971 el = FN(EL,scale_val)(el, isl_val_copy(v));
1972 pw = FN(PW,restore_base_at)(pw, i, el);
1975 isl_val_free(v);
1976 return pw;
1977 error:
1978 isl_val_free(v);
1979 FN(PW,free)(pw);
1980 return NULL;
1983 /* Divide the pieces of "pw" by "v" and return the result.
1985 __isl_give PW *FN(PW,scale_down_val)(__isl_take PW *pw, __isl_take isl_val *v)
1987 int i;
1988 isl_size n;
1990 if (!pw || !v)
1991 goto error;
1993 if (isl_val_is_one(v)) {
1994 isl_val_free(v);
1995 return pw;
1998 if (!isl_val_is_rat(v))
1999 isl_die(isl_val_get_ctx(v), isl_error_invalid,
2000 "expecting rational factor", goto error);
2001 if (isl_val_is_zero(v))
2002 isl_die(isl_val_get_ctx(v), isl_error_invalid,
2003 "cannot scale down by zero", goto error);
2005 if (isl_val_is_neg(v))
2006 pw = FN(PW,negate_type)(pw);
2007 n = FN(PW,n_piece)(pw);
2008 if (n < 0)
2009 goto error;
2011 for (i = 0; i < n; ++i) {
2012 EL *el;
2014 el = FN(PW,take_base_at)(pw, i);
2015 el = FN(EL,scale_down_val)(el, isl_val_copy(v));
2016 pw = FN(PW,restore_base_at)(pw, i, el);
2019 isl_val_free(v);
2020 return pw;
2021 error:
2022 isl_val_free(v);
2023 FN(PW,free)(pw);
2024 return NULL;
2027 __isl_give PW *FN(PW,scale)(__isl_take PW *pw, isl_int v)
2029 return FN(PW,mul_isl_int)(pw, v);
2032 /* Apply some normalization to "pw".
2033 * In particular, sort the pieces according to their function value
2034 * expressions, combining pairs of adjacent pieces with
2035 * the same such expression, and then normalize the domains of the pieces.
2037 * We normalize in place, but if anything goes wrong we need
2038 * to return NULL, so we need to make sure we don't change the
2039 * meaning of any possible other copies of "pw".
2041 __isl_give PW *FN(PW,normalize)(__isl_take PW *pw)
2043 int i;
2044 isl_set *set;
2046 pw = FN(PW,sort_unique)(pw);
2047 if (!pw)
2048 return NULL;
2049 for (i = 0; i < pw->n; ++i) {
2050 set = isl_set_normalize(isl_set_copy(pw->p[i].set));
2051 if (!set)
2052 return FN(PW,free)(pw);
2053 isl_set_free(pw->p[i].set);
2054 pw->p[i].set = set;
2057 return pw;
2060 /* Is pw1 obviously equal to pw2?
2061 * That is, do they have obviously identical cells and obviously identical
2062 * elements on each cell?
2064 * If "pw1" or "pw2" contain any NaNs, then they are considered
2065 * not to be the same. A NaN is not equal to anything, not even
2066 * to another NaN.
2068 isl_bool FN(PW,plain_is_equal)(__isl_keep PW *pw1, __isl_keep PW *pw2)
2070 int i;
2071 isl_bool equal, has_nan;
2073 if (!pw1 || !pw2)
2074 return isl_bool_error;
2076 has_nan = FN(PW,involves_nan)(pw1);
2077 if (has_nan >= 0 && !has_nan)
2078 has_nan = FN(PW,involves_nan)(pw2);
2079 if (has_nan < 0 || has_nan)
2080 return isl_bool_not(has_nan);
2082 if (pw1 == pw2)
2083 return isl_bool_true;
2084 equal = FN(PW,has_equal_space)(pw1, pw2);
2085 if (equal < 0 || !equal)
2086 return equal;
2088 pw1 = FN(PW,copy)(pw1);
2089 pw2 = FN(PW,copy)(pw2);
2090 pw1 = FN(PW,normalize)(pw1);
2091 pw2 = FN(PW,normalize)(pw2);
2092 if (!pw1 || !pw2)
2093 goto error;
2095 equal = isl_bool_ok(pw1->n == pw2->n);
2096 for (i = 0; equal && i < pw1->n; ++i) {
2097 equal = isl_set_plain_is_equal(pw1->p[i].set, pw2->p[i].set);
2098 if (equal < 0)
2099 goto error;
2100 if (!equal)
2101 break;
2102 equal = FN(EL,plain_is_equal)(pw1->p[i].FIELD, pw2->p[i].FIELD);
2103 if (equal < 0)
2104 goto error;
2107 FN(PW,free)(pw1);
2108 FN(PW,free)(pw2);
2109 return equal;
2110 error:
2111 FN(PW,free)(pw1);
2112 FN(PW,free)(pw2);
2113 return isl_bool_error;
2116 /* Does "pw" involve any NaNs?
2118 isl_bool FN(PW,involves_nan)(__isl_keep PW *pw)
2120 int i;
2122 if (!pw)
2123 return isl_bool_error;
2124 if (pw->n == 0)
2125 return isl_bool_false;
2127 for (i = 0; i < pw->n; ++i) {
2128 isl_bool has_nan = FN(EL,involves_nan)(pw->p[i].FIELD);
2129 if (has_nan < 0 || has_nan)
2130 return has_nan;
2133 return isl_bool_false;