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