isl_space_is_equal: use isl_space_has_equal_tuples
[isl.git] / isl_pw_templ.c
blob92c94d3213fa75ca1045ea44defad2f388553d77
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 #ifdef HAS_TYPE
104 __isl_give PW *FN(PW,alloc)(enum isl_fold type,
105 __isl_take isl_set *set, __isl_take EL *el)
106 #else
107 __isl_give PW *FN(PW,alloc)(__isl_take isl_set *set, __isl_take EL *el)
108 #endif
110 PW *pw;
112 if (!set || !el)
113 goto error;
115 #ifdef HAS_TYPE
116 pw = FN(PW,alloc_size)(FN(EL,get_space)(el), type, 1);
117 #else
118 pw = FN(PW,alloc_size)(FN(EL,get_space)(el), 1);
119 #endif
121 return FN(PW,add_piece)(pw, set, el);
122 error:
123 isl_set_free(set);
124 FN(EL,free)(el);
125 return NULL;
128 __isl_give PW *FN(PW,dup)(__isl_keep PW *pw)
130 int i;
131 PW *dup;
133 if (!pw)
134 return NULL;
136 #ifdef HAS_TYPE
137 dup = FN(PW,alloc_size)(isl_space_copy(pw->dim), pw->type, pw->n);
138 #else
139 dup = FN(PW,alloc_size)(isl_space_copy(pw->dim), pw->n);
140 #endif
141 if (!dup)
142 return NULL;
144 for (i = 0; i < pw->n; ++i)
145 dup = FN(PW,add_piece)(dup, isl_set_copy(pw->p[i].set),
146 FN(EL,copy)(pw->p[i].FIELD));
148 return dup;
151 __isl_give PW *FN(PW,cow)(__isl_take PW *pw)
153 if (!pw)
154 return NULL;
156 if (pw->ref == 1)
157 return pw;
158 pw->ref--;
159 return FN(PW,dup)(pw);
162 __isl_give PW *FN(PW,copy)(__isl_keep PW *pw)
164 if (!pw)
165 return NULL;
167 pw->ref++;
168 return pw;
171 __isl_null PW *FN(PW,free)(__isl_take PW *pw)
173 int i;
175 if (!pw)
176 return NULL;
177 if (--pw->ref > 0)
178 return NULL;
180 for (i = 0; i < pw->n; ++i) {
181 isl_set_free(pw->p[i].set);
182 FN(EL,free)(pw->p[i].FIELD);
184 isl_space_free(pw->dim);
185 free(pw);
187 return NULL;
190 const char *FN(PW,get_dim_name)(__isl_keep PW *pw, enum isl_dim_type type,
191 unsigned pos)
193 return pw ? isl_space_get_dim_name(pw->dim, type, pos) : NULL;
196 isl_bool FN(PW,has_dim_id)(__isl_keep PW *pw, enum isl_dim_type type,
197 unsigned pos)
199 return pw ? isl_space_has_dim_id(pw->dim, type, pos) : isl_bool_error;
202 __isl_give isl_id *FN(PW,get_dim_id)(__isl_keep PW *pw, enum isl_dim_type type,
203 unsigned pos)
205 return pw ? isl_space_get_dim_id(pw->dim, type, pos) : NULL;
208 isl_bool FN(PW,has_tuple_name)(__isl_keep PW *pw, enum isl_dim_type type)
210 return pw ? isl_space_has_tuple_name(pw->dim, type) : isl_bool_error;
213 const char *FN(PW,get_tuple_name)(__isl_keep PW *pw, enum isl_dim_type type)
215 return pw ? isl_space_get_tuple_name(pw->dim, type) : NULL;
218 isl_bool FN(PW,has_tuple_id)(__isl_keep PW *pw, enum isl_dim_type type)
220 return pw ? isl_space_has_tuple_id(pw->dim, type) : isl_bool_error;
223 __isl_give isl_id *FN(PW,get_tuple_id)(__isl_keep PW *pw, enum isl_dim_type type)
225 return pw ? isl_space_get_tuple_id(pw->dim, type) : NULL;
228 isl_bool FN(PW,IS_ZERO)(__isl_keep PW *pw)
230 if (!pw)
231 return isl_bool_error;
233 return pw->n == 0;
236 #ifndef NO_REALIGN
237 __isl_give PW *FN(PW,realign_domain)(__isl_take PW *pw,
238 __isl_take isl_reordering *exp)
240 int i;
242 pw = FN(PW,cow)(pw);
243 if (!pw || !exp)
244 goto error;
246 for (i = 0; i < pw->n; ++i) {
247 pw->p[i].set = isl_set_realign(pw->p[i].set,
248 isl_reordering_copy(exp));
249 if (!pw->p[i].set)
250 goto error;
251 pw->p[i].FIELD = FN(EL,realign_domain)(pw->p[i].FIELD,
252 isl_reordering_copy(exp));
253 if (!pw->p[i].FIELD)
254 goto error;
257 pw = FN(PW,reset_domain_space)(pw, isl_space_copy(exp->dim));
259 isl_reordering_free(exp);
260 return pw;
261 error:
262 isl_reordering_free(exp);
263 FN(PW,free)(pw);
264 return NULL;
267 /* Align the parameters of "pw" to those of "model".
269 __isl_give PW *FN(PW,align_params)(__isl_take PW *pw, __isl_take isl_space *model)
271 isl_ctx *ctx;
273 if (!pw || !model)
274 goto error;
276 ctx = isl_space_get_ctx(model);
277 if (!isl_space_has_named_params(model))
278 isl_die(ctx, isl_error_invalid,
279 "model has unnamed parameters", goto error);
280 if (!isl_space_has_named_params(pw->dim))
281 isl_die(ctx, isl_error_invalid,
282 "input has unnamed parameters", goto error);
283 if (!isl_space_match(pw->dim, isl_dim_param, model, isl_dim_param)) {
284 isl_reordering *exp;
286 model = isl_space_drop_dims(model, isl_dim_in,
287 0, isl_space_dim(model, isl_dim_in));
288 model = isl_space_drop_dims(model, isl_dim_out,
289 0, isl_space_dim(model, isl_dim_out));
290 exp = isl_parameter_alignment_reordering(pw->dim, model);
291 exp = isl_reordering_extend_space(exp,
292 FN(PW,get_domain_space)(pw));
293 pw = FN(PW,realign_domain)(pw, exp);
296 isl_space_free(model);
297 return pw;
298 error:
299 isl_space_free(model);
300 FN(PW,free)(pw);
301 return NULL;
304 static __isl_give PW *FN(PW,align_params_pw_pw_and)(__isl_take PW *pw1,
305 __isl_take PW *pw2,
306 __isl_give PW *(*fn)(__isl_take PW *pw1, __isl_take PW *pw2))
308 isl_ctx *ctx;
310 if (!pw1 || !pw2)
311 goto error;
312 if (isl_space_match(pw1->dim, isl_dim_param, pw2->dim, isl_dim_param))
313 return fn(pw1, pw2);
314 ctx = FN(PW,get_ctx)(pw1);
315 if (!isl_space_has_named_params(pw1->dim) ||
316 !isl_space_has_named_params(pw2->dim))
317 isl_die(ctx, isl_error_invalid,
318 "unaligned unnamed parameters", goto error);
319 pw1 = FN(PW,align_params)(pw1, FN(PW,get_space)(pw2));
320 pw2 = FN(PW,align_params)(pw2, FN(PW,get_space)(pw1));
321 return fn(pw1, pw2);
322 error:
323 FN(PW,free)(pw1);
324 FN(PW,free)(pw2);
325 return NULL;
328 static __isl_give PW *FN(PW,align_params_pw_set_and)(__isl_take PW *pw,
329 __isl_take isl_set *set,
330 __isl_give PW *(*fn)(__isl_take PW *pw, __isl_take isl_set *set))
332 isl_ctx *ctx;
333 isl_bool aligned;
335 if (!pw || !set)
336 goto error;
337 aligned = isl_set_space_has_equal_params(set, pw->dim);
338 if (aligned < 0)
339 goto error;
340 if (aligned)
341 return fn(pw, set);
342 ctx = FN(PW,get_ctx)(pw);
343 if (!isl_space_has_named_params(pw->dim) ||
344 !isl_space_has_named_params(set->dim))
345 isl_die(ctx, isl_error_invalid,
346 "unaligned unnamed parameters", goto error);
347 pw = FN(PW,align_params)(pw, isl_set_get_space(set));
348 set = isl_set_align_params(set, FN(PW,get_space)(pw));
349 return fn(pw, set);
350 error:
351 FN(PW,free)(pw);
352 isl_set_free(set);
353 return NULL;
355 #endif
357 static __isl_give PW *FN(PW,union_add_aligned)(__isl_take PW *pw1,
358 __isl_take PW *pw2)
360 int i, j, n;
361 struct PW *res;
362 isl_ctx *ctx;
363 isl_set *set;
365 if (!pw1 || !pw2)
366 goto error;
368 ctx = isl_space_get_ctx(pw1->dim);
369 #ifdef HAS_TYPE
370 if (pw1->type != pw2->type)
371 isl_die(ctx, isl_error_invalid,
372 "fold types don't match", goto error);
373 #endif
374 isl_assert(ctx, isl_space_is_equal(pw1->dim, pw2->dim), goto error);
376 if (FN(PW,IS_ZERO)(pw1)) {
377 FN(PW,free)(pw1);
378 return pw2;
381 if (FN(PW,IS_ZERO)(pw2)) {
382 FN(PW,free)(pw2);
383 return pw1;
386 n = (pw1->n + 1) * (pw2->n + 1);
387 #ifdef HAS_TYPE
388 res = FN(PW,alloc_size)(isl_space_copy(pw1->dim), pw1->type, n);
389 #else
390 res = FN(PW,alloc_size)(isl_space_copy(pw1->dim), n);
391 #endif
393 for (i = 0; i < pw1->n; ++i) {
394 set = isl_set_copy(pw1->p[i].set);
395 for (j = 0; j < pw2->n; ++j) {
396 struct isl_set *common;
397 EL *sum;
398 common = isl_set_intersect(isl_set_copy(pw1->p[i].set),
399 isl_set_copy(pw2->p[j].set));
400 if (isl_set_plain_is_empty(common)) {
401 isl_set_free(common);
402 continue;
404 set = isl_set_subtract(set,
405 isl_set_copy(pw2->p[j].set));
407 sum = FN(EL,add_on_domain)(common,
408 FN(EL,copy)(pw1->p[i].FIELD),
409 FN(EL,copy)(pw2->p[j].FIELD));
411 res = FN(PW,add_piece)(res, common, sum);
413 res = FN(PW,add_piece)(res, set, FN(EL,copy)(pw1->p[i].FIELD));
416 for (j = 0; j < pw2->n; ++j) {
417 set = isl_set_copy(pw2->p[j].set);
418 for (i = 0; i < pw1->n; ++i)
419 set = isl_set_subtract(set,
420 isl_set_copy(pw1->p[i].set));
421 res = FN(PW,add_piece)(res, set, FN(EL,copy)(pw2->p[j].FIELD));
424 FN(PW,free)(pw1);
425 FN(PW,free)(pw2);
427 return res;
428 error:
429 FN(PW,free)(pw1);
430 FN(PW,free)(pw2);
431 return NULL;
434 /* Private version of "union_add". For isl_pw_qpolynomial and
435 * isl_pw_qpolynomial_fold, we prefer to simply call it "add".
437 static __isl_give PW *FN(PW,union_add_)(__isl_take PW *pw1, __isl_take PW *pw2)
439 return FN(PW,align_params_pw_pw_and)(pw1, pw2,
440 &FN(PW,union_add_aligned));
443 /* Make sure "pw" has room for at least "n" more pieces.
445 * If there is only one reference to pw, we extend it in place.
446 * Otherwise, we create a new PW and copy the pieces.
448 static __isl_give PW *FN(PW,grow)(__isl_take PW *pw, int n)
450 int i;
451 isl_ctx *ctx;
452 PW *res;
454 if (!pw)
455 return NULL;
456 if (pw->n + n <= pw->size)
457 return pw;
458 ctx = FN(PW,get_ctx)(pw);
459 n += pw->n;
460 if (pw->ref == 1) {
461 res = isl_realloc(ctx, pw, struct PW,
462 sizeof(struct PW) + (n - 1) * sizeof(S(PW,piece)));
463 if (!res)
464 return FN(PW,free)(pw);
465 res->size = n;
466 return res;
468 #ifdef HAS_TYPE
469 res = FN(PW,alloc_size)(isl_space_copy(pw->dim), pw->type, n);
470 #else
471 res = FN(PW,alloc_size)(isl_space_copy(pw->dim), n);
472 #endif
473 if (!res)
474 return FN(PW,free)(pw);
475 for (i = 0; i < pw->n; ++i)
476 res = FN(PW,add_piece)(res, isl_set_copy(pw->p[i].set),
477 FN(EL,copy)(pw->p[i].FIELD));
478 FN(PW,free)(pw);
479 return res;
482 static __isl_give PW *FN(PW,add_disjoint_aligned)(__isl_take PW *pw1,
483 __isl_take PW *pw2)
485 int i;
486 isl_ctx *ctx;
488 if (!pw1 || !pw2)
489 goto error;
491 if (pw1->size < pw1->n + pw2->n && pw1->n < pw2->n)
492 return FN(PW,add_disjoint_aligned)(pw2, pw1);
494 ctx = isl_space_get_ctx(pw1->dim);
495 #ifdef HAS_TYPE
496 if (pw1->type != pw2->type)
497 isl_die(ctx, isl_error_invalid,
498 "fold types don't match", goto error);
499 #endif
500 isl_assert(ctx, isl_space_is_equal(pw1->dim, pw2->dim), goto error);
502 if (FN(PW,IS_ZERO)(pw1)) {
503 FN(PW,free)(pw1);
504 return pw2;
507 if (FN(PW,IS_ZERO)(pw2)) {
508 FN(PW,free)(pw2);
509 return pw1;
512 pw1 = FN(PW,grow)(pw1, pw2->n);
513 if (!pw1)
514 goto error;
516 for (i = 0; i < pw2->n; ++i)
517 pw1 = FN(PW,add_piece)(pw1,
518 isl_set_copy(pw2->p[i].set),
519 FN(EL,copy)(pw2->p[i].FIELD));
521 FN(PW,free)(pw2);
523 return pw1;
524 error:
525 FN(PW,free)(pw1);
526 FN(PW,free)(pw2);
527 return NULL;
530 __isl_give PW *FN(PW,add_disjoint)(__isl_take PW *pw1, __isl_take PW *pw2)
532 return FN(PW,align_params_pw_pw_and)(pw1, pw2,
533 &FN(PW,add_disjoint_aligned));
536 /* This function is currently only used from isl_aff.c
538 static __isl_give PW *FN(PW,on_shared_domain_in)(__isl_take PW *pw1,
539 __isl_take PW *pw2, __isl_take isl_space *space,
540 __isl_give EL *(*fn)(__isl_take EL *el1, __isl_take EL *el2))
541 __attribute__ ((unused));
543 /* Apply "fn" to pairs of elements from pw1 and pw2 on shared domains.
544 * The result of "fn" (and therefore also of this function) lives in "space".
546 static __isl_give PW *FN(PW,on_shared_domain_in)(__isl_take PW *pw1,
547 __isl_take PW *pw2, __isl_take isl_space *space,
548 __isl_give EL *(*fn)(__isl_take EL *el1, __isl_take EL *el2))
550 int i, j, n;
551 PW *res = NULL;
553 if (!pw1 || !pw2)
554 goto error;
556 n = pw1->n * pw2->n;
557 #ifdef HAS_TYPE
558 res = FN(PW,alloc_size)(isl_space_copy(space), pw1->type, n);
559 #else
560 res = FN(PW,alloc_size)(isl_space_copy(space), n);
561 #endif
563 for (i = 0; i < pw1->n; ++i) {
564 for (j = 0; j < pw2->n; ++j) {
565 isl_set *common;
566 EL *res_ij;
567 int empty;
569 common = isl_set_intersect(
570 isl_set_copy(pw1->p[i].set),
571 isl_set_copy(pw2->p[j].set));
572 empty = isl_set_plain_is_empty(common);
573 if (empty < 0 || empty) {
574 isl_set_free(common);
575 if (empty < 0)
576 goto error;
577 continue;
580 res_ij = fn(FN(EL,copy)(pw1->p[i].FIELD),
581 FN(EL,copy)(pw2->p[j].FIELD));
582 res_ij = FN(EL,gist)(res_ij, isl_set_copy(common));
584 res = FN(PW,add_piece)(res, common, res_ij);
588 isl_space_free(space);
589 FN(PW,free)(pw1);
590 FN(PW,free)(pw2);
591 return res;
592 error:
593 isl_space_free(space);
594 FN(PW,free)(pw1);
595 FN(PW,free)(pw2);
596 FN(PW,free)(res);
597 return NULL;
600 /* This function is currently only used from isl_aff.c
602 static __isl_give PW *FN(PW,on_shared_domain)(__isl_take PW *pw1,
603 __isl_take PW *pw2,
604 __isl_give EL *(*fn)(__isl_take EL *el1, __isl_take EL *el2))
605 __attribute__ ((unused));
607 /* Apply "fn" to pairs of elements from pw1 and pw2 on shared domains.
608 * The result of "fn" is assumed to live in the same space as "pw1" and "pw2".
610 static __isl_give PW *FN(PW,on_shared_domain)(__isl_take PW *pw1,
611 __isl_take PW *pw2,
612 __isl_give EL *(*fn)(__isl_take EL *el1, __isl_take EL *el2))
614 isl_space *space;
616 if (!pw1 || !pw2)
617 goto error;
619 space = isl_space_copy(pw1->dim);
620 return FN(PW,on_shared_domain_in)(pw1, pw2, space, fn);
621 error:
622 FN(PW,free)(pw1);
623 FN(PW,free)(pw2);
624 return NULL;
627 #ifndef NO_NEG
628 __isl_give PW *FN(PW,neg)(__isl_take PW *pw)
630 int i;
632 if (!pw)
633 return NULL;
635 if (FN(PW,IS_ZERO)(pw))
636 return pw;
638 pw = FN(PW,cow)(pw);
639 if (!pw)
640 return NULL;
642 for (i = 0; i < pw->n; ++i) {
643 pw->p[i].FIELD = FN(EL,neg)(pw->p[i].FIELD);
644 if (!pw->p[i].FIELD)
645 return FN(PW,free)(pw);
648 return pw;
650 #endif
652 #ifndef NO_SUB
653 __isl_give PW *FN(PW,sub)(__isl_take PW *pw1, __isl_take PW *pw2)
655 return FN(PW,add)(pw1, FN(PW,neg)(pw2));
657 #endif
659 #ifndef NO_EVAL
660 __isl_give isl_val *FN(PW,eval)(__isl_take PW *pw, __isl_take isl_point *pnt)
662 int i;
663 int found = 0;
664 isl_ctx *ctx;
665 isl_space *pnt_dim = NULL;
666 isl_val *v;
668 if (!pw || !pnt)
669 goto error;
670 ctx = isl_point_get_ctx(pnt);
671 pnt_dim = isl_point_get_space(pnt);
672 isl_assert(ctx, isl_space_is_domain_internal(pnt_dim, pw->dim),
673 goto error);
675 for (i = 0; i < pw->n; ++i) {
676 found = isl_set_contains_point(pw->p[i].set, pnt);
677 if (found < 0)
678 goto error;
679 if (found)
680 break;
682 if (found)
683 v = FN(EL,eval)(FN(EL,copy)(pw->p[i].FIELD),
684 isl_point_copy(pnt));
685 else
686 v = isl_val_zero(ctx);
687 FN(PW,free)(pw);
688 isl_space_free(pnt_dim);
689 isl_point_free(pnt);
690 return v;
691 error:
692 FN(PW,free)(pw);
693 isl_space_free(pnt_dim);
694 isl_point_free(pnt);
695 return NULL;
697 #endif
699 /* Return the parameter domain of "pw".
701 __isl_give isl_set *FN(PW,params)(__isl_take PW *pw)
703 return isl_set_params(FN(PW,domain)(pw));
706 __isl_give isl_set *FN(PW,domain)(__isl_take PW *pw)
708 int i;
709 isl_set *dom;
711 if (!pw)
712 return NULL;
714 dom = isl_set_empty(FN(PW,get_domain_space)(pw));
715 for (i = 0; i < pw->n; ++i)
716 dom = isl_set_union_disjoint(dom, isl_set_copy(pw->p[i].set));
718 FN(PW,free)(pw);
720 return dom;
723 /* Exploit the equalities in the domain of piece "i" of "pw"
724 * to simplify the associated function.
725 * If the domain of piece "i" is empty, then remove it entirely,
726 * replacing it with the final piece.
728 static int FN(PW,exploit_equalities_and_remove_if_empty)(__isl_keep PW *pw,
729 int i)
731 isl_basic_set *aff;
732 int empty = isl_set_plain_is_empty(pw->p[i].set);
734 if (empty < 0)
735 return -1;
736 if (empty) {
737 isl_set_free(pw->p[i].set);
738 FN(EL,free)(pw->p[i].FIELD);
739 if (i != pw->n - 1)
740 pw->p[i] = pw->p[pw->n - 1];
741 pw->n--;
743 return 0;
746 aff = isl_set_affine_hull(isl_set_copy(pw->p[i].set));
747 pw->p[i].FIELD = FN(EL,substitute_equalities)(pw->p[i].FIELD, aff);
748 if (!pw->p[i].FIELD)
749 return -1;
751 return 0;
754 /* Convert a piecewise expression defined over a parameter domain
755 * into one that is defined over a zero-dimensional set.
757 __isl_give PW *FN(PW,from_range)(__isl_take PW *pw)
759 isl_space *space;
761 if (!pw)
762 return NULL;
763 if (!isl_space_is_set(pw->dim))
764 isl_die(FN(PW,get_ctx)(pw), isl_error_invalid,
765 "not living in a set space", return FN(PW,free)(pw));
767 space = FN(PW,get_space)(pw);
768 space = isl_space_from_range(space);
769 pw = FN(PW,reset_space)(pw, space);
771 return pw;
774 /* Fix the value of the given parameter or domain dimension of "pw"
775 * to be equal to "value".
777 __isl_give PW *FN(PW,fix_si)(__isl_take PW *pw, enum isl_dim_type type,
778 unsigned pos, int value)
780 int i;
782 if (!pw)
783 return NULL;
785 if (type == isl_dim_out)
786 isl_die(FN(PW,get_ctx)(pw), isl_error_invalid,
787 "cannot fix output dimension", return FN(PW,free)(pw));
789 if (pw->n == 0)
790 return pw;
792 if (type == isl_dim_in)
793 type = isl_dim_set;
795 pw = FN(PW,cow)(pw);
796 if (!pw)
797 return FN(PW,free)(pw);
799 for (i = pw->n - 1; i >= 0; --i) {
800 pw->p[i].set = isl_set_fix_si(pw->p[i].set, type, pos, value);
801 if (FN(PW,exploit_equalities_and_remove_if_empty)(pw, i) < 0)
802 return FN(PW,free)(pw);
805 return pw;
808 /* Restrict the domain of "pw" by combining each cell
809 * with "set" through a call to "fn", where "fn" may be
810 * isl_set_intersect, isl_set_intersect_params or isl_set_subtract.
812 static __isl_give PW *FN(PW,restrict_domain_aligned)(__isl_take PW *pw,
813 __isl_take isl_set *set,
814 __isl_give isl_set *(*fn)(__isl_take isl_set *set1,
815 __isl_take isl_set *set2))
817 int i;
819 if (!pw || !set)
820 goto error;
822 if (pw->n == 0) {
823 isl_set_free(set);
824 return pw;
827 pw = FN(PW,cow)(pw);
828 if (!pw)
829 goto error;
831 for (i = pw->n - 1; i >= 0; --i) {
832 pw->p[i].set = fn(pw->p[i].set, isl_set_copy(set));
833 if (FN(PW,exploit_equalities_and_remove_if_empty)(pw, i) < 0)
834 goto error;
837 isl_set_free(set);
838 return pw;
839 error:
840 isl_set_free(set);
841 FN(PW,free)(pw);
842 return NULL;
845 static __isl_give PW *FN(PW,intersect_domain_aligned)(__isl_take PW *pw,
846 __isl_take isl_set *set)
848 return FN(PW,restrict_domain_aligned)(pw, set, &isl_set_intersect);
851 __isl_give PW *FN(PW,intersect_domain)(__isl_take PW *pw,
852 __isl_take isl_set *context)
854 return FN(PW,align_params_pw_set_and)(pw, context,
855 &FN(PW,intersect_domain_aligned));
858 static __isl_give PW *FN(PW,intersect_params_aligned)(__isl_take PW *pw,
859 __isl_take isl_set *set)
861 return FN(PW,restrict_domain_aligned)(pw, set,
862 &isl_set_intersect_params);
865 /* Intersect the domain of "pw" with the parameter domain "context".
867 __isl_give PW *FN(PW,intersect_params)(__isl_take PW *pw,
868 __isl_take isl_set *context)
870 return FN(PW,align_params_pw_set_and)(pw, context,
871 &FN(PW,intersect_params_aligned));
874 /* Subtract "domain' from the domain of "pw", assuming their
875 * parameters have been aligned.
877 static __isl_give PW *FN(PW,subtract_domain_aligned)(__isl_take PW *pw,
878 __isl_take isl_set *domain)
880 return FN(PW,restrict_domain_aligned)(pw, domain, &isl_set_subtract);
883 /* Subtract "domain' from the domain of "pw".
885 __isl_give PW *FN(PW,subtract_domain)(__isl_take PW *pw,
886 __isl_take isl_set *domain)
888 return FN(PW,align_params_pw_set_and)(pw, domain,
889 &FN(PW,subtract_domain_aligned));
892 /* Compute the gist of "pw" with respect to the domain constraints
893 * of "context" for the case where the domain of the last element
894 * of "pw" is equal to "context".
895 * Call "fn_el" to compute the gist of this element, replace
896 * its domain by the universe and drop all other elements
897 * as their domains are necessarily disjoint from "context".
899 static __isl_give PW *FN(PW,gist_last)(__isl_take PW *pw,
900 __isl_take isl_set *context,
901 __isl_give EL *(*fn_el)(__isl_take EL *el, __isl_take isl_set *set))
903 int i;
904 isl_space *space;
906 for (i = 0; i < pw->n - 1; ++i) {
907 isl_set_free(pw->p[i].set);
908 FN(EL,free)(pw->p[i].FIELD);
910 pw->p[0].FIELD = pw->p[pw->n - 1].FIELD;
911 pw->p[0].set = pw->p[pw->n - 1].set;
912 pw->n = 1;
914 space = isl_set_get_space(context);
915 pw->p[0].FIELD = fn_el(pw->p[0].FIELD, context);
916 context = isl_set_universe(space);
917 isl_set_free(pw->p[0].set);
918 pw->p[0].set = context;
920 if (!pw->p[0].FIELD || !pw->p[0].set)
921 return FN(PW,free)(pw);
923 return pw;
926 /* Compute the gist of "pw" with respect to the domain constraints
927 * of "context". Call "fn_el" to compute the gist of the elements
928 * and "fn_dom" to compute the gist of the domains.
930 * If the piecewise expression is empty or the context is the universe,
931 * then nothing can be simplified.
933 static __isl_give PW *FN(PW,gist_aligned)(__isl_take PW *pw,
934 __isl_take isl_set *context,
935 __isl_give EL *(*fn_el)(__isl_take EL *el,
936 __isl_take isl_set *set),
937 __isl_give isl_set *(*fn_dom)(__isl_take isl_set *set,
938 __isl_take isl_basic_set *bset))
940 int i;
941 int is_universe;
942 isl_bool aligned;
943 isl_basic_set *hull = NULL;
945 if (!pw || !context)
946 goto error;
948 if (pw->n == 0) {
949 isl_set_free(context);
950 return pw;
953 is_universe = isl_set_plain_is_universe(context);
954 if (is_universe < 0)
955 goto error;
956 if (is_universe) {
957 isl_set_free(context);
958 return pw;
961 aligned = isl_set_space_has_equal_params(context, pw->dim);
962 if (aligned < 0)
963 goto error;
964 if (!aligned) {
965 pw = FN(PW,align_params)(pw, isl_set_get_space(context));
966 context = isl_set_align_params(context, FN(PW,get_space)(pw));
969 pw = FN(PW,cow)(pw);
970 if (!pw)
971 goto error;
973 if (pw->n == 1) {
974 int equal;
976 equal = isl_set_plain_is_equal(pw->p[0].set, context);
977 if (equal < 0)
978 goto error;
979 if (equal)
980 return FN(PW,gist_last)(pw, context, fn_el);
983 context = isl_set_compute_divs(context);
984 hull = isl_set_simple_hull(isl_set_copy(context));
986 for (i = pw->n - 1; i >= 0; --i) {
987 isl_set *set_i;
988 int empty;
990 if (i == pw->n - 1) {
991 int equal;
992 equal = isl_set_plain_is_equal(pw->p[i].set, context);
993 if (equal < 0)
994 goto error;
995 if (equal) {
996 isl_basic_set_free(hull);
997 return FN(PW,gist_last)(pw, context, fn_el);
1000 set_i = isl_set_intersect(isl_set_copy(pw->p[i].set),
1001 isl_set_copy(context));
1002 empty = isl_set_plain_is_empty(set_i);
1003 pw->p[i].FIELD = fn_el(pw->p[i].FIELD, set_i);
1004 pw->p[i].set = fn_dom(pw->p[i].set, isl_basic_set_copy(hull));
1005 if (empty < 0 || !pw->p[i].FIELD || !pw->p[i].set)
1006 goto error;
1007 if (empty) {
1008 isl_set_free(pw->p[i].set);
1009 FN(EL,free)(pw->p[i].FIELD);
1010 if (i != pw->n - 1)
1011 pw->p[i] = pw->p[pw->n - 1];
1012 pw->n--;
1016 isl_basic_set_free(hull);
1017 isl_set_free(context);
1019 return pw;
1020 error:
1021 FN(PW,free)(pw);
1022 isl_basic_set_free(hull);
1023 isl_set_free(context);
1024 return NULL;
1027 static __isl_give PW *FN(PW,gist_domain_aligned)(__isl_take PW *pw,
1028 __isl_take isl_set *set)
1030 return FN(PW,gist_aligned)(pw, set, &FN(EL,gist),
1031 &isl_set_gist_basic_set);
1034 __isl_give PW *FN(PW,gist)(__isl_take PW *pw, __isl_take isl_set *context)
1036 return FN(PW,align_params_pw_set_and)(pw, context,
1037 &FN(PW,gist_domain_aligned));
1040 static __isl_give PW *FN(PW,gist_params_aligned)(__isl_take PW *pw,
1041 __isl_take isl_set *set)
1043 return FN(PW,gist_aligned)(pw, set, &FN(EL,gist_params),
1044 &isl_set_gist_params_basic_set);
1047 __isl_give PW *FN(PW,gist_params)(__isl_take PW *pw,
1048 __isl_take isl_set *context)
1050 return FN(PW,align_params_pw_set_and)(pw, context,
1051 &FN(PW,gist_params_aligned));
1054 /* Return -1 if the piece "p1" should be sorted before "p2"
1055 * and 1 if it should be sorted after "p2".
1056 * Return 0 if they do not need to be sorted in a specific order.
1058 * The two pieces are compared on the basis of their function value expressions.
1060 static int FN(PW,sort_field_cmp)(const void *p1, const void *p2, void *arg)
1062 struct FN(PW,piece) const *pc1 = p1;
1063 struct FN(PW,piece) const *pc2 = p2;
1065 return FN(EL,plain_cmp)(pc1->FIELD, pc2->FIELD);
1068 /* Sort the pieces of "pw" according to their function value
1069 * expressions and then combine pairs of adjacent pieces with
1070 * the same such expression.
1072 * The sorting is performed in place because it does not
1073 * change the meaning of "pw", but care needs to be
1074 * taken not to change any possible other copies of "pw"
1075 * in case anything goes wrong.
1077 __isl_give PW *FN(PW,sort)(__isl_take PW *pw)
1079 int i, j;
1080 isl_set *set;
1082 if (!pw)
1083 return NULL;
1084 if (pw->n <= 1)
1085 return pw;
1086 if (isl_sort(pw->p, pw->n, sizeof(pw->p[0]),
1087 &FN(PW,sort_field_cmp), NULL) < 0)
1088 return FN(PW,free)(pw);
1089 for (i = pw->n - 1; i >= 1; --i) {
1090 if (!FN(EL,plain_is_equal)(pw->p[i - 1].FIELD, pw->p[i].FIELD))
1091 continue;
1092 set = isl_set_union(isl_set_copy(pw->p[i - 1].set),
1093 isl_set_copy(pw->p[i].set));
1094 if (!set)
1095 return FN(PW,free)(pw);
1096 isl_set_free(pw->p[i].set);
1097 FN(EL,free)(pw->p[i].FIELD);
1098 isl_set_free(pw->p[i - 1].set);
1099 pw->p[i - 1].set = set;
1100 for (j = i + 1; j < pw->n; ++j)
1101 pw->p[j - 1] = pw->p[j];
1102 pw->n--;
1105 return pw;
1108 /* Coalesce the domains of "pw".
1110 * Prior to the actual coalescing, first sort the pieces such that
1111 * pieces with the same function value expression are combined
1112 * into a single piece, the combined domain of which can then
1113 * be coalesced.
1115 __isl_give PW *FN(PW,coalesce)(__isl_take PW *pw)
1117 int i;
1119 pw = FN(PW,sort)(pw);
1120 if (!pw)
1121 return NULL;
1123 for (i = 0; i < pw->n; ++i) {
1124 pw->p[i].set = isl_set_coalesce(pw->p[i].set);
1125 if (!pw->p[i].set)
1126 goto error;
1129 return pw;
1130 error:
1131 FN(PW,free)(pw);
1132 return NULL;
1135 isl_ctx *FN(PW,get_ctx)(__isl_keep PW *pw)
1137 return pw ? isl_space_get_ctx(pw->dim) : NULL;
1140 #ifndef NO_INVOLVES_DIMS
1141 isl_bool FN(PW,involves_dims)(__isl_keep PW *pw, enum isl_dim_type type,
1142 unsigned first, unsigned n)
1144 int i;
1145 enum isl_dim_type set_type;
1147 if (!pw)
1148 return isl_bool_error;
1149 if (pw->n == 0 || n == 0)
1150 return isl_bool_false;
1152 set_type = type == isl_dim_in ? isl_dim_set : type;
1154 for (i = 0; i < pw->n; ++i) {
1155 isl_bool involves = FN(EL,involves_dims)(pw->p[i].FIELD,
1156 type, first, n);
1157 if (involves < 0 || involves)
1158 return involves;
1159 involves = isl_set_involves_dims(pw->p[i].set,
1160 set_type, first, n);
1161 if (involves < 0 || involves)
1162 return involves;
1164 return isl_bool_false;
1166 #endif
1168 __isl_give PW *FN(PW,set_dim_name)(__isl_take PW *pw,
1169 enum isl_dim_type type, unsigned pos, const char *s)
1171 int i;
1172 enum isl_dim_type set_type;
1174 pw = FN(PW,cow)(pw);
1175 if (!pw)
1176 return NULL;
1178 set_type = type == isl_dim_in ? isl_dim_set : type;
1180 pw->dim = isl_space_set_dim_name(pw->dim, type, pos, s);
1181 if (!pw->dim)
1182 goto error;
1184 for (i = 0; i < pw->n; ++i) {
1185 pw->p[i].set = isl_set_set_dim_name(pw->p[i].set,
1186 set_type, pos, s);
1187 if (!pw->p[i].set)
1188 goto error;
1189 pw->p[i].FIELD = FN(EL,set_dim_name)(pw->p[i].FIELD, type, pos, s);
1190 if (!pw->p[i].FIELD)
1191 goto error;
1194 return pw;
1195 error:
1196 FN(PW,free)(pw);
1197 return NULL;
1200 #ifndef NO_DROP_DIMS
1201 __isl_give PW *FN(PW,drop_dims)(__isl_take PW *pw,
1202 enum isl_dim_type type, unsigned first, unsigned n)
1204 int i;
1205 enum isl_dim_type set_type;
1207 if (!pw)
1208 return NULL;
1209 if (n == 0 && !isl_space_get_tuple_name(pw->dim, type))
1210 return pw;
1212 set_type = type == isl_dim_in ? isl_dim_set : type;
1214 pw = FN(PW,cow)(pw);
1215 if (!pw)
1216 return NULL;
1217 pw->dim = isl_space_drop_dims(pw->dim, type, first, n);
1218 if (!pw->dim)
1219 goto error;
1220 for (i = 0; i < pw->n; ++i) {
1221 pw->p[i].FIELD = FN(EL,drop_dims)(pw->p[i].FIELD, type, first, n);
1222 if (!pw->p[i].FIELD)
1223 goto error;
1224 if (type == isl_dim_out)
1225 continue;
1226 pw->p[i].set = isl_set_drop(pw->p[i].set, set_type, first, n);
1227 if (!pw->p[i].set)
1228 goto error;
1231 return pw;
1232 error:
1233 FN(PW,free)(pw);
1234 return NULL;
1237 /* This function is very similar to drop_dims.
1238 * The only difference is that the cells may still involve
1239 * the specified dimensions. They are removed using
1240 * isl_set_project_out instead of isl_set_drop.
1242 __isl_give PW *FN(PW,project_out)(__isl_take PW *pw,
1243 enum isl_dim_type type, unsigned first, unsigned n)
1245 int i;
1246 enum isl_dim_type set_type;
1248 if (!pw)
1249 return NULL;
1250 if (n == 0 && !isl_space_get_tuple_name(pw->dim, type))
1251 return pw;
1253 set_type = type == isl_dim_in ? isl_dim_set : type;
1255 pw = FN(PW,cow)(pw);
1256 if (!pw)
1257 return NULL;
1258 pw->dim = isl_space_drop_dims(pw->dim, type, first, n);
1259 if (!pw->dim)
1260 goto error;
1261 for (i = 0; i < pw->n; ++i) {
1262 pw->p[i].set = isl_set_project_out(pw->p[i].set,
1263 set_type, first, n);
1264 if (!pw->p[i].set)
1265 goto error;
1266 pw->p[i].FIELD = FN(EL,drop_dims)(pw->p[i].FIELD, type, first, n);
1267 if (!pw->p[i].FIELD)
1268 goto error;
1271 return pw;
1272 error:
1273 FN(PW,free)(pw);
1274 return NULL;
1277 /* Project the domain of pw onto its parameter space.
1279 __isl_give PW *FN(PW,project_domain_on_params)(__isl_take PW *pw)
1281 isl_space *space;
1282 unsigned n;
1284 n = FN(PW,dim)(pw, isl_dim_in);
1285 pw = FN(PW,project_out)(pw, isl_dim_in, 0, n);
1286 space = FN(PW,get_domain_space)(pw);
1287 space = isl_space_params(space);
1288 pw = FN(PW,reset_domain_space)(pw, space);
1289 return pw;
1291 #endif
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 __isl_give isl_space *FN(PW,get_space)(__isl_keep PW *pw)
1461 return pw ? isl_space_copy(pw->dim) : NULL;
1464 __isl_give isl_space *FN(PW,get_domain_space)(__isl_keep PW *pw)
1466 return pw ? isl_space_domain(isl_space_copy(pw->dim)) : NULL;
1469 /* Return the position of the dimension of the given type and name
1470 * in "pw".
1471 * Return -1 if no such dimension can be found.
1473 int FN(PW,find_dim_by_name)(__isl_keep PW *pw,
1474 enum isl_dim_type type, const char *name)
1476 if (!pw)
1477 return -1;
1478 return isl_space_find_dim_by_name(pw->dim, type, name);
1481 #ifndef NO_RESET_DIM
1482 /* Reset the space of "pw". Since we don't know if the elements
1483 * represent the spaces themselves or their domains, we pass along
1484 * both when we call their reset_space_and_domain.
1486 static __isl_give PW *FN(PW,reset_space_and_domain)(__isl_take PW *pw,
1487 __isl_take isl_space *space, __isl_take isl_space *domain)
1489 int i;
1491 pw = FN(PW,cow)(pw);
1492 if (!pw || !space || !domain)
1493 goto error;
1495 for (i = 0; i < pw->n; ++i) {
1496 pw->p[i].set = isl_set_reset_space(pw->p[i].set,
1497 isl_space_copy(domain));
1498 if (!pw->p[i].set)
1499 goto error;
1500 pw->p[i].FIELD = FN(EL,reset_space_and_domain)(pw->p[i].FIELD,
1501 isl_space_copy(space), isl_space_copy(domain));
1502 if (!pw->p[i].FIELD)
1503 goto error;
1506 isl_space_free(domain);
1508 isl_space_free(pw->dim);
1509 pw->dim = space;
1511 return pw;
1512 error:
1513 isl_space_free(domain);
1514 isl_space_free(space);
1515 FN(PW,free)(pw);
1516 return NULL;
1519 __isl_give PW *FN(PW,reset_domain_space)(__isl_take PW *pw,
1520 __isl_take isl_space *domain)
1522 isl_space *space;
1524 space = isl_space_extend_domain_with_range(isl_space_copy(domain),
1525 FN(PW,get_space)(pw));
1526 return FN(PW,reset_space_and_domain)(pw, space, domain);
1529 __isl_give PW *FN(PW,reset_space)(__isl_take PW *pw, __isl_take isl_space *dim)
1531 isl_space *domain;
1533 domain = isl_space_domain(isl_space_copy(dim));
1534 return FN(PW,reset_space_and_domain)(pw, dim, domain);
1537 __isl_give PW *FN(PW,set_tuple_id)(__isl_take PW *pw, enum isl_dim_type type,
1538 __isl_take isl_id *id)
1540 isl_space *space;
1542 pw = FN(PW,cow)(pw);
1543 if (!pw)
1544 goto error;
1546 space = FN(PW,get_space)(pw);
1547 space = isl_space_set_tuple_id(space, type, id);
1549 return FN(PW,reset_space)(pw, space);
1550 error:
1551 isl_id_free(id);
1552 return FN(PW,free)(pw);
1555 /* Drop the id on the specified tuple.
1557 __isl_give PW *FN(PW,reset_tuple_id)(__isl_take PW *pw, enum isl_dim_type type)
1559 isl_space *space;
1561 if (!pw)
1562 return NULL;
1563 if (!FN(PW,has_tuple_id)(pw, type))
1564 return pw;
1566 pw = FN(PW,cow)(pw);
1567 if (!pw)
1568 return NULL;
1570 space = FN(PW,get_space)(pw);
1571 space = isl_space_reset_tuple_id(space, type);
1573 return FN(PW,reset_space)(pw, space);
1576 __isl_give PW *FN(PW,set_dim_id)(__isl_take PW *pw,
1577 enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)
1579 pw = FN(PW,cow)(pw);
1580 if (!pw)
1581 goto error;
1582 pw->dim = isl_space_set_dim_id(pw->dim, type, pos, id);
1583 return FN(PW,reset_space)(pw, isl_space_copy(pw->dim));
1584 error:
1585 isl_id_free(id);
1586 return FN(PW,free)(pw);
1588 #endif
1590 /* Reset the user pointer on all identifiers of parameters and tuples
1591 * of the space of "pw".
1593 __isl_give PW *FN(PW,reset_user)(__isl_take PW *pw)
1595 isl_space *space;
1597 space = FN(PW,get_space)(pw);
1598 space = isl_space_reset_user(space);
1600 return FN(PW,reset_space)(pw, space);
1603 isl_bool FN(PW,has_equal_space)(__isl_keep PW *pw1, __isl_keep PW *pw2)
1605 if (!pw1 || !pw2)
1606 return isl_bool_error;
1608 return isl_space_is_equal(pw1->dim, pw2->dim);
1611 #ifndef NO_MORPH
1612 __isl_give PW *FN(PW,morph_domain)(__isl_take PW *pw,
1613 __isl_take isl_morph *morph)
1615 int i;
1616 isl_ctx *ctx;
1618 if (!pw || !morph)
1619 goto error;
1621 ctx = isl_space_get_ctx(pw->dim);
1622 isl_assert(ctx, isl_space_is_domain_internal(morph->dom->dim, pw->dim),
1623 goto error);
1625 pw = FN(PW,cow)(pw);
1626 if (!pw)
1627 goto error;
1628 pw->dim = isl_space_extend_domain_with_range(
1629 isl_space_copy(morph->ran->dim), pw->dim);
1630 if (!pw->dim)
1631 goto error;
1633 for (i = 0; i < pw->n; ++i) {
1634 pw->p[i].set = isl_morph_set(isl_morph_copy(morph), pw->p[i].set);
1635 if (!pw->p[i].set)
1636 goto error;
1637 pw->p[i].FIELD = FN(EL,morph_domain)(pw->p[i].FIELD,
1638 isl_morph_copy(morph));
1639 if (!pw->p[i].FIELD)
1640 goto error;
1643 isl_morph_free(morph);
1645 return pw;
1646 error:
1647 FN(PW,free)(pw);
1648 isl_morph_free(morph);
1649 return NULL;
1651 #endif
1653 int FN(PW,n_piece)(__isl_keep PW *pw)
1655 return pw ? pw->n : 0;
1658 isl_stat FN(PW,foreach_piece)(__isl_keep PW *pw,
1659 isl_stat (*fn)(__isl_take isl_set *set, __isl_take EL *el, void *user),
1660 void *user)
1662 int i;
1664 if (!pw)
1665 return isl_stat_error;
1667 for (i = 0; i < pw->n; ++i)
1668 if (fn(isl_set_copy(pw->p[i].set),
1669 FN(EL,copy)(pw->p[i].FIELD), user) < 0)
1670 return isl_stat_error;
1672 return isl_stat_ok;
1675 #ifndef NO_LIFT
1676 static isl_bool any_divs(__isl_keep isl_set *set)
1678 int i;
1680 if (!set)
1681 return isl_bool_error;
1683 for (i = 0; i < set->n; ++i)
1684 if (set->p[i]->n_div > 0)
1685 return isl_bool_true;
1687 return isl_bool_false;
1690 static isl_stat foreach_lifted_subset(__isl_take isl_set *set,
1691 __isl_take EL *el,
1692 isl_stat (*fn)(__isl_take isl_set *set, __isl_take EL *el,
1693 void *user), void *user)
1695 int i;
1697 if (!set || !el)
1698 goto error;
1700 for (i = 0; i < set->n; ++i) {
1701 isl_set *lift;
1702 EL *copy;
1704 lift = isl_set_from_basic_set(isl_basic_set_copy(set->p[i]));
1705 lift = isl_set_lift(lift);
1707 copy = FN(EL,copy)(el);
1708 copy = FN(EL,lift)(copy, isl_set_get_space(lift));
1710 if (fn(lift, copy, user) < 0)
1711 goto error;
1714 isl_set_free(set);
1715 FN(EL,free)(el);
1717 return isl_stat_ok;
1718 error:
1719 isl_set_free(set);
1720 FN(EL,free)(el);
1721 return isl_stat_error;
1724 isl_stat FN(PW,foreach_lifted_piece)(__isl_keep PW *pw,
1725 isl_stat (*fn)(__isl_take isl_set *set, __isl_take EL *el,
1726 void *user), void *user)
1728 int i;
1730 if (!pw)
1731 return isl_stat_error;
1733 for (i = 0; i < pw->n; ++i) {
1734 isl_bool any;
1735 isl_set *set;
1736 EL *el;
1738 any = any_divs(pw->p[i].set);
1739 if (any < 0)
1740 return isl_stat_error;
1741 set = isl_set_copy(pw->p[i].set);
1742 el = FN(EL,copy)(pw->p[i].FIELD);
1743 if (!any) {
1744 if (fn(set, el, user) < 0)
1745 return isl_stat_error;
1746 continue;
1748 if (foreach_lifted_subset(set, el, fn, user) < 0)
1749 return isl_stat_error;
1752 return isl_stat_ok;
1754 #endif
1756 #ifndef NO_MOVE_DIMS
1757 __isl_give PW *FN(PW,move_dims)(__isl_take PW *pw,
1758 enum isl_dim_type dst_type, unsigned dst_pos,
1759 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
1761 int i;
1763 pw = FN(PW,cow)(pw);
1764 if (!pw)
1765 return NULL;
1767 pw->dim = isl_space_move_dims(pw->dim, dst_type, dst_pos, src_type, src_pos, n);
1768 if (!pw->dim)
1769 goto error;
1771 for (i = 0; i < pw->n; ++i) {
1772 pw->p[i].FIELD = FN(EL,move_dims)(pw->p[i].FIELD,
1773 dst_type, dst_pos, src_type, src_pos, n);
1774 if (!pw->p[i].FIELD)
1775 goto error;
1778 if (dst_type == isl_dim_in)
1779 dst_type = isl_dim_set;
1780 if (src_type == isl_dim_in)
1781 src_type = isl_dim_set;
1783 for (i = 0; i < pw->n; ++i) {
1784 pw->p[i].set = isl_set_move_dims(pw->p[i].set,
1785 dst_type, dst_pos,
1786 src_type, src_pos, n);
1787 if (!pw->p[i].set)
1788 goto error;
1791 return pw;
1792 error:
1793 FN(PW,free)(pw);
1794 return NULL;
1796 #endif
1798 __isl_give PW *FN(PW,mul_isl_int)(__isl_take PW *pw, isl_int v)
1800 int i;
1802 if (isl_int_is_one(v))
1803 return pw;
1804 if (pw && DEFAULT_IS_ZERO && isl_int_is_zero(v)) {
1805 PW *zero;
1806 isl_space *dim = FN(PW,get_space)(pw);
1807 #ifdef HAS_TYPE
1808 zero = FN(PW,ZERO)(dim, pw->type);
1809 #else
1810 zero = FN(PW,ZERO)(dim);
1811 #endif
1812 FN(PW,free)(pw);
1813 return zero;
1815 pw = FN(PW,cow)(pw);
1816 if (!pw)
1817 return NULL;
1818 if (pw->n == 0)
1819 return pw;
1821 #ifdef HAS_TYPE
1822 if (isl_int_is_neg(v))
1823 pw->type = isl_fold_type_negate(pw->type);
1824 #endif
1825 for (i = 0; i < pw->n; ++i) {
1826 pw->p[i].FIELD = FN(EL,scale)(pw->p[i].FIELD, v);
1827 if (!pw->p[i].FIELD)
1828 goto error;
1831 return pw;
1832 error:
1833 FN(PW,free)(pw);
1834 return NULL;
1837 /* Multiply the pieces of "pw" by "v" and return the result.
1839 __isl_give PW *FN(PW,scale_val)(__isl_take PW *pw, __isl_take isl_val *v)
1841 int i;
1843 if (!pw || !v)
1844 goto error;
1846 if (isl_val_is_one(v)) {
1847 isl_val_free(v);
1848 return pw;
1850 if (pw && DEFAULT_IS_ZERO && isl_val_is_zero(v)) {
1851 PW *zero;
1852 isl_space *space = FN(PW,get_space)(pw);
1853 #ifdef HAS_TYPE
1854 zero = FN(PW,ZERO)(space, pw->type);
1855 #else
1856 zero = FN(PW,ZERO)(space);
1857 #endif
1858 FN(PW,free)(pw);
1859 isl_val_free(v);
1860 return zero;
1862 if (pw->n == 0) {
1863 isl_val_free(v);
1864 return pw;
1866 pw = FN(PW,cow)(pw);
1867 if (!pw)
1868 goto error;
1870 #ifdef HAS_TYPE
1871 if (isl_val_is_neg(v))
1872 pw->type = isl_fold_type_negate(pw->type);
1873 #endif
1874 for (i = 0; i < pw->n; ++i) {
1875 pw->p[i].FIELD = FN(EL,scale_val)(pw->p[i].FIELD,
1876 isl_val_copy(v));
1877 if (!pw->p[i].FIELD)
1878 goto error;
1881 isl_val_free(v);
1882 return pw;
1883 error:
1884 isl_val_free(v);
1885 FN(PW,free)(pw);
1886 return NULL;
1889 /* Divide the pieces of "pw" by "v" and return the result.
1891 __isl_give PW *FN(PW,scale_down_val)(__isl_take PW *pw, __isl_take isl_val *v)
1893 int i;
1895 if (!pw || !v)
1896 goto error;
1898 if (isl_val_is_one(v)) {
1899 isl_val_free(v);
1900 return pw;
1903 if (!isl_val_is_rat(v))
1904 isl_die(isl_val_get_ctx(v), isl_error_invalid,
1905 "expecting rational factor", goto error);
1906 if (isl_val_is_zero(v))
1907 isl_die(isl_val_get_ctx(v), isl_error_invalid,
1908 "cannot scale down by zero", goto error);
1910 if (pw->n == 0) {
1911 isl_val_free(v);
1912 return pw;
1914 pw = FN(PW,cow)(pw);
1915 if (!pw)
1916 goto error;
1918 #ifdef HAS_TYPE
1919 if (isl_val_is_neg(v))
1920 pw->type = isl_fold_type_negate(pw->type);
1921 #endif
1922 for (i = 0; i < pw->n; ++i) {
1923 pw->p[i].FIELD = FN(EL,scale_down_val)(pw->p[i].FIELD,
1924 isl_val_copy(v));
1925 if (!pw->p[i].FIELD)
1926 goto error;
1929 isl_val_free(v);
1930 return pw;
1931 error:
1932 isl_val_free(v);
1933 FN(PW,free)(pw);
1934 return NULL;
1937 __isl_give PW *FN(PW,scale)(__isl_take PW *pw, isl_int v)
1939 return FN(PW,mul_isl_int)(pw, v);
1942 /* Apply some normalization to "pw".
1943 * In particular, sort the pieces according to their function value
1944 * expressions, combining pairs of adjacent pieces with
1945 * the same such expression, and then normalize the domains of the pieces.
1947 * We normalize in place, but if anything goes wrong we need
1948 * to return NULL, so we need to make sure we don't change the
1949 * meaning of any possible other copies of "pw".
1951 __isl_give PW *FN(PW,normalize)(__isl_take PW *pw)
1953 int i;
1954 isl_set *set;
1956 pw = FN(PW,sort)(pw);
1957 if (!pw)
1958 return NULL;
1959 for (i = 0; i < pw->n; ++i) {
1960 set = isl_set_normalize(isl_set_copy(pw->p[i].set));
1961 if (!set)
1962 return FN(PW,free)(pw);
1963 isl_set_free(pw->p[i].set);
1964 pw->p[i].set = set;
1967 return pw;
1970 /* Is pw1 obviously equal to pw2?
1971 * That is, do they have obviously identical cells and obviously identical
1972 * elements on each cell?
1974 * If "pw1" or "pw2" contain any NaNs, then they are considered
1975 * not to be the same. A NaN is not equal to anything, not even
1976 * to another NaN.
1978 isl_bool FN(PW,plain_is_equal)(__isl_keep PW *pw1, __isl_keep PW *pw2)
1980 int i;
1981 isl_bool equal, has_nan;
1983 if (!pw1 || !pw2)
1984 return isl_bool_error;
1986 has_nan = FN(PW,involves_nan)(pw1);
1987 if (has_nan >= 0 && !has_nan)
1988 has_nan = FN(PW,involves_nan)(pw2);
1989 if (has_nan < 0 || has_nan)
1990 return isl_bool_not(has_nan);
1992 if (pw1 == pw2)
1993 return isl_bool_true;
1994 if (!isl_space_is_equal(pw1->dim, pw2->dim))
1995 return isl_bool_false;
1997 pw1 = FN(PW,copy)(pw1);
1998 pw2 = FN(PW,copy)(pw2);
1999 pw1 = FN(PW,normalize)(pw1);
2000 pw2 = FN(PW,normalize)(pw2);
2001 if (!pw1 || !pw2)
2002 goto error;
2004 equal = pw1->n == pw2->n;
2005 for (i = 0; equal && i < pw1->n; ++i) {
2006 equal = isl_set_plain_is_equal(pw1->p[i].set, pw2->p[i].set);
2007 if (equal < 0)
2008 goto error;
2009 if (!equal)
2010 break;
2011 equal = FN(EL,plain_is_equal)(pw1->p[i].FIELD, pw2->p[i].FIELD);
2012 if (equal < 0)
2013 goto error;
2016 FN(PW,free)(pw1);
2017 FN(PW,free)(pw2);
2018 return equal;
2019 error:
2020 FN(PW,free)(pw1);
2021 FN(PW,free)(pw2);
2022 return isl_bool_error;
2025 /* Does "pw" involve any NaNs?
2027 isl_bool FN(PW,involves_nan)(__isl_keep PW *pw)
2029 int i;
2031 if (!pw)
2032 return isl_bool_error;
2033 if (pw->n == 0)
2034 return isl_bool_false;
2036 for (i = 0; i < pw->n; ++i) {
2037 isl_bool has_nan = FN(EL,involves_nan)(pw->p[i].FIELD);
2038 if (has_nan < 0 || has_nan)
2039 return has_nan;
2042 return isl_bool_false;
2045 #ifndef NO_PULLBACK
2046 static __isl_give PW *FN(PW,align_params_pw_multi_aff_and)(__isl_take PW *pw,
2047 __isl_take isl_multi_aff *ma,
2048 __isl_give PW *(*fn)(__isl_take PW *pw, __isl_take isl_multi_aff *ma))
2050 isl_ctx *ctx;
2051 isl_space *ma_space;
2053 ma_space = isl_multi_aff_get_space(ma);
2054 if (!pw || !ma || !ma_space)
2055 goto error;
2056 if (isl_space_match(pw->dim, isl_dim_param, ma_space, isl_dim_param)) {
2057 isl_space_free(ma_space);
2058 return fn(pw, ma);
2060 ctx = FN(PW,get_ctx)(pw);
2061 if (!isl_space_has_named_params(pw->dim) ||
2062 !isl_space_has_named_params(ma_space))
2063 isl_die(ctx, isl_error_invalid,
2064 "unaligned unnamed parameters", goto error);
2065 pw = FN(PW,align_params)(pw, ma_space);
2066 ma = isl_multi_aff_align_params(ma, FN(PW,get_space)(pw));
2067 return fn(pw, ma);
2068 error:
2069 isl_space_free(ma_space);
2070 FN(PW,free)(pw);
2071 isl_multi_aff_free(ma);
2072 return NULL;
2075 static __isl_give PW *FN(PW,align_params_pw_pw_multi_aff_and)(__isl_take PW *pw,
2076 __isl_take isl_pw_multi_aff *pma,
2077 __isl_give PW *(*fn)(__isl_take PW *pw,
2078 __isl_take isl_pw_multi_aff *ma))
2080 isl_ctx *ctx;
2081 isl_space *pma_space;
2083 pma_space = isl_pw_multi_aff_get_space(pma);
2084 if (!pw || !pma || !pma_space)
2085 goto error;
2086 if (isl_space_match(pw->dim, isl_dim_param, pma_space, isl_dim_param)) {
2087 isl_space_free(pma_space);
2088 return fn(pw, pma);
2090 ctx = FN(PW,get_ctx)(pw);
2091 if (!isl_space_has_named_params(pw->dim) ||
2092 !isl_space_has_named_params(pma_space))
2093 isl_die(ctx, isl_error_invalid,
2094 "unaligned unnamed parameters", goto error);
2095 pw = FN(PW,align_params)(pw, pma_space);
2096 pma = isl_pw_multi_aff_align_params(pma, FN(PW,get_space)(pw));
2097 return fn(pw, pma);
2098 error:
2099 isl_space_free(pma_space);
2100 FN(PW,free)(pw);
2101 isl_pw_multi_aff_free(pma);
2102 return NULL;
2105 /* Compute the pullback of "pw" by the function represented by "ma".
2106 * In other words, plug in "ma" in "pw".
2108 static __isl_give PW *FN(PW,pullback_multi_aff_aligned)(__isl_take PW *pw,
2109 __isl_take isl_multi_aff *ma)
2111 int i;
2112 isl_space *space = NULL;
2114 ma = isl_multi_aff_align_divs(ma);
2115 pw = FN(PW,cow)(pw);
2116 if (!pw || !ma)
2117 goto error;
2119 space = isl_space_join(isl_multi_aff_get_space(ma),
2120 FN(PW,get_space)(pw));
2122 for (i = 0; i < pw->n; ++i) {
2123 pw->p[i].set = isl_set_preimage_multi_aff(pw->p[i].set,
2124 isl_multi_aff_copy(ma));
2125 if (!pw->p[i].set)
2126 goto error;
2127 pw->p[i].FIELD = FN(EL,pullback_multi_aff)(pw->p[i].FIELD,
2128 isl_multi_aff_copy(ma));
2129 if (!pw->p[i].FIELD)
2130 goto error;
2133 pw = FN(PW,reset_space)(pw, space);
2134 isl_multi_aff_free(ma);
2135 return pw;
2136 error:
2137 isl_space_free(space);
2138 isl_multi_aff_free(ma);
2139 FN(PW,free)(pw);
2140 return NULL;
2143 __isl_give PW *FN(PW,pullback_multi_aff)(__isl_take PW *pw,
2144 __isl_take isl_multi_aff *ma)
2146 return FN(PW,align_params_pw_multi_aff_and)(pw, ma,
2147 &FN(PW,pullback_multi_aff_aligned));
2150 /* Compute the pullback of "pw" by the function represented by "pma".
2151 * In other words, plug in "pma" in "pw".
2153 static __isl_give PW *FN(PW,pullback_pw_multi_aff_aligned)(__isl_take PW *pw,
2154 __isl_take isl_pw_multi_aff *pma)
2156 int i;
2157 PW *res;
2159 if (!pma)
2160 goto error;
2162 if (pma->n == 0) {
2163 isl_space *space;
2164 space = isl_space_join(isl_pw_multi_aff_get_space(pma),
2165 FN(PW,get_space)(pw));
2166 isl_pw_multi_aff_free(pma);
2167 res = FN(PW,empty)(space);
2168 FN(PW,free)(pw);
2169 return res;
2172 res = FN(PW,pullback_multi_aff)(FN(PW,copy)(pw),
2173 isl_multi_aff_copy(pma->p[0].maff));
2174 res = FN(PW,intersect_domain)(res, isl_set_copy(pma->p[0].set));
2176 for (i = 1; i < pma->n; ++i) {
2177 PW *res_i;
2179 res_i = FN(PW,pullback_multi_aff)(FN(PW,copy)(pw),
2180 isl_multi_aff_copy(pma->p[i].maff));
2181 res_i = FN(PW,intersect_domain)(res_i,
2182 isl_set_copy(pma->p[i].set));
2183 res = FN(PW,add_disjoint)(res, res_i);
2186 isl_pw_multi_aff_free(pma);
2187 FN(PW,free)(pw);
2188 return res;
2189 error:
2190 isl_pw_multi_aff_free(pma);
2191 FN(PW,free)(pw);
2192 return NULL;
2195 __isl_give PW *FN(PW,pullback_pw_multi_aff)(__isl_take PW *pw,
2196 __isl_take isl_pw_multi_aff *pma)
2198 return FN(PW,align_params_pw_pw_multi_aff_and)(pw, pma,
2199 &FN(PW,pullback_pw_multi_aff_aligned));
2201 #endif