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