isl_*_mod_multi_val: plug memory leak on error path
[isl.git] / isl_pw_templ.c
bloba060f636a031919cf322bfdee1b8b6c20cb1b8bd
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/aff.h>
15 #include <isl_sort.h>
16 #include <isl_val_private.h>
18 #include <isl_pw_macro.h>
20 #ifdef HAS_TYPE
21 __isl_give PW *FN(PW,alloc_size)(__isl_take isl_space *dim,
22 enum isl_fold type, int n)
23 #else
24 __isl_give PW *FN(PW,alloc_size)(__isl_take isl_space *dim, int n)
25 #endif
27 isl_ctx *ctx;
28 struct PW *pw;
30 if (!dim)
31 return NULL;
32 ctx = isl_space_get_ctx(dim);
33 isl_assert(ctx, n >= 0, goto error);
34 pw = isl_alloc(ctx, struct PW,
35 sizeof(struct PW) + (n - 1) * sizeof(S(PW,piece)));
36 if (!pw)
37 goto error;
39 pw->ref = 1;
40 #ifdef HAS_TYPE
41 pw->type = type;
42 #endif
43 pw->size = n;
44 pw->n = 0;
45 pw->dim = dim;
46 return pw;
47 error:
48 isl_space_free(dim);
49 return NULL;
52 #ifdef HAS_TYPE
53 __isl_give PW *FN(PW,ZERO)(__isl_take isl_space *dim, enum isl_fold type)
55 return FN(PW,alloc_size)(dim, type, 0);
57 #else
58 __isl_give PW *FN(PW,ZERO)(__isl_take isl_space *dim)
60 return FN(PW,alloc_size)(dim, 0);
62 #endif
64 __isl_give PW *FN(PW,add_piece)(__isl_take PW *pw,
65 __isl_take isl_set *set, __isl_take EL *el)
67 isl_ctx *ctx;
68 isl_space *el_dim = NULL;
70 if (!pw || !set || !el)
71 goto error;
73 if (isl_set_plain_is_empty(set) || FN(EL,EL_IS_ZERO)(el)) {
74 isl_set_free(set);
75 FN(EL,free)(el);
76 return pw;
79 ctx = isl_set_get_ctx(set);
80 #ifdef HAS_TYPE
81 if (pw->type != el->type)
82 isl_die(ctx, isl_error_invalid, "fold types don't match",
83 goto error);
84 #endif
85 el_dim = FN(EL,get_space(el));
86 isl_assert(ctx, isl_space_is_equal(pw->dim, el_dim), goto error);
87 isl_assert(ctx, pw->n < pw->size, goto error);
89 pw->p[pw->n].set = set;
90 pw->p[pw->n].FIELD = el;
91 pw->n++;
93 isl_space_free(el_dim);
94 return pw;
95 error:
96 isl_space_free(el_dim);
97 FN(PW,free)(pw);
98 isl_set_free(set);
99 FN(EL,free)(el);
100 return NULL;
103 /* Does the space of "set" correspond to that of the domain of "el".
105 static isl_bool FN(PW,compatible_domain)(__isl_keep EL *el,
106 __isl_keep isl_set *set)
108 isl_bool ok;
109 isl_space *el_space, *set_space;
111 if (!set || !el)
112 return isl_bool_error;
113 set_space = isl_set_get_space(set);
114 el_space = FN(EL,get_space)(el);
115 ok = isl_space_is_domain_internal(set_space, el_space);
116 isl_space_free(el_space);
117 isl_space_free(set_space);
118 return ok;
121 /* Check that the space of "set" corresponds to that of the domain of "el".
123 static isl_stat FN(PW,check_compatible_domain)(__isl_keep EL *el,
124 __isl_keep isl_set *set)
126 isl_bool ok;
128 ok = FN(PW,compatible_domain)(el, set);
129 if (ok < 0)
130 return isl_stat_error;
131 if (!ok)
132 isl_die(isl_set_get_ctx(set), isl_error_invalid,
133 "incompatible spaces", return isl_stat_error);
135 return isl_stat_ok;
138 #ifdef HAS_TYPE
139 __isl_give PW *FN(PW,alloc)(enum isl_fold type,
140 __isl_take isl_set *set, __isl_take EL *el)
141 #else
142 __isl_give PW *FN(PW,alloc)(__isl_take isl_set *set, __isl_take EL *el)
143 #endif
145 PW *pw;
147 if (FN(PW,check_compatible_domain)(el, set) < 0)
148 goto error;
150 #ifdef HAS_TYPE
151 pw = FN(PW,alloc_size)(FN(EL,get_space)(el), type, 1);
152 #else
153 pw = FN(PW,alloc_size)(FN(EL,get_space)(el), 1);
154 #endif
156 return FN(PW,add_piece)(pw, set, el);
157 error:
158 isl_set_free(set);
159 FN(EL,free)(el);
160 return NULL;
163 __isl_give PW *FN(PW,dup)(__isl_keep PW *pw)
165 int i;
166 PW *dup;
168 if (!pw)
169 return NULL;
171 #ifdef HAS_TYPE
172 dup = FN(PW,alloc_size)(isl_space_copy(pw->dim), pw->type, pw->n);
173 #else
174 dup = FN(PW,alloc_size)(isl_space_copy(pw->dim), pw->n);
175 #endif
176 if (!dup)
177 return NULL;
179 for (i = 0; i < pw->n; ++i)
180 dup = FN(PW,add_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 const char *FN(PW,get_dim_name)(__isl_keep PW *pw, enum isl_dim_type type,
226 unsigned pos)
228 return pw ? isl_space_get_dim_name(pw->dim, type, pos) : NULL;
231 isl_bool FN(PW,has_dim_id)(__isl_keep PW *pw, enum isl_dim_type type,
232 unsigned pos)
234 return pw ? isl_space_has_dim_id(pw->dim, type, pos) : isl_bool_error;
237 __isl_give isl_id *FN(PW,get_dim_id)(__isl_keep PW *pw, enum isl_dim_type type,
238 unsigned pos)
240 return pw ? isl_space_get_dim_id(pw->dim, type, pos) : NULL;
243 isl_bool FN(PW,has_tuple_name)(__isl_keep PW *pw, enum isl_dim_type type)
245 return pw ? isl_space_has_tuple_name(pw->dim, type) : isl_bool_error;
248 const char *FN(PW,get_tuple_name)(__isl_keep PW *pw, enum isl_dim_type type)
250 return pw ? isl_space_get_tuple_name(pw->dim, type) : NULL;
253 isl_bool FN(PW,has_tuple_id)(__isl_keep PW *pw, enum isl_dim_type type)
255 return pw ? isl_space_has_tuple_id(pw->dim, type) : isl_bool_error;
258 __isl_give isl_id *FN(PW,get_tuple_id)(__isl_keep PW *pw, enum isl_dim_type type)
260 return pw ? isl_space_get_tuple_id(pw->dim, type) : NULL;
263 isl_bool FN(PW,IS_ZERO)(__isl_keep PW *pw)
265 if (!pw)
266 return isl_bool_error;
268 return pw->n == 0;
271 #ifndef NO_REALIGN
272 __isl_give PW *FN(PW,realign_domain)(__isl_take PW *pw,
273 __isl_take isl_reordering *exp)
275 int i;
277 pw = FN(PW,cow)(pw);
278 if (!pw || !exp)
279 goto error;
281 for (i = 0; i < pw->n; ++i) {
282 pw->p[i].set = isl_set_realign(pw->p[i].set,
283 isl_reordering_copy(exp));
284 if (!pw->p[i].set)
285 goto error;
286 pw->p[i].FIELD = FN(EL,realign_domain)(pw->p[i].FIELD,
287 isl_reordering_copy(exp));
288 if (!pw->p[i].FIELD)
289 goto error;
292 pw = FN(PW,reset_domain_space)(pw, isl_space_copy(exp->dim));
294 isl_reordering_free(exp);
295 return pw;
296 error:
297 isl_reordering_free(exp);
298 FN(PW,free)(pw);
299 return NULL;
302 /* Align the parameters of "pw" to those of "model".
304 __isl_give PW *FN(PW,align_params)(__isl_take PW *pw, __isl_take isl_space *model)
306 isl_ctx *ctx;
308 if (!pw || !model)
309 goto error;
311 ctx = isl_space_get_ctx(model);
312 if (!isl_space_has_named_params(model))
313 isl_die(ctx, isl_error_invalid,
314 "model has unnamed parameters", goto error);
315 if (!isl_space_has_named_params(pw->dim))
316 isl_die(ctx, isl_error_invalid,
317 "input has unnamed parameters", goto error);
318 if (!isl_space_match(pw->dim, isl_dim_param, model, isl_dim_param)) {
319 isl_reordering *exp;
321 model = isl_space_drop_dims(model, isl_dim_in,
322 0, isl_space_dim(model, isl_dim_in));
323 model = isl_space_drop_dims(model, isl_dim_out,
324 0, isl_space_dim(model, isl_dim_out));
325 exp = isl_parameter_alignment_reordering(pw->dim, model);
326 exp = isl_reordering_extend_space(exp,
327 FN(PW,get_domain_space)(pw));
328 pw = FN(PW,realign_domain)(pw, exp);
331 isl_space_free(model);
332 return pw;
333 error:
334 isl_space_free(model);
335 FN(PW,free)(pw);
336 return NULL;
339 static __isl_give PW *FN(PW,align_params_pw_pw_and)(__isl_take PW *pw1,
340 __isl_take PW *pw2,
341 __isl_give PW *(*fn)(__isl_take PW *pw1, __isl_take PW *pw2))
343 isl_ctx *ctx;
345 if (!pw1 || !pw2)
346 goto error;
347 if (isl_space_match(pw1->dim, isl_dim_param, pw2->dim, isl_dim_param))
348 return fn(pw1, pw2);
349 ctx = FN(PW,get_ctx)(pw1);
350 if (!isl_space_has_named_params(pw1->dim) ||
351 !isl_space_has_named_params(pw2->dim))
352 isl_die(ctx, isl_error_invalid,
353 "unaligned unnamed parameters", goto error);
354 pw1 = FN(PW,align_params)(pw1, FN(PW,get_space)(pw2));
355 pw2 = FN(PW,align_params)(pw2, FN(PW,get_space)(pw1));
356 return fn(pw1, pw2);
357 error:
358 FN(PW,free)(pw1);
359 FN(PW,free)(pw2);
360 return NULL;
363 static __isl_give PW *FN(PW,align_params_pw_set_and)(__isl_take PW *pw,
364 __isl_take isl_set *set,
365 __isl_give PW *(*fn)(__isl_take PW *pw, __isl_take isl_set *set))
367 isl_ctx *ctx;
369 if (!pw || !set)
370 goto error;
371 if (isl_space_match(pw->dim, isl_dim_param, set->dim, isl_dim_param))
372 return fn(pw, set);
373 ctx = FN(PW,get_ctx)(pw);
374 if (!isl_space_has_named_params(pw->dim) ||
375 !isl_space_has_named_params(set->dim))
376 isl_die(ctx, isl_error_invalid,
377 "unaligned unnamed parameters", goto error);
378 pw = FN(PW,align_params)(pw, isl_set_get_space(set));
379 set = isl_set_align_params(set, FN(PW,get_space)(pw));
380 return fn(pw, set);
381 error:
382 FN(PW,free)(pw);
383 isl_set_free(set);
384 return NULL;
386 #endif
388 static __isl_give PW *FN(PW,union_add_aligned)(__isl_take PW *pw1,
389 __isl_take PW *pw2)
391 int i, j, n;
392 struct PW *res;
393 isl_ctx *ctx;
394 isl_set *set;
396 if (!pw1 || !pw2)
397 goto error;
399 ctx = isl_space_get_ctx(pw1->dim);
400 #ifdef HAS_TYPE
401 if (pw1->type != pw2->type)
402 isl_die(ctx, isl_error_invalid,
403 "fold types don't match", goto error);
404 #endif
405 isl_assert(ctx, isl_space_is_equal(pw1->dim, pw2->dim), goto error);
407 if (FN(PW,IS_ZERO)(pw1)) {
408 FN(PW,free)(pw1);
409 return pw2;
412 if (FN(PW,IS_ZERO)(pw2)) {
413 FN(PW,free)(pw2);
414 return pw1;
417 n = (pw1->n + 1) * (pw2->n + 1);
418 #ifdef HAS_TYPE
419 res = FN(PW,alloc_size)(isl_space_copy(pw1->dim), pw1->type, n);
420 #else
421 res = FN(PW,alloc_size)(isl_space_copy(pw1->dim), n);
422 #endif
424 for (i = 0; i < pw1->n; ++i) {
425 set = isl_set_copy(pw1->p[i].set);
426 for (j = 0; j < pw2->n; ++j) {
427 struct isl_set *common;
428 EL *sum;
429 common = isl_set_intersect(isl_set_copy(pw1->p[i].set),
430 isl_set_copy(pw2->p[j].set));
431 if (isl_set_plain_is_empty(common)) {
432 isl_set_free(common);
433 continue;
435 set = isl_set_subtract(set,
436 isl_set_copy(pw2->p[j].set));
438 sum = FN(EL,add_on_domain)(common,
439 FN(EL,copy)(pw1->p[i].FIELD),
440 FN(EL,copy)(pw2->p[j].FIELD));
442 res = FN(PW,add_piece)(res, common, sum);
444 res = FN(PW,add_piece)(res, set, FN(EL,copy)(pw1->p[i].FIELD));
447 for (j = 0; j < pw2->n; ++j) {
448 set = isl_set_copy(pw2->p[j].set);
449 for (i = 0; i < pw1->n; ++i)
450 set = isl_set_subtract(set,
451 isl_set_copy(pw1->p[i].set));
452 res = FN(PW,add_piece)(res, set, FN(EL,copy)(pw2->p[j].FIELD));
455 FN(PW,free)(pw1);
456 FN(PW,free)(pw2);
458 return res;
459 error:
460 FN(PW,free)(pw1);
461 FN(PW,free)(pw2);
462 return NULL;
465 /* Private version of "union_add". For isl_pw_qpolynomial and
466 * isl_pw_qpolynomial_fold, we prefer to simply call it "add".
468 static __isl_give PW *FN(PW,union_add_)(__isl_take PW *pw1, __isl_take PW *pw2)
470 return FN(PW,align_params_pw_pw_and)(pw1, pw2,
471 &FN(PW,union_add_aligned));
474 /* Make sure "pw" has room for at least "n" more pieces.
476 * If there is only one reference to pw, we extend it in place.
477 * Otherwise, we create a new PW and copy the pieces.
479 static __isl_give PW *FN(PW,grow)(__isl_take PW *pw, int n)
481 int i;
482 isl_ctx *ctx;
483 PW *res;
485 if (!pw)
486 return NULL;
487 if (pw->n + n <= pw->size)
488 return pw;
489 ctx = FN(PW,get_ctx)(pw);
490 n += pw->n;
491 if (pw->ref == 1) {
492 res = isl_realloc(ctx, pw, struct PW,
493 sizeof(struct PW) + (n - 1) * sizeof(S(PW,piece)));
494 if (!res)
495 return FN(PW,free)(pw);
496 res->size = n;
497 return res;
499 #ifdef HAS_TYPE
500 res = FN(PW,alloc_size)(isl_space_copy(pw->dim), pw->type, n);
501 #else
502 res = FN(PW,alloc_size)(isl_space_copy(pw->dim), n);
503 #endif
504 if (!res)
505 return FN(PW,free)(pw);
506 for (i = 0; i < pw->n; ++i)
507 res = FN(PW,add_piece)(res, isl_set_copy(pw->p[i].set),
508 FN(EL,copy)(pw->p[i].FIELD));
509 FN(PW,free)(pw);
510 return res;
513 static __isl_give PW *FN(PW,add_disjoint_aligned)(__isl_take PW *pw1,
514 __isl_take PW *pw2)
516 int i;
517 isl_ctx *ctx;
519 if (!pw1 || !pw2)
520 goto error;
522 if (pw1->size < pw1->n + pw2->n && pw1->n < pw2->n)
523 return FN(PW,add_disjoint_aligned)(pw2, pw1);
525 ctx = isl_space_get_ctx(pw1->dim);
526 #ifdef HAS_TYPE
527 if (pw1->type != pw2->type)
528 isl_die(ctx, isl_error_invalid,
529 "fold types don't match", goto error);
530 #endif
531 isl_assert(ctx, isl_space_is_equal(pw1->dim, pw2->dim), goto error);
533 if (FN(PW,IS_ZERO)(pw1)) {
534 FN(PW,free)(pw1);
535 return pw2;
538 if (FN(PW,IS_ZERO)(pw2)) {
539 FN(PW,free)(pw2);
540 return pw1;
543 pw1 = FN(PW,grow)(pw1, pw2->n);
544 if (!pw1)
545 goto error;
547 for (i = 0; i < pw2->n; ++i)
548 pw1 = FN(PW,add_piece)(pw1,
549 isl_set_copy(pw2->p[i].set),
550 FN(EL,copy)(pw2->p[i].FIELD));
552 FN(PW,free)(pw2);
554 return pw1;
555 error:
556 FN(PW,free)(pw1);
557 FN(PW,free)(pw2);
558 return NULL;
561 __isl_give PW *FN(PW,add_disjoint)(__isl_take PW *pw1, __isl_take PW *pw2)
563 return FN(PW,align_params_pw_pw_and)(pw1, pw2,
564 &FN(PW,add_disjoint_aligned));
567 /* This function is currently only used from isl_aff.c
569 static __isl_give PW *FN(PW,on_shared_domain_in)(__isl_take PW *pw1,
570 __isl_take PW *pw2, __isl_take isl_space *space,
571 __isl_give EL *(*fn)(__isl_take EL *el1, __isl_take EL *el2))
572 __attribute__ ((unused));
574 /* Apply "fn" to pairs of elements from pw1 and pw2 on shared domains.
575 * The result of "fn" (and therefore also of this function) lives in "space".
577 static __isl_give PW *FN(PW,on_shared_domain_in)(__isl_take PW *pw1,
578 __isl_take PW *pw2, __isl_take isl_space *space,
579 __isl_give EL *(*fn)(__isl_take EL *el1, __isl_take EL *el2))
581 int i, j, n;
582 PW *res = NULL;
584 if (!pw1 || !pw2)
585 goto error;
587 n = pw1->n * pw2->n;
588 #ifdef HAS_TYPE
589 res = FN(PW,alloc_size)(isl_space_copy(space), pw1->type, n);
590 #else
591 res = FN(PW,alloc_size)(isl_space_copy(space), n);
592 #endif
594 for (i = 0; i < pw1->n; ++i) {
595 for (j = 0; j < pw2->n; ++j) {
596 isl_set *common;
597 EL *res_ij;
598 int empty;
600 common = isl_set_intersect(
601 isl_set_copy(pw1->p[i].set),
602 isl_set_copy(pw2->p[j].set));
603 empty = isl_set_plain_is_empty(common);
604 if (empty < 0 || empty) {
605 isl_set_free(common);
606 if (empty < 0)
607 goto error;
608 continue;
611 res_ij = fn(FN(EL,copy)(pw1->p[i].FIELD),
612 FN(EL,copy)(pw2->p[j].FIELD));
613 res_ij = FN(EL,gist)(res_ij, isl_set_copy(common));
615 res = FN(PW,add_piece)(res, common, res_ij);
619 isl_space_free(space);
620 FN(PW,free)(pw1);
621 FN(PW,free)(pw2);
622 return res;
623 error:
624 isl_space_free(space);
625 FN(PW,free)(pw1);
626 FN(PW,free)(pw2);
627 FN(PW,free)(res);
628 return NULL;
631 /* This function is currently only used from isl_aff.c
633 static __isl_give PW *FN(PW,on_shared_domain)(__isl_take PW *pw1,
634 __isl_take PW *pw2,
635 __isl_give EL *(*fn)(__isl_take EL *el1, __isl_take EL *el2))
636 __attribute__ ((unused));
638 /* Apply "fn" to pairs of elements from pw1 and pw2 on shared domains.
639 * The result of "fn" is assumed to live in the same space as "pw1" and "pw2".
641 static __isl_give PW *FN(PW,on_shared_domain)(__isl_take PW *pw1,
642 __isl_take PW *pw2,
643 __isl_give EL *(*fn)(__isl_take EL *el1, __isl_take EL *el2))
645 isl_space *space;
647 if (!pw1 || !pw2)
648 goto error;
650 space = isl_space_copy(pw1->dim);
651 return FN(PW,on_shared_domain_in)(pw1, pw2, space, fn);
652 error:
653 FN(PW,free)(pw1);
654 FN(PW,free)(pw2);
655 return NULL;
658 #ifndef NO_NEG
659 __isl_give PW *FN(PW,neg)(__isl_take PW *pw)
661 int i;
663 if (!pw)
664 return NULL;
666 if (FN(PW,IS_ZERO)(pw))
667 return pw;
669 pw = FN(PW,cow)(pw);
670 if (!pw)
671 return NULL;
673 for (i = 0; i < pw->n; ++i) {
674 pw->p[i].FIELD = FN(EL,neg)(pw->p[i].FIELD);
675 if (!pw->p[i].FIELD)
676 return FN(PW,free)(pw);
679 return pw;
681 #endif
683 #ifndef NO_SUB
684 __isl_give PW *FN(PW,sub)(__isl_take PW *pw1, __isl_take PW *pw2)
686 return FN(PW,add)(pw1, FN(PW,neg)(pw2));
688 #endif
690 #ifndef NO_EVAL
691 __isl_give isl_val *FN(PW,eval)(__isl_take PW *pw, __isl_take isl_point *pnt)
693 int i;
694 int found = 0;
695 isl_ctx *ctx;
696 isl_space *pnt_dim = NULL;
697 isl_val *v;
699 if (!pw || !pnt)
700 goto error;
701 ctx = isl_point_get_ctx(pnt);
702 pnt_dim = isl_point_get_space(pnt);
703 isl_assert(ctx, isl_space_is_domain_internal(pnt_dim, pw->dim),
704 goto error);
706 for (i = 0; i < pw->n; ++i) {
707 found = isl_set_contains_point(pw->p[i].set, pnt);
708 if (found < 0)
709 goto error;
710 if (found)
711 break;
713 if (found)
714 v = FN(EL,eval)(FN(EL,copy)(pw->p[i].FIELD),
715 isl_point_copy(pnt));
716 else
717 v = isl_val_zero(ctx);
718 FN(PW,free)(pw);
719 isl_space_free(pnt_dim);
720 isl_point_free(pnt);
721 return v;
722 error:
723 FN(PW,free)(pw);
724 isl_space_free(pnt_dim);
725 isl_point_free(pnt);
726 return NULL;
728 #endif
730 /* Return the parameter domain of "pw".
732 __isl_give isl_set *FN(PW,params)(__isl_take PW *pw)
734 return isl_set_params(FN(PW,domain)(pw));
737 __isl_give isl_set *FN(PW,domain)(__isl_take PW *pw)
739 int i;
740 isl_set *dom;
742 if (!pw)
743 return NULL;
745 dom = isl_set_empty(FN(PW,get_domain_space)(pw));
746 for (i = 0; i < pw->n; ++i)
747 dom = isl_set_union_disjoint(dom, isl_set_copy(pw->p[i].set));
749 FN(PW,free)(pw);
751 return dom;
754 /* Exploit the equalities in the domain of piece "i" of "pw"
755 * to simplify the associated function.
756 * If the domain of piece "i" is empty, then remove it entirely,
757 * replacing it with the final piece.
759 static int FN(PW,exploit_equalities_and_remove_if_empty)(__isl_keep PW *pw,
760 int i)
762 isl_basic_set *aff;
763 int empty = isl_set_plain_is_empty(pw->p[i].set);
765 if (empty < 0)
766 return -1;
767 if (empty) {
768 isl_set_free(pw->p[i].set);
769 FN(EL,free)(pw->p[i].FIELD);
770 if (i != pw->n - 1)
771 pw->p[i] = pw->p[pw->n - 1];
772 pw->n--;
774 return 0;
777 aff = isl_set_affine_hull(isl_set_copy(pw->p[i].set));
778 pw->p[i].FIELD = FN(EL,substitute_equalities)(pw->p[i].FIELD, aff);
779 if (!pw->p[i].FIELD)
780 return -1;
782 return 0;
785 /* Convert a piecewise expression defined over a parameter domain
786 * into one that is defined over a zero-dimensional set.
788 __isl_give PW *FN(PW,from_range)(__isl_take PW *pw)
790 isl_space *space;
792 if (!pw)
793 return NULL;
794 if (!isl_space_is_set(pw->dim))
795 isl_die(FN(PW,get_ctx)(pw), isl_error_invalid,
796 "not living in a set space", return FN(PW,free)(pw));
798 space = FN(PW,get_space)(pw);
799 space = isl_space_from_range(space);
800 pw = FN(PW,reset_space)(pw, space);
802 return pw;
805 /* Fix the value of the given parameter or domain dimension of "pw"
806 * to be equal to "value".
808 __isl_give PW *FN(PW,fix_si)(__isl_take PW *pw, enum isl_dim_type type,
809 unsigned pos, int value)
811 int i;
813 if (!pw)
814 return NULL;
816 if (type == isl_dim_out)
817 isl_die(FN(PW,get_ctx)(pw), isl_error_invalid,
818 "cannot fix output dimension", return FN(PW,free)(pw));
820 if (pw->n == 0)
821 return pw;
823 if (type == isl_dim_in)
824 type = isl_dim_set;
826 pw = FN(PW,cow)(pw);
827 if (!pw)
828 return FN(PW,free)(pw);
830 for (i = pw->n - 1; i >= 0; --i) {
831 pw->p[i].set = isl_set_fix_si(pw->p[i].set, type, pos, value);
832 if (FN(PW,exploit_equalities_and_remove_if_empty)(pw, i) < 0)
833 return FN(PW,free)(pw);
836 return pw;
839 /* Restrict the domain of "pw" by combining each cell
840 * with "set" through a call to "fn", where "fn" may be
841 * isl_set_intersect, isl_set_intersect_params or isl_set_subtract.
843 static __isl_give PW *FN(PW,restrict_domain_aligned)(__isl_take PW *pw,
844 __isl_take isl_set *set,
845 __isl_give isl_set *(*fn)(__isl_take isl_set *set1,
846 __isl_take isl_set *set2))
848 int i;
850 if (!pw || !set)
851 goto error;
853 if (pw->n == 0) {
854 isl_set_free(set);
855 return pw;
858 pw = FN(PW,cow)(pw);
859 if (!pw)
860 goto error;
862 for (i = pw->n - 1; i >= 0; --i) {
863 pw->p[i].set = fn(pw->p[i].set, isl_set_copy(set));
864 if (FN(PW,exploit_equalities_and_remove_if_empty)(pw, i) < 0)
865 goto error;
868 isl_set_free(set);
869 return pw;
870 error:
871 isl_set_free(set);
872 FN(PW,free)(pw);
873 return NULL;
876 static __isl_give PW *FN(PW,intersect_domain_aligned)(__isl_take PW *pw,
877 __isl_take isl_set *set)
879 return FN(PW,restrict_domain_aligned)(pw, set, &isl_set_intersect);
882 __isl_give PW *FN(PW,intersect_domain)(__isl_take PW *pw,
883 __isl_take isl_set *context)
885 return FN(PW,align_params_pw_set_and)(pw, context,
886 &FN(PW,intersect_domain_aligned));
889 static __isl_give PW *FN(PW,intersect_params_aligned)(__isl_take PW *pw,
890 __isl_take isl_set *set)
892 return FN(PW,restrict_domain_aligned)(pw, set,
893 &isl_set_intersect_params);
896 /* Intersect the domain of "pw" with the parameter domain "context".
898 __isl_give PW *FN(PW,intersect_params)(__isl_take PW *pw,
899 __isl_take isl_set *context)
901 return FN(PW,align_params_pw_set_and)(pw, context,
902 &FN(PW,intersect_params_aligned));
905 /* Subtract "domain' from the domain of "pw", assuming their
906 * parameters have been aligned.
908 static __isl_give PW *FN(PW,subtract_domain_aligned)(__isl_take PW *pw,
909 __isl_take isl_set *domain)
911 return FN(PW,restrict_domain_aligned)(pw, domain, &isl_set_subtract);
914 /* Subtract "domain' from the domain of "pw".
916 __isl_give PW *FN(PW,subtract_domain)(__isl_take PW *pw,
917 __isl_take isl_set *domain)
919 return FN(PW,align_params_pw_set_and)(pw, domain,
920 &FN(PW,subtract_domain_aligned));
923 /* Compute the gist of "pw" with respect to the domain constraints
924 * of "context" for the case where the domain of the last element
925 * of "pw" is equal to "context".
926 * Call "fn_el" to compute the gist of this element, replace
927 * its domain by the universe and drop all other elements
928 * as their domains are necessarily disjoint from "context".
930 static __isl_give PW *FN(PW,gist_last)(__isl_take PW *pw,
931 __isl_take isl_set *context,
932 __isl_give EL *(*fn_el)(__isl_take EL *el, __isl_take isl_set *set))
934 int i;
935 isl_space *space;
937 for (i = 0; i < pw->n - 1; ++i) {
938 isl_set_free(pw->p[i].set);
939 FN(EL,free)(pw->p[i].FIELD);
941 pw->p[0].FIELD = pw->p[pw->n - 1].FIELD;
942 pw->p[0].set = pw->p[pw->n - 1].set;
943 pw->n = 1;
945 space = isl_set_get_space(context);
946 pw->p[0].FIELD = fn_el(pw->p[0].FIELD, context);
947 context = isl_set_universe(space);
948 isl_set_free(pw->p[0].set);
949 pw->p[0].set = context;
951 if (!pw->p[0].FIELD || !pw->p[0].set)
952 return FN(PW,free)(pw);
954 return pw;
957 /* Compute the gist of "pw" with respect to the domain constraints
958 * of "context". Call "fn_el" to compute the gist of the elements
959 * and "fn_dom" to compute the gist of the domains.
961 * If the piecewise expression is empty or the context is the universe,
962 * then nothing can be simplified.
964 static __isl_give PW *FN(PW,gist_aligned)(__isl_take PW *pw,
965 __isl_take isl_set *context,
966 __isl_give EL *(*fn_el)(__isl_take EL *el,
967 __isl_take isl_set *set),
968 __isl_give isl_set *(*fn_dom)(__isl_take isl_set *set,
969 __isl_take isl_basic_set *bset))
971 int i;
972 int is_universe;
973 isl_basic_set *hull = NULL;
975 if (!pw || !context)
976 goto error;
978 if (pw->n == 0) {
979 isl_set_free(context);
980 return pw;
983 is_universe = isl_set_plain_is_universe(context);
984 if (is_universe < 0)
985 goto error;
986 if (is_universe) {
987 isl_set_free(context);
988 return pw;
991 if (!isl_space_match(pw->dim, isl_dim_param,
992 context->dim, isl_dim_param)) {
993 pw = FN(PW,align_params)(pw, isl_set_get_space(context));
994 context = isl_set_align_params(context, FN(PW,get_space)(pw));
997 pw = FN(PW,cow)(pw);
998 if (!pw)
999 goto error;
1001 if (pw->n == 1) {
1002 int equal;
1004 equal = isl_set_plain_is_equal(pw->p[0].set, context);
1005 if (equal < 0)
1006 goto error;
1007 if (equal)
1008 return FN(PW,gist_last)(pw, context, fn_el);
1011 context = isl_set_compute_divs(context);
1012 hull = isl_set_simple_hull(isl_set_copy(context));
1014 for (i = pw->n - 1; i >= 0; --i) {
1015 isl_set *set_i;
1016 int empty;
1018 if (i == pw->n - 1) {
1019 int equal;
1020 equal = isl_set_plain_is_equal(pw->p[i].set, context);
1021 if (equal < 0)
1022 goto error;
1023 if (equal) {
1024 isl_basic_set_free(hull);
1025 return FN(PW,gist_last)(pw, context, fn_el);
1028 set_i = isl_set_intersect(isl_set_copy(pw->p[i].set),
1029 isl_set_copy(context));
1030 empty = isl_set_plain_is_empty(set_i);
1031 pw->p[i].FIELD = fn_el(pw->p[i].FIELD, set_i);
1032 pw->p[i].set = fn_dom(pw->p[i].set, isl_basic_set_copy(hull));
1033 if (empty < 0 || !pw->p[i].FIELD || !pw->p[i].set)
1034 goto error;
1035 if (empty) {
1036 isl_set_free(pw->p[i].set);
1037 FN(EL,free)(pw->p[i].FIELD);
1038 if (i != pw->n - 1)
1039 pw->p[i] = pw->p[pw->n - 1];
1040 pw->n--;
1044 isl_basic_set_free(hull);
1045 isl_set_free(context);
1047 return pw;
1048 error:
1049 FN(PW,free)(pw);
1050 isl_basic_set_free(hull);
1051 isl_set_free(context);
1052 return NULL;
1055 static __isl_give PW *FN(PW,gist_domain_aligned)(__isl_take PW *pw,
1056 __isl_take isl_set *set)
1058 return FN(PW,gist_aligned)(pw, set, &FN(EL,gist),
1059 &isl_set_gist_basic_set);
1062 __isl_give PW *FN(PW,gist)(__isl_take PW *pw, __isl_take isl_set *context)
1064 return FN(PW,align_params_pw_set_and)(pw, context,
1065 &FN(PW,gist_domain_aligned));
1068 static __isl_give PW *FN(PW,gist_params_aligned)(__isl_take PW *pw,
1069 __isl_take isl_set *set)
1071 return FN(PW,gist_aligned)(pw, set, &FN(EL,gist_params),
1072 &isl_set_gist_params_basic_set);
1075 __isl_give PW *FN(PW,gist_params)(__isl_take PW *pw,
1076 __isl_take isl_set *context)
1078 return FN(PW,align_params_pw_set_and)(pw, context,
1079 &FN(PW,gist_params_aligned));
1082 /* Return -1 if the piece "p1" should be sorted before "p2"
1083 * and 1 if it should be sorted after "p2".
1084 * Return 0 if they do not need to be sorted in a specific order.
1086 * The two pieces are compared on the basis of their function value expressions.
1088 static int FN(PW,sort_field_cmp)(const void *p1, const void *p2, void *arg)
1090 struct FN(PW,piece) const *pc1 = p1;
1091 struct FN(PW,piece) const *pc2 = p2;
1093 return FN(EL,plain_cmp)(pc1->FIELD, pc2->FIELD);
1096 /* Sort the pieces of "pw" according to their function value
1097 * expressions and then combine pairs of adjacent pieces with
1098 * the same such expression.
1100 * The sorting is performed in place because it does not
1101 * change the meaning of "pw", but care needs to be
1102 * taken not to change any possible other copies of "pw"
1103 * in case anything goes wrong.
1105 __isl_give PW *FN(PW,sort)(__isl_take PW *pw)
1107 int i, j;
1108 isl_set *set;
1110 if (!pw)
1111 return NULL;
1112 if (pw->n <= 1)
1113 return pw;
1114 if (isl_sort(pw->p, pw->n, sizeof(pw->p[0]),
1115 &FN(PW,sort_field_cmp), NULL) < 0)
1116 return FN(PW,free)(pw);
1117 for (i = pw->n - 1; i >= 1; --i) {
1118 if (!FN(EL,plain_is_equal)(pw->p[i - 1].FIELD, pw->p[i].FIELD))
1119 continue;
1120 set = isl_set_union(isl_set_copy(pw->p[i - 1].set),
1121 isl_set_copy(pw->p[i].set));
1122 if (!set)
1123 return FN(PW,free)(pw);
1124 isl_set_free(pw->p[i].set);
1125 FN(EL,free)(pw->p[i].FIELD);
1126 isl_set_free(pw->p[i - 1].set);
1127 pw->p[i - 1].set = set;
1128 for (j = i + 1; j < pw->n; ++j)
1129 pw->p[j - 1] = pw->p[j];
1130 pw->n--;
1133 return pw;
1136 /* Coalesce the domains of "pw".
1138 * Prior to the actual coalescing, first sort the pieces such that
1139 * pieces with the same function value expression are combined
1140 * into a single piece, the combined domain of which can then
1141 * be coalesced.
1143 __isl_give PW *FN(PW,coalesce)(__isl_take PW *pw)
1145 int i;
1147 pw = FN(PW,sort)(pw);
1148 if (!pw)
1149 return NULL;
1151 for (i = 0; i < pw->n; ++i) {
1152 pw->p[i].set = isl_set_coalesce(pw->p[i].set);
1153 if (!pw->p[i].set)
1154 goto error;
1157 return pw;
1158 error:
1159 FN(PW,free)(pw);
1160 return NULL;
1163 isl_ctx *FN(PW,get_ctx)(__isl_keep PW *pw)
1165 return pw ? isl_space_get_ctx(pw->dim) : NULL;
1168 #ifndef NO_INVOLVES_DIMS
1169 isl_bool FN(PW,involves_dims)(__isl_keep PW *pw, enum isl_dim_type type,
1170 unsigned first, unsigned n)
1172 int i;
1173 enum isl_dim_type set_type;
1175 if (!pw)
1176 return isl_bool_error;
1177 if (pw->n == 0 || n == 0)
1178 return isl_bool_false;
1180 set_type = type == isl_dim_in ? isl_dim_set : type;
1182 for (i = 0; i < pw->n; ++i) {
1183 isl_bool involves = FN(EL,involves_dims)(pw->p[i].FIELD,
1184 type, first, n);
1185 if (involves < 0 || involves)
1186 return involves;
1187 involves = isl_set_involves_dims(pw->p[i].set,
1188 set_type, first, n);
1189 if (involves < 0 || involves)
1190 return involves;
1192 return isl_bool_false;
1194 #endif
1196 __isl_give PW *FN(PW,set_dim_name)(__isl_take PW *pw,
1197 enum isl_dim_type type, unsigned pos, const char *s)
1199 int i;
1200 enum isl_dim_type set_type;
1202 pw = FN(PW,cow)(pw);
1203 if (!pw)
1204 return NULL;
1206 set_type = type == isl_dim_in ? isl_dim_set : type;
1208 pw->dim = isl_space_set_dim_name(pw->dim, type, pos, s);
1209 if (!pw->dim)
1210 goto error;
1212 for (i = 0; i < pw->n; ++i) {
1213 pw->p[i].set = isl_set_set_dim_name(pw->p[i].set,
1214 set_type, pos, s);
1215 if (!pw->p[i].set)
1216 goto error;
1217 pw->p[i].FIELD = FN(EL,set_dim_name)(pw->p[i].FIELD, type, pos, s);
1218 if (!pw->p[i].FIELD)
1219 goto error;
1222 return pw;
1223 error:
1224 FN(PW,free)(pw);
1225 return NULL;
1228 #ifndef NO_DROP_DIMS
1229 __isl_give PW *FN(PW,drop_dims)(__isl_take PW *pw,
1230 enum isl_dim_type type, unsigned first, unsigned n)
1232 int i;
1233 enum isl_dim_type set_type;
1235 if (!pw)
1236 return NULL;
1237 if (n == 0 && !isl_space_get_tuple_name(pw->dim, type))
1238 return pw;
1240 set_type = type == isl_dim_in ? isl_dim_set : type;
1242 pw = FN(PW,cow)(pw);
1243 if (!pw)
1244 return NULL;
1245 pw->dim = isl_space_drop_dims(pw->dim, type, first, n);
1246 if (!pw->dim)
1247 goto error;
1248 for (i = 0; i < pw->n; ++i) {
1249 pw->p[i].FIELD = FN(EL,drop_dims)(pw->p[i].FIELD, type, first, n);
1250 if (!pw->p[i].FIELD)
1251 goto error;
1252 if (type == isl_dim_out)
1253 continue;
1254 pw->p[i].set = isl_set_drop(pw->p[i].set, set_type, first, n);
1255 if (!pw->p[i].set)
1256 goto error;
1259 return pw;
1260 error:
1261 FN(PW,free)(pw);
1262 return NULL;
1265 /* This function is very similar to drop_dims.
1266 * The only difference is that the cells may still involve
1267 * the specified dimensions. They are removed using
1268 * isl_set_project_out instead of isl_set_drop.
1270 __isl_give PW *FN(PW,project_out)(__isl_take PW *pw,
1271 enum isl_dim_type type, unsigned first, unsigned n)
1273 int i;
1274 enum isl_dim_type set_type;
1276 if (!pw)
1277 return NULL;
1278 if (n == 0 && !isl_space_get_tuple_name(pw->dim, type))
1279 return pw;
1281 set_type = type == isl_dim_in ? isl_dim_set : type;
1283 pw = FN(PW,cow)(pw);
1284 if (!pw)
1285 return NULL;
1286 pw->dim = isl_space_drop_dims(pw->dim, type, first, n);
1287 if (!pw->dim)
1288 goto error;
1289 for (i = 0; i < pw->n; ++i) {
1290 pw->p[i].set = isl_set_project_out(pw->p[i].set,
1291 set_type, first, n);
1292 if (!pw->p[i].set)
1293 goto error;
1294 pw->p[i].FIELD = FN(EL,drop_dims)(pw->p[i].FIELD, type, first, n);
1295 if (!pw->p[i].FIELD)
1296 goto error;
1299 return pw;
1300 error:
1301 FN(PW,free)(pw);
1302 return NULL;
1305 /* Project the domain of pw onto its parameter space.
1307 __isl_give PW *FN(PW,project_domain_on_params)(__isl_take PW *pw)
1309 isl_space *space;
1310 unsigned n;
1312 n = FN(PW,dim)(pw, isl_dim_in);
1313 pw = FN(PW,project_out)(pw, isl_dim_in, 0, n);
1314 space = FN(PW,get_domain_space)(pw);
1315 space = isl_space_params(space);
1316 pw = FN(PW,reset_domain_space)(pw, space);
1317 return pw;
1319 #endif
1321 #ifndef NO_INSERT_DIMS
1322 __isl_give PW *FN(PW,insert_dims)(__isl_take PW *pw, enum isl_dim_type type,
1323 unsigned first, unsigned n)
1325 int i;
1326 enum isl_dim_type set_type;
1328 if (!pw)
1329 return NULL;
1330 if (n == 0 && !isl_space_is_named_or_nested(pw->dim, type))
1331 return pw;
1333 set_type = type == isl_dim_in ? isl_dim_set : type;
1335 pw = FN(PW,cow)(pw);
1336 if (!pw)
1337 return NULL;
1339 pw->dim = isl_space_insert_dims(pw->dim, type, first, n);
1340 if (!pw->dim)
1341 goto error;
1343 for (i = 0; i < pw->n; ++i) {
1344 pw->p[i].set = isl_set_insert_dims(pw->p[i].set,
1345 set_type, first, n);
1346 if (!pw->p[i].set)
1347 goto error;
1348 pw->p[i].FIELD = FN(EL,insert_dims)(pw->p[i].FIELD,
1349 type, first, n);
1350 if (!pw->p[i].FIELD)
1351 goto error;
1354 return pw;
1355 error:
1356 FN(PW,free)(pw);
1357 return NULL;
1359 #endif
1361 __isl_give PW *FN(PW,fix_dim)(__isl_take PW *pw,
1362 enum isl_dim_type type, unsigned pos, isl_int v)
1364 int i;
1366 if (!pw)
1367 return NULL;
1369 if (type == isl_dim_in)
1370 type = isl_dim_set;
1372 pw = FN(PW,cow)(pw);
1373 if (!pw)
1374 return NULL;
1375 for (i = 0; i < pw->n; ++i) {
1376 pw->p[i].set = isl_set_fix(pw->p[i].set, type, pos, v);
1377 if (FN(PW,exploit_equalities_and_remove_if_empty)(pw, i) < 0)
1378 return FN(PW,free)(pw);
1381 return pw;
1384 /* Fix the value of the variable at position "pos" of type "type" of "pw"
1385 * to be equal to "v".
1387 __isl_give PW *FN(PW,fix_val)(__isl_take PW *pw,
1388 enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
1390 if (!v)
1391 return FN(PW,free)(pw);
1392 if (!isl_val_is_int(v))
1393 isl_die(FN(PW,get_ctx)(pw), isl_error_invalid,
1394 "expecting integer value", goto error);
1396 pw = FN(PW,fix_dim)(pw, type, pos, v->n);
1397 isl_val_free(v);
1399 return pw;
1400 error:
1401 isl_val_free(v);
1402 return FN(PW,free)(pw);
1405 unsigned FN(PW,dim)(__isl_keep PW *pw, enum isl_dim_type type)
1407 return pw ? isl_space_dim(pw->dim, type) : 0;
1410 __isl_give PW *FN(PW,split_dims)(__isl_take PW *pw,
1411 enum isl_dim_type type, unsigned first, unsigned n)
1413 int i;
1415 if (!pw)
1416 return NULL;
1417 if (n == 0)
1418 return pw;
1420 if (type == isl_dim_in)
1421 type = isl_dim_set;
1423 pw = FN(PW,cow)(pw);
1424 if (!pw)
1425 return NULL;
1426 if (!pw->dim)
1427 goto error;
1428 for (i = 0; i < pw->n; ++i) {
1429 pw->p[i].set = isl_set_split_dims(pw->p[i].set, type, first, n);
1430 if (!pw->p[i].set)
1431 goto error;
1434 return pw;
1435 error:
1436 FN(PW,free)(pw);
1437 return NULL;
1440 #ifndef NO_OPT
1441 /* Compute the maximal value attained by the piecewise quasipolynomial
1442 * on its domain or zero if the domain is empty.
1443 * In the worst case, the domain is scanned completely,
1444 * so the domain is assumed to be bounded.
1446 __isl_give isl_val *FN(PW,opt)(__isl_take PW *pw, int max)
1448 int i;
1449 isl_val *opt;
1451 if (!pw)
1452 return NULL;
1454 if (pw->n == 0) {
1455 opt = isl_val_zero(FN(PW,get_ctx)(pw));
1456 FN(PW,free)(pw);
1457 return opt;
1460 opt = FN(EL,opt_on_domain)(FN(EL,copy)(pw->p[0].FIELD),
1461 isl_set_copy(pw->p[0].set), max);
1462 for (i = 1; i < pw->n; ++i) {
1463 isl_val *opt_i;
1464 opt_i = FN(EL,opt_on_domain)(FN(EL,copy)(pw->p[i].FIELD),
1465 isl_set_copy(pw->p[i].set), max);
1466 if (max)
1467 opt = isl_val_max(opt, opt_i);
1468 else
1469 opt = isl_val_min(opt, opt_i);
1472 FN(PW,free)(pw);
1473 return opt;
1476 __isl_give isl_val *FN(PW,max)(__isl_take PW *pw)
1478 return FN(PW,opt)(pw, 1);
1481 __isl_give isl_val *FN(PW,min)(__isl_take PW *pw)
1483 return FN(PW,opt)(pw, 0);
1485 #endif
1487 __isl_give isl_space *FN(PW,get_space)(__isl_keep PW *pw)
1489 return pw ? isl_space_copy(pw->dim) : NULL;
1492 __isl_give isl_space *FN(PW,get_domain_space)(__isl_keep PW *pw)
1494 return pw ? isl_space_domain(isl_space_copy(pw->dim)) : NULL;
1497 /* Return the position of the dimension of the given type and name
1498 * in "pw".
1499 * Return -1 if no such dimension can be found.
1501 int FN(PW,find_dim_by_name)(__isl_keep PW *pw,
1502 enum isl_dim_type type, const char *name)
1504 if (!pw)
1505 return -1;
1506 return isl_space_find_dim_by_name(pw->dim, type, name);
1509 #ifndef NO_RESET_DIM
1510 /* Reset the space of "pw". Since we don't know if the elements
1511 * represent the spaces themselves or their domains, we pass along
1512 * both when we call their reset_space_and_domain.
1514 static __isl_give PW *FN(PW,reset_space_and_domain)(__isl_take PW *pw,
1515 __isl_take isl_space *space, __isl_take isl_space *domain)
1517 int i;
1519 pw = FN(PW,cow)(pw);
1520 if (!pw || !space || !domain)
1521 goto error;
1523 for (i = 0; i < pw->n; ++i) {
1524 pw->p[i].set = isl_set_reset_space(pw->p[i].set,
1525 isl_space_copy(domain));
1526 if (!pw->p[i].set)
1527 goto error;
1528 pw->p[i].FIELD = FN(EL,reset_space_and_domain)(pw->p[i].FIELD,
1529 isl_space_copy(space), isl_space_copy(domain));
1530 if (!pw->p[i].FIELD)
1531 goto error;
1534 isl_space_free(domain);
1536 isl_space_free(pw->dim);
1537 pw->dim = space;
1539 return pw;
1540 error:
1541 isl_space_free(domain);
1542 isl_space_free(space);
1543 FN(PW,free)(pw);
1544 return NULL;
1547 __isl_give PW *FN(PW,reset_domain_space)(__isl_take PW *pw,
1548 __isl_take isl_space *domain)
1550 isl_space *space;
1552 space = isl_space_extend_domain_with_range(isl_space_copy(domain),
1553 FN(PW,get_space)(pw));
1554 return FN(PW,reset_space_and_domain)(pw, space, domain);
1557 __isl_give PW *FN(PW,reset_space)(__isl_take PW *pw, __isl_take isl_space *dim)
1559 isl_space *domain;
1561 domain = isl_space_domain(isl_space_copy(dim));
1562 return FN(PW,reset_space_and_domain)(pw, dim, domain);
1565 __isl_give PW *FN(PW,set_tuple_id)(__isl_take PW *pw, enum isl_dim_type type,
1566 __isl_take isl_id *id)
1568 isl_space *space;
1570 pw = FN(PW,cow)(pw);
1571 if (!pw)
1572 goto error;
1574 space = FN(PW,get_space)(pw);
1575 space = isl_space_set_tuple_id(space, type, id);
1577 return FN(PW,reset_space)(pw, space);
1578 error:
1579 isl_id_free(id);
1580 return FN(PW,free)(pw);
1583 /* Drop the id on the specified tuple.
1585 __isl_give PW *FN(PW,reset_tuple_id)(__isl_take PW *pw, enum isl_dim_type type)
1587 isl_space *space;
1589 if (!pw)
1590 return NULL;
1591 if (!FN(PW,has_tuple_id)(pw, type))
1592 return pw;
1594 pw = FN(PW,cow)(pw);
1595 if (!pw)
1596 return NULL;
1598 space = FN(PW,get_space)(pw);
1599 space = isl_space_reset_tuple_id(space, type);
1601 return FN(PW,reset_space)(pw, space);
1604 __isl_give PW *FN(PW,set_dim_id)(__isl_take PW *pw,
1605 enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)
1607 pw = FN(PW,cow)(pw);
1608 if (!pw)
1609 goto error;
1610 pw->dim = isl_space_set_dim_id(pw->dim, type, pos, id);
1611 return FN(PW,reset_space)(pw, isl_space_copy(pw->dim));
1612 error:
1613 isl_id_free(id);
1614 return FN(PW,free)(pw);
1616 #endif
1618 /* Reset the user pointer on all identifiers of parameters and tuples
1619 * of the space of "pw".
1621 __isl_give PW *FN(PW,reset_user)(__isl_take PW *pw)
1623 isl_space *space;
1625 space = FN(PW,get_space)(pw);
1626 space = isl_space_reset_user(space);
1628 return FN(PW,reset_space)(pw, space);
1631 int FN(PW,has_equal_space)(__isl_keep PW *pw1, __isl_keep PW *pw2)
1633 if (!pw1 || !pw2)
1634 return -1;
1636 return isl_space_is_equal(pw1->dim, pw2->dim);
1639 #ifndef NO_MORPH
1640 __isl_give PW *FN(PW,morph_domain)(__isl_take PW *pw,
1641 __isl_take isl_morph *morph)
1643 int i;
1644 isl_ctx *ctx;
1646 if (!pw || !morph)
1647 goto error;
1649 ctx = isl_space_get_ctx(pw->dim);
1650 isl_assert(ctx, isl_space_is_domain_internal(morph->dom->dim, pw->dim),
1651 goto error);
1653 pw = FN(PW,cow)(pw);
1654 if (!pw)
1655 goto error;
1656 pw->dim = isl_space_extend_domain_with_range(
1657 isl_space_copy(morph->ran->dim), pw->dim);
1658 if (!pw->dim)
1659 goto error;
1661 for (i = 0; i < pw->n; ++i) {
1662 pw->p[i].set = isl_morph_set(isl_morph_copy(morph), pw->p[i].set);
1663 if (!pw->p[i].set)
1664 goto error;
1665 pw->p[i].FIELD = FN(EL,morph_domain)(pw->p[i].FIELD,
1666 isl_morph_copy(morph));
1667 if (!pw->p[i].FIELD)
1668 goto error;
1671 isl_morph_free(morph);
1673 return pw;
1674 error:
1675 FN(PW,free)(pw);
1676 isl_morph_free(morph);
1677 return NULL;
1679 #endif
1681 int FN(PW,n_piece)(__isl_keep PW *pw)
1683 return pw ? pw->n : 0;
1686 isl_stat FN(PW,foreach_piece)(__isl_keep PW *pw,
1687 isl_stat (*fn)(__isl_take isl_set *set, __isl_take EL *el, void *user),
1688 void *user)
1690 int i;
1692 if (!pw)
1693 return isl_stat_error;
1695 for (i = 0; i < pw->n; ++i)
1696 if (fn(isl_set_copy(pw->p[i].set),
1697 FN(EL,copy)(pw->p[i].FIELD), user) < 0)
1698 return isl_stat_error;
1700 return isl_stat_ok;
1703 #ifndef NO_LIFT
1704 static int any_divs(__isl_keep isl_set *set)
1706 int i;
1708 if (!set)
1709 return -1;
1711 for (i = 0; i < set->n; ++i)
1712 if (set->p[i]->n_div > 0)
1713 return 1;
1715 return 0;
1718 static isl_stat foreach_lifted_subset(__isl_take isl_set *set,
1719 __isl_take EL *el,
1720 isl_stat (*fn)(__isl_take isl_set *set, __isl_take EL *el,
1721 void *user), void *user)
1723 int i;
1725 if (!set || !el)
1726 goto error;
1728 for (i = 0; i < set->n; ++i) {
1729 isl_set *lift;
1730 EL *copy;
1732 lift = isl_set_from_basic_set(isl_basic_set_copy(set->p[i]));
1733 lift = isl_set_lift(lift);
1735 copy = FN(EL,copy)(el);
1736 copy = FN(EL,lift)(copy, isl_set_get_space(lift));
1738 if (fn(lift, copy, user) < 0)
1739 goto error;
1742 isl_set_free(set);
1743 FN(EL,free)(el);
1745 return isl_stat_ok;
1746 error:
1747 isl_set_free(set);
1748 FN(EL,free)(el);
1749 return isl_stat_error;
1752 isl_stat FN(PW,foreach_lifted_piece)(__isl_keep PW *pw,
1753 isl_stat (*fn)(__isl_take isl_set *set, __isl_take EL *el,
1754 void *user), void *user)
1756 int i;
1758 if (!pw)
1759 return isl_stat_error;
1761 for (i = 0; i < pw->n; ++i) {
1762 isl_set *set;
1763 EL *el;
1765 set = isl_set_copy(pw->p[i].set);
1766 el = FN(EL,copy)(pw->p[i].FIELD);
1767 if (!any_divs(set)) {
1768 if (fn(set, el, user) < 0)
1769 return isl_stat_error;
1770 continue;
1772 if (foreach_lifted_subset(set, el, fn, user) < 0)
1773 return isl_stat_error;
1776 return isl_stat_ok;
1778 #endif
1780 #ifndef NO_MOVE_DIMS
1781 __isl_give PW *FN(PW,move_dims)(__isl_take PW *pw,
1782 enum isl_dim_type dst_type, unsigned dst_pos,
1783 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
1785 int i;
1787 pw = FN(PW,cow)(pw);
1788 if (!pw)
1789 return NULL;
1791 pw->dim = isl_space_move_dims(pw->dim, dst_type, dst_pos, src_type, src_pos, n);
1792 if (!pw->dim)
1793 goto error;
1795 for (i = 0; i < pw->n; ++i) {
1796 pw->p[i].FIELD = FN(EL,move_dims)(pw->p[i].FIELD,
1797 dst_type, dst_pos, src_type, src_pos, n);
1798 if (!pw->p[i].FIELD)
1799 goto error;
1802 if (dst_type == isl_dim_in)
1803 dst_type = isl_dim_set;
1804 if (src_type == isl_dim_in)
1805 src_type = isl_dim_set;
1807 for (i = 0; i < pw->n; ++i) {
1808 pw->p[i].set = isl_set_move_dims(pw->p[i].set,
1809 dst_type, dst_pos,
1810 src_type, src_pos, n);
1811 if (!pw->p[i].set)
1812 goto error;
1815 return pw;
1816 error:
1817 FN(PW,free)(pw);
1818 return NULL;
1820 #endif
1822 __isl_give PW *FN(PW,mul_isl_int)(__isl_take PW *pw, isl_int v)
1824 int i;
1826 if (isl_int_is_one(v))
1827 return pw;
1828 if (pw && DEFAULT_IS_ZERO && isl_int_is_zero(v)) {
1829 PW *zero;
1830 isl_space *dim = FN(PW,get_space)(pw);
1831 #ifdef HAS_TYPE
1832 zero = FN(PW,ZERO)(dim, pw->type);
1833 #else
1834 zero = FN(PW,ZERO)(dim);
1835 #endif
1836 FN(PW,free)(pw);
1837 return zero;
1839 pw = FN(PW,cow)(pw);
1840 if (!pw)
1841 return NULL;
1842 if (pw->n == 0)
1843 return pw;
1845 #ifdef HAS_TYPE
1846 if (isl_int_is_neg(v))
1847 pw->type = isl_fold_type_negate(pw->type);
1848 #endif
1849 for (i = 0; i < pw->n; ++i) {
1850 pw->p[i].FIELD = FN(EL,scale)(pw->p[i].FIELD, v);
1851 if (!pw->p[i].FIELD)
1852 goto error;
1855 return pw;
1856 error:
1857 FN(PW,free)(pw);
1858 return NULL;
1861 /* Multiply the pieces of "pw" by "v" and return the result.
1863 __isl_give PW *FN(PW,scale_val)(__isl_take PW *pw, __isl_take isl_val *v)
1865 int i;
1867 if (!pw || !v)
1868 goto error;
1870 if (isl_val_is_one(v)) {
1871 isl_val_free(v);
1872 return pw;
1874 if (pw && DEFAULT_IS_ZERO && isl_val_is_zero(v)) {
1875 PW *zero;
1876 isl_space *space = FN(PW,get_space)(pw);
1877 #ifdef HAS_TYPE
1878 zero = FN(PW,ZERO)(space, pw->type);
1879 #else
1880 zero = FN(PW,ZERO)(space);
1881 #endif
1882 FN(PW,free)(pw);
1883 isl_val_free(v);
1884 return zero;
1886 if (pw->n == 0) {
1887 isl_val_free(v);
1888 return pw;
1890 pw = FN(PW,cow)(pw);
1891 if (!pw)
1892 goto error;
1894 #ifdef HAS_TYPE
1895 if (isl_val_is_neg(v))
1896 pw->type = isl_fold_type_negate(pw->type);
1897 #endif
1898 for (i = 0; i < pw->n; ++i) {
1899 pw->p[i].FIELD = FN(EL,scale_val)(pw->p[i].FIELD,
1900 isl_val_copy(v));
1901 if (!pw->p[i].FIELD)
1902 goto error;
1905 isl_val_free(v);
1906 return pw;
1907 error:
1908 isl_val_free(v);
1909 FN(PW,free)(pw);
1910 return NULL;
1913 /* Divide the pieces of "pw" by "v" and return the result.
1915 __isl_give PW *FN(PW,scale_down_val)(__isl_take PW *pw, __isl_take isl_val *v)
1917 int i;
1919 if (!pw || !v)
1920 goto error;
1922 if (isl_val_is_one(v)) {
1923 isl_val_free(v);
1924 return pw;
1927 if (!isl_val_is_rat(v))
1928 isl_die(isl_val_get_ctx(v), isl_error_invalid,
1929 "expecting rational factor", goto error);
1930 if (isl_val_is_zero(v))
1931 isl_die(isl_val_get_ctx(v), isl_error_invalid,
1932 "cannot scale down by zero", goto error);
1934 if (pw->n == 0) {
1935 isl_val_free(v);
1936 return pw;
1938 pw = FN(PW,cow)(pw);
1939 if (!pw)
1940 goto error;
1942 #ifdef HAS_TYPE
1943 if (isl_val_is_neg(v))
1944 pw->type = isl_fold_type_negate(pw->type);
1945 #endif
1946 for (i = 0; i < pw->n; ++i) {
1947 pw->p[i].FIELD = FN(EL,scale_down_val)(pw->p[i].FIELD,
1948 isl_val_copy(v));
1949 if (!pw->p[i].FIELD)
1950 goto error;
1953 isl_val_free(v);
1954 return pw;
1955 error:
1956 isl_val_free(v);
1957 FN(PW,free)(pw);
1958 return NULL;
1961 __isl_give PW *FN(PW,scale)(__isl_take PW *pw, isl_int v)
1963 return FN(PW,mul_isl_int)(pw, v);
1966 /* Apply some normalization to "pw".
1967 * In particular, sort the pieces according to their function value
1968 * expressions, combining pairs of adjacent pieces with
1969 * the same such expression, and then normalize the domains of the pieces.
1971 * We normalize in place, but if anything goes wrong we need
1972 * to return NULL, so we need to make sure we don't change the
1973 * meaning of any possible other copies of "pw".
1975 __isl_give PW *FN(PW,normalize)(__isl_take PW *pw)
1977 int i;
1978 isl_set *set;
1980 pw = FN(PW,sort)(pw);
1981 if (!pw)
1982 return NULL;
1983 for (i = 0; i < pw->n; ++i) {
1984 set = isl_set_normalize(isl_set_copy(pw->p[i].set));
1985 if (!set)
1986 return FN(PW,free)(pw);
1987 isl_set_free(pw->p[i].set);
1988 pw->p[i].set = set;
1991 return pw;
1994 /* Is pw1 obviously equal to pw2?
1995 * That is, do they have obviously identical cells and obviously identical
1996 * elements on each cell?
1998 isl_bool FN(PW,plain_is_equal)(__isl_keep PW *pw1, __isl_keep PW *pw2)
2000 int i;
2001 isl_bool equal;
2003 if (!pw1 || !pw2)
2004 return isl_bool_error;
2006 if (pw1 == pw2)
2007 return isl_bool_true;
2008 if (!isl_space_is_equal(pw1->dim, pw2->dim))
2009 return isl_bool_false;
2011 pw1 = FN(PW,copy)(pw1);
2012 pw2 = FN(PW,copy)(pw2);
2013 pw1 = FN(PW,normalize)(pw1);
2014 pw2 = FN(PW,normalize)(pw2);
2015 if (!pw1 || !pw2)
2016 goto error;
2018 equal = pw1->n == pw2->n;
2019 for (i = 0; equal && i < pw1->n; ++i) {
2020 equal = isl_set_plain_is_equal(pw1->p[i].set, pw2->p[i].set);
2021 if (equal < 0)
2022 goto error;
2023 if (!equal)
2024 break;
2025 equal = FN(EL,plain_is_equal)(pw1->p[i].FIELD, pw2->p[i].FIELD);
2026 if (equal < 0)
2027 goto error;
2030 FN(PW,free)(pw1);
2031 FN(PW,free)(pw2);
2032 return equal;
2033 error:
2034 FN(PW,free)(pw1);
2035 FN(PW,free)(pw2);
2036 return isl_bool_error;
2039 #ifndef NO_PULLBACK
2040 static __isl_give PW *FN(PW,align_params_pw_multi_aff_and)(__isl_take PW *pw,
2041 __isl_take isl_multi_aff *ma,
2042 __isl_give PW *(*fn)(__isl_take PW *pw, __isl_take isl_multi_aff *ma))
2044 isl_ctx *ctx;
2045 isl_space *ma_space;
2047 ma_space = isl_multi_aff_get_space(ma);
2048 if (!pw || !ma || !ma_space)
2049 goto error;
2050 if (isl_space_match(pw->dim, isl_dim_param, ma_space, isl_dim_param)) {
2051 isl_space_free(ma_space);
2052 return fn(pw, ma);
2054 ctx = FN(PW,get_ctx)(pw);
2055 if (!isl_space_has_named_params(pw->dim) ||
2056 !isl_space_has_named_params(ma_space))
2057 isl_die(ctx, isl_error_invalid,
2058 "unaligned unnamed parameters", goto error);
2059 pw = FN(PW,align_params)(pw, ma_space);
2060 ma = isl_multi_aff_align_params(ma, FN(PW,get_space)(pw));
2061 return fn(pw, ma);
2062 error:
2063 isl_space_free(ma_space);
2064 FN(PW,free)(pw);
2065 isl_multi_aff_free(ma);
2066 return NULL;
2069 static __isl_give PW *FN(PW,align_params_pw_pw_multi_aff_and)(__isl_take PW *pw,
2070 __isl_take isl_pw_multi_aff *pma,
2071 __isl_give PW *(*fn)(__isl_take PW *pw,
2072 __isl_take isl_pw_multi_aff *ma))
2074 isl_ctx *ctx;
2075 isl_space *pma_space;
2077 pma_space = isl_pw_multi_aff_get_space(pma);
2078 if (!pw || !pma || !pma_space)
2079 goto error;
2080 if (isl_space_match(pw->dim, isl_dim_param, pma_space, isl_dim_param)) {
2081 isl_space_free(pma_space);
2082 return fn(pw, pma);
2084 ctx = FN(PW,get_ctx)(pw);
2085 if (!isl_space_has_named_params(pw->dim) ||
2086 !isl_space_has_named_params(pma_space))
2087 isl_die(ctx, isl_error_invalid,
2088 "unaligned unnamed parameters", goto error);
2089 pw = FN(PW,align_params)(pw, pma_space);
2090 pma = isl_pw_multi_aff_align_params(pma, FN(PW,get_space)(pw));
2091 return fn(pw, pma);
2092 error:
2093 isl_space_free(pma_space);
2094 FN(PW,free)(pw);
2095 isl_pw_multi_aff_free(pma);
2096 return NULL;
2099 /* Compute the pullback of "pw" by the function represented by "ma".
2100 * In other words, plug in "ma" in "pw".
2102 static __isl_give PW *FN(PW,pullback_multi_aff_aligned)(__isl_take PW *pw,
2103 __isl_take isl_multi_aff *ma)
2105 int i;
2106 isl_space *space = NULL;
2108 ma = isl_multi_aff_align_divs(ma);
2109 pw = FN(PW,cow)(pw);
2110 if (!pw || !ma)
2111 goto error;
2113 space = isl_space_join(isl_multi_aff_get_space(ma),
2114 FN(PW,get_space)(pw));
2116 for (i = 0; i < pw->n; ++i) {
2117 pw->p[i].set = isl_set_preimage_multi_aff(pw->p[i].set,
2118 isl_multi_aff_copy(ma));
2119 if (!pw->p[i].set)
2120 goto error;
2121 pw->p[i].FIELD = FN(EL,pullback_multi_aff)(pw->p[i].FIELD,
2122 isl_multi_aff_copy(ma));
2123 if (!pw->p[i].FIELD)
2124 goto error;
2127 pw = FN(PW,reset_space)(pw, space);
2128 isl_multi_aff_free(ma);
2129 return pw;
2130 error:
2131 isl_space_free(space);
2132 isl_multi_aff_free(ma);
2133 FN(PW,free)(pw);
2134 return NULL;
2137 __isl_give PW *FN(PW,pullback_multi_aff)(__isl_take PW *pw,
2138 __isl_take isl_multi_aff *ma)
2140 return FN(PW,align_params_pw_multi_aff_and)(pw, ma,
2141 &FN(PW,pullback_multi_aff_aligned));
2144 /* Compute the pullback of "pw" by the function represented by "pma".
2145 * In other words, plug in "pma" in "pw".
2147 static __isl_give PW *FN(PW,pullback_pw_multi_aff_aligned)(__isl_take PW *pw,
2148 __isl_take isl_pw_multi_aff *pma)
2150 int i;
2151 PW *res;
2153 if (!pma)
2154 goto error;
2156 if (pma->n == 0) {
2157 isl_space *space;
2158 space = isl_space_join(isl_pw_multi_aff_get_space(pma),
2159 FN(PW,get_space)(pw));
2160 isl_pw_multi_aff_free(pma);
2161 res = FN(PW,empty)(space);
2162 FN(PW,free)(pw);
2163 return res;
2166 res = FN(PW,pullback_multi_aff)(FN(PW,copy)(pw),
2167 isl_multi_aff_copy(pma->p[0].maff));
2168 res = FN(PW,intersect_domain)(res, isl_set_copy(pma->p[0].set));
2170 for (i = 1; i < pma->n; ++i) {
2171 PW *res_i;
2173 res_i = FN(PW,pullback_multi_aff)(FN(PW,copy)(pw),
2174 isl_multi_aff_copy(pma->p[i].maff));
2175 res_i = FN(PW,intersect_domain)(res_i,
2176 isl_set_copy(pma->p[i].set));
2177 res = FN(PW,add_disjoint)(res, res_i);
2180 isl_pw_multi_aff_free(pma);
2181 FN(PW,free)(pw);
2182 return res;
2183 error:
2184 isl_pw_multi_aff_free(pma);
2185 FN(PW,free)(pw);
2186 return NULL;
2189 __isl_give PW *FN(PW,pullback_pw_multi_aff)(__isl_take PW *pw,
2190 __isl_take isl_pw_multi_aff *pma)
2192 return FN(PW,align_params_pw_pw_multi_aff_and)(pw, pma,
2193 &FN(PW,pullback_pw_multi_aff_aligned));
2195 #endif