add isl_pw_multi_aff_involves_dims
[isl.git] / isl_pw_templ.c
blob5f9ffe9da01693c197d2bda2996bebe5efbad10c
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 #ifdef HAS_TYPE
22 __isl_give PW *FN(PW,alloc_size)(__isl_take isl_space *dim,
23 enum isl_fold type, int n)
24 #else
25 __isl_give PW *FN(PW,alloc_size)(__isl_take isl_space *dim, int n)
26 #endif
28 isl_ctx *ctx;
29 struct PW *pw;
31 if (!dim)
32 return NULL;
33 ctx = isl_space_get_ctx(dim);
34 isl_assert(ctx, n >= 0, goto error);
35 pw = isl_alloc(ctx, struct PW,
36 sizeof(struct PW) + (n - 1) * sizeof(S(PW,piece)));
37 if (!pw)
38 goto error;
40 pw->ref = 1;
41 #ifdef HAS_TYPE
42 pw->type = type;
43 #endif
44 pw->size = n;
45 pw->n = 0;
46 pw->dim = dim;
47 return pw;
48 error:
49 isl_space_free(dim);
50 return NULL;
53 #ifdef HAS_TYPE
54 __isl_give PW *FN(PW,ZERO)(__isl_take isl_space *dim, enum isl_fold type)
56 return FN(PW,alloc_size)(dim, type, 0);
58 #else
59 __isl_give PW *FN(PW,ZERO)(__isl_take isl_space *dim)
61 return FN(PW,alloc_size)(dim, 0);
63 #endif
65 __isl_give PW *FN(PW,add_piece)(__isl_take PW *pw,
66 __isl_take isl_set *set, __isl_take EL *el)
68 isl_ctx *ctx;
69 isl_space *el_dim = NULL;
71 if (!pw || !set || !el)
72 goto error;
74 if (isl_set_plain_is_empty(set) || FN(EL,EL_IS_ZERO)(el)) {
75 isl_set_free(set);
76 FN(EL,free)(el);
77 return pw;
80 ctx = isl_set_get_ctx(set);
81 #ifdef HAS_TYPE
82 if (pw->type != el->type)
83 isl_die(ctx, isl_error_invalid, "fold types don't match",
84 goto error);
85 #endif
86 el_dim = FN(EL,get_space(el));
87 isl_assert(ctx, isl_space_is_equal(pw->dim, el_dim), goto error);
88 isl_assert(ctx, pw->n < pw->size, goto error);
90 pw->p[pw->n].set = set;
91 pw->p[pw->n].FIELD = el;
92 pw->n++;
94 isl_space_free(el_dim);
95 return pw;
96 error:
97 isl_space_free(el_dim);
98 FN(PW,free)(pw);
99 isl_set_free(set);
100 FN(EL,free)(el);
101 return NULL;
104 /* Does the space of "set" correspond to that of the domain of "el".
106 static isl_bool FN(PW,compatible_domain)(__isl_keep EL *el,
107 __isl_keep isl_set *set)
109 isl_bool ok;
110 isl_space *el_space, *set_space;
112 if (!set || !el)
113 return isl_bool_error;
114 set_space = isl_set_get_space(set);
115 el_space = FN(EL,get_space)(el);
116 ok = isl_space_is_domain_internal(set_space, el_space);
117 isl_space_free(el_space);
118 isl_space_free(set_space);
119 return ok;
122 /* Check that the space of "set" corresponds to that of the domain of "el".
124 static isl_stat FN(PW,check_compatible_domain)(__isl_keep EL *el,
125 __isl_keep isl_set *set)
127 isl_bool ok;
129 ok = FN(PW,compatible_domain)(el, set);
130 if (ok < 0)
131 return isl_stat_error;
132 if (!ok)
133 isl_die(isl_set_get_ctx(set), isl_error_invalid,
134 "incompatible spaces", return isl_stat_error);
136 return isl_stat_ok;
139 #ifdef HAS_TYPE
140 __isl_give PW *FN(PW,alloc)(enum isl_fold type,
141 __isl_take isl_set *set, __isl_take EL *el)
142 #else
143 __isl_give PW *FN(PW,alloc)(__isl_take isl_set *set, __isl_take EL *el)
144 #endif
146 PW *pw;
148 if (FN(PW,check_compatible_domain)(el, set) < 0)
149 goto error;
151 #ifdef HAS_TYPE
152 pw = FN(PW,alloc_size)(FN(EL,get_space)(el), type, 1);
153 #else
154 pw = FN(PW,alloc_size)(FN(EL,get_space)(el), 1);
155 #endif
157 return FN(PW,add_piece)(pw, set, el);
158 error:
159 isl_set_free(set);
160 FN(EL,free)(el);
161 return NULL;
164 __isl_give PW *FN(PW,dup)(__isl_keep PW *pw)
166 int i;
167 PW *dup;
169 if (!pw)
170 return NULL;
172 #ifdef HAS_TYPE
173 dup = FN(PW,alloc_size)(isl_space_copy(pw->dim), pw->type, pw->n);
174 #else
175 dup = FN(PW,alloc_size)(isl_space_copy(pw->dim), pw->n);
176 #endif
177 if (!dup)
178 return NULL;
180 for (i = 0; i < pw->n; ++i)
181 dup = FN(PW,add_piece)(dup, isl_set_copy(pw->p[i].set),
182 FN(EL,copy)(pw->p[i].FIELD));
184 return dup;
187 __isl_give PW *FN(PW,cow)(__isl_take PW *pw)
189 if (!pw)
190 return NULL;
192 if (pw->ref == 1)
193 return pw;
194 pw->ref--;
195 return FN(PW,dup)(pw);
198 __isl_give PW *FN(PW,copy)(__isl_keep PW *pw)
200 if (!pw)
201 return NULL;
203 pw->ref++;
204 return pw;
207 __isl_null PW *FN(PW,free)(__isl_take PW *pw)
209 int i;
211 if (!pw)
212 return NULL;
213 if (--pw->ref > 0)
214 return NULL;
216 for (i = 0; i < pw->n; ++i) {
217 isl_set_free(pw->p[i].set);
218 FN(EL,free)(pw->p[i].FIELD);
220 isl_space_free(pw->dim);
221 free(pw);
223 return NULL;
226 const char *FN(PW,get_dim_name)(__isl_keep PW *pw, enum isl_dim_type type,
227 unsigned pos)
229 return pw ? isl_space_get_dim_name(pw->dim, type, pos) : NULL;
232 isl_bool FN(PW,has_dim_id)(__isl_keep PW *pw, enum isl_dim_type type,
233 unsigned pos)
235 return pw ? isl_space_has_dim_id(pw->dim, type, pos) : isl_bool_error;
238 __isl_give isl_id *FN(PW,get_dim_id)(__isl_keep PW *pw, enum isl_dim_type type,
239 unsigned pos)
241 return pw ? isl_space_get_dim_id(pw->dim, type, pos) : NULL;
244 isl_bool FN(PW,has_tuple_name)(__isl_keep PW *pw, enum isl_dim_type type)
246 return pw ? isl_space_has_tuple_name(pw->dim, type) : isl_bool_error;
249 const char *FN(PW,get_tuple_name)(__isl_keep PW *pw, enum isl_dim_type type)
251 return pw ? isl_space_get_tuple_name(pw->dim, type) : NULL;
254 isl_bool FN(PW,has_tuple_id)(__isl_keep PW *pw, enum isl_dim_type type)
256 return pw ? isl_space_has_tuple_id(pw->dim, type) : isl_bool_error;
259 __isl_give isl_id *FN(PW,get_tuple_id)(__isl_keep PW *pw, enum isl_dim_type type)
261 return pw ? isl_space_get_tuple_id(pw->dim, type) : NULL;
264 isl_bool FN(PW,IS_ZERO)(__isl_keep PW *pw)
266 if (!pw)
267 return isl_bool_error;
269 return pw->n == 0;
272 #ifndef NO_REALIGN
273 __isl_give PW *FN(PW,realign_domain)(__isl_take PW *pw,
274 __isl_take isl_reordering *exp)
276 int i;
278 pw = FN(PW,cow)(pw);
279 if (!pw || !exp)
280 goto error;
282 for (i = 0; i < pw->n; ++i) {
283 pw->p[i].set = isl_set_realign(pw->p[i].set,
284 isl_reordering_copy(exp));
285 if (!pw->p[i].set)
286 goto error;
287 pw->p[i].FIELD = FN(EL,realign_domain)(pw->p[i].FIELD,
288 isl_reordering_copy(exp));
289 if (!pw->p[i].FIELD)
290 goto error;
293 pw = FN(PW,reset_domain_space)(pw, isl_space_copy(exp->dim));
295 isl_reordering_free(exp);
296 return pw;
297 error:
298 isl_reordering_free(exp);
299 FN(PW,free)(pw);
300 return NULL;
303 /* Align the parameters of "pw" to those of "model".
305 __isl_give PW *FN(PW,align_params)(__isl_take PW *pw, __isl_take isl_space *model)
307 isl_ctx *ctx;
308 isl_bool equal_params;
310 if (!pw || !model)
311 goto error;
313 ctx = isl_space_get_ctx(model);
314 if (!isl_space_has_named_params(model))
315 isl_die(ctx, isl_error_invalid,
316 "model has unnamed parameters", goto error);
317 if (!isl_space_has_named_params(pw->dim))
318 isl_die(ctx, isl_error_invalid,
319 "input has unnamed parameters", goto error);
320 equal_params = isl_space_has_equal_params(pw->dim, model);
321 if (equal_params < 0)
322 goto error;
323 if (!equal_params) {
324 isl_reordering *exp;
326 model = isl_space_drop_dims(model, isl_dim_in,
327 0, isl_space_dim(model, isl_dim_in));
328 model = isl_space_drop_dims(model, isl_dim_out,
329 0, isl_space_dim(model, isl_dim_out));
330 exp = isl_parameter_alignment_reordering(pw->dim, model);
331 exp = isl_reordering_extend_space(exp,
332 FN(PW,get_domain_space)(pw));
333 pw = FN(PW,realign_domain)(pw, exp);
336 isl_space_free(model);
337 return pw;
338 error:
339 isl_space_free(model);
340 FN(PW,free)(pw);
341 return NULL;
344 static __isl_give PW *FN(PW,align_params_pw_pw_and)(__isl_take PW *pw1,
345 __isl_take PW *pw2,
346 __isl_give PW *(*fn)(__isl_take PW *pw1, __isl_take PW *pw2))
348 isl_ctx *ctx;
349 isl_bool equal_params;
351 if (!pw1 || !pw2)
352 goto error;
353 equal_params = isl_space_has_equal_params(pw1->dim, pw2->dim);
354 if (equal_params < 0)
355 goto error;
356 if (equal_params)
357 return fn(pw1, pw2);
358 ctx = FN(PW,get_ctx)(pw1);
359 if (!isl_space_has_named_params(pw1->dim) ||
360 !isl_space_has_named_params(pw2->dim))
361 isl_die(ctx, isl_error_invalid,
362 "unaligned unnamed parameters", goto error);
363 pw1 = FN(PW,align_params)(pw1, FN(PW,get_space)(pw2));
364 pw2 = FN(PW,align_params)(pw2, FN(PW,get_space)(pw1));
365 return fn(pw1, pw2);
366 error:
367 FN(PW,free)(pw1);
368 FN(PW,free)(pw2);
369 return NULL;
372 static __isl_give PW *FN(PW,align_params_pw_set_and)(__isl_take PW *pw,
373 __isl_take isl_set *set,
374 __isl_give PW *(*fn)(__isl_take PW *pw, __isl_take isl_set *set))
376 isl_ctx *ctx;
377 isl_bool aligned;
379 if (!pw || !set)
380 goto error;
381 aligned = isl_set_space_has_equal_params(set, pw->dim);
382 if (aligned < 0)
383 goto error;
384 if (aligned)
385 return fn(pw, set);
386 ctx = FN(PW,get_ctx)(pw);
387 if (!isl_space_has_named_params(pw->dim) ||
388 !isl_space_has_named_params(set->dim))
389 isl_die(ctx, isl_error_invalid,
390 "unaligned unnamed parameters", goto error);
391 pw = FN(PW,align_params)(pw, isl_set_get_space(set));
392 set = isl_set_align_params(set, FN(PW,get_space)(pw));
393 return fn(pw, set);
394 error:
395 FN(PW,free)(pw);
396 isl_set_free(set);
397 return NULL;
399 #endif
401 static __isl_give PW *FN(PW,union_add_aligned)(__isl_take PW *pw1,
402 __isl_take PW *pw2)
404 int i, j, n;
405 struct PW *res;
406 isl_ctx *ctx;
407 isl_set *set;
409 if (!pw1 || !pw2)
410 goto error;
412 ctx = isl_space_get_ctx(pw1->dim);
413 #ifdef HAS_TYPE
414 if (pw1->type != pw2->type)
415 isl_die(ctx, isl_error_invalid,
416 "fold types don't match", goto error);
417 #endif
418 isl_assert(ctx, isl_space_is_equal(pw1->dim, pw2->dim), goto error);
420 if (FN(PW,IS_ZERO)(pw1)) {
421 FN(PW,free)(pw1);
422 return pw2;
425 if (FN(PW,IS_ZERO)(pw2)) {
426 FN(PW,free)(pw2);
427 return pw1;
430 n = (pw1->n + 1) * (pw2->n + 1);
431 #ifdef HAS_TYPE
432 res = FN(PW,alloc_size)(isl_space_copy(pw1->dim), pw1->type, n);
433 #else
434 res = FN(PW,alloc_size)(isl_space_copy(pw1->dim), n);
435 #endif
437 for (i = 0; i < pw1->n; ++i) {
438 set = isl_set_copy(pw1->p[i].set);
439 for (j = 0; j < pw2->n; ++j) {
440 struct isl_set *common;
441 EL *sum;
442 common = isl_set_intersect(isl_set_copy(pw1->p[i].set),
443 isl_set_copy(pw2->p[j].set));
444 if (isl_set_plain_is_empty(common)) {
445 isl_set_free(common);
446 continue;
448 set = isl_set_subtract(set,
449 isl_set_copy(pw2->p[j].set));
451 sum = FN(EL,add_on_domain)(common,
452 FN(EL,copy)(pw1->p[i].FIELD),
453 FN(EL,copy)(pw2->p[j].FIELD));
455 res = FN(PW,add_piece)(res, common, sum);
457 res = FN(PW,add_piece)(res, set, FN(EL,copy)(pw1->p[i].FIELD));
460 for (j = 0; j < pw2->n; ++j) {
461 set = isl_set_copy(pw2->p[j].set);
462 for (i = 0; i < pw1->n; ++i)
463 set = isl_set_subtract(set,
464 isl_set_copy(pw1->p[i].set));
465 res = FN(PW,add_piece)(res, set, FN(EL,copy)(pw2->p[j].FIELD));
468 FN(PW,free)(pw1);
469 FN(PW,free)(pw2);
471 return res;
472 error:
473 FN(PW,free)(pw1);
474 FN(PW,free)(pw2);
475 return NULL;
478 /* Private version of "union_add". For isl_pw_qpolynomial and
479 * isl_pw_qpolynomial_fold, we prefer to simply call it "add".
481 static __isl_give PW *FN(PW,union_add_)(__isl_take PW *pw1, __isl_take PW *pw2)
483 return FN(PW,align_params_pw_pw_and)(pw1, pw2,
484 &FN(PW,union_add_aligned));
487 /* Make sure "pw" has room for at least "n" more pieces.
489 * If there is only one reference to pw, we extend it in place.
490 * Otherwise, we create a new PW and copy the pieces.
492 static __isl_give PW *FN(PW,grow)(__isl_take PW *pw, int n)
494 int i;
495 isl_ctx *ctx;
496 PW *res;
498 if (!pw)
499 return NULL;
500 if (pw->n + n <= pw->size)
501 return pw;
502 ctx = FN(PW,get_ctx)(pw);
503 n += pw->n;
504 if (pw->ref == 1) {
505 res = isl_realloc(ctx, pw, struct PW,
506 sizeof(struct PW) + (n - 1) * sizeof(S(PW,piece)));
507 if (!res)
508 return FN(PW,free)(pw);
509 res->size = n;
510 return res;
512 #ifdef HAS_TYPE
513 res = FN(PW,alloc_size)(isl_space_copy(pw->dim), pw->type, n);
514 #else
515 res = FN(PW,alloc_size)(isl_space_copy(pw->dim), n);
516 #endif
517 if (!res)
518 return FN(PW,free)(pw);
519 for (i = 0; i < pw->n; ++i)
520 res = FN(PW,add_piece)(res, isl_set_copy(pw->p[i].set),
521 FN(EL,copy)(pw->p[i].FIELD));
522 FN(PW,free)(pw);
523 return res;
526 static __isl_give PW *FN(PW,add_disjoint_aligned)(__isl_take PW *pw1,
527 __isl_take PW *pw2)
529 int i;
530 isl_ctx *ctx;
532 if (!pw1 || !pw2)
533 goto error;
535 if (pw1->size < pw1->n + pw2->n && pw1->n < pw2->n)
536 return FN(PW,add_disjoint_aligned)(pw2, pw1);
538 ctx = isl_space_get_ctx(pw1->dim);
539 #ifdef HAS_TYPE
540 if (pw1->type != pw2->type)
541 isl_die(ctx, isl_error_invalid,
542 "fold types don't match", goto error);
543 #endif
544 isl_assert(ctx, isl_space_is_equal(pw1->dim, pw2->dim), goto error);
546 if (FN(PW,IS_ZERO)(pw1)) {
547 FN(PW,free)(pw1);
548 return pw2;
551 if (FN(PW,IS_ZERO)(pw2)) {
552 FN(PW,free)(pw2);
553 return pw1;
556 pw1 = FN(PW,grow)(pw1, pw2->n);
557 if (!pw1)
558 goto error;
560 for (i = 0; i < pw2->n; ++i)
561 pw1 = FN(PW,add_piece)(pw1,
562 isl_set_copy(pw2->p[i].set),
563 FN(EL,copy)(pw2->p[i].FIELD));
565 FN(PW,free)(pw2);
567 return pw1;
568 error:
569 FN(PW,free)(pw1);
570 FN(PW,free)(pw2);
571 return NULL;
574 __isl_give PW *FN(PW,add_disjoint)(__isl_take PW *pw1, __isl_take PW *pw2)
576 return FN(PW,align_params_pw_pw_and)(pw1, pw2,
577 &FN(PW,add_disjoint_aligned));
580 /* This function is currently only used from isl_aff.c
582 static __isl_give PW *FN(PW,on_shared_domain_in)(__isl_take PW *pw1,
583 __isl_take PW *pw2, __isl_take isl_space *space,
584 __isl_give EL *(*fn)(__isl_take EL *el1, __isl_take EL *el2))
585 __attribute__ ((unused));
587 /* Apply "fn" to pairs of elements from pw1 and pw2 on shared domains.
588 * The result of "fn" (and therefore also of this function) lives in "space".
590 static __isl_give PW *FN(PW,on_shared_domain_in)(__isl_take PW *pw1,
591 __isl_take PW *pw2, __isl_take isl_space *space,
592 __isl_give EL *(*fn)(__isl_take EL *el1, __isl_take EL *el2))
594 int i, j, n;
595 PW *res = NULL;
597 if (!pw1 || !pw2)
598 goto error;
600 n = pw1->n * pw2->n;
601 #ifdef HAS_TYPE
602 res = FN(PW,alloc_size)(isl_space_copy(space), pw1->type, n);
603 #else
604 res = FN(PW,alloc_size)(isl_space_copy(space), n);
605 #endif
607 for (i = 0; i < pw1->n; ++i) {
608 for (j = 0; j < pw2->n; ++j) {
609 isl_set *common;
610 EL *res_ij;
611 int empty;
613 common = isl_set_intersect(
614 isl_set_copy(pw1->p[i].set),
615 isl_set_copy(pw2->p[j].set));
616 empty = isl_set_plain_is_empty(common);
617 if (empty < 0 || empty) {
618 isl_set_free(common);
619 if (empty < 0)
620 goto error;
621 continue;
624 res_ij = fn(FN(EL,copy)(pw1->p[i].FIELD),
625 FN(EL,copy)(pw2->p[j].FIELD));
626 res_ij = FN(EL,gist)(res_ij, isl_set_copy(common));
628 res = FN(PW,add_piece)(res, common, res_ij);
632 isl_space_free(space);
633 FN(PW,free)(pw1);
634 FN(PW,free)(pw2);
635 return res;
636 error:
637 isl_space_free(space);
638 FN(PW,free)(pw1);
639 FN(PW,free)(pw2);
640 FN(PW,free)(res);
641 return NULL;
644 /* This function is currently only used from isl_aff.c
646 static __isl_give PW *FN(PW,on_shared_domain)(__isl_take PW *pw1,
647 __isl_take PW *pw2,
648 __isl_give EL *(*fn)(__isl_take EL *el1, __isl_take EL *el2))
649 __attribute__ ((unused));
651 /* Apply "fn" to pairs of elements from pw1 and pw2 on shared domains.
652 * The result of "fn" is assumed to live in the same space as "pw1" and "pw2".
654 static __isl_give PW *FN(PW,on_shared_domain)(__isl_take PW *pw1,
655 __isl_take PW *pw2,
656 __isl_give EL *(*fn)(__isl_take EL *el1, __isl_take EL *el2))
658 isl_space *space;
660 if (!pw1 || !pw2)
661 goto error;
663 space = isl_space_copy(pw1->dim);
664 return FN(PW,on_shared_domain_in)(pw1, pw2, space, fn);
665 error:
666 FN(PW,free)(pw1);
667 FN(PW,free)(pw2);
668 return NULL;
671 #ifndef NO_NEG
672 __isl_give PW *FN(PW,neg)(__isl_take PW *pw)
674 int i;
676 if (!pw)
677 return NULL;
679 if (FN(PW,IS_ZERO)(pw))
680 return pw;
682 pw = FN(PW,cow)(pw);
683 if (!pw)
684 return NULL;
686 for (i = 0; i < pw->n; ++i) {
687 pw->p[i].FIELD = FN(EL,neg)(pw->p[i].FIELD);
688 if (!pw->p[i].FIELD)
689 return FN(PW,free)(pw);
692 return pw;
694 #endif
696 #ifndef NO_SUB
697 __isl_give PW *FN(PW,sub)(__isl_take PW *pw1, __isl_take PW *pw2)
699 return FN(PW,add)(pw1, FN(PW,neg)(pw2));
701 #endif
703 /* Return the parameter domain of "pw".
705 __isl_give isl_set *FN(PW,params)(__isl_take PW *pw)
707 return isl_set_params(FN(PW,domain)(pw));
710 __isl_give isl_set *FN(PW,domain)(__isl_take PW *pw)
712 int i;
713 isl_set *dom;
715 if (!pw)
716 return NULL;
718 dom = isl_set_empty(FN(PW,get_domain_space)(pw));
719 for (i = 0; i < pw->n; ++i)
720 dom = isl_set_union_disjoint(dom, isl_set_copy(pw->p[i].set));
722 FN(PW,free)(pw);
724 return dom;
727 /* Exploit the equalities in the domain of piece "i" of "pw"
728 * to simplify the associated function.
729 * If the domain of piece "i" is empty, then remove it entirely,
730 * replacing it with the final piece.
732 static int FN(PW,exploit_equalities_and_remove_if_empty)(__isl_keep PW *pw,
733 int i)
735 isl_basic_set *aff;
736 int empty = isl_set_plain_is_empty(pw->p[i].set);
738 if (empty < 0)
739 return -1;
740 if (empty) {
741 isl_set_free(pw->p[i].set);
742 FN(EL,free)(pw->p[i].FIELD);
743 if (i != pw->n - 1)
744 pw->p[i] = pw->p[pw->n - 1];
745 pw->n--;
747 return 0;
750 aff = isl_set_affine_hull(isl_set_copy(pw->p[i].set));
751 pw->p[i].FIELD = FN(EL,substitute_equalities)(pw->p[i].FIELD, aff);
752 if (!pw->p[i].FIELD)
753 return -1;
755 return 0;
758 /* Convert a piecewise expression defined over a parameter domain
759 * into one that is defined over a zero-dimensional set.
761 __isl_give PW *FN(PW,from_range)(__isl_take PW *pw)
763 isl_space *space;
765 if (!pw)
766 return NULL;
767 if (!isl_space_is_set(pw->dim))
768 isl_die(FN(PW,get_ctx)(pw), isl_error_invalid,
769 "not living in a set space", return FN(PW,free)(pw));
771 space = FN(PW,get_space)(pw);
772 space = isl_space_from_range(space);
773 pw = FN(PW,reset_space)(pw, space);
775 return pw;
778 /* Fix the value of the given parameter or domain dimension of "pw"
779 * to be equal to "value".
781 __isl_give PW *FN(PW,fix_si)(__isl_take PW *pw, enum isl_dim_type type,
782 unsigned pos, int value)
784 int i;
786 if (!pw)
787 return NULL;
789 if (type == isl_dim_out)
790 isl_die(FN(PW,get_ctx)(pw), isl_error_invalid,
791 "cannot fix output dimension", return FN(PW,free)(pw));
793 if (pw->n == 0)
794 return pw;
796 if (type == isl_dim_in)
797 type = isl_dim_set;
799 pw = FN(PW,cow)(pw);
800 if (!pw)
801 return FN(PW,free)(pw);
803 for (i = pw->n - 1; i >= 0; --i) {
804 pw->p[i].set = isl_set_fix_si(pw->p[i].set, type, pos, value);
805 if (FN(PW,exploit_equalities_and_remove_if_empty)(pw, i) < 0)
806 return FN(PW,free)(pw);
809 return pw;
812 /* Restrict the domain of "pw" by combining each cell
813 * with "set" through a call to "fn", where "fn" may be
814 * isl_set_intersect, isl_set_intersect_params or isl_set_subtract.
816 static __isl_give PW *FN(PW,restrict_domain_aligned)(__isl_take PW *pw,
817 __isl_take isl_set *set,
818 __isl_give isl_set *(*fn)(__isl_take isl_set *set1,
819 __isl_take isl_set *set2))
821 int i;
823 if (!pw || !set)
824 goto error;
826 if (pw->n == 0) {
827 isl_set_free(set);
828 return pw;
831 pw = FN(PW,cow)(pw);
832 if (!pw)
833 goto error;
835 for (i = pw->n - 1; i >= 0; --i) {
836 pw->p[i].set = fn(pw->p[i].set, isl_set_copy(set));
837 if (FN(PW,exploit_equalities_and_remove_if_empty)(pw, i) < 0)
838 goto error;
841 isl_set_free(set);
842 return pw;
843 error:
844 isl_set_free(set);
845 FN(PW,free)(pw);
846 return NULL;
849 static __isl_give PW *FN(PW,intersect_domain_aligned)(__isl_take PW *pw,
850 __isl_take isl_set *set)
852 return FN(PW,restrict_domain_aligned)(pw, set, &isl_set_intersect);
855 __isl_give PW *FN(PW,intersect_domain)(__isl_take PW *pw,
856 __isl_take isl_set *context)
858 return FN(PW,align_params_pw_set_and)(pw, context,
859 &FN(PW,intersect_domain_aligned));
862 static __isl_give PW *FN(PW,intersect_params_aligned)(__isl_take PW *pw,
863 __isl_take isl_set *set)
865 return FN(PW,restrict_domain_aligned)(pw, set,
866 &isl_set_intersect_params);
869 /* Intersect the domain of "pw" with the parameter domain "context".
871 __isl_give PW *FN(PW,intersect_params)(__isl_take PW *pw,
872 __isl_take isl_set *context)
874 return FN(PW,align_params_pw_set_and)(pw, context,
875 &FN(PW,intersect_params_aligned));
878 /* Subtract "domain' from the domain of "pw", assuming their
879 * parameters have been aligned.
881 static __isl_give PW *FN(PW,subtract_domain_aligned)(__isl_take PW *pw,
882 __isl_take isl_set *domain)
884 return FN(PW,restrict_domain_aligned)(pw, domain, &isl_set_subtract);
887 /* Subtract "domain' from the domain of "pw".
889 __isl_give PW *FN(PW,subtract_domain)(__isl_take PW *pw,
890 __isl_take isl_set *domain)
892 return FN(PW,align_params_pw_set_and)(pw, domain,
893 &FN(PW,subtract_domain_aligned));
896 /* Compute the gist of "pw" with respect to the domain constraints
897 * of "context" for the case where the domain of the last element
898 * of "pw" is equal to "context".
899 * Call "fn_el" to compute the gist of this element, replace
900 * its domain by the universe and drop all other elements
901 * as their domains are necessarily disjoint from "context".
903 static __isl_give PW *FN(PW,gist_last)(__isl_take PW *pw,
904 __isl_take isl_set *context,
905 __isl_give EL *(*fn_el)(__isl_take EL *el, __isl_take isl_set *set))
907 int i;
908 isl_space *space;
910 for (i = 0; i < pw->n - 1; ++i) {
911 isl_set_free(pw->p[i].set);
912 FN(EL,free)(pw->p[i].FIELD);
914 pw->p[0].FIELD = pw->p[pw->n - 1].FIELD;
915 pw->p[0].set = pw->p[pw->n - 1].set;
916 pw->n = 1;
918 space = isl_set_get_space(context);
919 pw->p[0].FIELD = fn_el(pw->p[0].FIELD, context);
920 context = isl_set_universe(space);
921 isl_set_free(pw->p[0].set);
922 pw->p[0].set = context;
924 if (!pw->p[0].FIELD || !pw->p[0].set)
925 return FN(PW,free)(pw);
927 return pw;
930 /* Compute the gist of "pw" with respect to the domain constraints
931 * of "context". Call "fn_el" to compute the gist of the elements
932 * and "fn_dom" to compute the gist of the domains.
934 * If the piecewise expression is empty or the context is the universe,
935 * then nothing can be simplified.
937 static __isl_give PW *FN(PW,gist_aligned)(__isl_take PW *pw,
938 __isl_take isl_set *context,
939 __isl_give EL *(*fn_el)(__isl_take EL *el,
940 __isl_take isl_set *set),
941 __isl_give isl_set *(*fn_dom)(__isl_take isl_set *set,
942 __isl_take isl_basic_set *bset))
944 int i;
945 int is_universe;
946 isl_bool aligned;
947 isl_basic_set *hull = NULL;
949 if (!pw || !context)
950 goto error;
952 if (pw->n == 0) {
953 isl_set_free(context);
954 return pw;
957 is_universe = isl_set_plain_is_universe(context);
958 if (is_universe < 0)
959 goto error;
960 if (is_universe) {
961 isl_set_free(context);
962 return pw;
965 aligned = isl_set_space_has_equal_params(context, pw->dim);
966 if (aligned < 0)
967 goto error;
968 if (!aligned) {
969 pw = FN(PW,align_params)(pw, isl_set_get_space(context));
970 context = isl_set_align_params(context, FN(PW,get_space)(pw));
973 pw = FN(PW,cow)(pw);
974 if (!pw)
975 goto error;
977 if (pw->n == 1) {
978 int equal;
980 equal = isl_set_plain_is_equal(pw->p[0].set, context);
981 if (equal < 0)
982 goto error;
983 if (equal)
984 return FN(PW,gist_last)(pw, context, fn_el);
987 context = isl_set_compute_divs(context);
988 hull = isl_set_simple_hull(isl_set_copy(context));
990 for (i = pw->n - 1; i >= 0; --i) {
991 isl_set *set_i;
992 int empty;
994 if (i == pw->n - 1) {
995 int equal;
996 equal = isl_set_plain_is_equal(pw->p[i].set, context);
997 if (equal < 0)
998 goto error;
999 if (equal) {
1000 isl_basic_set_free(hull);
1001 return FN(PW,gist_last)(pw, context, fn_el);
1004 set_i = isl_set_intersect(isl_set_copy(pw->p[i].set),
1005 isl_set_copy(context));
1006 empty = isl_set_plain_is_empty(set_i);
1007 pw->p[i].FIELD = fn_el(pw->p[i].FIELD, set_i);
1008 pw->p[i].set = fn_dom(pw->p[i].set, isl_basic_set_copy(hull));
1009 if (empty < 0 || !pw->p[i].FIELD || !pw->p[i].set)
1010 goto error;
1011 if (empty) {
1012 isl_set_free(pw->p[i].set);
1013 FN(EL,free)(pw->p[i].FIELD);
1014 if (i != pw->n - 1)
1015 pw->p[i] = pw->p[pw->n - 1];
1016 pw->n--;
1020 isl_basic_set_free(hull);
1021 isl_set_free(context);
1023 return pw;
1024 error:
1025 FN(PW,free)(pw);
1026 isl_basic_set_free(hull);
1027 isl_set_free(context);
1028 return NULL;
1031 static __isl_give PW *FN(PW,gist_domain_aligned)(__isl_take PW *pw,
1032 __isl_take isl_set *set)
1034 return FN(PW,gist_aligned)(pw, set, &FN(EL,gist),
1035 &isl_set_gist_basic_set);
1038 __isl_give PW *FN(PW,gist)(__isl_take PW *pw, __isl_take isl_set *context)
1040 return FN(PW,align_params_pw_set_and)(pw, context,
1041 &FN(PW,gist_domain_aligned));
1044 static __isl_give PW *FN(PW,gist_params_aligned)(__isl_take PW *pw,
1045 __isl_take isl_set *set)
1047 return FN(PW,gist_aligned)(pw, set, &FN(EL,gist_params),
1048 &isl_set_gist_params_basic_set);
1051 __isl_give PW *FN(PW,gist_params)(__isl_take PW *pw,
1052 __isl_take isl_set *context)
1054 return FN(PW,align_params_pw_set_and)(pw, context,
1055 &FN(PW,gist_params_aligned));
1058 /* Return -1 if the piece "p1" should be sorted before "p2"
1059 * and 1 if it should be sorted after "p2".
1060 * Return 0 if they do not need to be sorted in a specific order.
1062 * The two pieces are compared on the basis of their function value expressions.
1064 static int FN(PW,sort_field_cmp)(const void *p1, const void *p2, void *arg)
1066 struct FN(PW,piece) const *pc1 = p1;
1067 struct FN(PW,piece) const *pc2 = p2;
1069 return FN(EL,plain_cmp)(pc1->FIELD, pc2->FIELD);
1072 /* Sort the pieces of "pw" according to their function value
1073 * expressions and then combine pairs of adjacent pieces with
1074 * the same such expression.
1076 * The sorting is performed in place because it does not
1077 * change the meaning of "pw", but care needs to be
1078 * taken not to change any possible other copies of "pw"
1079 * in case anything goes wrong.
1081 __isl_give PW *FN(PW,sort)(__isl_take PW *pw)
1083 int i, j;
1084 isl_set *set;
1086 if (!pw)
1087 return NULL;
1088 if (pw->n <= 1)
1089 return pw;
1090 if (isl_sort(pw->p, pw->n, sizeof(pw->p[0]),
1091 &FN(PW,sort_field_cmp), NULL) < 0)
1092 return FN(PW,free)(pw);
1093 for (i = pw->n - 1; i >= 1; --i) {
1094 if (!FN(EL,plain_is_equal)(pw->p[i - 1].FIELD, pw->p[i].FIELD))
1095 continue;
1096 set = isl_set_union(isl_set_copy(pw->p[i - 1].set),
1097 isl_set_copy(pw->p[i].set));
1098 if (!set)
1099 return FN(PW,free)(pw);
1100 isl_set_free(pw->p[i].set);
1101 FN(EL,free)(pw->p[i].FIELD);
1102 isl_set_free(pw->p[i - 1].set);
1103 pw->p[i - 1].set = set;
1104 for (j = i + 1; j < pw->n; ++j)
1105 pw->p[j - 1] = pw->p[j];
1106 pw->n--;
1109 return pw;
1112 /* Coalesce the domains of "pw".
1114 * Prior to the actual coalescing, first sort the pieces such that
1115 * pieces with the same function value expression are combined
1116 * into a single piece, the combined domain of which can then
1117 * be coalesced.
1119 __isl_give PW *FN(PW,coalesce)(__isl_take PW *pw)
1121 int i;
1123 pw = FN(PW,sort)(pw);
1124 if (!pw)
1125 return NULL;
1127 for (i = 0; i < pw->n; ++i) {
1128 pw->p[i].set = isl_set_coalesce(pw->p[i].set);
1129 if (!pw->p[i].set)
1130 goto error;
1133 return pw;
1134 error:
1135 FN(PW,free)(pw);
1136 return NULL;
1139 isl_ctx *FN(PW,get_ctx)(__isl_keep PW *pw)
1141 return pw ? isl_space_get_ctx(pw->dim) : NULL;
1144 isl_bool FN(PW,involves_dims)(__isl_keep PW *pw, enum isl_dim_type type,
1145 unsigned first, unsigned n)
1147 int i;
1148 enum isl_dim_type set_type;
1150 if (!pw)
1151 return isl_bool_error;
1152 if (pw->n == 0 || n == 0)
1153 return isl_bool_false;
1155 set_type = type == isl_dim_in ? isl_dim_set : type;
1157 for (i = 0; i < pw->n; ++i) {
1158 isl_bool involves = FN(EL,involves_dims)(pw->p[i].FIELD,
1159 type, first, n);
1160 if (involves < 0 || involves)
1161 return involves;
1162 involves = isl_set_involves_dims(pw->p[i].set,
1163 set_type, first, n);
1164 if (involves < 0 || involves)
1165 return involves;
1167 return isl_bool_false;
1170 __isl_give PW *FN(PW,set_dim_name)(__isl_take PW *pw,
1171 enum isl_dim_type type, unsigned pos, const char *s)
1173 int i;
1174 enum isl_dim_type set_type;
1176 pw = FN(PW,cow)(pw);
1177 if (!pw)
1178 return NULL;
1180 set_type = type == isl_dim_in ? isl_dim_set : type;
1182 pw->dim = isl_space_set_dim_name(pw->dim, type, pos, s);
1183 if (!pw->dim)
1184 goto error;
1186 for (i = 0; i < pw->n; ++i) {
1187 pw->p[i].set = isl_set_set_dim_name(pw->p[i].set,
1188 set_type, pos, s);
1189 if (!pw->p[i].set)
1190 goto error;
1191 pw->p[i].FIELD = FN(EL,set_dim_name)(pw->p[i].FIELD, type, pos, s);
1192 if (!pw->p[i].FIELD)
1193 goto error;
1196 return pw;
1197 error:
1198 FN(PW,free)(pw);
1199 return NULL;
1202 __isl_give PW *FN(PW,drop_dims)(__isl_take PW *pw,
1203 enum isl_dim_type type, unsigned first, unsigned n)
1205 int i;
1206 enum isl_dim_type set_type;
1208 if (!pw)
1209 return NULL;
1210 if (n == 0 && !isl_space_get_tuple_name(pw->dim, type))
1211 return pw;
1213 set_type = type == isl_dim_in ? isl_dim_set : type;
1215 pw = FN(PW,cow)(pw);
1216 if (!pw)
1217 return NULL;
1218 pw->dim = isl_space_drop_dims(pw->dim, type, first, n);
1219 if (!pw->dim)
1220 goto error;
1221 for (i = 0; i < pw->n; ++i) {
1222 pw->p[i].FIELD = FN(EL,drop_dims)(pw->p[i].FIELD, type, first, n);
1223 if (!pw->p[i].FIELD)
1224 goto error;
1225 if (type == isl_dim_out)
1226 continue;
1227 pw->p[i].set = isl_set_drop(pw->p[i].set, set_type, first, n);
1228 if (!pw->p[i].set)
1229 goto error;
1232 return pw;
1233 error:
1234 FN(PW,free)(pw);
1235 return NULL;
1238 /* This function is very similar to drop_dims.
1239 * The only difference is that the cells may still involve
1240 * the specified dimensions. They are removed using
1241 * isl_set_project_out instead of isl_set_drop.
1243 __isl_give PW *FN(PW,project_out)(__isl_take PW *pw,
1244 enum isl_dim_type type, unsigned first, unsigned n)
1246 int i;
1247 enum isl_dim_type set_type;
1249 if (!pw)
1250 return NULL;
1251 if (n == 0 && !isl_space_get_tuple_name(pw->dim, type))
1252 return pw;
1254 set_type = type == isl_dim_in ? isl_dim_set : type;
1256 pw = FN(PW,cow)(pw);
1257 if (!pw)
1258 return NULL;
1259 pw->dim = isl_space_drop_dims(pw->dim, type, first, n);
1260 if (!pw->dim)
1261 goto error;
1262 for (i = 0; i < pw->n; ++i) {
1263 pw->p[i].set = isl_set_project_out(pw->p[i].set,
1264 set_type, first, n);
1265 if (!pw->p[i].set)
1266 goto error;
1267 pw->p[i].FIELD = FN(EL,drop_dims)(pw->p[i].FIELD, type, first, n);
1268 if (!pw->p[i].FIELD)
1269 goto error;
1272 return pw;
1273 error:
1274 FN(PW,free)(pw);
1275 return NULL;
1278 /* Project the domain of pw onto its parameter space.
1280 __isl_give PW *FN(PW,project_domain_on_params)(__isl_take PW *pw)
1282 isl_space *space;
1283 unsigned n;
1285 n = FN(PW,dim)(pw, isl_dim_in);
1286 pw = FN(PW,project_out)(pw, isl_dim_in, 0, n);
1287 space = FN(PW,get_domain_space)(pw);
1288 space = isl_space_params(space);
1289 pw = FN(PW,reset_domain_space)(pw, space);
1290 return pw;
1293 #ifndef NO_INSERT_DIMS
1294 __isl_give PW *FN(PW,insert_dims)(__isl_take PW *pw, enum isl_dim_type type,
1295 unsigned first, unsigned n)
1297 int i;
1298 enum isl_dim_type set_type;
1300 if (!pw)
1301 return NULL;
1302 if (n == 0 && !isl_space_is_named_or_nested(pw->dim, type))
1303 return pw;
1305 set_type = type == isl_dim_in ? isl_dim_set : type;
1307 pw = FN(PW,cow)(pw);
1308 if (!pw)
1309 return NULL;
1311 pw->dim = isl_space_insert_dims(pw->dim, type, first, n);
1312 if (!pw->dim)
1313 goto error;
1315 for (i = 0; i < pw->n; ++i) {
1316 pw->p[i].set = isl_set_insert_dims(pw->p[i].set,
1317 set_type, first, n);
1318 if (!pw->p[i].set)
1319 goto error;
1320 pw->p[i].FIELD = FN(EL,insert_dims)(pw->p[i].FIELD,
1321 type, first, n);
1322 if (!pw->p[i].FIELD)
1323 goto error;
1326 return pw;
1327 error:
1328 FN(PW,free)(pw);
1329 return NULL;
1331 #endif
1333 __isl_give PW *FN(PW,fix_dim)(__isl_take PW *pw,
1334 enum isl_dim_type type, unsigned pos, isl_int v)
1336 int i;
1338 if (!pw)
1339 return NULL;
1341 if (type == isl_dim_in)
1342 type = isl_dim_set;
1344 pw = FN(PW,cow)(pw);
1345 if (!pw)
1346 return NULL;
1347 for (i = 0; i < pw->n; ++i) {
1348 pw->p[i].set = isl_set_fix(pw->p[i].set, type, pos, v);
1349 if (FN(PW,exploit_equalities_and_remove_if_empty)(pw, i) < 0)
1350 return FN(PW,free)(pw);
1353 return pw;
1356 /* Fix the value of the variable at position "pos" of type "type" of "pw"
1357 * to be equal to "v".
1359 __isl_give PW *FN(PW,fix_val)(__isl_take PW *pw,
1360 enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
1362 if (!v)
1363 return FN(PW,free)(pw);
1364 if (!isl_val_is_int(v))
1365 isl_die(FN(PW,get_ctx)(pw), isl_error_invalid,
1366 "expecting integer value", goto error);
1368 pw = FN(PW,fix_dim)(pw, type, pos, v->n);
1369 isl_val_free(v);
1371 return pw;
1372 error:
1373 isl_val_free(v);
1374 return FN(PW,free)(pw);
1377 unsigned FN(PW,dim)(__isl_keep PW *pw, enum isl_dim_type type)
1379 return pw ? isl_space_dim(pw->dim, type) : 0;
1382 __isl_give PW *FN(PW,split_dims)(__isl_take PW *pw,
1383 enum isl_dim_type type, unsigned first, unsigned n)
1385 int i;
1387 if (!pw)
1388 return NULL;
1389 if (n == 0)
1390 return pw;
1392 if (type == isl_dim_in)
1393 type = isl_dim_set;
1395 pw = FN(PW,cow)(pw);
1396 if (!pw)
1397 return NULL;
1398 if (!pw->dim)
1399 goto error;
1400 for (i = 0; i < pw->n; ++i) {
1401 pw->p[i].set = isl_set_split_dims(pw->p[i].set, type, first, n);
1402 if (!pw->p[i].set)
1403 goto error;
1406 return pw;
1407 error:
1408 FN(PW,free)(pw);
1409 return NULL;
1412 #ifndef NO_OPT
1413 /* Compute the maximal value attained by the piecewise quasipolynomial
1414 * on its domain or zero if the domain is empty.
1415 * In the worst case, the domain is scanned completely,
1416 * so the domain is assumed to be bounded.
1418 __isl_give isl_val *FN(PW,opt)(__isl_take PW *pw, int max)
1420 int i;
1421 isl_val *opt;
1423 if (!pw)
1424 return NULL;
1426 if (pw->n == 0) {
1427 opt = isl_val_zero(FN(PW,get_ctx)(pw));
1428 FN(PW,free)(pw);
1429 return opt;
1432 opt = FN(EL,opt_on_domain)(FN(EL,copy)(pw->p[0].FIELD),
1433 isl_set_copy(pw->p[0].set), max);
1434 for (i = 1; i < pw->n; ++i) {
1435 isl_val *opt_i;
1436 opt_i = FN(EL,opt_on_domain)(FN(EL,copy)(pw->p[i].FIELD),
1437 isl_set_copy(pw->p[i].set), max);
1438 if (max)
1439 opt = isl_val_max(opt, opt_i);
1440 else
1441 opt = isl_val_min(opt, opt_i);
1444 FN(PW,free)(pw);
1445 return opt;
1448 __isl_give isl_val *FN(PW,max)(__isl_take PW *pw)
1450 return FN(PW,opt)(pw, 1);
1453 __isl_give isl_val *FN(PW,min)(__isl_take PW *pw)
1455 return FN(PW,opt)(pw, 0);
1457 #endif
1459 /* Return the space of "pw".
1461 __isl_keep isl_space *FN(PW,peek_space)(__isl_keep PW *pw)
1463 return pw ? pw->dim : NULL;
1466 __isl_give isl_space *FN(PW,get_space)(__isl_keep PW *pw)
1468 return isl_space_copy(FN(PW,peek_space)(pw));
1471 __isl_give isl_space *FN(PW,get_domain_space)(__isl_keep PW *pw)
1473 return pw ? isl_space_domain(isl_space_copy(pw->dim)) : NULL;
1476 /* Return the position of the dimension of the given type and name
1477 * in "pw".
1478 * Return -1 if no such dimension can be found.
1480 int FN(PW,find_dim_by_name)(__isl_keep PW *pw,
1481 enum isl_dim_type type, const char *name)
1483 if (!pw)
1484 return -1;
1485 return isl_space_find_dim_by_name(pw->dim, type, name);
1488 #ifndef NO_RESET_DIM
1489 /* Reset the space of "pw". Since we don't know if the elements
1490 * represent the spaces themselves or their domains, we pass along
1491 * both when we call their reset_space_and_domain.
1493 static __isl_give PW *FN(PW,reset_space_and_domain)(__isl_take PW *pw,
1494 __isl_take isl_space *space, __isl_take isl_space *domain)
1496 int i;
1498 pw = FN(PW,cow)(pw);
1499 if (!pw || !space || !domain)
1500 goto error;
1502 for (i = 0; i < pw->n; ++i) {
1503 pw->p[i].set = isl_set_reset_space(pw->p[i].set,
1504 isl_space_copy(domain));
1505 if (!pw->p[i].set)
1506 goto error;
1507 pw->p[i].FIELD = FN(EL,reset_space_and_domain)(pw->p[i].FIELD,
1508 isl_space_copy(space), isl_space_copy(domain));
1509 if (!pw->p[i].FIELD)
1510 goto error;
1513 isl_space_free(domain);
1515 isl_space_free(pw->dim);
1516 pw->dim = space;
1518 return pw;
1519 error:
1520 isl_space_free(domain);
1521 isl_space_free(space);
1522 FN(PW,free)(pw);
1523 return NULL;
1526 __isl_give PW *FN(PW,reset_domain_space)(__isl_take PW *pw,
1527 __isl_take isl_space *domain)
1529 isl_space *space;
1531 space = isl_space_extend_domain_with_range(isl_space_copy(domain),
1532 FN(PW,get_space)(pw));
1533 return FN(PW,reset_space_and_domain)(pw, space, domain);
1536 __isl_give PW *FN(PW,reset_space)(__isl_take PW *pw, __isl_take isl_space *dim)
1538 isl_space *domain;
1540 domain = isl_space_domain(isl_space_copy(dim));
1541 return FN(PW,reset_space_and_domain)(pw, dim, domain);
1544 __isl_give PW *FN(PW,set_tuple_id)(__isl_take PW *pw, enum isl_dim_type type,
1545 __isl_take isl_id *id)
1547 isl_space *space;
1549 pw = FN(PW,cow)(pw);
1550 if (!pw)
1551 goto error;
1553 space = FN(PW,get_space)(pw);
1554 space = isl_space_set_tuple_id(space, type, id);
1556 return FN(PW,reset_space)(pw, space);
1557 error:
1558 isl_id_free(id);
1559 return FN(PW,free)(pw);
1562 /* Drop the id on the specified tuple.
1564 __isl_give PW *FN(PW,reset_tuple_id)(__isl_take PW *pw, enum isl_dim_type type)
1566 isl_space *space;
1568 if (!pw)
1569 return NULL;
1570 if (!FN(PW,has_tuple_id)(pw, type))
1571 return pw;
1573 pw = FN(PW,cow)(pw);
1574 if (!pw)
1575 return NULL;
1577 space = FN(PW,get_space)(pw);
1578 space = isl_space_reset_tuple_id(space, type);
1580 return FN(PW,reset_space)(pw, space);
1583 __isl_give PW *FN(PW,set_dim_id)(__isl_take PW *pw,
1584 enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)
1586 pw = FN(PW,cow)(pw);
1587 if (!pw)
1588 goto error;
1589 pw->dim = isl_space_set_dim_id(pw->dim, type, pos, id);
1590 return FN(PW,reset_space)(pw, isl_space_copy(pw->dim));
1591 error:
1592 isl_id_free(id);
1593 return FN(PW,free)(pw);
1595 #endif
1597 /* Reset the user pointer on all identifiers of parameters and tuples
1598 * of the space of "pw".
1600 __isl_give PW *FN(PW,reset_user)(__isl_take PW *pw)
1602 isl_space *space;
1604 space = FN(PW,get_space)(pw);
1605 space = isl_space_reset_user(space);
1607 return FN(PW,reset_space)(pw, space);
1610 isl_bool FN(PW,has_equal_space)(__isl_keep PW *pw1, __isl_keep PW *pw2)
1612 if (!pw1 || !pw2)
1613 return isl_bool_error;
1615 return isl_space_is_equal(pw1->dim, pw2->dim);
1618 #ifndef NO_MORPH
1619 __isl_give PW *FN(PW,morph_domain)(__isl_take PW *pw,
1620 __isl_take isl_morph *morph)
1622 int i;
1623 isl_ctx *ctx;
1625 if (!pw || !morph)
1626 goto error;
1628 ctx = isl_space_get_ctx(pw->dim);
1629 isl_assert(ctx, isl_space_is_domain_internal(morph->dom->dim, pw->dim),
1630 goto error);
1632 pw = FN(PW,cow)(pw);
1633 if (!pw)
1634 goto error;
1635 pw->dim = isl_space_extend_domain_with_range(
1636 isl_space_copy(morph->ran->dim), pw->dim);
1637 if (!pw->dim)
1638 goto error;
1640 for (i = 0; i < pw->n; ++i) {
1641 pw->p[i].set = isl_morph_set(isl_morph_copy(morph), pw->p[i].set);
1642 if (!pw->p[i].set)
1643 goto error;
1644 pw->p[i].FIELD = FN(EL,morph_domain)(pw->p[i].FIELD,
1645 isl_morph_copy(morph));
1646 if (!pw->p[i].FIELD)
1647 goto error;
1650 isl_morph_free(morph);
1652 return pw;
1653 error:
1654 FN(PW,free)(pw);
1655 isl_morph_free(morph);
1656 return NULL;
1658 #endif
1660 int FN(PW,n_piece)(__isl_keep PW *pw)
1662 return pw ? pw->n : 0;
1665 isl_stat FN(PW,foreach_piece)(__isl_keep PW *pw,
1666 isl_stat (*fn)(__isl_take isl_set *set, __isl_take EL *el, void *user),
1667 void *user)
1669 int i;
1671 if (!pw)
1672 return isl_stat_error;
1674 for (i = 0; i < pw->n; ++i)
1675 if (fn(isl_set_copy(pw->p[i].set),
1676 FN(EL,copy)(pw->p[i].FIELD), user) < 0)
1677 return isl_stat_error;
1679 return isl_stat_ok;
1682 #ifndef NO_LIFT
1683 static isl_bool any_divs(__isl_keep isl_set *set)
1685 int i;
1687 if (!set)
1688 return isl_bool_error;
1690 for (i = 0; i < set->n; ++i)
1691 if (set->p[i]->n_div > 0)
1692 return isl_bool_true;
1694 return isl_bool_false;
1697 static isl_stat foreach_lifted_subset(__isl_take isl_set *set,
1698 __isl_take EL *el,
1699 isl_stat (*fn)(__isl_take isl_set *set, __isl_take EL *el,
1700 void *user), void *user)
1702 int i;
1704 if (!set || !el)
1705 goto error;
1707 for (i = 0; i < set->n; ++i) {
1708 isl_set *lift;
1709 EL *copy;
1711 lift = isl_set_from_basic_set(isl_basic_set_copy(set->p[i]));
1712 lift = isl_set_lift(lift);
1714 copy = FN(EL,copy)(el);
1715 copy = FN(EL,lift)(copy, isl_set_get_space(lift));
1717 if (fn(lift, copy, user) < 0)
1718 goto error;
1721 isl_set_free(set);
1722 FN(EL,free)(el);
1724 return isl_stat_ok;
1725 error:
1726 isl_set_free(set);
1727 FN(EL,free)(el);
1728 return isl_stat_error;
1731 isl_stat FN(PW,foreach_lifted_piece)(__isl_keep PW *pw,
1732 isl_stat (*fn)(__isl_take isl_set *set, __isl_take EL *el,
1733 void *user), void *user)
1735 int i;
1737 if (!pw)
1738 return isl_stat_error;
1740 for (i = 0; i < pw->n; ++i) {
1741 isl_bool any;
1742 isl_set *set;
1743 EL *el;
1745 any = any_divs(pw->p[i].set);
1746 if (any < 0)
1747 return isl_stat_error;
1748 set = isl_set_copy(pw->p[i].set);
1749 el = FN(EL,copy)(pw->p[i].FIELD);
1750 if (!any) {
1751 if (fn(set, el, user) < 0)
1752 return isl_stat_error;
1753 continue;
1755 if (foreach_lifted_subset(set, el, fn, user) < 0)
1756 return isl_stat_error;
1759 return isl_stat_ok;
1761 #endif
1763 #ifndef NO_MOVE_DIMS
1764 __isl_give PW *FN(PW,move_dims)(__isl_take PW *pw,
1765 enum isl_dim_type dst_type, unsigned dst_pos,
1766 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
1768 int i;
1770 pw = FN(PW,cow)(pw);
1771 if (!pw)
1772 return NULL;
1774 pw->dim = isl_space_move_dims(pw->dim, dst_type, dst_pos, src_type, src_pos, n);
1775 if (!pw->dim)
1776 goto error;
1778 for (i = 0; i < pw->n; ++i) {
1779 pw->p[i].FIELD = FN(EL,move_dims)(pw->p[i].FIELD,
1780 dst_type, dst_pos, src_type, src_pos, n);
1781 if (!pw->p[i].FIELD)
1782 goto error;
1785 if (dst_type == isl_dim_in)
1786 dst_type = isl_dim_set;
1787 if (src_type == isl_dim_in)
1788 src_type = isl_dim_set;
1790 for (i = 0; i < pw->n; ++i) {
1791 pw->p[i].set = isl_set_move_dims(pw->p[i].set,
1792 dst_type, dst_pos,
1793 src_type, src_pos, n);
1794 if (!pw->p[i].set)
1795 goto error;
1798 return pw;
1799 error:
1800 FN(PW,free)(pw);
1801 return NULL;
1803 #endif
1805 __isl_give PW *FN(PW,mul_isl_int)(__isl_take PW *pw, isl_int v)
1807 int i;
1809 if (isl_int_is_one(v))
1810 return pw;
1811 if (pw && DEFAULT_IS_ZERO && isl_int_is_zero(v)) {
1812 PW *zero;
1813 isl_space *dim = FN(PW,get_space)(pw);
1814 #ifdef HAS_TYPE
1815 zero = FN(PW,ZERO)(dim, pw->type);
1816 #else
1817 zero = FN(PW,ZERO)(dim);
1818 #endif
1819 FN(PW,free)(pw);
1820 return zero;
1822 pw = FN(PW,cow)(pw);
1823 if (!pw)
1824 return NULL;
1825 if (pw->n == 0)
1826 return pw;
1828 #ifdef HAS_TYPE
1829 if (isl_int_is_neg(v))
1830 pw->type = isl_fold_type_negate(pw->type);
1831 #endif
1832 for (i = 0; i < pw->n; ++i) {
1833 pw->p[i].FIELD = FN(EL,scale)(pw->p[i].FIELD, v);
1834 if (!pw->p[i].FIELD)
1835 goto error;
1838 return pw;
1839 error:
1840 FN(PW,free)(pw);
1841 return NULL;
1844 /* Multiply the pieces of "pw" by "v" and return the result.
1846 __isl_give PW *FN(PW,scale_val)(__isl_take PW *pw, __isl_take isl_val *v)
1848 int i;
1850 if (!pw || !v)
1851 goto error;
1853 if (isl_val_is_one(v)) {
1854 isl_val_free(v);
1855 return pw;
1857 if (pw && DEFAULT_IS_ZERO && isl_val_is_zero(v)) {
1858 PW *zero;
1859 isl_space *space = FN(PW,get_space)(pw);
1860 #ifdef HAS_TYPE
1861 zero = FN(PW,ZERO)(space, pw->type);
1862 #else
1863 zero = FN(PW,ZERO)(space);
1864 #endif
1865 FN(PW,free)(pw);
1866 isl_val_free(v);
1867 return zero;
1869 if (pw->n == 0) {
1870 isl_val_free(v);
1871 return pw;
1873 pw = FN(PW,cow)(pw);
1874 if (!pw)
1875 goto error;
1877 #ifdef HAS_TYPE
1878 if (isl_val_is_neg(v))
1879 pw->type = isl_fold_type_negate(pw->type);
1880 #endif
1881 for (i = 0; i < pw->n; ++i) {
1882 pw->p[i].FIELD = FN(EL,scale_val)(pw->p[i].FIELD,
1883 isl_val_copy(v));
1884 if (!pw->p[i].FIELD)
1885 goto error;
1888 isl_val_free(v);
1889 return pw;
1890 error:
1891 isl_val_free(v);
1892 FN(PW,free)(pw);
1893 return NULL;
1896 /* Divide the pieces of "pw" by "v" and return the result.
1898 __isl_give PW *FN(PW,scale_down_val)(__isl_take PW *pw, __isl_take isl_val *v)
1900 int i;
1902 if (!pw || !v)
1903 goto error;
1905 if (isl_val_is_one(v)) {
1906 isl_val_free(v);
1907 return pw;
1910 if (!isl_val_is_rat(v))
1911 isl_die(isl_val_get_ctx(v), isl_error_invalid,
1912 "expecting rational factor", goto error);
1913 if (isl_val_is_zero(v))
1914 isl_die(isl_val_get_ctx(v), isl_error_invalid,
1915 "cannot scale down by zero", goto error);
1917 if (pw->n == 0) {
1918 isl_val_free(v);
1919 return pw;
1921 pw = FN(PW,cow)(pw);
1922 if (!pw)
1923 goto error;
1925 #ifdef HAS_TYPE
1926 if (isl_val_is_neg(v))
1927 pw->type = isl_fold_type_negate(pw->type);
1928 #endif
1929 for (i = 0; i < pw->n; ++i) {
1930 pw->p[i].FIELD = FN(EL,scale_down_val)(pw->p[i].FIELD,
1931 isl_val_copy(v));
1932 if (!pw->p[i].FIELD)
1933 goto error;
1936 isl_val_free(v);
1937 return pw;
1938 error:
1939 isl_val_free(v);
1940 FN(PW,free)(pw);
1941 return NULL;
1944 __isl_give PW *FN(PW,scale)(__isl_take PW *pw, isl_int v)
1946 return FN(PW,mul_isl_int)(pw, v);
1949 /* Apply some normalization to "pw".
1950 * In particular, sort the pieces according to their function value
1951 * expressions, combining pairs of adjacent pieces with
1952 * the same such expression, and then normalize the domains of the pieces.
1954 * We normalize in place, but if anything goes wrong we need
1955 * to return NULL, so we need to make sure we don't change the
1956 * meaning of any possible other copies of "pw".
1958 __isl_give PW *FN(PW,normalize)(__isl_take PW *pw)
1960 int i;
1961 isl_set *set;
1963 pw = FN(PW,sort)(pw);
1964 if (!pw)
1965 return NULL;
1966 for (i = 0; i < pw->n; ++i) {
1967 set = isl_set_normalize(isl_set_copy(pw->p[i].set));
1968 if (!set)
1969 return FN(PW,free)(pw);
1970 isl_set_free(pw->p[i].set);
1971 pw->p[i].set = set;
1974 return pw;
1977 /* Is pw1 obviously equal to pw2?
1978 * That is, do they have obviously identical cells and obviously identical
1979 * elements on each cell?
1981 * If "pw1" or "pw2" contain any NaNs, then they are considered
1982 * not to be the same. A NaN is not equal to anything, not even
1983 * to another NaN.
1985 isl_bool FN(PW,plain_is_equal)(__isl_keep PW *pw1, __isl_keep PW *pw2)
1987 int i;
1988 isl_bool equal, has_nan;
1990 if (!pw1 || !pw2)
1991 return isl_bool_error;
1993 has_nan = FN(PW,involves_nan)(pw1);
1994 if (has_nan >= 0 && !has_nan)
1995 has_nan = FN(PW,involves_nan)(pw2);
1996 if (has_nan < 0 || has_nan)
1997 return isl_bool_not(has_nan);
1999 if (pw1 == pw2)
2000 return isl_bool_true;
2001 if (!isl_space_is_equal(pw1->dim, pw2->dim))
2002 return isl_bool_false;
2004 pw1 = FN(PW,copy)(pw1);
2005 pw2 = FN(PW,copy)(pw2);
2006 pw1 = FN(PW,normalize)(pw1);
2007 pw2 = FN(PW,normalize)(pw2);
2008 if (!pw1 || !pw2)
2009 goto error;
2011 equal = pw1->n == pw2->n;
2012 for (i = 0; equal && i < pw1->n; ++i) {
2013 equal = isl_set_plain_is_equal(pw1->p[i].set, pw2->p[i].set);
2014 if (equal < 0)
2015 goto error;
2016 if (!equal)
2017 break;
2018 equal = FN(EL,plain_is_equal)(pw1->p[i].FIELD, pw2->p[i].FIELD);
2019 if (equal < 0)
2020 goto error;
2023 FN(PW,free)(pw1);
2024 FN(PW,free)(pw2);
2025 return equal;
2026 error:
2027 FN(PW,free)(pw1);
2028 FN(PW,free)(pw2);
2029 return isl_bool_error;
2032 /* Does "pw" involve any NaNs?
2034 isl_bool FN(PW,involves_nan)(__isl_keep PW *pw)
2036 int i;
2038 if (!pw)
2039 return isl_bool_error;
2040 if (pw->n == 0)
2041 return isl_bool_false;
2043 for (i = 0; i < pw->n; ++i) {
2044 isl_bool has_nan = FN(EL,involves_nan)(pw->p[i].FIELD);
2045 if (has_nan < 0 || has_nan)
2046 return has_nan;
2049 return isl_bool_false;
2052 #ifndef NO_PULLBACK
2053 static __isl_give PW *FN(PW,align_params_pw_multi_aff_and)(__isl_take PW *pw,
2054 __isl_take isl_multi_aff *ma,
2055 __isl_give PW *(*fn)(__isl_take PW *pw, __isl_take isl_multi_aff *ma))
2057 isl_ctx *ctx;
2058 isl_bool equal_params;
2059 isl_space *ma_space;
2061 ma_space = isl_multi_aff_get_space(ma);
2062 if (!pw || !ma || !ma_space)
2063 goto error;
2064 equal_params = isl_space_has_equal_params(pw->dim, ma_space);
2065 if (equal_params < 0)
2066 goto error;
2067 if (equal_params) {
2068 isl_space_free(ma_space);
2069 return fn(pw, ma);
2071 ctx = FN(PW,get_ctx)(pw);
2072 if (!isl_space_has_named_params(pw->dim) ||
2073 !isl_space_has_named_params(ma_space))
2074 isl_die(ctx, isl_error_invalid,
2075 "unaligned unnamed parameters", goto error);
2076 pw = FN(PW,align_params)(pw, ma_space);
2077 ma = isl_multi_aff_align_params(ma, FN(PW,get_space)(pw));
2078 return fn(pw, ma);
2079 error:
2080 isl_space_free(ma_space);
2081 FN(PW,free)(pw);
2082 isl_multi_aff_free(ma);
2083 return NULL;
2086 static __isl_give PW *FN(PW,align_params_pw_pw_multi_aff_and)(__isl_take PW *pw,
2087 __isl_take isl_pw_multi_aff *pma,
2088 __isl_give PW *(*fn)(__isl_take PW *pw,
2089 __isl_take isl_pw_multi_aff *ma))
2091 isl_ctx *ctx;
2092 isl_bool equal_params;
2093 isl_space *pma_space;
2095 pma_space = isl_pw_multi_aff_get_space(pma);
2096 if (!pw || !pma || !pma_space)
2097 goto error;
2098 equal_params = isl_space_has_equal_params(pw->dim, pma_space);
2099 if (equal_params < 0)
2100 goto error;
2101 if (equal_params) {
2102 isl_space_free(pma_space);
2103 return fn(pw, pma);
2105 ctx = FN(PW,get_ctx)(pw);
2106 if (!isl_space_has_named_params(pw->dim) ||
2107 !isl_space_has_named_params(pma_space))
2108 isl_die(ctx, isl_error_invalid,
2109 "unaligned unnamed parameters", goto error);
2110 pw = FN(PW,align_params)(pw, pma_space);
2111 pma = isl_pw_multi_aff_align_params(pma, FN(PW,get_space)(pw));
2112 return fn(pw, pma);
2113 error:
2114 isl_space_free(pma_space);
2115 FN(PW,free)(pw);
2116 isl_pw_multi_aff_free(pma);
2117 return NULL;
2120 /* Compute the pullback of "pw" by the function represented by "ma".
2121 * In other words, plug in "ma" in "pw".
2123 static __isl_give PW *FN(PW,pullback_multi_aff_aligned)(__isl_take PW *pw,
2124 __isl_take isl_multi_aff *ma)
2126 int i;
2127 isl_space *space = NULL;
2129 ma = isl_multi_aff_align_divs(ma);
2130 pw = FN(PW,cow)(pw);
2131 if (!pw || !ma)
2132 goto error;
2134 space = isl_space_join(isl_multi_aff_get_space(ma),
2135 FN(PW,get_space)(pw));
2137 for (i = 0; i < pw->n; ++i) {
2138 pw->p[i].set = isl_set_preimage_multi_aff(pw->p[i].set,
2139 isl_multi_aff_copy(ma));
2140 if (!pw->p[i].set)
2141 goto error;
2142 pw->p[i].FIELD = FN(EL,pullback_multi_aff)(pw->p[i].FIELD,
2143 isl_multi_aff_copy(ma));
2144 if (!pw->p[i].FIELD)
2145 goto error;
2148 pw = FN(PW,reset_space)(pw, space);
2149 isl_multi_aff_free(ma);
2150 return pw;
2151 error:
2152 isl_space_free(space);
2153 isl_multi_aff_free(ma);
2154 FN(PW,free)(pw);
2155 return NULL;
2158 __isl_give PW *FN(PW,pullback_multi_aff)(__isl_take PW *pw,
2159 __isl_take isl_multi_aff *ma)
2161 return FN(PW,align_params_pw_multi_aff_and)(pw, ma,
2162 &FN(PW,pullback_multi_aff_aligned));
2165 /* Compute the pullback of "pw" by the function represented by "pma".
2166 * In other words, plug in "pma" in "pw".
2168 static __isl_give PW *FN(PW,pullback_pw_multi_aff_aligned)(__isl_take PW *pw,
2169 __isl_take isl_pw_multi_aff *pma)
2171 int i;
2172 PW *res;
2174 if (!pma)
2175 goto error;
2177 if (pma->n == 0) {
2178 isl_space *space;
2179 space = isl_space_join(isl_pw_multi_aff_get_space(pma),
2180 FN(PW,get_space)(pw));
2181 isl_pw_multi_aff_free(pma);
2182 res = FN(PW,empty)(space);
2183 FN(PW,free)(pw);
2184 return res;
2187 res = FN(PW,pullback_multi_aff)(FN(PW,copy)(pw),
2188 isl_multi_aff_copy(pma->p[0].maff));
2189 res = FN(PW,intersect_domain)(res, isl_set_copy(pma->p[0].set));
2191 for (i = 1; i < pma->n; ++i) {
2192 PW *res_i;
2194 res_i = FN(PW,pullback_multi_aff)(FN(PW,copy)(pw),
2195 isl_multi_aff_copy(pma->p[i].maff));
2196 res_i = FN(PW,intersect_domain)(res_i,
2197 isl_set_copy(pma->p[i].set));
2198 res = FN(PW,add_disjoint)(res, res_i);
2201 isl_pw_multi_aff_free(pma);
2202 FN(PW,free)(pw);
2203 return res;
2204 error:
2205 isl_pw_multi_aff_free(pma);
2206 FN(PW,free)(pw);
2207 return NULL;
2210 __isl_give PW *FN(PW,pullback_pw_multi_aff)(__isl_take PW *pw,
2211 __isl_take isl_pw_multi_aff *pma)
2213 return FN(PW,align_params_pw_pw_multi_aff_and)(pw, pma,
2214 &FN(PW,pullback_pw_multi_aff_aligned));
2216 #endif