add isl_pw_qpolynomial_fold
[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 static __isl_give PW *FN(PW,alloc_)(__isl_take isl_dim *dim, int n)
7 {
8         struct PW *pw;
9
10         if (!dim)
11                 return NULL;
12         isl_assert(dim->ctx, n >= 0, goto error);
13         pw = isl_alloc(dim->ctx, struct PW,
14                         sizeof(struct PW) + (n - 1) * sizeof(S(PW,piece)));
15         if (!pw)
16                 goto error;
17
18         pw->ref = 1;
19         pw->size = n;
20         pw->n = 0;
21         pw->dim = dim;
22         return pw;
23 error:
24         isl_dim_free(dim);
25         return NULL;
26 }
27
28 __isl_give PW *FN(PW,zero)(__isl_take isl_dim *dim)
29 {
30         return FN(PW,alloc_)(dim, 0);
31 }
32
33 __isl_give PW *FN(PW,add_piece)(__isl_take PW *pw,
34         __isl_take isl_set *set, __isl_take EL *el)
35 {
36         if (!pw || !set || !el)
37                 goto error;
38
39         if (isl_set_fast_is_empty(set) || FN(EL,IS_ZERO)(el)) {
40                 isl_set_free(set);
41                 FN(EL,free)(el);
42                 return pw;
43         }
44
45         isl_assert(set->ctx, isl_dim_equal(pw->dim, el->dim), goto error);
46         isl_assert(set->ctx, pw->n < pw->size, goto error);
47
48         pw->p[pw->n].set = set;
49         pw->p[pw->n].FIELD = el;
50         pw->n++;
51         
52         return pw;
53 error:
54         FN(PW,free)(pw);
55         isl_set_free(set);
56         FN(EL,free)(el);
57         return NULL;
58 }
59
60 __isl_give PW *FN(PW,alloc)(__isl_take isl_set *set, __isl_take EL *el)
61 {
62         PW *pw;
63
64         if (!set || !el)
65                 goto error;
66
67         pw = FN(PW,alloc_)(isl_set_get_dim(set), 1);
68
69         return FN(PW,add_piece)(pw, set, el);
70 error:
71         isl_set_free(set);
72         FN(EL,free)(el);
73         return NULL;
74 }
75
76 __isl_give PW *FN(PW,dup)(__isl_keep PW *pw)
77 {
78         int i;
79         PW *dup;
80
81         if (!pw)
82                 return NULL;
83
84         dup = FN(PW,alloc_)(isl_dim_copy(pw->dim), pw->n);
85         if (!dup)
86                 return NULL;
87
88         for (i = 0; i < pw->n; ++i)
89                 dup = FN(PW,add_piece)(dup, isl_set_copy(pw->p[i].set),
90                                             FN(EL,copy)(pw->p[i].FIELD));
91
92         return dup;
93 error:
94         FN(PW,free)(dup);
95         return NULL;
96 }
97
98 __isl_give PW *FN(PW,copy)(__isl_keep PW *pw)
99 {
100         if (!pw)
101                 return;
102
103         pw->ref++;
104         return pw;
105 }
106
107 void FN(PW,free)(__isl_take PW *pw)
108 {
109         int i;
110
111         if (!pw)
112                 return;
113         if (--pw->ref > 0)
114                 return;
115
116         for (i = 0; i < pw->n; ++i) {
117                 isl_set_free(pw->p[i].set);
118                 FN(EL,free)(pw->p[i].FIELD);
119         }
120         isl_dim_free(pw->dim);
121         free(pw);
122 }
123
124 int FN(PW,is_zero)(__isl_keep PW *pw)
125 {
126         if (!pw)
127                 return -1;
128
129         return pw->n == 0;
130 }
131
132 __isl_give PW *FN(PW,add)(__isl_take PW *pw1, __isl_take PW *pw2)
133 {
134         int i, j, n;
135         struct PW *res;
136         isl_set *set;
137
138         if (!pw1 || !pw2)
139                 goto error;
140
141         isl_assert(pw1->dim->ctx, isl_dim_equal(pw1->dim, pw2->dim), goto error);
142
143         if (FN(PW,is_zero)(pw1)) {
144                 FN(PW,free)(pw1);
145                 return pw2;
146         }
147
148         if (FN(PW,is_zero)(pw2)) {
149                 FN(PW,free)(pw2);
150                 return pw1;
151         }
152
153         n = (pw1->n + 1) * (pw2->n + 1);
154         res = FN(PW,alloc_)(isl_dim_copy(pw1->dim), n);
155
156         for (i = 0; i < pw1->n; ++i) {
157                 set = isl_set_copy(pw1->p[i].set);
158                 for (j = 0; j < pw2->n; ++j) {
159                         struct isl_set *common;
160                         EL *sum;
161                         set = isl_set_subtract(set,
162                                         isl_set_copy(pw2->p[j].set));
163                         common = isl_set_intersect(isl_set_copy(pw1->p[i].set),
164                                                 isl_set_copy(pw2->p[j].set));
165                         if (isl_set_fast_is_empty(common)) {
166                                 isl_set_free(common);
167                                 continue;
168                         }
169
170                         sum = FN(EL,ADD)(FN(EL,copy)(pw1->p[i].FIELD),
171                                          FN(EL,copy)(pw2->p[j].FIELD));
172
173                         res = FN(PW,add_piece)(res, common, sum);
174                 }
175                 res = FN(PW,add_piece)(res, set, FN(EL,copy)(pw1->p[i].FIELD));
176         }
177
178         for (j = 0; j < pw2->n; ++j) {
179                 set = isl_set_copy(pw2->p[j].set);
180                 for (i = 0; i < pw1->n; ++i)
181                         set = isl_set_subtract(set,
182                                         isl_set_copy(pw1->p[i].set));
183                 res = FN(PW,add_piece)(res, set, FN(EL,copy)(pw2->p[j].FIELD));
184         }
185
186         FN(PW,free)(pw1);
187         FN(PW,free)(pw2);
188
189         return res;
190 error:
191         FN(PW,free)(pw1);
192         FN(PW,free)(pw2);
193         return NULL;
194 }
195
196 __isl_give PW *FN(PW,add_disjoint)(__isl_take PW *pw1, __isl_take PW *pw2)
197 {
198         int i;
199         PW *res;
200
201         if (!pw1 || !pw2)
202                 goto error;
203
204         isl_assert(pw1->dim->ctx, isl_dim_equal(pw1->dim, pw2->dim), goto error);
205
206         if (FN(PW,is_zero)(pw1)) {
207                 FN(PW,free)(pw1);
208                 return pw2;
209         }
210
211         if (FN(PW,is_zero)(pw2)) {
212                 FN(PW,free)(pw2);
213                 return pw1;
214         }
215
216         res = FN(PW,alloc_)(isl_dim_copy(pw1->dim), pw1->n + pw2->n);
217
218         for (i = 0; i < pw1->n; ++i)
219                 res = FN(PW,add_piece)(res,
220                                 isl_set_copy(pw1->p[i].set),
221                                 FN(EL,copy)(pw1->p[i].FIELD));
222
223         for (i = 0; i < pw2->n; ++i)
224                 res = FN(PW,add_piece)(res,
225                                 isl_set_copy(pw2->p[i].set),
226                                 FN(EL,copy)(pw2->p[i].FIELD));
227
228         FN(PW,free)(pw1);
229         FN(PW,free)(pw2);
230
231         return res;
232 error:
233         FN(PW,free)(pw1);
234         FN(PW,free)(pw2);
235         return NULL;
236 }