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