isl_pw_*_free: return NULL
[platform/upstream/isl.git] / isl_pw_templ.c
1 #define xFN(TYPE,NAME) TYPE ## _ ## NAME
2 #define FN(TYPE,NAME) xFN(TYPE,NAME)
3 #define xS(TYPE,NAME) struct TYPE ## _ ## NAME
4 #define S(TYPE,NAME) xS(TYPE,NAME)
5
6 #ifdef HAS_TYPE
7 static __isl_give PW *FN(PW,alloc_)(__isl_take isl_dim *dim,
8         enum isl_fold type, int n)
9 #else
10 static __isl_give PW *FN(PW,alloc_)(__isl_take isl_dim *dim, int n)
11 #endif
12 {
13         isl_ctx *ctx;
14         struct PW *pw;
15
16         if (!dim)
17                 return NULL;
18         ctx = isl_dim_get_ctx(dim);
19         isl_assert(ctx, n >= 0, goto error);
20         pw = isl_alloc(ctx, struct PW,
21                         sizeof(struct PW) + (n - 1) * sizeof(S(PW,piece)));
22         if (!pw)
23                 goto error;
24
25         pw->ref = 1;
26 #ifdef HAS_TYPE
27         pw->type = type;
28 #endif
29         pw->size = n;
30         pw->n = 0;
31         pw->dim = dim;
32         return pw;
33 error:
34         isl_dim_free(dim);
35         return NULL;
36 }
37
38 #ifdef HAS_TYPE
39 __isl_give PW *FN(PW,zero)(__isl_take isl_dim *dim, enum isl_fold type)
40 {
41         return FN(PW,alloc_)(dim, type, 0);
42 }
43 #else
44 __isl_give PW *FN(PW,zero)(__isl_take isl_dim *dim)
45 {
46         return FN(PW,alloc_)(dim, 0);
47 }
48 #endif
49
50 __isl_give PW *FN(PW,add_piece)(__isl_take PW *pw,
51         __isl_take isl_set *set, __isl_take EL *el)
52 {
53         isl_ctx *ctx;
54         isl_dim *el_dim = NULL;
55
56         if (!pw || !set || !el)
57                 goto error;
58
59         if (isl_set_plain_is_empty(set) || FN(EL,IS_ZERO)(el)) {
60                 isl_set_free(set);
61                 FN(EL,free)(el);
62                 return pw;
63         }
64
65         ctx = isl_set_get_ctx(set);
66 #ifdef HAS_TYPE
67         if (pw->type != el->type)
68                 isl_die(ctx, isl_error_invalid, "fold types don't match",
69                         goto error);
70 #endif
71         el_dim = FN(EL,get_dim(el));
72         isl_assert(ctx, isl_dim_equal(pw->dim, el_dim), goto error);
73         isl_assert(ctx, pw->n < pw->size, goto error);
74
75         pw->p[pw->n].set = set;
76         pw->p[pw->n].FIELD = el;
77         pw->n++;
78         
79         isl_dim_free(el_dim);
80         return pw;
81 error:
82         isl_dim_free(el_dim);
83         FN(PW,free)(pw);
84         isl_set_free(set);
85         FN(EL,free)(el);
86         return NULL;
87 }
88
89 #ifdef HAS_TYPE
90 __isl_give PW *FN(PW,alloc)(enum isl_fold type,
91         __isl_take isl_set *set, __isl_take EL *el)
92 #else
93 __isl_give PW *FN(PW,alloc)(__isl_take isl_set *set, __isl_take EL *el)
94 #endif
95 {
96         PW *pw;
97
98         if (!set || !el)
99                 goto error;
100
101 #ifdef HAS_TYPE
102         pw = FN(PW,alloc_)(isl_set_get_dim(set), type, 1);
103 #else
104         pw = FN(PW,alloc_)(isl_set_get_dim(set), 1);
105 #endif
106
107         return FN(PW,add_piece)(pw, set, el);
108 error:
109         isl_set_free(set);
110         FN(EL,free)(el);
111         return NULL;
112 }
113
114 __isl_give PW *FN(PW,dup)(__isl_keep PW *pw)
115 {
116         int i;
117         PW *dup;
118
119         if (!pw)
120                 return NULL;
121
122 #ifdef HAS_TYPE
123         dup = FN(PW,alloc_)(isl_dim_copy(pw->dim), pw->type, pw->n);
124 #else
125         dup = FN(PW,alloc_)(isl_dim_copy(pw->dim), pw->n);
126 #endif
127         if (!dup)
128                 return NULL;
129
130         for (i = 0; i < pw->n; ++i)
131                 dup = FN(PW,add_piece)(dup, isl_set_copy(pw->p[i].set),
132                                             FN(EL,copy)(pw->p[i].FIELD));
133
134         return dup;
135 }
136
137 __isl_give PW *FN(PW,cow)(__isl_take PW *pw)
138 {
139         if (!pw)
140                 return NULL;
141
142         if (pw->ref == 1)
143                 return pw;
144         pw->ref--;
145         return FN(PW,dup)(pw);
146 }
147
148 __isl_give PW *FN(PW,copy)(__isl_keep PW *pw)
149 {
150         if (!pw)
151                 return NULL;
152
153         pw->ref++;
154         return pw;
155 }
156
157 void *FN(PW,free)(__isl_take PW *pw)
158 {
159         int i;
160
161         if (!pw)
162                 return NULL;
163         if (--pw->ref > 0)
164                 return NULL;
165
166         for (i = 0; i < pw->n; ++i) {
167                 isl_set_free(pw->p[i].set);
168                 FN(EL,free)(pw->p[i].FIELD);
169         }
170         isl_dim_free(pw->dim);
171         free(pw);
172
173         return NULL;
174 }
175
176 int FN(PW,is_zero)(__isl_keep PW *pw)
177 {
178         if (!pw)
179                 return -1;
180
181         return pw->n == 0;
182 }
183
184 __isl_give PW *FN(PW,add)(__isl_take PW *pw1, __isl_take PW *pw2)
185 {
186         int i, j, n;
187         struct PW *res;
188         isl_ctx *ctx;
189         isl_set *set;
190
191         if (!pw1 || !pw2)
192                 goto error;
193
194         ctx = isl_dim_get_ctx(pw1->dim);
195 #ifdef HAS_TYPE
196         if (pw1->type != pw2->type)
197                 isl_die(ctx, isl_error_invalid,
198                         "fold types don't match", goto error);
199 #endif
200         isl_assert(ctx, isl_dim_equal(pw1->dim, pw2->dim), goto error);
201
202         if (FN(PW,is_zero)(pw1)) {
203                 FN(PW,free)(pw1);
204                 return pw2;
205         }
206
207         if (FN(PW,is_zero)(pw2)) {
208                 FN(PW,free)(pw2);
209                 return pw1;
210         }
211
212         n = (pw1->n + 1) * (pw2->n + 1);
213 #ifdef HAS_TYPE
214         res = FN(PW,alloc_)(isl_dim_copy(pw1->dim), pw1->type, n);
215 #else
216         res = FN(PW,alloc_)(isl_dim_copy(pw1->dim), n);
217 #endif
218
219         for (i = 0; i < pw1->n; ++i) {
220                 set = isl_set_copy(pw1->p[i].set);
221                 for (j = 0; j < pw2->n; ++j) {
222                         struct isl_set *common;
223                         EL *sum;
224                         set = isl_set_subtract(set,
225                                         isl_set_copy(pw2->p[j].set));
226                         common = isl_set_intersect(isl_set_copy(pw1->p[i].set),
227                                                 isl_set_copy(pw2->p[j].set));
228                         if (isl_set_plain_is_empty(common)) {
229                                 isl_set_free(common);
230                                 continue;
231                         }
232
233                         sum = FN(EL,add_on_domain)(common,
234                                                    FN(EL,copy)(pw1->p[i].FIELD),
235                                                    FN(EL,copy)(pw2->p[j].FIELD));
236
237                         res = FN(PW,add_piece)(res, common, sum);
238                 }
239                 res = FN(PW,add_piece)(res, set, FN(EL,copy)(pw1->p[i].FIELD));
240         }
241
242         for (j = 0; j < pw2->n; ++j) {
243                 set = isl_set_copy(pw2->p[j].set);
244                 for (i = 0; i < pw1->n; ++i)
245                         set = isl_set_subtract(set,
246                                         isl_set_copy(pw1->p[i].set));
247                 res = FN(PW,add_piece)(res, set, FN(EL,copy)(pw2->p[j].FIELD));
248         }
249
250         FN(PW,free)(pw1);
251         FN(PW,free)(pw2);
252
253         return res;
254 error:
255         FN(PW,free)(pw1);
256         FN(PW,free)(pw2);
257         return NULL;
258 }
259
260 __isl_give PW *FN(PW,add_disjoint)(__isl_take PW *pw1, __isl_take PW *pw2)
261 {
262         int i;
263         isl_ctx *ctx;
264         PW *res;
265
266         if (!pw1 || !pw2)
267                 goto error;
268
269         ctx = isl_dim_get_ctx(pw1->dim);
270 #ifdef HAS_TYPE
271         if (pw1->type != pw2->type)
272                 isl_die(ctx, isl_error_invalid,
273                         "fold types don't match", goto error);
274 #endif
275         isl_assert(ctx, isl_dim_equal(pw1->dim, pw2->dim), goto error);
276
277         if (FN(PW,is_zero)(pw1)) {
278                 FN(PW,free)(pw1);
279                 return pw2;
280         }
281
282         if (FN(PW,is_zero)(pw2)) {
283                 FN(PW,free)(pw2);
284                 return pw1;
285         }
286
287 #ifdef HAS_TYPE
288         res = FN(PW,alloc_)(isl_dim_copy(pw1->dim), pw1->type, pw1->n + pw2->n);
289 #else
290         res = FN(PW,alloc_)(isl_dim_copy(pw1->dim), pw1->n + pw2->n);
291 #endif
292
293         for (i = 0; i < pw1->n; ++i)
294                 res = FN(PW,add_piece)(res,
295                                 isl_set_copy(pw1->p[i].set),
296                                 FN(EL,copy)(pw1->p[i].FIELD));
297
298         for (i = 0; i < pw2->n; ++i)
299                 res = FN(PW,add_piece)(res,
300                                 isl_set_copy(pw2->p[i].set),
301                                 FN(EL,copy)(pw2->p[i].FIELD));
302
303         FN(PW,free)(pw1);
304         FN(PW,free)(pw2);
305
306         return res;
307 error:
308         FN(PW,free)(pw1);
309         FN(PW,free)(pw2);
310         return NULL;
311 }
312
313 __isl_give isl_qpolynomial *FN(PW,eval)(__isl_take PW *pw,
314         __isl_take isl_point *pnt)
315 {
316         int i;
317         int found = 0;
318         isl_ctx *ctx;
319         isl_dim *pnt_dim = NULL;
320         isl_qpolynomial *qp;
321
322         if (!pw || !pnt)
323                 goto error;
324         ctx = isl_point_get_ctx(pnt);
325         pnt_dim = isl_point_get_dim(pnt);
326         isl_assert(ctx, isl_dim_equal(pnt_dim, pw->dim), goto error);
327
328         for (i = 0; i < pw->n; ++i) {
329                 found = isl_set_contains_point(pw->p[i].set, pnt);
330                 if (found < 0)
331                         goto error;
332                 if (found)
333                         break;
334         }
335         if (found)
336                 qp = FN(EL,eval)(FN(EL,copy)(pw->p[i].FIELD),
337                                             isl_point_copy(pnt));
338         else
339                 qp = isl_qpolynomial_zero(isl_dim_copy(pw->dim));
340         FN(PW,free)(pw);
341         isl_dim_free(pnt_dim);
342         isl_point_free(pnt);
343         return qp;
344 error:
345         FN(PW,free)(pw);
346         isl_dim_free(pnt_dim);
347         isl_point_free(pnt);
348         return NULL;
349 }
350
351 __isl_give isl_set *FN(PW,domain)(__isl_take PW *pw)
352 {
353         int i;
354         isl_set *dom;
355
356         if (!pw)
357                 return NULL;
358
359         dom = isl_set_empty(isl_dim_copy(pw->dim));
360         for (i = 0; i < pw->n; ++i)
361                 dom = isl_set_union_disjoint(dom, isl_set_copy(pw->p[i].set));
362
363         FN(PW,free)(pw);
364
365         return dom;
366 }
367
368 __isl_give PW *FN(PW,intersect_domain)(__isl_take PW *pw, __isl_take isl_set *set)
369 {
370         int i;
371
372         if (!pw || !set)
373                 goto error;
374
375         if (pw->n == 0) {
376                 isl_set_free(set);
377                 return pw;
378         }
379
380         pw = FN(PW,cow)(pw);
381         if (!pw)
382                 goto error;
383
384         for (i = pw->n - 1; i >= 0; --i) {
385                 isl_basic_set *aff;
386                 pw->p[i].set = isl_set_intersect(pw->p[i].set, isl_set_copy(set));
387                 if (!pw->p[i].set)
388                         goto error;
389                 aff = isl_set_affine_hull(isl_set_copy(pw->p[i].set));
390                 pw->p[i].FIELD = FN(EL,substitute_equalities)(pw->p[i].FIELD,
391                                                                 aff);
392                 if (isl_set_plain_is_empty(pw->p[i].set)) {
393                         isl_set_free(pw->p[i].set);
394                         FN(EL,free)(pw->p[i].FIELD);
395                         if (i != pw->n - 1)
396                                 pw->p[i] = pw->p[pw->n - 1];
397                         pw->n--;
398                 }
399         }
400         
401         isl_set_free(set);
402         return pw;
403 error:
404         isl_set_free(set);
405         FN(PW,free)(pw);
406         return NULL;
407 }
408
409 __isl_give PW *FN(PW,gist)(__isl_take PW *pw, __isl_take isl_set *context)
410 {
411         int i;
412         isl_basic_set *hull = NULL;
413
414         if (!pw || !context)
415                 goto error;
416
417         if (pw->n == 0) {
418                 isl_set_free(context);
419                 return pw;
420         }
421
422         context = isl_set_compute_divs(context);
423         hull = isl_set_simple_hull(isl_set_copy(context));
424
425         pw = FN(PW,cow)(pw);
426         if (!pw)
427                 goto error;
428
429         for (i = pw->n - 1; i >= 0; --i) {
430                 pw->p[i].set = isl_set_intersect(pw->p[i].set,
431                                                  isl_set_copy(context));
432                 if (!pw->p[i].set)
433                         goto error;
434                 pw->p[i].FIELD = FN(EL,gist)(pw->p[i].FIELD,
435                                              isl_set_copy(pw->p[i].set));
436                 pw->p[i].set = isl_set_gist_basic_set(pw->p[i].set,
437                                                 isl_basic_set_copy(hull));
438                 if (!pw->p[i].set)
439                         goto error;
440                 if (isl_set_plain_is_empty(pw->p[i].set)) {
441                         isl_set_free(pw->p[i].set);
442                         FN(EL,free)(pw->p[i].FIELD);
443                         if (i != pw->n - 1)
444                                 pw->p[i] = pw->p[pw->n - 1];
445                         pw->n--;
446                 }
447         }
448
449         isl_basic_set_free(hull);
450         isl_set_free(context);
451
452         return pw;
453 error:
454         FN(PW,free)(pw);
455         isl_basic_set_free(hull);
456         isl_set_free(context);
457         return NULL;
458 }
459
460 __isl_give PW *FN(PW,coalesce)(__isl_take PW *pw)
461 {
462         int i, j;
463
464         if (!pw)
465                 return NULL;
466         if (pw->n == 0)
467                 return pw;
468
469         for (i = pw->n - 1; i >= 0; --i) {
470                 for (j = i - 1; j >= 0; --j) {
471                         if (!FN(EL,plain_is_equal)(pw->p[i].FIELD,
472                                                         pw->p[j].FIELD))
473                                 continue;
474                         pw->p[j].set = isl_set_union(pw->p[j].set,
475                                                         pw->p[i].set);
476                         FN(EL,free)(pw->p[i].FIELD);
477                         if (i != pw->n - 1)
478                                 pw->p[i] = pw->p[pw->n - 1];
479                         pw->n--;
480                         break;
481                 }
482                 if (j >= 0)
483                         continue;
484                 pw->p[i].set = isl_set_coalesce(pw->p[i].set);
485                 if (!pw->p[i].set)
486                         goto error;
487         }
488
489         return pw;
490 error:
491         FN(PW,free)(pw);
492         return NULL;
493 }
494
495 isl_ctx *FN(PW,get_ctx)(__isl_keep PW *pw)
496 {
497         return pw ? isl_dim_get_ctx(pw->dim) : NULL;
498 }
499
500 int FN(PW,involves_dims)(__isl_keep PW *pw, enum isl_dim_type type,
501         unsigned first, unsigned n)
502 {
503         int i;
504
505         if (!pw)
506                 return -1;
507         if (pw->n == 0 || n == 0)
508                 return 0;
509         for (i = 0; i < pw->n; ++i) {
510                 int involves = FN(EL,involves_dims)(pw->p[i].FIELD,
511                                                         type, first, n);
512                 if (involves < 0 || involves)
513                         return involves;
514                 involves = isl_set_involves_dims(pw->p[i].set, type, first, n);
515                 if (involves < 0 || involves)
516                         return involves;
517         }
518         return 0;
519 }
520
521 __isl_give PW *FN(PW,set_dim_name)(__isl_take PW *pw,
522         enum isl_dim_type type, unsigned pos, const char *s)
523 {
524         int i;
525
526         pw = FN(PW,cow)(pw);
527         if (!pw)
528                 return NULL;
529
530         pw->dim = isl_dim_set_name(pw->dim, type, pos, s);
531         if (!pw->dim)
532                 goto error;
533
534         for (i = 0; i < pw->n; ++i) {
535                 pw->p[i].set = isl_set_set_dim_name(pw->p[i].set, type, pos, s);
536                 if (!pw->p[i].set)
537                         goto error;
538                 pw->p[i].FIELD = FN(EL,set_dim_name)(pw->p[i].FIELD, type, pos, s);
539                 if (!pw->p[i].FIELD)
540                         goto error;
541         }
542
543         return pw;
544 error:
545         FN(PW,free)(pw);
546         return NULL;
547 }
548
549 __isl_give PW *FN(PW,drop_dims)(__isl_take PW *pw,
550         enum isl_dim_type type, unsigned first, unsigned n)
551 {
552         int i;
553
554         if (!pw)
555                 return NULL;
556         if (n == 0 && !isl_dim_get_tuple_name(pw->dim, type))
557                 return pw;
558
559         pw = FN(PW,cow)(pw);
560         if (!pw)
561                 return NULL;
562         pw->dim = isl_dim_drop(pw->dim, type, first, n);
563         if (!pw->dim)
564                 goto error;
565         for (i = 0; i < pw->n; ++i) {
566                 pw->p[i].set = isl_set_drop(pw->p[i].set, type, first, n);
567                 if (!pw->p[i].set)
568                         goto error;
569                 pw->p[i].FIELD = FN(EL,drop_dims)(pw->p[i].FIELD, type, first, n);
570                 if (!pw->p[i].FIELD)
571                         goto error;
572         }
573
574         return pw;
575 error:
576         FN(PW,free)(pw);
577         return NULL;
578 }
579
580 __isl_give PW *FN(PW,insert_dims)(__isl_take PW *pw, enum isl_dim_type type,
581         unsigned first, unsigned n)
582 {
583         int i;
584
585         if (!pw)
586                 return NULL;
587         if (n == 0 && !isl_dim_is_named_or_nested(pw->dim, type))
588                 return pw;
589
590         pw = FN(PW,cow)(pw);
591         if (!pw)
592                 return NULL;
593
594         pw->dim = isl_dim_insert(pw->dim, type, first, n);
595         if (!pw->dim)
596                 goto error;
597
598         for (i = 0; i < pw->n; ++i) {
599                 pw->p[i].set = isl_set_insert(pw->p[i].set, type, first, n);
600                 if (!pw->p[i].set)
601                         goto error;
602                 pw->p[i].FIELD = FN(EL,insert_dims)(pw->p[i].FIELD,
603                                                                 type, first, n);
604                 if (!pw->p[i].FIELD)
605                         goto error;
606         }
607
608         return pw;
609 error:
610         FN(PW,free)(pw);
611         return NULL;
612 }
613
614 __isl_give PW *FN(PW,fix_dim)(__isl_take PW *pw,
615         enum isl_dim_type type, unsigned pos, isl_int v)
616 {
617         int i;
618
619         if (!pw)
620                 return NULL;
621
622         pw = FN(PW,cow)(pw);
623         if (!pw)
624                 return NULL;
625         for (i = 0; i < pw->n; ++i) {
626                 pw->p[i].set = isl_set_fix(pw->p[i].set, type, pos, v);
627                 if (!pw->p[i].set)
628                         goto error;
629         }
630
631         return pw;
632 error:
633         FN(PW,free)(pw);
634         return NULL;
635 }
636
637 unsigned FN(PW,dim)(__isl_keep PW *pw, enum isl_dim_type type)
638 {
639         return pw ? isl_dim_size(pw->dim, type) : 0;
640 }
641
642 __isl_give PW *FN(PW,split_dims)(__isl_take PW *pw,
643         enum isl_dim_type type, unsigned first, unsigned n)
644 {
645         int i;
646
647         if (!pw)
648                 return NULL;
649         if (n == 0)
650                 return pw;
651
652         pw = FN(PW,cow)(pw);
653         if (!pw)
654                 return NULL;
655         if (!pw->dim)
656                 goto error;
657         for (i = 0; i < pw->n; ++i) {
658                 pw->p[i].set = isl_set_split_dims(pw->p[i].set, type, first, n);
659                 if (!pw->p[i].set)
660                         goto error;
661         }
662
663         return pw;
664 error:
665         FN(PW,free)(pw);
666         return NULL;
667 }
668
669 /* Compute the maximal value attained by the piecewise quasipolynomial
670  * on its domain or zero if the domain is empty.
671  * In the worst case, the domain is scanned completely,
672  * so the domain is assumed to be bounded.
673  */
674 __isl_give isl_qpolynomial *FN(PW,opt)(__isl_take PW *pw, int max)
675 {
676         int i;
677         isl_qpolynomial *opt;
678
679         if (!pw)
680                 return NULL;
681
682         if (pw->n == 0) {
683                 isl_dim *dim = isl_dim_copy(pw->dim);
684                 FN(PW,free)(pw);
685                 return isl_qpolynomial_zero(dim);
686         }
687
688         opt = FN(EL,opt_on_domain)(FN(EL,copy)(pw->p[0].FIELD),
689                                         isl_set_copy(pw->p[0].set), max);
690         for (i = 1; i < pw->n; ++i) {
691                 isl_qpolynomial *opt_i;
692                 opt_i = FN(EL,opt_on_domain)(FN(EL,copy)(pw->p[i].FIELD),
693                                                 isl_set_copy(pw->p[i].set), max);
694                 if (max)
695                         opt = isl_qpolynomial_max_cst(opt, opt_i);
696                 else
697                         opt = isl_qpolynomial_min_cst(opt, opt_i);
698         }
699
700         FN(PW,free)(pw);
701         return opt;
702 }
703
704 __isl_give isl_qpolynomial *FN(PW,max)(__isl_take PW *pw)
705 {
706         return FN(PW,opt)(pw, 1);
707 }
708
709 __isl_give isl_qpolynomial *FN(PW,min)(__isl_take PW *pw)
710 {
711         return FN(PW,opt)(pw, 0);
712 }
713
714 __isl_give isl_dim *FN(PW,get_dim)(__isl_keep PW *pw)
715 {
716         return pw ? isl_dim_copy(pw->dim) : NULL;
717 }
718
719 __isl_give PW *FN(PW,reset_dim)(__isl_take PW *pw, __isl_take isl_dim *dim)
720 {
721         int i;
722
723         pw = FN(PW,cow)(pw);
724         if (!pw || !dim)
725                 goto error;
726
727         for (i = 0; i < pw->n; ++i) {
728                 pw->p[i].set = isl_set_reset_dim(pw->p[i].set,
729                                                  isl_dim_copy(dim));
730                 if (!pw->p[i].set)
731                         goto error;
732                 pw->p[i].FIELD = FN(EL,reset_dim)(pw->p[i].FIELD,
733                                                   isl_dim_copy(dim));
734                 if (!pw->p[i].FIELD)
735                         goto error;
736         }
737         isl_dim_free(pw->dim);
738         pw->dim = dim;
739
740         return pw;
741 error:
742         isl_dim_free(dim);
743         FN(PW,free)(pw);
744         return NULL;
745 }
746
747 int FN(PW,has_equal_dim)(__isl_keep PW *pw1, __isl_keep PW *pw2)
748 {
749         if (!pw1 || !pw2)
750                 return -1;
751
752         return isl_dim_equal(pw1->dim, pw2->dim);
753 }
754
755 __isl_give PW *FN(PW,morph)(__isl_take PW *pw, __isl_take isl_morph *morph)
756 {
757         int i;
758         isl_ctx *ctx;
759
760         if (!pw || !morph)
761                 goto error;
762
763         ctx = isl_dim_get_ctx(pw->dim);
764         isl_assert(ctx, isl_dim_equal(pw->dim, morph->dom->dim),
765                 goto error);
766
767         pw = FN(PW,cow)(pw);
768         if (!pw)
769                 goto error;
770         isl_dim_free(pw->dim);
771         pw->dim = isl_dim_copy(morph->ran->dim);
772         if (!pw->dim)
773                 goto error;
774
775         for (i = 0; i < pw->n; ++i) {
776                 pw->p[i].set = isl_morph_set(isl_morph_copy(morph), pw->p[i].set);
777                 if (!pw->p[i].set)
778                         goto error;
779                 pw->p[i].FIELD = FN(EL,morph)(pw->p[i].FIELD,
780                                                 isl_morph_copy(morph));
781                 if (!pw->p[i].FIELD)
782                         goto error;
783         }
784
785         isl_morph_free(morph);
786
787         return pw;
788 error:
789         FN(PW,free)(pw);
790         isl_morph_free(morph);
791         return NULL;
792 }
793
794 int FN(PW,foreach_piece)(__isl_keep PW *pw,
795         int (*fn)(__isl_take isl_set *set, __isl_take EL *el, void *user),
796         void *user)
797 {
798         int i;
799
800         if (!pw)
801                 return -1;
802
803         for (i = 0; i < pw->n; ++i)
804                 if (fn(isl_set_copy(pw->p[i].set),
805                                 FN(EL,copy)(pw->p[i].FIELD), user) < 0)
806                         return -1;
807
808         return 0;
809 }
810
811 static int any_divs(__isl_keep isl_set *set)
812 {
813         int i;
814
815         if (!set)
816                 return -1;
817
818         for (i = 0; i < set->n; ++i)
819                 if (set->p[i]->n_div > 0)
820                         return 1;
821
822         return 0;
823 }
824
825 static int foreach_lifted_subset(__isl_take isl_set *set, __isl_take EL *el,
826         int (*fn)(__isl_take isl_set *set, __isl_take EL *el,
827                     void *user), void *user)
828 {
829         int i;
830
831         if (!set || !el)
832                 goto error;
833
834         for (i = 0; i < set->n; ++i) {
835                 isl_set *lift;
836                 EL *copy;
837
838                 lift = isl_set_from_basic_set(isl_basic_set_copy(set->p[i]));
839                 lift = isl_set_lift(lift);
840
841                 copy = FN(EL,copy)(el);
842                 copy = FN(EL,lift)(copy, isl_set_get_dim(lift));
843
844                 if (fn(lift, copy, user) < 0)
845                         goto error;
846         }
847
848         isl_set_free(set);
849         FN(EL,free)(el);
850
851         return 0;
852 error:
853         isl_set_free(set);
854         FN(EL,free)(el);
855         return -1;
856 }
857
858 int FN(PW,foreach_lifted_piece)(__isl_keep PW *pw,
859         int (*fn)(__isl_take isl_set *set, __isl_take EL *el,
860                     void *user), void *user)
861 {
862         int i;
863
864         if (!pw)
865                 return -1;
866
867         for (i = 0; i < pw->n; ++i) {
868                 isl_set *set;
869                 EL *el;
870
871                 set = isl_set_copy(pw->p[i].set);
872                 el = FN(EL,copy)(pw->p[i].FIELD);
873                 if (!any_divs(set)) {
874                         if (fn(set, el, user) < 0)
875                                 return -1;
876                         continue;
877                 }
878                 if (foreach_lifted_subset(set, el, fn, user) < 0)
879                         return -1;
880         }
881
882         return 0;
883 }
884
885 __isl_give PW *FN(PW,move_dims)(__isl_take PW *pw,
886         enum isl_dim_type dst_type, unsigned dst_pos,
887         enum isl_dim_type src_type, unsigned src_pos, unsigned n)
888 {
889         int i;
890
891         pw = FN(PW,cow)(pw);
892         if (!pw)
893                 return NULL;
894
895         pw->dim = isl_dim_move(pw->dim, dst_type, dst_pos, src_type, src_pos, n);
896         if (!pw->dim)
897                 goto error;
898
899         for (i = 0; i < pw->n; ++i) {
900                 pw->p[i].set = isl_set_move_dims(pw->p[i].set,
901                                                 dst_type, dst_pos,
902                                                 src_type, src_pos, n);
903                 if (!pw->p[i].set)
904                         goto error;
905                 pw->p[i].FIELD = FN(EL,move_dims)(pw->p[i].FIELD,
906                                         dst_type, dst_pos, src_type, src_pos, n);
907                 if (!pw->p[i].FIELD)
908                         goto error;
909         }
910
911         return pw;
912 error:
913         FN(PW,free)(pw);
914         return NULL;
915 }
916
917 __isl_give PW *FN(PW,realign)(__isl_take PW *pw, __isl_take isl_reordering *exp)
918 {
919         int i;
920
921         pw = FN(PW,cow)(pw);
922         if (!pw || !exp)
923                 return NULL;
924
925         for (i = 0; i < pw->n; ++i) {
926                 pw->p[i].set = isl_set_realign(pw->p[i].set,
927                                                     isl_reordering_copy(exp));
928                 if (!pw->p[i].set)
929                         goto error;
930                 pw->p[i].FIELD = FN(EL,realign)(pw->p[i].FIELD,
931                                                     isl_reordering_copy(exp));
932                 if (!pw->p[i].FIELD)
933                         goto error;
934         }
935
936         pw = FN(PW,reset_dim)(pw, isl_dim_copy(exp->dim));
937
938         isl_reordering_free(exp);
939         return pw;
940 error:
941         isl_reordering_free(exp);
942         FN(PW,free)(pw);
943         return NULL;
944 }
945
946 __isl_give PW *FN(PW,mul_isl_int)(__isl_take PW *pw, isl_int v)
947 {
948         int i;
949
950         if (isl_int_is_one(v))
951                 return pw;
952         if (pw && isl_int_is_zero(v)) {
953                 PW *zero;
954                 isl_dim *dim = FN(PW,get_dim)(pw);
955 #ifdef HAS_TYPE
956                 zero = FN(PW,zero)(dim, pw->type);
957 #else
958                 zero = FN(PW,zero)(dim);
959 #endif
960                 FN(PW,free)(pw);
961                 return zero;
962         }
963         pw = FN(PW,cow)(pw);
964         if (!pw)
965                 return NULL;
966         if (pw->n == 0)
967                 return pw;
968
969 #ifdef HAS_TYPE
970         if (isl_int_is_neg(v))
971                 pw->type = isl_fold_type_negate(pw->type);
972 #endif
973         for (i = 0; i < pw->n; ++i) {
974                 pw->p[i].FIELD = FN(EL,scale)(pw->p[i].FIELD, v);
975                 if (!pw->p[i].FIELD)
976                         goto error;
977         }
978
979         return pw;
980 error:
981         FN(PW,free)(pw);
982         return NULL;
983 }