isl_union_templ.c: minor clean-up
[platform/upstream/isl.git] / isl_union_templ.c
1 /*
2  * Copyright 2010      INRIA Saclay
3  *
4  * Use of this software is governed by the GNU LGPLv2.1 license
5  *
6  * Written by Sven Verdoolaege, INRIA Saclay - Ile-de-France,
7  * Parc Club Orsay Universite, ZAC des vignes, 4 rue Jacques Monod,
8  * 91893 Orsay, France 
9  */
10
11 #define xFN(TYPE,NAME) TYPE ## _ ## NAME
12 #define FN(TYPE,NAME) xFN(TYPE,NAME)
13 #define xS(TYPE,NAME) struct TYPE ## _ ## NAME
14 #define S(TYPE,NAME) xS(TYPE,NAME)
15
16 struct UNION {
17         int ref;
18 #ifdef HAS_TYPE
19         enum isl_fold type;
20 #endif
21         isl_dim *dim;
22
23         struct isl_hash_table   table;
24 };
25
26 __isl_give UNION *FN(UNION,cow)(__isl_take UNION *u);
27
28 isl_ctx *FN(UNION,get_ctx)(__isl_keep UNION *u)
29 {
30         return u ? u->dim->ctx : NULL;
31 }
32
33 __isl_give isl_dim *FN(UNION,get_dim)(__isl_keep UNION *u)
34 {
35         if (!u)
36                 return NULL;
37         return isl_dim_copy(u->dim);
38 }
39
40 #ifdef HAS_TYPE
41 static __isl_give UNION *FN(UNION,alloc)(__isl_take isl_dim *dim,
42         enum isl_fold type, int size)
43 #else
44 static __isl_give UNION *FN(UNION,alloc)(__isl_take isl_dim *dim, int size)
45 #endif
46 {
47         UNION *u;
48
49         u = isl_calloc_type(ctx, UNION);
50         if (!u)
51                 return NULL;
52
53         u->ref = 1;
54 #ifdef HAS_TYPE
55         u->type = type;
56 #endif
57         u->dim = dim;
58         if (isl_hash_table_init(dim->ctx, &u->table, size) < 0)
59                 goto error;
60
61         return u;
62 error:
63         isl_dim_free(dim);
64         FN(UNION,free)(u);
65         return NULL;
66 }
67
68 #ifdef HAS_TYPE
69 __isl_give UNION *FN(UNION,zero)(__isl_take isl_dim *dim, enum isl_fold type)
70 {
71         return FN(UNION,alloc)(dim, type, 16);
72 }
73 #else
74 __isl_give UNION *FN(UNION,zero)(__isl_take isl_dim *dim)
75 {
76         return FN(UNION,alloc)(dim, 16);
77 }
78 #endif
79
80 __isl_give UNION *FN(UNION,copy)(__isl_keep UNION *u)
81 {
82         if (!u)
83                 return NULL;
84
85         u->ref++;
86         return u;
87 }
88
89 S(UNION,foreach_data)
90 {
91         int (*fn)(__isl_take PART *part, void *user);
92         void *user;
93 };
94
95 static int call_on_copy(void **entry, void *user)
96 {
97         PART *part = *entry;
98         S(UNION,foreach_data) *data = (S(UNION,foreach_data) *)user;
99
100         return data->fn(FN(PART,copy)(part), data->user);
101 }
102
103 int FN(FN(UNION,foreach),PARTS)(__isl_keep UNION *u,
104         int (*fn)(__isl_take PART *part, void *user), void *user)
105 {
106         S(UNION,foreach_data) data = { fn, user };
107
108         if (!u)
109                 return -1;
110
111         return isl_hash_table_foreach(u->dim->ctx, &u->table,
112                                       &call_on_copy, &data);
113 }
114
115 static int has_dim(const void *entry, const void *val)
116 {
117         PART *part = (PART *)entry;
118         isl_dim *dim = (isl_dim *)val;
119
120         return isl_dim_equal(part->dim, dim);
121 }
122
123 __isl_give UNION *FN(FN(UNION,add),PARTS)(__isl_take UNION *u,
124         __isl_take PART *part)
125 {
126         uint32_t hash;
127         struct isl_hash_table_entry *entry;
128
129         if (!part)
130                 goto error;
131
132         if (FN(PART,is_zero)(part)) {
133                 FN(PART,free)(part);
134                 return u;
135         }
136
137         u = FN(UNION,cow)(u);
138
139         if (!u)
140                 goto error;
141
142         isl_assert(u->dim->ctx, isl_dim_match(part->dim, isl_dim_param, u->dim,
143                                               isl_dim_param), goto error);
144
145         hash = isl_dim_get_hash(part->dim);
146         entry = isl_hash_table_find(u->dim->ctx, &u->table, hash,
147                                     &has_dim, part->dim, 1);
148         if (!entry)
149                 goto error;
150
151         if (!entry->data)
152                 entry->data = part;
153         else {
154                 entry->data = FN(PART,add)(entry->data, FN(PART,copy)(part));
155                 if (!entry->data)
156                         goto error;
157                 FN(PART,free)(part);
158                 if (FN(PART,is_zero)(entry->data)) {
159                         FN(PART,free)(entry->data);
160                         isl_hash_table_remove(u->dim->ctx, &u->table, entry);
161                 }
162         }
163
164         return u;
165 error:
166         FN(PART,free)(part);
167         FN(UNION,free)(u);
168         return NULL;
169 }
170
171 static int add_part(__isl_take PART *part, void *user)
172 {
173         UNION **u = (UNION **)user;
174
175         *u = FN(FN(UNION,add),PARTS)(*u, part);
176
177         return 0;
178 }
179
180 __isl_give UNION *FN(UNION,dup)(__isl_keep UNION *u)
181 {
182         UNION *dup;
183
184         if (!u)
185                 return NULL;
186
187 #ifdef HAS_TYPE
188         dup = FN(UNION,zero)(isl_dim_copy(u->dim), u->type);
189 #else
190         dup = FN(UNION,zero)(isl_dim_copy(u->dim));
191 #endif
192         if (FN(FN(UNION,foreach),PARTS)(u, &add_part, &dup) < 0)
193                 goto error;
194         return dup;
195 error:
196         FN(UNION,free)(dup);
197         return NULL;
198 }
199
200 __isl_give UNION *FN(UNION,cow)(__isl_take UNION *u)
201 {
202         if (!u)
203                 return NULL;
204
205         if (u->ref == 1)
206                 return u;
207         u->ref--;
208         return FN(UNION,dup)(u);
209 }
210
211 static int free_u_entry(void **entry, void *user)
212 {
213         PART *part = *entry;
214         FN(PART,free)(part);
215         return 0;
216 }
217
218 void FN(UNION,free)(__isl_take UNION *u)
219 {
220         if (!u)
221                 return;
222
223         if (--u->ref > 0)
224                 return;
225
226         isl_hash_table_foreach(u->dim->ctx, &u->table, &free_u_entry, NULL);
227         isl_hash_table_clear(&u->table);
228         isl_dim_free(u->dim);
229         free(u);
230 }
231
232 __isl_give UNION *FN(UNION,add)(__isl_take UNION *u1, __isl_take UNION *u2)
233 {
234         u1 = FN(UNION,cow)(u1);
235
236         if (!u1 || !u2)
237                 goto error;
238
239         if (FN(FN(UNION,foreach),PARTS)(u2, &add_part, &u1) < 0)
240                 goto error;
241
242         FN(UNION,free)(u2);
243
244         return u1;
245 error:
246         FN(UNION,free)(u1);
247         FN(UNION,free)(u2);
248         return NULL;
249 }
250
251 __isl_give UNION *FN(FN(UNION,from),PARTS)(__isl_take PART *part)
252 {
253         isl_dim *dim;
254         UNION *u;
255
256         if (!part)
257                 return NULL;
258
259         dim = FN(PART,get_dim)(part);
260         dim = isl_dim_drop(dim, isl_dim_in, 0, isl_dim_size(dim, isl_dim_in));
261         dim = isl_dim_drop(dim, isl_dim_out, 0, isl_dim_size(dim, isl_dim_out));
262 #ifdef HAS_TYPE
263         u = FN(UNION,zero)(dim, part->type);
264 #else
265         u = FN(UNION,zero)(dim);
266 #endif
267         u = FN(FN(UNION,add),PARTS)(u, part);
268
269         return u;
270 }
271
272 S(UNION,match_bin_data) {
273         UNION *u2;
274         UNION *res;
275 };
276
277 static __isl_give UNION *match_bin_op(__isl_take UNION *u1,
278         __isl_take UNION *u2, int (*fn)(void **, void *))
279 {
280         S(UNION,match_bin_data) data = { u2, NULL };
281
282         if (!u1 || !u2)
283                 goto error;
284
285 #ifdef HAS_TYPE
286         data.res = FN(UNION,alloc)(isl_dim_copy(u1->dim), u1->type, u1->table.n);
287 #else
288         data.res = FN(UNION,alloc)(isl_dim_copy(u1->dim), u1->table.n);
289 #endif
290         if (isl_hash_table_foreach(u1->dim->ctx, &u1->table, fn, &data) < 0)
291                 goto error;
292
293         FN(UNION,free)(u1);
294         FN(UNION,free)(u2);
295         return data.res;
296 error:
297         FN(UNION,free)(u1);
298         FN(UNION,free)(u2);
299         FN(UNION,free)(data.res);
300         return NULL;
301 }
302
303 S(UNION,match_set_data) {
304         isl_union_set *uset;
305         UNION *res;
306         __isl_give PW *(*fn)(__isl_take PW*, __isl_take isl_set*);
307 };
308
309 static int set_has_dim(const void *entry, const void *val)
310 {
311         isl_set *set = (isl_set *)entry;
312         isl_dim *dim = (isl_dim *)val;
313
314         return isl_dim_equal(set->dim, dim);
315 }
316
317 static int match_set_entry(void **entry, void *user)
318 {
319         S(UNION,match_set_data) *data = user;
320         uint32_t hash;
321         struct isl_hash_table_entry *entry2;
322         isl_dim *dim;
323         PW *pw = *entry;
324         int empty;
325
326         hash = isl_dim_get_hash(pw->dim);
327         entry2 = isl_hash_table_find(data->uset->dim->ctx, &data->uset->table,
328                                      hash, &set_has_dim, pw->dim, 0);
329         if (!entry2)
330                 return 0;
331
332         pw = FN(PW,copy)(pw);
333         pw = data->fn(pw, isl_set_copy(entry2->data));
334
335         empty = FN(PW,is_zero)(pw);
336         if (empty < 0) {
337                 FN(PW,free)(pw);
338                 return -1;
339         }
340         if (empty) {
341                 FN(PW,free)(pw);
342                 return 0;
343         }
344
345         data->res = FN(FN(UNION,add),PARTS)(data->res, pw);
346
347         return 0;
348 }
349
350 static __isl_give UNION *match_set_op(__isl_take UNION *u,
351         __isl_take isl_union_set *uset,
352         __isl_give PW *(*fn)(__isl_take PW*, __isl_take isl_set*))
353 {
354         S(UNION,match_set_data) data = { uset, NULL, fn };
355
356         if (!u || !uset)
357                 goto error;
358
359 #ifdef HAS_TYPE
360         data.res = FN(UNION,alloc)(isl_dim_copy(u->dim), u->type, u->table.n);
361 #else
362         data.res = FN(UNION,alloc)(isl_dim_copy(u->dim), u->table.n);
363 #endif
364         if (isl_hash_table_foreach(u->dim->ctx, &u->table,
365                                    &match_set_entry, &data) < 0)
366                 goto error;
367
368         FN(UNION,free)(u);
369         isl_union_set_free(uset);
370         return data.res;
371 error:
372         FN(UNION,free)(u);
373         isl_union_set_free(uset);
374         FN(UNION,free)(data.res);
375         return NULL;
376 }
377
378 __isl_give UNION *FN(UNION,intersect_domain)(__isl_take UNION *u,
379         __isl_take isl_union_set *uset)
380 {
381         return match_set_op(u, uset, &FN(PW,intersect_domain));
382 }
383
384 __isl_give UNION *FN(UNION,gist)(__isl_take UNION *u,
385         __isl_take isl_union_set *uset)
386 {
387         return match_set_op(u, uset, &FN(PW,gist));
388 }
389
390 __isl_give isl_qpolynomial *FN(UNION,eval)(__isl_take UNION *u,
391         __isl_take isl_point *pnt)
392 {
393         uint32_t hash;
394         struct isl_hash_table_entry *entry;
395         isl_qpolynomial *qp;
396
397         if (!u || !pnt)
398                 goto error;
399
400         hash = isl_dim_get_hash(pnt->dim);
401         entry = isl_hash_table_find(u->dim->ctx, &u->table,
402                                     hash, &has_dim, pnt->dim, 0);
403         if (!entry) {
404                 qp = isl_qpolynomial_zero(isl_dim_copy(pnt->dim));
405                 isl_point_free(pnt);
406         } else {
407                 qp = FN(PART,eval)(FN(PART,copy)(entry->data), pnt);
408         }
409         FN(UNION,free)(u);
410         return qp;
411 error:
412         FN(UNION,free)(u);
413         isl_point_free(pnt);
414         return NULL;
415 }
416
417 static int coalesce_entry(void **entry, void *user)
418 {
419         PW **pw = (PW **)entry;
420
421         *pw = FN(PW,coalesce)(*pw);
422         if (!*pw)
423                 return -1;
424
425         return 0;
426 }
427
428 __isl_give UNION *FN(UNION,coalesce)(__isl_take UNION *u)
429 {
430         if (!u)
431                 return NULL;
432
433         if (isl_hash_table_foreach(u->dim->ctx, &u->table,
434                                    &coalesce_entry, NULL) < 0)
435                 goto error;
436
437         return u;
438 error:
439         FN(UNION,free)(u);
440         return NULL;
441 }
442
443 static int domain(__isl_take PART *part, void *user)
444 {
445         isl_union_set **uset = (isl_union_set **)user;
446
447         *uset = isl_union_set_add_set(*uset, FN(PART,domain)(part));
448
449         return 0;
450 }
451
452 __isl_give isl_union_set *FN(UNION,domain)(__isl_take UNION *u)
453 {
454         isl_union_set *uset;
455
456         uset = isl_union_set_empty(FN(UNION,get_dim)(u));
457         if (FN(FN(UNION,foreach),PARTS)(u, &domain, &uset) < 0)
458                 goto error;
459
460         FN(UNION,free)(u);
461         
462         return uset;
463 error:
464         isl_union_set_free(uset);
465         FN(UNION,free)(u);
466         return NULL;
467 }