isl_map_gist: also perform gist in universe context
[platform/upstream/isl.git] / isl_union_map.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 #include <isl_ctx.h>
12 #include <isl_hash.h>
13 #include <isl_map.h>
14 #include <isl_set.h>
15 #include <isl_dim_private.h>
16 #include <isl_union_map_private.h>
17 #include <isl_union_set.h>
18
19 static __isl_give isl_union_map *isl_union_map_alloc(__isl_take isl_dim *dim,
20         int size)
21 {
22         isl_union_map *umap;
23
24         if (!dim)
25                 return NULL;
26
27         umap = isl_calloc_type(dim->ctx, isl_union_map);
28         if (!umap)
29                 return NULL;
30
31         umap->ref = 1;
32         umap->dim = dim;
33         if (isl_hash_table_init(dim->ctx, &umap->table, size) < 0)
34                 goto error;
35
36         return umap;
37 error:
38         isl_dim_free(dim);
39         isl_union_map_free(umap);
40         return NULL;
41 }
42
43 __isl_give isl_union_map *isl_union_map_empty(__isl_take isl_dim *dim)
44 {
45         return isl_union_map_alloc(dim, 16);
46 }
47
48 __isl_give isl_union_set *isl_union_set_empty(__isl_take isl_dim *dim)
49 {
50         return isl_union_map_empty(dim);
51 }
52
53 isl_ctx *isl_union_map_get_ctx(__isl_keep isl_union_map *umap)
54 {
55         return umap ? umap->dim->ctx : NULL;
56 }
57
58 __isl_give isl_dim *isl_union_map_get_dim(__isl_keep isl_union_map *umap)
59 {
60         if (!umap)
61                 return NULL;
62         return isl_dim_copy(umap->dim);
63 }
64
65 __isl_give isl_dim *isl_union_set_get_dim(__isl_keep isl_union_set *uset)
66 {
67         return isl_union_map_get_dim(uset);
68 }
69
70 static int free_umap_entry(void **entry, void *user)
71 {
72         isl_map *map = *entry;
73         isl_map_free(map);
74         return 0;
75 }
76
77 static int add_map(__isl_take isl_map *map, void *user)
78 {
79         isl_union_map **umap = (isl_union_map **)user;
80
81         *umap = isl_union_map_add_map(*umap, map);
82
83         return 0;
84 }
85
86 __isl_give isl_union_map *isl_union_map_dup(__isl_keep isl_union_map *umap)
87 {
88         isl_union_map *dup;
89
90         if (!umap)
91                 return NULL;
92
93         dup = isl_union_map_empty(isl_dim_copy(umap->dim));
94         if (isl_union_map_foreach_map(umap, &add_map, &dup) < 0)
95                 goto error;
96         return dup;
97 error:
98         isl_union_map_free(dup);
99         return NULL;
100 }
101
102 __isl_give isl_union_map *isl_union_map_cow(__isl_take isl_union_map *umap)
103 {
104         if (!umap)
105                 return NULL;
106
107         if (umap->ref == 1)
108                 return umap;
109         umap->ref--;
110         return isl_union_map_dup(umap);
111 }
112
113 __isl_give isl_union_map *isl_union_map_union(__isl_take isl_union_map *umap1,
114         __isl_take isl_union_map *umap2)
115 {
116         umap1 = isl_union_map_cow(umap1);
117
118         if (!umap1 || !umap2)
119                 goto error;
120
121         if (isl_union_map_foreach_map(umap2, &add_map, &umap1) < 0)
122                 goto error;
123
124         isl_union_map_free(umap2);
125
126         return umap1;
127 error:
128         isl_union_map_free(umap1);
129         isl_union_map_free(umap2);
130         return NULL;
131 }
132
133 __isl_give isl_union_set *isl_union_set_union(__isl_take isl_union_set *uset1,
134         __isl_take isl_union_set *uset2)
135 {
136         return isl_union_map_union(uset1, uset2);
137 }
138
139 __isl_give isl_union_map *isl_union_map_copy(__isl_keep isl_union_map *umap)
140 {
141         if (!umap)
142                 return NULL;
143
144         umap->ref++;
145         return umap;
146 }
147
148 __isl_give isl_union_set *isl_union_set_copy(__isl_keep isl_union_set *uset)
149 {
150         return isl_union_map_copy(uset);
151 }
152
153 void isl_union_map_free(__isl_take isl_union_map *umap)
154 {
155         if (!umap)
156                 return;
157
158         if (--umap->ref > 0)
159                 return;
160
161         isl_hash_table_foreach(umap->dim->ctx, &umap->table,
162                                &free_umap_entry, NULL);
163         isl_hash_table_clear(&umap->table);
164         isl_dim_free(umap->dim);
165         free(umap);
166 }
167
168 void isl_union_set_free(__isl_take isl_union_set *uset)
169 {
170         isl_union_map_free(uset);
171 }
172
173 static int has_dim(const void *entry, const void *val)
174 {
175         isl_map *map = (isl_map *)entry;
176         isl_dim *dim = (isl_dim *)val;
177
178         return isl_dim_equal(map->dim, dim);
179 }
180
181 __isl_give isl_union_map *isl_union_map_add_map(__isl_take isl_union_map *umap,
182         __isl_take isl_map *map)
183 {
184         uint32_t hash;
185         struct isl_hash_table_entry *entry;
186
187         if (isl_map_fast_is_empty(map)) {
188                 isl_map_free(map);
189                 return umap;
190         }
191
192         umap = isl_union_map_cow(umap);
193
194         if (!map || !umap)
195                 goto error;
196
197         isl_assert(map->ctx, isl_dim_match(map->dim, isl_dim_param, umap->dim,
198                                            isl_dim_param), goto error);
199
200         hash = isl_dim_get_hash(map->dim);
201         entry = isl_hash_table_find(umap->dim->ctx, &umap->table, hash,
202                                     &has_dim, map->dim, 1);
203         if (!entry)
204                 goto error;
205
206         if (!entry->data)
207                 entry->data = map;
208         else {
209                 entry->data = isl_map_union(entry->data, isl_map_copy(map));
210                 if (!entry->data)
211                         goto error;
212                 isl_map_free(map);
213         }
214
215         return umap;
216 error:
217         isl_map_free(map);
218         isl_union_map_free(umap);
219         return NULL;
220 }
221
222 __isl_give isl_union_set *isl_union_set_add_set(__isl_take isl_union_set *uset,
223         __isl_take isl_set *set)
224 {
225         return isl_union_map_add_map(uset, (isl_map *)set);
226 }
227
228 __isl_give isl_union_map *isl_union_map_from_map(__isl_take isl_map *map)
229 {
230         isl_dim *dim;
231         isl_union_map *umap;
232
233         if (!map)
234                 return NULL;
235
236         dim = isl_map_get_dim(map);
237         dim = isl_dim_drop(dim, isl_dim_in, 0, isl_dim_size(dim, isl_dim_in));
238         dim = isl_dim_drop(dim, isl_dim_out, 0, isl_dim_size(dim, isl_dim_out));
239         umap = isl_union_map_empty(dim);
240         umap = isl_union_map_add_map(umap, map);
241
242         return umap;
243 }
244
245 __isl_give isl_union_set *isl_union_set_from_set(__isl_take isl_set *set)
246 {
247         return isl_union_map_from_map((isl_map *)set);
248 }
249
250 struct isl_union_map_foreach_data
251 {
252         int (*fn)(__isl_take isl_map *map, void *user);
253         void *user;
254 };
255
256 static int call_on_copy(void **entry, void *user)
257 {
258         isl_map *map = *entry;
259         struct isl_union_map_foreach_data *data;
260         data = (struct isl_union_map_foreach_data *)user;
261
262         return data->fn(isl_map_copy(map), data->user);
263 }
264
265 int isl_union_map_foreach_map(__isl_keep isl_union_map *umap,
266         int (*fn)(__isl_take isl_map *map, void *user), void *user)
267 {
268         struct isl_union_map_foreach_data data = { fn, user };
269
270         if (!umap)
271                 return -1;
272
273         return isl_hash_table_foreach(umap->dim->ctx, &umap->table,
274                                       &call_on_copy, &data);
275 }
276
277 int isl_union_set_foreach_set(__isl_keep isl_union_set *uset,
278         int (*fn)(__isl_take isl_set *set, void *user), void *user)
279 {
280         return isl_union_map_foreach_map(uset,
281                 (int(*)(__isl_take isl_map *, void*))fn, user);
282 }
283
284 struct isl_union_set_foreach_point_data {
285         int (*fn)(__isl_take isl_point *pnt, void *user);
286         void *user;
287 };
288
289 static int foreach_point(__isl_take isl_set *set, void *user)
290 {
291         struct isl_union_set_foreach_point_data *data = user;
292         int r;
293
294         r = isl_set_foreach_point(set, data->fn, data->user);
295         isl_set_free(set);
296
297         return r;
298 }
299
300 int isl_union_set_foreach_point(__isl_keep isl_union_set *uset,
301         int (*fn)(__isl_take isl_point *pnt, void *user), void *user)
302 {
303         struct isl_union_set_foreach_point_data data = { fn, user };
304         return isl_union_set_foreach_set(uset, &foreach_point, &data);
305 }
306
307 struct isl_union_map_gen_bin_data {
308         isl_union_map *umap2;
309         isl_union_map *res;
310 };
311
312 static int subtract_entry(void **entry, void *user)
313 {
314         struct isl_union_map_gen_bin_data *data = user;
315         uint32_t hash;
316         struct isl_hash_table_entry *entry2;
317         isl_map *map = *entry;
318
319         hash = isl_dim_get_hash(map->dim);
320         entry2 = isl_hash_table_find(data->umap2->dim->ctx, &data->umap2->table,
321                                      hash, &has_dim, map->dim, 0);
322         map = isl_map_copy(map);
323         if (entry2) {
324                 int empty;
325                 map = isl_map_subtract(map, isl_map_copy(entry2->data));
326
327                 empty = isl_map_is_empty(map);
328                 if (empty < 0) {
329                         isl_map_free(map);
330                         return -1;
331                 }
332                 if (empty) {
333                         isl_map_free(map);
334                         return 0;
335                 }
336         }
337         data->res = isl_union_map_add_map(data->res, map);
338
339         return 0;
340 }
341
342 static __isl_give isl_union_map *gen_bin_op(__isl_take isl_union_map *umap1,
343         __isl_take isl_union_map *umap2, int (*fn)(void **, void *))
344 {
345         struct isl_union_map_gen_bin_data data = { umap2, NULL };
346
347         if (!umap1 || !umap2)
348                 goto error;
349
350         data.res = isl_union_map_alloc(isl_dim_copy(umap1->dim),
351                                        umap1->table.n);
352         if (isl_hash_table_foreach(umap1->dim->ctx, &umap1->table,
353                                    fn, &data) < 0)
354                 goto error;
355
356         isl_union_map_free(umap1);
357         isl_union_map_free(umap2);
358         return data.res;
359 error:
360         isl_union_map_free(umap1);
361         isl_union_map_free(umap2);
362         isl_union_map_free(data.res);
363         return NULL;
364 }
365
366 __isl_give isl_union_map *isl_union_map_subtract(
367         __isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2)
368 {
369         return gen_bin_op(umap1, umap2, &subtract_entry);
370 }
371
372 __isl_give isl_union_set *isl_union_set_subtract(
373         __isl_take isl_union_set *uset1, __isl_take isl_union_set *uset2)
374 {
375         return isl_union_map_subtract(uset1, uset2);
376 }
377
378 struct isl_union_map_match_bin_data {
379         isl_union_map *umap2;
380         isl_union_map *res;
381         __isl_give isl_map *(*fn)(__isl_take isl_map*, __isl_take isl_map*);
382 };
383
384 static int match_bin_entry(void **entry, void *user)
385 {
386         struct isl_union_map_match_bin_data *data = user;
387         uint32_t hash;
388         struct isl_hash_table_entry *entry2;
389         isl_map *map = *entry;
390         int empty;
391
392         hash = isl_dim_get_hash(map->dim);
393         entry2 = isl_hash_table_find(data->umap2->dim->ctx, &data->umap2->table,
394                                      hash, &has_dim, map->dim, 0);
395         if (!entry2)
396                 return 0;
397
398         map = isl_map_copy(map);
399         map = data->fn(map, isl_map_copy(entry2->data));
400
401         empty = isl_map_is_empty(map);
402         if (empty < 0) {
403                 isl_map_free(map);
404                 return -1;
405         }
406         if (empty) {
407                 isl_map_free(map);
408                 return 0;
409         }
410
411         data->res = isl_union_map_add_map(data->res, map);
412
413         return 0;
414 }
415
416 static __isl_give isl_union_map *match_bin_op(__isl_take isl_union_map *umap1,
417         __isl_take isl_union_map *umap2,
418         __isl_give isl_map *(*fn)(__isl_take isl_map*, __isl_take isl_map*))
419 {
420         struct isl_union_map_match_bin_data data = { umap2, NULL, fn };
421
422         if (!umap1 || !umap2)
423                 goto error;
424
425         data.res = isl_union_map_alloc(isl_dim_copy(umap1->dim),
426                                        umap1->table.n);
427         if (isl_hash_table_foreach(umap1->dim->ctx, &umap1->table,
428                                    &match_bin_entry, &data) < 0)
429                 goto error;
430
431         isl_union_map_free(umap1);
432         isl_union_map_free(umap2);
433         return data.res;
434 error:
435         isl_union_map_free(umap1);
436         isl_union_map_free(umap2);
437         isl_union_map_free(data.res);
438         return NULL;
439 }
440
441 __isl_give isl_union_map *isl_union_map_intersect(
442         __isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2)
443 {
444         return match_bin_op(umap1, umap2, &isl_map_intersect);
445 }
446
447 __isl_give isl_union_set *isl_union_set_intersect(
448         __isl_take isl_union_set *uset1, __isl_take isl_union_set *uset2)
449 {
450         return isl_union_map_intersect(uset1, uset2);
451 }
452
453 __isl_give isl_union_map *isl_union_map_gist(__isl_take isl_union_map *umap,
454         __isl_take isl_union_map *context)
455 {
456         return match_bin_op(umap, context, &isl_map_gist);
457 }
458
459 __isl_give isl_union_set *isl_union_set_gist(__isl_take isl_union_set *uset,
460         __isl_take isl_union_set *context)
461 {
462         return isl_union_map_gist(uset, context);
463 }
464
465 static int intersect_domain_entry(void **entry, void *user)
466 {
467         struct isl_union_map_gen_bin_data *data = user;
468         uint32_t hash;
469         struct isl_hash_table_entry *entry2;
470         isl_dim *dim;
471         isl_map *map = *entry;
472         int empty;
473
474         dim = isl_map_get_dim(map);
475         dim = isl_dim_domain(dim);
476         hash = isl_dim_get_hash(dim);
477         entry2 = isl_hash_table_find(data->umap2->dim->ctx, &data->umap2->table,
478                                      hash, &has_dim, dim, 0);
479         isl_dim_free(dim);
480         if (!entry2)
481                 return 0;
482
483         map = isl_map_copy(map);
484         map = isl_map_intersect_domain(map, isl_set_copy(entry2->data));
485
486         empty = isl_map_is_empty(map);
487         if (empty < 0) {
488                 isl_map_free(map);
489                 return -1;
490         }
491         if (empty) {
492                 isl_map_free(map);
493                 return 0;
494         }
495
496         data->res = isl_union_map_add_map(data->res, map);
497
498         return 0;
499 }
500
501 __isl_give isl_union_map *isl_union_map_intersect_domain(
502         __isl_take isl_union_map *umap, __isl_take isl_union_set *uset)
503 {
504         return gen_bin_op(umap, uset, &intersect_domain_entry);
505 }
506
507 struct isl_union_map_bin_data {
508         isl_union_map *umap2;
509         isl_union_map *res;
510         isl_map *map;
511         int (*fn)(void **entry, void *user);
512 };
513
514 static int apply_range_entry(void **entry, void *user)
515 {
516         struct isl_union_map_bin_data *data = user;
517         isl_map *map2 = *entry;
518         int empty;
519
520         if (!isl_dim_tuple_match(data->map->dim, isl_dim_out,
521                                  map2->dim, isl_dim_in))
522                 return 0;
523
524         map2 = isl_map_apply_range(isl_map_copy(data->map), isl_map_copy(map2));
525
526         empty = isl_map_is_empty(map2);
527         if (empty < 0) {
528                 isl_map_free(map2);
529                 return -1;
530         }
531         if (empty) {
532                 isl_map_free(map2);
533                 return 0;
534         }
535
536         data->res = isl_union_map_add_map(data->res, map2);
537
538         return 0;
539 }
540
541 static int bin_entry(void **entry, void *user)
542 {
543         struct isl_union_map_bin_data *data = user;
544         isl_map *map = *entry;
545
546         data->map = map;
547         if (isl_hash_table_foreach(data->umap2->dim->ctx, &data->umap2->table,
548                                    data->fn, data) < 0)
549                 return -1;
550
551         return 0;
552 }
553
554 static __isl_give isl_union_map *bin_op(__isl_take isl_union_map *umap1,
555         __isl_take isl_union_map *umap2, int (*fn)(void **entry, void *user))
556 {
557         struct isl_union_map_bin_data data = { umap2, NULL, NULL, fn };
558
559         if (!umap1 || !umap2)
560                 goto error;
561
562         data.res = isl_union_map_alloc(isl_dim_copy(umap1->dim),
563                                        umap1->table.n);
564         if (isl_hash_table_foreach(umap1->dim->ctx, &umap1->table,
565                                    &bin_entry, &data) < 0)
566                 goto error;
567
568         isl_union_map_free(umap1);
569         isl_union_map_free(umap2);
570         return data.res;
571 error:
572         isl_union_map_free(umap1);
573         isl_union_map_free(umap2);
574         isl_union_map_free(data.res);
575         return NULL;
576 }
577
578 __isl_give isl_union_map *isl_union_map_apply_range(
579         __isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2)
580 {
581         return bin_op(umap1, umap2, &apply_range_entry);
582 }
583
584 __isl_give isl_union_set *isl_union_set_apply(
585         __isl_take isl_union_set *uset, __isl_take isl_union_map *umap)
586 {
587         return isl_union_map_apply_range(uset, umap);
588 }
589
590 static int product_entry(void **entry, void *user)
591 {
592         struct isl_union_map_bin_data *data = user;
593         isl_map *map2 = *entry;
594
595         map2 = isl_map_product(isl_map_copy(data->map), isl_map_copy(map2));
596
597         data->res = isl_union_map_add_map(data->res, map2);
598
599         return 0;
600 }
601
602 __isl_give isl_union_map *isl_union_map_product(__isl_take isl_union_map *umap1,
603         __isl_take isl_union_map *umap2)
604 {
605         return bin_op(umap1, umap2, &product_entry);
606 }
607
608 __isl_give isl_union_set *isl_union_set_product(__isl_take isl_union_set *uset1,
609         __isl_take isl_union_set *uset2)
610 {
611         return isl_union_map_product(uset1, uset2);
612 }
613
614 __isl_give isl_union_map *isl_union_map_from_range(
615         __isl_take isl_union_set *uset)
616 {
617         return uset;
618 }
619
620 __isl_give isl_union_map *isl_union_map_from_domain(
621         __isl_take isl_union_set *uset)
622 {
623         return isl_union_map_reverse(isl_union_map_from_range(uset));
624 }
625
626 __isl_give isl_union_map *isl_union_map_from_domain_and_range(
627         __isl_take isl_union_set *domain, __isl_take isl_union_set *range)
628 {
629         return isl_union_map_apply_range(isl_union_map_from_domain(domain),
630                                          isl_union_map_from_range(range));
631 }
632
633 static __isl_give isl_union_map *un_op(__isl_take isl_union_map *umap,
634         int (*fn)(void **, void *), int cow)
635 {
636         if (cow)
637                 umap = isl_union_map_cow(umap);
638         if (!umap)
639                 return NULL;
640
641         if (isl_hash_table_foreach(umap->dim->ctx, &umap->table, fn, NULL) < 0)
642                 goto error;
643
644         return umap;
645 error:
646         isl_union_map_free(umap);
647         return NULL;
648 }
649
650 static int affine_entry(void **entry, void *user)
651 {
652         isl_map **map = (isl_map **)entry;
653
654         *map = isl_map_from_basic_map(isl_map_affine_hull(*map));
655
656         return *map ? 0 : -1;
657 }
658
659 __isl_give isl_union_map *isl_union_map_affine_hull(
660         __isl_take isl_union_map *umap)
661 {
662         return un_op(umap, &affine_entry, 1);
663 }
664
665 __isl_give isl_union_set *isl_union_set_affine_hull(
666         __isl_take isl_union_set *uset)
667 {
668         return isl_union_map_affine_hull(uset);
669 }
670
671 static int coalesce_entry(void **entry, void *user)
672 {
673         isl_map **map = (isl_map **)entry;
674
675         *map = isl_map_coalesce(*map);
676
677         return *map ? 0 : -1;
678 }
679
680 __isl_give isl_union_map *isl_union_map_coalesce(
681         __isl_take isl_union_map *umap)
682 {
683         return un_op(umap, &coalesce_entry, 0);
684 }
685
686 __isl_give isl_union_set *isl_union_set_coalesce(
687         __isl_take isl_union_set *uset)
688 {
689         return isl_union_map_coalesce(uset);
690 }
691
692 static int compute_divs_entry(void **entry, void *user)
693 {
694         isl_map **map = (isl_map **)entry;
695
696         *map = isl_map_compute_divs(*map);
697
698         return *map ? 0 : -1;
699 }
700
701 __isl_give isl_union_map *isl_union_map_compute_divs(
702         __isl_take isl_union_map *umap)
703 {
704         return un_op(umap, &compute_divs_entry, 0);
705 }
706
707 __isl_give isl_union_set *isl_union_set_compute_divs(
708         __isl_take isl_union_set *uset)
709 {
710         return isl_union_map_compute_divs(uset);
711 }
712
713 static int lexmin_entry(void **entry, void *user)
714 {
715         isl_map **map = (isl_map **)entry;
716
717         *map = isl_map_lexmin(*map);
718
719         return *map ? 0 : -1;
720 }
721
722 __isl_give isl_union_map *isl_union_map_lexmin(
723         __isl_take isl_union_map *umap)
724 {
725         return un_op(umap, &lexmin_entry, 1);
726 }
727
728 __isl_give isl_union_set *isl_union_set_lexmin(
729         __isl_take isl_union_set *uset)
730 {
731         return isl_union_map_lexmin(uset);
732 }
733
734 static int lexmax_entry(void **entry, void *user)
735 {
736         isl_map **map = (isl_map **)entry;
737
738         *map = isl_map_lexmax(*map);
739
740         return *map ? 0 : -1;
741 }
742
743 __isl_give isl_union_map *isl_union_map_lexmax(
744         __isl_take isl_union_map *umap)
745 {
746         return un_op(umap, &lexmax_entry, 1);
747 }
748
749 __isl_give isl_union_set *isl_union_set_lexmax(
750         __isl_take isl_union_set *uset)
751 {
752         return isl_union_map_lexmax(uset);
753 }
754
755 static __isl_give isl_union_set *cond_un_op(__isl_take isl_union_map *umap,
756         int (*fn)(void **, void *))
757 {
758         isl_union_set *res;
759
760         if (!umap)
761                 return NULL;
762
763         res = isl_union_map_alloc(isl_dim_copy(umap->dim), umap->table.n);
764         if (isl_hash_table_foreach(umap->dim->ctx, &umap->table, fn, &res) < 0)
765                 goto error;
766
767         isl_union_map_free(umap);
768         return res;
769 error:
770         isl_union_map_free(umap);
771         isl_union_set_free(res);
772         return NULL;
773 }
774
775 static int reverse_entry(void **entry, void *user)
776 {
777         isl_map *map = *entry;
778         isl_union_map **res = user;
779
780         *res = isl_union_map_add_map(*res, isl_map_reverse(isl_map_copy(map)));
781
782         return 0;
783 }
784
785 __isl_give isl_union_map *isl_union_map_reverse(__isl_take isl_union_map *umap)
786 {
787         return cond_un_op(umap, &reverse_entry);
788 }
789
790 static int domain_entry(void **entry, void *user)
791 {
792         isl_map *map = *entry;
793         isl_union_set **res = user;
794
795         *res = isl_union_set_add_set(*res, isl_map_domain(isl_map_copy(map)));
796
797         return 0;
798 }
799
800 __isl_give isl_union_set *isl_union_map_domain(__isl_take isl_union_map *umap)
801 {
802         return cond_un_op(umap, &domain_entry);
803 }
804
805 static int range_entry(void **entry, void *user)
806 {
807         isl_map *map = *entry;
808         isl_union_set **res = user;
809
810         *res = isl_union_set_add_set(*res, isl_map_range(isl_map_copy(map)));
811
812         return 0;
813 }
814
815 __isl_give isl_union_set *isl_union_map_range(__isl_take isl_union_map *umap)
816 {
817         return cond_un_op(umap, &range_entry);
818 }
819
820 static int deltas_entry(void **entry, void *user)
821 {
822         isl_map *map = *entry;
823         isl_union_set **res = user;
824
825         if (!isl_dim_tuple_match(map->dim, isl_dim_in, map->dim, isl_dim_out))
826                 return 0;
827
828         *res = isl_union_set_add_set(*res, isl_map_deltas(isl_map_copy(map)));
829
830         return 0;
831 }
832
833 __isl_give isl_union_set *isl_union_map_deltas(__isl_take isl_union_map *umap)
834 {
835         return cond_un_op(umap, &deltas_entry);
836 }
837
838 static int unwrap_entry(void **entry, void *user)
839 {
840         isl_set *set = *entry;
841         isl_union_set **res = user;
842
843         if (!isl_set_is_wrapping(set))
844                 return 0;
845
846         *res = isl_union_map_add_map(*res, isl_set_unwrap(isl_set_copy(set)));
847
848         return 0;
849 }
850
851 __isl_give isl_union_map *isl_union_set_unwrap(__isl_take isl_union_set *uset)
852 {
853         return cond_un_op(uset, &unwrap_entry);
854 }
855
856 static int wrap_entry(void **entry, void *user)
857 {
858         isl_map *map = *entry;
859         isl_union_set **res = user;
860
861         *res = isl_union_set_add_set(*res, isl_map_wrap(isl_map_copy(map)));
862
863         return 0;
864 }
865
866 __isl_give isl_union_set *isl_union_map_wrap(__isl_take isl_union_map *umap)
867 {
868         return cond_un_op(umap, &wrap_entry);
869 }
870
871 struct isl_union_map_is_subset_data {
872         isl_union_map *umap2;
873         int is_subset;
874 };
875
876 static int is_subset_entry(void **entry, void *user)
877 {
878         struct isl_union_map_is_subset_data *data = user;
879         uint32_t hash;
880         struct isl_hash_table_entry *entry2;
881         isl_map *map = *entry;
882
883         hash = isl_dim_get_hash(map->dim);
884         entry2 = isl_hash_table_find(data->umap2->dim->ctx, &data->umap2->table,
885                                      hash, &has_dim, map->dim, 0);
886         if (!entry2) {
887                 data->is_subset = 0;
888                 return -1;
889         }
890
891         data->is_subset = isl_map_is_subset(map, entry2->data);
892         if (data->is_subset < 0 || !data->is_subset)
893                 return -1;
894
895         return 0;
896 }
897
898 int isl_union_map_is_subset(__isl_keep isl_union_map *umap1,
899         __isl_keep isl_union_map *umap2)
900 {
901         struct isl_union_map_is_subset_data data = { umap2, 1 };
902
903         if (!umap1 || !umap2)
904                 return -1;
905
906         if (isl_hash_table_foreach(umap1->dim->ctx, &umap1->table,
907                                    &is_subset_entry, &data) < 0 &&
908             data.is_subset)
909                 return -1;
910
911         return data.is_subset;
912 }
913
914 int isl_union_map_is_equal(__isl_keep isl_union_map *umap1,
915         __isl_keep isl_union_map *umap2)
916 {
917         int is_subset;
918
919         if (!umap1 || !umap2)
920                 return -1;
921         is_subset = isl_union_map_is_subset(umap1, umap2);
922         if (is_subset != 1)
923                 return is_subset;
924         is_subset = isl_union_map_is_subset(umap2, umap1);
925         return is_subset;
926 }
927
928 int isl_union_map_is_strict_subset(__isl_keep isl_union_map *umap1,
929         __isl_keep isl_union_map *umap2)
930 {
931         int is_subset;
932
933         if (!umap1 || !umap2)
934                 return -1;
935         is_subset = isl_union_map_is_subset(umap1, umap2);
936         if (is_subset != 1)
937                 return is_subset;
938         is_subset = isl_union_map_is_subset(umap2, umap1);
939         if (is_subset == -1)
940                 return is_subset;
941         return !is_subset;
942 }
943
944 static int sample_entry(void **entry, void *user)
945 {
946         isl_basic_map **sample = (isl_basic_map **)user;
947         isl_map *map = *entry;
948
949         *sample = isl_map_sample(isl_map_copy(map));
950         if (!*sample)
951                 return -1;
952         if (!isl_basic_map_fast_is_empty(*sample))
953                 return -1;
954         return 0;
955 }
956
957 __isl_give isl_basic_map *isl_union_map_sample(__isl_take isl_union_map *umap)
958 {
959         isl_basic_map *sample = NULL;
960
961         if (!umap)
962                 return NULL;
963
964         if (isl_hash_table_foreach(umap->dim->ctx, &umap->table,
965                                    &sample_entry, &sample) < 0 &&
966             !sample)
967                 goto error;
968
969         isl_union_map_free(umap);
970
971         return sample;
972 error:
973         isl_union_map_free(umap);
974         return NULL;
975 }
976
977 __isl_give isl_basic_set *isl_union_set_sample(__isl_take isl_union_set *uset)
978 {
979         return (isl_basic_set *)isl_union_map_sample(uset);
980 }
981
982 static int empty_entry(void **entry, void *user)
983 {
984         int *empty = user;
985         isl_map *map = *entry;
986
987         if (isl_map_is_empty(map))
988                 return 0;
989
990         *empty = 0;
991
992         return -1;
993 }
994
995 __isl_give int isl_union_map_is_empty(__isl_keep isl_union_map *umap)
996 {
997         int empty = 1;
998
999         if (!umap)
1000                 return -1;
1001
1002         if (isl_hash_table_foreach(umap->dim->ctx, &umap->table,
1003                                    &empty_entry, &empty) < 0 && empty)
1004                 return -1;
1005
1006         return empty;
1007 }
1008
1009 int isl_union_set_is_empty(__isl_keep isl_union_set *uset)
1010 {
1011         return isl_union_map_is_empty(uset);
1012 }