isl_pw_qpolynomial_intersect_domain: simplify polynomials using equalities
[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 __isl_give isl_union_set *cond_un_op(__isl_take isl_union_map *umap,
794         int (*fn)(void **, void *))
795 {
796         isl_union_set *res;
797
798         if (!umap)
799                 return NULL;
800
801         res = isl_union_map_alloc(isl_dim_copy(umap->dim), umap->table.n);
802         if (isl_hash_table_foreach(umap->dim->ctx, &umap->table, fn, &res) < 0)
803                 goto error;
804
805         isl_union_map_free(umap);
806         return res;
807 error:
808         isl_union_map_free(umap);
809         isl_union_set_free(res);
810         return NULL;
811 }
812
813 static int deltas_entry(void **entry, void *user)
814 {
815         isl_map *map = *entry;
816         isl_union_set **res = user;
817
818         if (!isl_dim_tuple_match(map->dim, isl_dim_in, map->dim, isl_dim_out))
819                 return 0;
820
821         *res = isl_union_set_add_set(*res, isl_map_deltas(isl_map_copy(map)));
822
823         return 0;
824 }
825
826 __isl_give isl_union_set *isl_union_map_deltas(__isl_take isl_union_map *umap)
827 {
828         return cond_un_op(umap, &deltas_entry);
829 }
830
831 static int unwrap_entry(void **entry, void *user)
832 {
833         isl_set *set = *entry;
834         isl_union_set **res = user;
835
836         if (!isl_set_is_wrapping(set))
837                 return 0;
838
839         *res = isl_union_map_add_map(*res, isl_set_unwrap(isl_set_copy(set)));
840
841         return 0;
842 }
843
844 __isl_give isl_union_map *isl_union_set_unwrap(__isl_take isl_union_set *uset)
845 {
846         return cond_un_op(uset, &unwrap_entry);
847 }
848
849 static int wrap_entry(void **entry, void *user)
850 {
851         isl_map **map = (isl_map **)entry;
852
853         *map = (isl_map *)isl_map_wrap(*map);
854
855         return *map ? 0 : -1;
856 }
857
858 __isl_give isl_union_set *isl_union_map_wrap(__isl_take isl_union_map *umap)
859 {
860         return un_op(umap, &wrap_entry, 1);
861 }
862
863 struct isl_union_map_is_subset_data {
864         isl_union_map *umap2;
865         int is_subset;
866 };
867
868 static int is_subset_entry(void **entry, void *user)
869 {
870         struct isl_union_map_is_subset_data *data = user;
871         uint32_t hash;
872         struct isl_hash_table_entry *entry2;
873         isl_map *map = *entry;
874
875         hash = isl_dim_get_hash(map->dim);
876         entry2 = isl_hash_table_find(data->umap2->dim->ctx, &data->umap2->table,
877                                      hash, &has_dim, map->dim, 0);
878         if (!entry2) {
879                 data->is_subset = 0;
880                 return -1;
881         }
882
883         data->is_subset = isl_map_is_subset(map, entry2->data);
884         if (data->is_subset < 0 || !data->is_subset)
885                 return -1;
886
887         return 0;
888 }
889
890 int isl_union_map_is_subset(__isl_keep isl_union_map *umap1,
891         __isl_keep isl_union_map *umap2)
892 {
893         struct isl_union_map_is_subset_data data = { umap2, 1 };
894
895         if (!umap1 || !umap2)
896                 return -1;
897
898         if (isl_hash_table_foreach(umap1->dim->ctx, &umap1->table,
899                                    &is_subset_entry, &data) < 0 &&
900             data.is_subset)
901                 return -1;
902
903         return data.is_subset;
904 }
905
906 int isl_union_map_is_equal(__isl_keep isl_union_map *umap1,
907         __isl_keep isl_union_map *umap2)
908 {
909         int is_subset;
910
911         if (!umap1 || !umap2)
912                 return -1;
913         is_subset = isl_union_map_is_subset(umap1, umap2);
914         if (is_subset != 1)
915                 return is_subset;
916         is_subset = isl_union_map_is_subset(umap2, umap1);
917         return is_subset;
918 }
919
920 int isl_union_map_is_strict_subset(__isl_keep isl_union_map *umap1,
921         __isl_keep isl_union_map *umap2)
922 {
923         int is_subset;
924
925         if (!umap1 || !umap2)
926                 return -1;
927         is_subset = isl_union_map_is_subset(umap1, umap2);
928         if (is_subset != 1)
929                 return is_subset;
930         is_subset = isl_union_map_is_subset(umap2, umap1);
931         if (is_subset == -1)
932                 return is_subset;
933         return !is_subset;
934 }
935
936 static int sample_entry(void **entry, void *user)
937 {
938         isl_basic_map **sample = (isl_basic_map **)user;
939         isl_map *map = *entry;
940
941         *sample = isl_map_sample(isl_map_copy(map));
942         if (!*sample)
943                 return -1;
944         if (!isl_basic_map_fast_is_empty(*sample))
945                 return -1;
946         return 0;
947 }
948
949 __isl_give isl_basic_map *isl_union_map_sample(__isl_take isl_union_map *umap)
950 {
951         isl_basic_map *sample = NULL;
952
953         if (!umap)
954                 return NULL;
955
956         if (isl_hash_table_foreach(umap->dim->ctx, &umap->table,
957                                    &sample_entry, &sample) < 0 &&
958             !sample)
959                 goto error;
960
961         isl_union_map_free(umap);
962
963         return sample;
964 error:
965         isl_union_map_free(umap);
966         return NULL;
967 }
968
969 __isl_give isl_basic_set *isl_union_set_sample(__isl_take isl_union_set *uset)
970 {
971         return (isl_basic_set *)isl_union_map_sample(uset);
972 }
973
974 static int empty_entry(void **entry, void *user)
975 {
976         int *empty = user;
977         isl_map *map = *entry;
978
979         if (isl_map_is_empty(map))
980                 return 0;
981
982         *empty = 0;
983
984         return -1;
985 }
986
987 __isl_give int isl_union_map_is_empty(__isl_keep isl_union_map *umap)
988 {
989         int empty = 1;
990
991         if (!umap)
992                 return -1;
993
994         if (isl_hash_table_foreach(umap->dim->ctx, &umap->table,
995                                    &sample_entry, &empty) < 0 && empty)
996                 return -1;
997
998         return empty;
999 }
1000
1001 int isl_union_set_is_empty(__isl_keep isl_union_set *uset)
1002 {
1003         return isl_union_map_is_empty(uset);
1004 }