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