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