isl_printer_print_pw_qpolynomial_fold: print dim as set instead of map
[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 int reverse_entry(void **entry, void *user)
634 {
635         isl_map **map = (isl_map **)entry;
636
637         *map = isl_map_reverse(*map);
638
639         return *map ? 0 : -1;
640 }
641
642 static __isl_give isl_union_map *un_op(__isl_take isl_union_map *umap,
643         int (*fn)(void **, void *), int cow)
644 {
645         if (cow)
646                 umap = isl_union_map_cow(umap);
647         if (!umap)
648                 return NULL;
649
650         if (isl_hash_table_foreach(umap->dim->ctx, &umap->table, fn, NULL) < 0)
651                 goto error;
652
653         return umap;
654 error:
655         isl_union_map_free(umap);
656         return NULL;
657 }
658
659 __isl_give isl_union_map *isl_union_map_reverse(__isl_take isl_union_map *umap)
660 {
661         return un_op(umap, &reverse_entry, 1);
662 }
663
664 static int affine_entry(void **entry, void *user)
665 {
666         isl_map **map = (isl_map **)entry;
667
668         *map = isl_map_from_basic_map(isl_map_affine_hull(*map));
669
670         return *map ? 0 : -1;
671 }
672
673 __isl_give isl_union_map *isl_union_map_affine_hull(
674         __isl_take isl_union_map *umap)
675 {
676         return un_op(umap, &affine_entry, 1);
677 }
678
679 __isl_give isl_union_set *isl_union_set_affine_hull(
680         __isl_take isl_union_set *uset)
681 {
682         return isl_union_map_affine_hull(uset);
683 }
684
685 static int coalesce_entry(void **entry, void *user)
686 {
687         isl_map **map = (isl_map **)entry;
688
689         *map = isl_map_coalesce(*map);
690
691         return *map ? 0 : -1;
692 }
693
694 __isl_give isl_union_map *isl_union_map_coalesce(
695         __isl_take isl_union_map *umap)
696 {
697         return un_op(umap, &coalesce_entry, 0);
698 }
699
700 __isl_give isl_union_set *isl_union_set_coalesce(
701         __isl_take isl_union_set *uset)
702 {
703         return isl_union_map_coalesce(uset);
704 }
705
706 static int compute_divs_entry(void **entry, void *user)
707 {
708         isl_map **map = (isl_map **)entry;
709
710         *map = isl_map_compute_divs(*map);
711
712         return *map ? 0 : -1;
713 }
714
715 __isl_give isl_union_map *isl_union_map_compute_divs(
716         __isl_take isl_union_map *umap)
717 {
718         return un_op(umap, &compute_divs_entry, 0);
719 }
720
721 __isl_give isl_union_set *isl_union_set_compute_divs(
722         __isl_take isl_union_set *uset)
723 {
724         return isl_union_map_compute_divs(uset);
725 }
726
727 static int lexmin_entry(void **entry, void *user)
728 {
729         isl_map **map = (isl_map **)entry;
730
731         *map = isl_map_lexmin(*map);
732
733         return *map ? 0 : -1;
734 }
735
736 __isl_give isl_union_map *isl_union_map_lexmin(
737         __isl_take isl_union_map *umap)
738 {
739         return un_op(umap, &lexmin_entry, 1);
740 }
741
742 __isl_give isl_union_set *isl_union_set_lexmin(
743         __isl_take isl_union_set *uset)
744 {
745         return isl_union_map_lexmin(uset);
746 }
747
748 static int lexmax_entry(void **entry, void *user)
749 {
750         isl_map **map = (isl_map **)entry;
751
752         *map = isl_map_lexmax(*map);
753
754         return *map ? 0 : -1;
755 }
756
757 __isl_give isl_union_map *isl_union_map_lexmax(
758         __isl_take isl_union_map *umap)
759 {
760         return un_op(umap, &lexmax_entry, 1);
761 }
762
763 __isl_give isl_union_set *isl_union_set_lexmax(
764         __isl_take isl_union_set *uset)
765 {
766         return isl_union_map_lexmax(uset);
767 }
768
769 static int domain_entry(void **entry, void *user)
770 {
771         *entry = isl_map_domain(*entry);
772
773         return *entry ? 0 : -1;
774 }
775
776 __isl_give isl_union_set *isl_union_map_domain(__isl_take isl_union_map *umap)
777 {
778         return un_op(umap, &domain_entry, 1);
779 }
780
781 static int range_entry(void **entry, void *user)
782 {
783         *entry = isl_map_range(*entry);
784
785         return *entry ? 0 : -1;
786 }
787
788 __isl_give isl_union_set *isl_union_map_range(__isl_take isl_union_map *umap)
789 {
790         return un_op(umap, &range_entry, 1);
791 }
792
793 static  int deltas_entry(void **entry, void *user)
794 {
795         isl_map *map = *entry;
796         isl_union_set **res = user;
797
798         if (!isl_dim_tuple_match(map->dim, isl_dim_in, map->dim, isl_dim_out))
799                 return 0;
800
801         *res = isl_union_set_add_set(*res, isl_map_deltas(isl_map_copy(map)));
802
803         return 0;
804 }
805
806 __isl_give isl_union_set *isl_union_map_deltas(__isl_take isl_union_map *umap)
807 {
808         isl_union_set *res;
809
810         if (!umap)
811                 return NULL;
812
813         res = isl_union_map_alloc(isl_dim_copy(umap->dim), umap->table.n);
814         if (isl_hash_table_foreach(umap->dim->ctx, &umap->table,
815                                    &deltas_entry, &res) < 0)
816                 goto error;
817
818         isl_union_map_free(umap);
819         return res;
820 error:
821         isl_union_map_free(umap);
822         isl_union_set_free(res);
823         return NULL;
824 }
825
826 struct isl_union_map_is_subset_data {
827         isl_union_map *umap2;
828         int is_subset;
829 };
830
831 static int is_subset_entry(void **entry, void *user)
832 {
833         struct isl_union_map_is_subset_data *data = user;
834         uint32_t hash;
835         struct isl_hash_table_entry *entry2;
836         isl_map *map = *entry;
837
838         hash = isl_dim_get_hash(map->dim);
839         entry2 = isl_hash_table_find(data->umap2->dim->ctx, &data->umap2->table,
840                                      hash, &has_dim, map->dim, 0);
841         if (!entry2) {
842                 data->is_subset = 0;
843                 return -1;
844         }
845
846         data->is_subset = isl_map_is_subset(map, entry2->data);
847         if (data->is_subset < 0 || !data->is_subset)
848                 return -1;
849
850         return 0;
851 }
852
853 int isl_union_map_is_subset(__isl_keep isl_union_map *umap1,
854         __isl_keep isl_union_map *umap2)
855 {
856         struct isl_union_map_is_subset_data data = { umap2, 1 };
857
858         if (!umap1 || !umap2)
859                 return -1;
860
861         if (isl_hash_table_foreach(umap1->dim->ctx, &umap1->table,
862                                    &is_subset_entry, &data) < 0 &&
863             data.is_subset)
864                 return -1;
865
866         return data.is_subset;
867 }
868
869 int isl_union_map_is_equal(__isl_keep isl_union_map *umap1,
870         __isl_keep isl_union_map *umap2)
871 {
872         int is_subset;
873
874         if (!umap1 || !umap2)
875                 return -1;
876         is_subset = isl_union_map_is_subset(umap1, umap2);
877         if (is_subset != 1)
878                 return is_subset;
879         is_subset = isl_union_map_is_subset(umap2, umap1);
880         return is_subset;
881 }
882
883 int isl_union_map_is_strict_subset(__isl_keep isl_union_map *umap1,
884         __isl_keep isl_union_map *umap2)
885 {
886         int is_subset;
887
888         if (!umap1 || !umap2)
889                 return -1;
890         is_subset = isl_union_map_is_subset(umap1, umap2);
891         if (is_subset != 1)
892                 return is_subset;
893         is_subset = isl_union_map_is_subset(umap2, umap1);
894         if (is_subset == -1)
895                 return is_subset;
896         return !is_subset;
897 }
898
899 static int sample_entry(void **entry, void *user)
900 {
901         isl_basic_map **sample = (isl_basic_map **)user;
902         isl_map *map = *entry;
903
904         *sample = isl_map_sample(isl_map_copy(map));
905         if (!*sample)
906                 return -1;
907         if (!isl_basic_map_fast_is_empty(*sample))
908                 return -1;
909         return 0;
910 }
911
912 __isl_give isl_basic_map *isl_union_map_sample(__isl_take isl_union_map *umap)
913 {
914         isl_basic_map *sample = NULL;
915
916         if (!umap)
917                 return NULL;
918
919         if (isl_hash_table_foreach(umap->dim->ctx, &umap->table,
920                                    &sample_entry, &sample) < 0 &&
921             !sample)
922                 goto error;
923
924         isl_union_map_free(umap);
925
926         return sample;
927 error:
928         isl_union_map_free(umap);
929         return NULL;
930 }
931
932 __isl_give isl_basic_set *isl_union_set_sample(__isl_take isl_union_set *uset)
933 {
934         return (isl_basic_set *)isl_union_map_sample(uset);
935 }
936
937 static int empty_entry(void **entry, void *user)
938 {
939         int *empty = user;
940         isl_map *map = *entry;
941
942         if (isl_map_is_empty(map))
943                 return 0;
944
945         *empty = 0;
946
947         return -1;
948 }
949
950 __isl_give int isl_union_map_is_empty(__isl_keep isl_union_map *umap)
951 {
952         int empty = 1;
953
954         if (!umap)
955                 return -1;
956
957         if (isl_hash_table_foreach(umap->dim->ctx, &umap->table,
958                                    &sample_entry, &empty) < 0 && empty)
959                 return -1;
960
961         return empty;
962 }
963
964 int isl_union_set_is_empty(__isl_keep isl_union_set *uset)
965 {
966         return isl_union_map_is_empty(uset);
967 }