e89d4a3d1941f74fe2058892e061851251d77209
[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,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 #ifndef NO_NEG
314 __isl_give PW *FN(PW,neg)(__isl_take PW *pw)
315 {
316         int i;
317
318         if (!pw)
319                 return NULL;
320
321         if (FN(PW,IS_ZERO)(pw))
322                 return pw;
323
324         pw = FN(PW,cow)(pw);
325         if (!pw)
326                 return NULL;
327
328         for (i = 0; i < pw->n; ++i) {
329                 pw->p[i].FIELD = FN(EL,neg)(pw->p[i].FIELD);
330                 if (!pw->p[i].FIELD)
331                         return FN(PW,free)(pw);
332         }
333
334         return pw;
335 }
336 #endif
337
338 #ifndef NO_EVAL
339 __isl_give isl_qpolynomial *FN(PW,eval)(__isl_take PW *pw,
340         __isl_take isl_point *pnt)
341 {
342         int i;
343         int found = 0;
344         isl_ctx *ctx;
345         isl_dim *pnt_dim = NULL;
346         isl_qpolynomial *qp;
347
348         if (!pw || !pnt)
349                 goto error;
350         ctx = isl_point_get_ctx(pnt);
351         pnt_dim = isl_point_get_dim(pnt);
352         isl_assert(ctx, isl_dim_equal(pnt_dim, pw->dim), goto error);
353
354         for (i = 0; i < pw->n; ++i) {
355                 found = isl_set_contains_point(pw->p[i].set, pnt);
356                 if (found < 0)
357                         goto error;
358                 if (found)
359                         break;
360         }
361         if (found)
362                 qp = FN(EL,eval)(FN(EL,copy)(pw->p[i].FIELD),
363                                             isl_point_copy(pnt));
364         else
365                 qp = isl_qpolynomial_zero(isl_dim_copy(pw->dim));
366         FN(PW,free)(pw);
367         isl_dim_free(pnt_dim);
368         isl_point_free(pnt);
369         return qp;
370 error:
371         FN(PW,free)(pw);
372         isl_dim_free(pnt_dim);
373         isl_point_free(pnt);
374         return NULL;
375 }
376 #endif
377
378 __isl_give isl_set *FN(PW,domain)(__isl_take PW *pw)
379 {
380         int i;
381         isl_set *dom;
382
383         if (!pw)
384                 return NULL;
385
386         dom = isl_set_empty(isl_dim_copy(pw->dim));
387         for (i = 0; i < pw->n; ++i)
388                 dom = isl_set_union_disjoint(dom, isl_set_copy(pw->p[i].set));
389
390         FN(PW,free)(pw);
391
392         return dom;
393 }
394
395 __isl_give PW *FN(PW,intersect_domain)(__isl_take PW *pw, __isl_take isl_set *set)
396 {
397         int i;
398
399         if (!pw || !set)
400                 goto error;
401
402         if (pw->n == 0) {
403                 isl_set_free(set);
404                 return pw;
405         }
406
407         pw = FN(PW,cow)(pw);
408         if (!pw)
409                 goto error;
410
411         for (i = pw->n - 1; i >= 0; --i) {
412                 isl_basic_set *aff;
413                 pw->p[i].set = isl_set_intersect(pw->p[i].set, isl_set_copy(set));
414                 if (!pw->p[i].set)
415                         goto error;
416                 aff = isl_set_affine_hull(isl_set_copy(pw->p[i].set));
417                 pw->p[i].FIELD = FN(EL,substitute_equalities)(pw->p[i].FIELD,
418                                                                 aff);
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_set_free(set);
429         return pw;
430 error:
431         isl_set_free(set);
432         FN(PW,free)(pw);
433         return NULL;
434 }
435
436 __isl_give PW *FN(PW,gist)(__isl_take PW *pw, __isl_take isl_set *context)
437 {
438         int i;
439         isl_basic_set *hull = NULL;
440
441         if (!pw || !context)
442                 goto error;
443
444         if (pw->n == 0) {
445                 isl_set_free(context);
446                 return pw;
447         }
448
449         context = isl_set_compute_divs(context);
450         hull = isl_set_simple_hull(isl_set_copy(context));
451
452         pw = FN(PW,cow)(pw);
453         if (!pw)
454                 goto error;
455
456         for (i = pw->n - 1; i >= 0; --i) {
457                 pw->p[i].set = isl_set_intersect(pw->p[i].set,
458                                                  isl_set_copy(context));
459                 if (!pw->p[i].set)
460                         goto error;
461                 pw->p[i].FIELD = FN(EL,gist)(pw->p[i].FIELD,
462                                              isl_set_copy(pw->p[i].set));
463                 pw->p[i].set = isl_set_gist_basic_set(pw->p[i].set,
464                                                 isl_basic_set_copy(hull));
465                 if (!pw->p[i].set)
466                         goto error;
467                 if (isl_set_plain_is_empty(pw->p[i].set)) {
468                         isl_set_free(pw->p[i].set);
469                         FN(EL,free)(pw->p[i].FIELD);
470                         if (i != pw->n - 1)
471                                 pw->p[i] = pw->p[pw->n - 1];
472                         pw->n--;
473                 }
474         }
475
476         isl_basic_set_free(hull);
477         isl_set_free(context);
478
479         return pw;
480 error:
481         FN(PW,free)(pw);
482         isl_basic_set_free(hull);
483         isl_set_free(context);
484         return NULL;
485 }
486
487 __isl_give PW *FN(PW,coalesce)(__isl_take PW *pw)
488 {
489         int i, j;
490
491         if (!pw)
492                 return NULL;
493         if (pw->n == 0)
494                 return pw;
495
496         for (i = pw->n - 1; i >= 0; --i) {
497                 for (j = i - 1; j >= 0; --j) {
498                         if (!FN(EL,plain_is_equal)(pw->p[i].FIELD,
499                                                         pw->p[j].FIELD))
500                                 continue;
501                         pw->p[j].set = isl_set_union(pw->p[j].set,
502                                                         pw->p[i].set);
503                         FN(EL,free)(pw->p[i].FIELD);
504                         if (i != pw->n - 1)
505                                 pw->p[i] = pw->p[pw->n - 1];
506                         pw->n--;
507                         break;
508                 }
509                 if (j >= 0)
510                         continue;
511                 pw->p[i].set = isl_set_coalesce(pw->p[i].set);
512                 if (!pw->p[i].set)
513                         goto error;
514         }
515
516         return pw;
517 error:
518         FN(PW,free)(pw);
519         return NULL;
520 }
521
522 isl_ctx *FN(PW,get_ctx)(__isl_keep PW *pw)
523 {
524         return pw ? isl_dim_get_ctx(pw->dim) : NULL;
525 }
526
527 #ifndef NO_INVOLVES_DIMS
528 int FN(PW,involves_dims)(__isl_keep PW *pw, enum isl_dim_type type,
529         unsigned first, unsigned n)
530 {
531         int i;
532
533         if (!pw)
534                 return -1;
535         if (pw->n == 0 || n == 0)
536                 return 0;
537         for (i = 0; i < pw->n; ++i) {
538                 int involves = FN(EL,involves_dims)(pw->p[i].FIELD,
539                                                         type, first, n);
540                 if (involves < 0 || involves)
541                         return involves;
542                 involves = isl_set_involves_dims(pw->p[i].set, type, first, n);
543                 if (involves < 0 || involves)
544                         return involves;
545         }
546         return 0;
547 }
548 #endif
549
550 __isl_give PW *FN(PW,set_dim_name)(__isl_take PW *pw,
551         enum isl_dim_type type, unsigned pos, const char *s)
552 {
553         int i;
554
555         pw = FN(PW,cow)(pw);
556         if (!pw)
557                 return NULL;
558
559         pw->dim = isl_dim_set_name(pw->dim, type, pos, s);
560         if (!pw->dim)
561                 goto error;
562
563         for (i = 0; i < pw->n; ++i) {
564                 pw->p[i].set = isl_set_set_dim_name(pw->p[i].set, type, pos, s);
565                 if (!pw->p[i].set)
566                         goto error;
567                 pw->p[i].FIELD = FN(EL,set_dim_name)(pw->p[i].FIELD, type, pos, s);
568                 if (!pw->p[i].FIELD)
569                         goto error;
570         }
571
572         return pw;
573 error:
574         FN(PW,free)(pw);
575         return NULL;
576 }
577
578 #ifndef NO_DROP_DIMS
579 __isl_give PW *FN(PW,drop_dims)(__isl_take PW *pw,
580         enum isl_dim_type type, unsigned first, unsigned n)
581 {
582         int i;
583
584         if (!pw)
585                 return NULL;
586         if (n == 0 && !isl_dim_get_tuple_name(pw->dim, type))
587                 return pw;
588
589         pw = FN(PW,cow)(pw);
590         if (!pw)
591                 return NULL;
592         pw->dim = isl_dim_drop(pw->dim, type, first, n);
593         if (!pw->dim)
594                 goto error;
595         for (i = 0; i < pw->n; ++i) {
596                 pw->p[i].set = isl_set_drop(pw->p[i].set, type, first, n);
597                 if (!pw->p[i].set)
598                         goto error;
599                 pw->p[i].FIELD = FN(EL,drop_dims)(pw->p[i].FIELD, type, first, n);
600                 if (!pw->p[i].FIELD)
601                         goto error;
602         }
603
604         return pw;
605 error:
606         FN(PW,free)(pw);
607         return NULL;
608 }
609 #endif
610
611 #ifndef NO_INSERT_DIMS
612 __isl_give PW *FN(PW,insert_dims)(__isl_take PW *pw, enum isl_dim_type type,
613         unsigned first, unsigned n)
614 {
615         int i;
616
617         if (!pw)
618                 return NULL;
619         if (n == 0 && !isl_dim_is_named_or_nested(pw->dim, type))
620                 return pw;
621
622         pw = FN(PW,cow)(pw);
623         if (!pw)
624                 return NULL;
625
626         pw->dim = isl_dim_insert(pw->dim, type, first, n);
627         if (!pw->dim)
628                 goto error;
629
630         for (i = 0; i < pw->n; ++i) {
631                 pw->p[i].set = isl_set_insert(pw->p[i].set, type, first, n);
632                 if (!pw->p[i].set)
633                         goto error;
634                 pw->p[i].FIELD = FN(EL,insert_dims)(pw->p[i].FIELD,
635                                                                 type, first, n);
636                 if (!pw->p[i].FIELD)
637                         goto error;
638         }
639
640         return pw;
641 error:
642         FN(PW,free)(pw);
643         return NULL;
644 }
645 #endif
646
647 __isl_give PW *FN(PW,fix_dim)(__isl_take PW *pw,
648         enum isl_dim_type type, unsigned pos, isl_int v)
649 {
650         int i;
651
652         if (!pw)
653                 return NULL;
654
655         pw = FN(PW,cow)(pw);
656         if (!pw)
657                 return NULL;
658         for (i = 0; i < pw->n; ++i) {
659                 pw->p[i].set = isl_set_fix(pw->p[i].set, type, pos, v);
660                 if (!pw->p[i].set)
661                         goto error;
662         }
663
664         return pw;
665 error:
666         FN(PW,free)(pw);
667         return NULL;
668 }
669
670 unsigned FN(PW,dim)(__isl_keep PW *pw, enum isl_dim_type type)
671 {
672         return pw ? isl_dim_size(pw->dim, type) : 0;
673 }
674
675 __isl_give PW *FN(PW,split_dims)(__isl_take PW *pw,
676         enum isl_dim_type type, unsigned first, unsigned n)
677 {
678         int i;
679
680         if (!pw)
681                 return NULL;
682         if (n == 0)
683                 return pw;
684
685         pw = FN(PW,cow)(pw);
686         if (!pw)
687                 return NULL;
688         if (!pw->dim)
689                 goto error;
690         for (i = 0; i < pw->n; ++i) {
691                 pw->p[i].set = isl_set_split_dims(pw->p[i].set, type, first, n);
692                 if (!pw->p[i].set)
693                         goto error;
694         }
695
696         return pw;
697 error:
698         FN(PW,free)(pw);
699         return NULL;
700 }
701
702 #ifndef NO_OPT
703 /* Compute the maximal value attained by the piecewise quasipolynomial
704  * on its domain or zero if the domain is empty.
705  * In the worst case, the domain is scanned completely,
706  * so the domain is assumed to be bounded.
707  */
708 __isl_give isl_qpolynomial *FN(PW,opt)(__isl_take PW *pw, int max)
709 {
710         int i;
711         isl_qpolynomial *opt;
712
713         if (!pw)
714                 return NULL;
715
716         if (pw->n == 0) {
717                 isl_dim *dim = isl_dim_copy(pw->dim);
718                 FN(PW,free)(pw);
719                 return isl_qpolynomial_zero(dim);
720         }
721
722         opt = FN(EL,opt_on_domain)(FN(EL,copy)(pw->p[0].FIELD),
723                                         isl_set_copy(pw->p[0].set), max);
724         for (i = 1; i < pw->n; ++i) {
725                 isl_qpolynomial *opt_i;
726                 opt_i = FN(EL,opt_on_domain)(FN(EL,copy)(pw->p[i].FIELD),
727                                                 isl_set_copy(pw->p[i].set), max);
728                 if (max)
729                         opt = isl_qpolynomial_max_cst(opt, opt_i);
730                 else
731                         opt = isl_qpolynomial_min_cst(opt, opt_i);
732         }
733
734         FN(PW,free)(pw);
735         return opt;
736 }
737
738 __isl_give isl_qpolynomial *FN(PW,max)(__isl_take PW *pw)
739 {
740         return FN(PW,opt)(pw, 1);
741 }
742
743 __isl_give isl_qpolynomial *FN(PW,min)(__isl_take PW *pw)
744 {
745         return FN(PW,opt)(pw, 0);
746 }
747 #endif
748
749 __isl_give isl_dim *FN(PW,get_dim)(__isl_keep PW *pw)
750 {
751         return pw ? isl_dim_copy(pw->dim) : NULL;
752 }
753
754 #ifndef NO_RESET_DIM
755 __isl_give PW *FN(PW,reset_dim)(__isl_take PW *pw, __isl_take isl_dim *dim)
756 {
757         int i;
758
759         pw = FN(PW,cow)(pw);
760         if (!pw || !dim)
761                 goto error;
762
763         for (i = 0; i < pw->n; ++i) {
764                 pw->p[i].set = isl_set_reset_dim(pw->p[i].set,
765                                                  isl_dim_copy(dim));
766                 if (!pw->p[i].set)
767                         goto error;
768                 pw->p[i].FIELD = FN(EL,reset_dim)(pw->p[i].FIELD,
769                                                   isl_dim_copy(dim));
770                 if (!pw->p[i].FIELD)
771                         goto error;
772         }
773         isl_dim_free(pw->dim);
774         pw->dim = dim;
775
776         return pw;
777 error:
778         isl_dim_free(dim);
779         FN(PW,free)(pw);
780         return NULL;
781 }
782 #endif
783
784 int FN(PW,has_equal_dim)(__isl_keep PW *pw1, __isl_keep PW *pw2)
785 {
786         if (!pw1 || !pw2)
787                 return -1;
788
789         return isl_dim_equal(pw1->dim, pw2->dim);
790 }
791
792 #ifndef NO_MORPH
793 __isl_give PW *FN(PW,morph)(__isl_take PW *pw, __isl_take isl_morph *morph)
794 {
795         int i;
796         isl_ctx *ctx;
797
798         if (!pw || !morph)
799                 goto error;
800
801         ctx = isl_dim_get_ctx(pw->dim);
802         isl_assert(ctx, isl_dim_equal(pw->dim, morph->dom->dim),
803                 goto error);
804
805         pw = FN(PW,cow)(pw);
806         if (!pw)
807                 goto error;
808         isl_dim_free(pw->dim);
809         pw->dim = isl_dim_copy(morph->ran->dim);
810         if (!pw->dim)
811                 goto error;
812
813         for (i = 0; i < pw->n; ++i) {
814                 pw->p[i].set = isl_morph_set(isl_morph_copy(morph), pw->p[i].set);
815                 if (!pw->p[i].set)
816                         goto error;
817                 pw->p[i].FIELD = FN(EL,morph)(pw->p[i].FIELD,
818                                                 isl_morph_copy(morph));
819                 if (!pw->p[i].FIELD)
820                         goto error;
821         }
822
823         isl_morph_free(morph);
824
825         return pw;
826 error:
827         FN(PW,free)(pw);
828         isl_morph_free(morph);
829         return NULL;
830 }
831 #endif
832
833 int FN(PW,foreach_piece)(__isl_keep PW *pw,
834         int (*fn)(__isl_take isl_set *set, __isl_take EL *el, void *user),
835         void *user)
836 {
837         int i;
838
839         if (!pw)
840                 return -1;
841
842         for (i = 0; i < pw->n; ++i)
843                 if (fn(isl_set_copy(pw->p[i].set),
844                                 FN(EL,copy)(pw->p[i].FIELD), user) < 0)
845                         return -1;
846
847         return 0;
848 }
849
850 #ifndef NO_LIFT
851 static int any_divs(__isl_keep isl_set *set)
852 {
853         int i;
854
855         if (!set)
856                 return -1;
857
858         for (i = 0; i < set->n; ++i)
859                 if (set->p[i]->n_div > 0)
860                         return 1;
861
862         return 0;
863 }
864
865 static int foreach_lifted_subset(__isl_take isl_set *set, __isl_take EL *el,
866         int (*fn)(__isl_take isl_set *set, __isl_take EL *el,
867                     void *user), void *user)
868 {
869         int i;
870
871         if (!set || !el)
872                 goto error;
873
874         for (i = 0; i < set->n; ++i) {
875                 isl_set *lift;
876                 EL *copy;
877
878                 lift = isl_set_from_basic_set(isl_basic_set_copy(set->p[i]));
879                 lift = isl_set_lift(lift);
880
881                 copy = FN(EL,copy)(el);
882                 copy = FN(EL,lift)(copy, isl_set_get_dim(lift));
883
884                 if (fn(lift, copy, user) < 0)
885                         goto error;
886         }
887
888         isl_set_free(set);
889         FN(EL,free)(el);
890
891         return 0;
892 error:
893         isl_set_free(set);
894         FN(EL,free)(el);
895         return -1;
896 }
897
898 int FN(PW,foreach_lifted_piece)(__isl_keep PW *pw,
899         int (*fn)(__isl_take isl_set *set, __isl_take EL *el,
900                     void *user), void *user)
901 {
902         int i;
903
904         if (!pw)
905                 return -1;
906
907         for (i = 0; i < pw->n; ++i) {
908                 isl_set *set;
909                 EL *el;
910
911                 set = isl_set_copy(pw->p[i].set);
912                 el = FN(EL,copy)(pw->p[i].FIELD);
913                 if (!any_divs(set)) {
914                         if (fn(set, el, user) < 0)
915                                 return -1;
916                         continue;
917                 }
918                 if (foreach_lifted_subset(set, el, fn, user) < 0)
919                         return -1;
920         }
921
922         return 0;
923 }
924 #endif
925
926 #ifndef NO_MOVE_DIMS
927 __isl_give PW *FN(PW,move_dims)(__isl_take PW *pw,
928         enum isl_dim_type dst_type, unsigned dst_pos,
929         enum isl_dim_type src_type, unsigned src_pos, unsigned n)
930 {
931         int i;
932
933         pw = FN(PW,cow)(pw);
934         if (!pw)
935                 return NULL;
936
937         pw->dim = isl_dim_move(pw->dim, dst_type, dst_pos, src_type, src_pos, n);
938         if (!pw->dim)
939                 goto error;
940
941         for (i = 0; i < pw->n; ++i) {
942                 pw->p[i].set = isl_set_move_dims(pw->p[i].set,
943                                                 dst_type, dst_pos,
944                                                 src_type, src_pos, n);
945                 if (!pw->p[i].set)
946                         goto error;
947                 pw->p[i].FIELD = FN(EL,move_dims)(pw->p[i].FIELD,
948                                         dst_type, dst_pos, src_type, src_pos, n);
949                 if (!pw->p[i].FIELD)
950                         goto error;
951         }
952
953         return pw;
954 error:
955         FN(PW,free)(pw);
956         return NULL;
957 }
958 #endif
959
960 #ifndef NO_REALIGN
961 __isl_give PW *FN(PW,realign)(__isl_take PW *pw, __isl_take isl_reordering *exp)
962 {
963         int i;
964
965         pw = FN(PW,cow)(pw);
966         if (!pw || !exp)
967                 return NULL;
968
969         for (i = 0; i < pw->n; ++i) {
970                 pw->p[i].set = isl_set_realign(pw->p[i].set,
971                                                     isl_reordering_copy(exp));
972                 if (!pw->p[i].set)
973                         goto error;
974                 pw->p[i].FIELD = FN(EL,realign)(pw->p[i].FIELD,
975                                                     isl_reordering_copy(exp));
976                 if (!pw->p[i].FIELD)
977                         goto error;
978         }
979
980         pw = FN(PW,reset_dim)(pw, isl_dim_copy(exp->dim));
981
982         isl_reordering_free(exp);
983         return pw;
984 error:
985         isl_reordering_free(exp);
986         FN(PW,free)(pw);
987         return NULL;
988 }
989 #endif
990
991 __isl_give PW *FN(PW,mul_isl_int)(__isl_take PW *pw, isl_int v)
992 {
993         int i;
994
995         if (isl_int_is_one(v))
996                 return pw;
997         if (pw && isl_int_is_zero(v)) {
998                 PW *zero;
999                 isl_dim *dim = FN(PW,get_dim)(pw);
1000 #ifdef HAS_TYPE
1001                 zero = FN(PW,ZERO)(dim, pw->type);
1002 #else
1003                 zero = FN(PW,ZERO)(dim);
1004 #endif
1005                 FN(PW,free)(pw);
1006                 return zero;
1007         }
1008         pw = FN(PW,cow)(pw);
1009         if (!pw)
1010                 return NULL;
1011         if (pw->n == 0)
1012                 return pw;
1013
1014 #ifdef HAS_TYPE
1015         if (isl_int_is_neg(v))
1016                 pw->type = isl_fold_type_negate(pw->type);
1017 #endif
1018         for (i = 0; i < pw->n; ++i) {
1019                 pw->p[i].FIELD = FN(EL,scale)(pw->p[i].FIELD, v);
1020                 if (!pw->p[i].FIELD)
1021                         goto error;
1022         }
1023
1024         return pw;
1025 error:
1026         FN(PW,free)(pw);
1027         return NULL;
1028 }