add isl_pw_*_plain_is_equal
[isl.git] / isl_union_map.c
blobf12fd97056d5dbb3027c2b127ffac5cbb1cb5ac3
1 /*
2 * Copyright 2010-2011 INRIA Saclay
4 * Use of this software is governed by the GNU LGPLv2.1 license
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 */
11 #define ISL_DIM_H
12 #include <isl_map_private.h>
13 #include <isl/ctx.h>
14 #include <isl/hash.h>
15 #include <isl/map.h>
16 #include <isl/set.h>
17 #include <isl_space_private.h>
18 #include <isl_union_map_private.h>
19 #include <isl/union_set.h>
21 static __isl_give isl_union_map *isl_union_map_alloc(__isl_take isl_space *dim,
22 int size)
24 isl_union_map *umap;
26 if (!dim)
27 return NULL;
29 umap = isl_calloc_type(dim->ctx, isl_union_map);
30 if (!umap)
31 return NULL;
33 umap->ref = 1;
34 umap->dim = dim;
35 if (isl_hash_table_init(dim->ctx, &umap->table, size) < 0)
36 goto error;
38 return umap;
39 error:
40 isl_space_free(dim);
41 isl_union_map_free(umap);
42 return NULL;
45 __isl_give isl_union_map *isl_union_map_empty(__isl_take isl_space *dim)
47 return isl_union_map_alloc(dim, 16);
50 __isl_give isl_union_set *isl_union_set_empty(__isl_take isl_space *dim)
52 return isl_union_map_empty(dim);
55 isl_ctx *isl_union_map_get_ctx(__isl_keep isl_union_map *umap)
57 return umap ? umap->dim->ctx : NULL;
60 isl_ctx *isl_union_set_get_ctx(__isl_keep isl_union_set *uset)
62 return uset ? uset->dim->ctx : NULL;
65 __isl_give isl_space *isl_union_map_get_space(__isl_keep isl_union_map *umap)
67 if (!umap)
68 return NULL;
69 return isl_space_copy(umap->dim);
72 __isl_give isl_space *isl_union_set_get_space(__isl_keep isl_union_set *uset)
74 return isl_union_map_get_space(uset);
77 static int free_umap_entry(void **entry, void *user)
79 isl_map *map = *entry;
80 isl_map_free(map);
81 return 0;
84 static int add_map(__isl_take isl_map *map, void *user)
86 isl_union_map **umap = (isl_union_map **)user;
88 *umap = isl_union_map_add_map(*umap, map);
90 return 0;
93 __isl_give isl_union_map *isl_union_map_dup(__isl_keep isl_union_map *umap)
95 isl_union_map *dup;
97 if (!umap)
98 return NULL;
100 dup = isl_union_map_empty(isl_space_copy(umap->dim));
101 if (isl_union_map_foreach_map(umap, &add_map, &dup) < 0)
102 goto error;
103 return dup;
104 error:
105 isl_union_map_free(dup);
106 return NULL;
109 __isl_give isl_union_map *isl_union_map_cow(__isl_take isl_union_map *umap)
111 if (!umap)
112 return NULL;
114 if (umap->ref == 1)
115 return umap;
116 umap->ref--;
117 return isl_union_map_dup(umap);
120 struct isl_union_align {
121 isl_reordering *exp;
122 isl_union_map *res;
125 static int align_entry(void **entry, void *user)
127 isl_map *map = *entry;
128 isl_reordering *exp;
129 struct isl_union_align *data = user;
131 exp = isl_reordering_extend_space(isl_reordering_copy(data->exp),
132 isl_map_get_space(map));
134 data->res = isl_union_map_add_map(data->res,
135 isl_map_realign(isl_map_copy(map), exp));
137 return 0;
140 /* Align the parameters of umap along those of model.
141 * The result has the parameters of model first, in the same order
142 * as they appear in model, followed by any remaining parameters of
143 * umap that do not appear in model.
145 __isl_give isl_union_map *isl_union_map_align_params(
146 __isl_take isl_union_map *umap, __isl_take isl_space *model)
148 struct isl_union_align data = { NULL, NULL };
150 if (!umap || !model)
151 goto error;
153 if (isl_space_match(umap->dim, isl_dim_param, model, isl_dim_param)) {
154 isl_space_free(model);
155 return umap;
158 model = isl_space_params(model);
159 data.exp = isl_parameter_alignment_reordering(umap->dim, model);
160 if (!data.exp)
161 goto error;
163 data.res = isl_union_map_alloc(isl_space_copy(data.exp->dim),
164 umap->table.n);
165 if (isl_hash_table_foreach(umap->dim->ctx, &umap->table,
166 &align_entry, &data) < 0)
167 goto error;
169 isl_reordering_free(data.exp);
170 isl_union_map_free(umap);
171 isl_space_free(model);
172 return data.res;
173 error:
174 isl_reordering_free(data.exp);
175 isl_union_map_free(umap);
176 isl_union_map_free(data.res);
177 isl_space_free(model);
178 return NULL;
181 __isl_give isl_union_set *isl_union_set_align_params(
182 __isl_take isl_union_set *uset, __isl_take isl_space *model)
184 return isl_union_map_align_params(uset, model);
187 __isl_give isl_union_map *isl_union_map_union(__isl_take isl_union_map *umap1,
188 __isl_take isl_union_map *umap2)
190 umap1 = isl_union_map_align_params(umap1, isl_union_map_get_space(umap2));
191 umap2 = isl_union_map_align_params(umap2, isl_union_map_get_space(umap1));
193 umap1 = isl_union_map_cow(umap1);
195 if (!umap1 || !umap2)
196 goto error;
198 if (isl_union_map_foreach_map(umap2, &add_map, &umap1) < 0)
199 goto error;
201 isl_union_map_free(umap2);
203 return umap1;
204 error:
205 isl_union_map_free(umap1);
206 isl_union_map_free(umap2);
207 return NULL;
210 __isl_give isl_union_set *isl_union_set_union(__isl_take isl_union_set *uset1,
211 __isl_take isl_union_set *uset2)
213 return isl_union_map_union(uset1, uset2);
216 __isl_give isl_union_map *isl_union_map_copy(__isl_keep isl_union_map *umap)
218 if (!umap)
219 return NULL;
221 umap->ref++;
222 return umap;
225 __isl_give isl_union_set *isl_union_set_copy(__isl_keep isl_union_set *uset)
227 return isl_union_map_copy(uset);
230 void *isl_union_map_free(__isl_take isl_union_map *umap)
232 if (!umap)
233 return NULL;
235 if (--umap->ref > 0)
236 return NULL;
238 isl_hash_table_foreach(umap->dim->ctx, &umap->table,
239 &free_umap_entry, NULL);
240 isl_hash_table_clear(&umap->table);
241 isl_space_free(umap->dim);
242 free(umap);
243 return NULL;
246 void *isl_union_set_free(__isl_take isl_union_set *uset)
248 return isl_union_map_free(uset);
251 static int has_dim(const void *entry, const void *val)
253 isl_map *map = (isl_map *)entry;
254 isl_space *dim = (isl_space *)val;
256 return isl_space_is_equal(map->dim, dim);
259 __isl_give isl_union_map *isl_union_map_add_map(__isl_take isl_union_map *umap,
260 __isl_take isl_map *map)
262 uint32_t hash;
263 struct isl_hash_table_entry *entry;
265 if (!map || !umap)
266 goto error;
268 if (isl_map_plain_is_empty(map)) {
269 isl_map_free(map);
270 return umap;
273 if (!isl_space_match(map->dim, isl_dim_param, umap->dim, isl_dim_param)) {
274 umap = isl_union_map_align_params(umap, isl_map_get_space(map));
275 map = isl_map_align_params(map, isl_union_map_get_space(umap));
278 umap = isl_union_map_cow(umap);
280 if (!map || !umap)
281 goto error;
283 hash = isl_space_get_hash(map->dim);
284 entry = isl_hash_table_find(umap->dim->ctx, &umap->table, hash,
285 &has_dim, map->dim, 1);
286 if (!entry)
287 goto error;
289 if (!entry->data)
290 entry->data = map;
291 else {
292 entry->data = isl_map_union(entry->data, isl_map_copy(map));
293 if (!entry->data)
294 goto error;
295 isl_map_free(map);
298 return umap;
299 error:
300 isl_map_free(map);
301 isl_union_map_free(umap);
302 return NULL;
305 __isl_give isl_union_set *isl_union_set_add_set(__isl_take isl_union_set *uset,
306 __isl_take isl_set *set)
308 return isl_union_map_add_map(uset, (isl_map *)set);
311 __isl_give isl_union_map *isl_union_map_from_map(__isl_take isl_map *map)
313 isl_space *dim;
314 isl_union_map *umap;
316 if (!map)
317 return NULL;
319 dim = isl_map_get_space(map);
320 dim = isl_space_params(dim);
321 umap = isl_union_map_empty(dim);
322 umap = isl_union_map_add_map(umap, map);
324 return umap;
327 __isl_give isl_union_set *isl_union_set_from_set(__isl_take isl_set *set)
329 return isl_union_map_from_map((isl_map *)set);
332 struct isl_union_map_foreach_data
334 int (*fn)(__isl_take isl_map *map, void *user);
335 void *user;
338 static int call_on_copy(void **entry, void *user)
340 isl_map *map = *entry;
341 struct isl_union_map_foreach_data *data;
342 data = (struct isl_union_map_foreach_data *)user;
344 return data->fn(isl_map_copy(map), data->user);
347 int isl_union_map_n_map(__isl_keep isl_union_map *umap)
349 return umap ? umap->table.n : 0;
352 int isl_union_set_n_set(__isl_keep isl_union_set *uset)
354 return uset ? uset->table.n : 0;
357 int isl_union_map_foreach_map(__isl_keep isl_union_map *umap,
358 int (*fn)(__isl_take isl_map *map, void *user), void *user)
360 struct isl_union_map_foreach_data data = { fn, user };
362 if (!umap)
363 return -1;
365 return isl_hash_table_foreach(umap->dim->ctx, &umap->table,
366 &call_on_copy, &data);
369 static int copy_map(void **entry, void *user)
371 isl_map *map = *entry;
372 isl_map **map_p = user;
374 *map_p = isl_map_copy(map);
376 return -1;
379 __isl_give isl_map *isl_map_from_union_map(__isl_take isl_union_map *umap)
381 isl_ctx *ctx;
382 isl_map *map = NULL;
384 if (!umap)
385 return NULL;
386 ctx = isl_union_map_get_ctx(umap);
387 if (umap->table.n != 1)
388 isl_die(ctx, isl_error_invalid,
389 "union map needs to contain elements in exactly "
390 "one space", return isl_union_map_free(umap));
392 isl_hash_table_foreach(ctx, &umap->table, &copy_map, &map);
394 isl_union_map_free(umap);
396 return map;
399 __isl_give isl_set *isl_set_from_union_set(__isl_take isl_union_set *uset)
401 return isl_map_from_union_map(uset);
404 __isl_give isl_map *isl_union_map_extract_map(__isl_keep isl_union_map *umap,
405 __isl_take isl_space *dim)
407 uint32_t hash;
408 struct isl_hash_table_entry *entry;
410 if (!umap || !dim)
411 goto error;
413 hash = isl_space_get_hash(dim);
414 entry = isl_hash_table_find(umap->dim->ctx, &umap->table, hash,
415 &has_dim, dim, 0);
416 if (!entry)
417 return isl_map_empty(dim);
418 isl_space_free(dim);
419 return isl_map_copy(entry->data);
420 error:
421 isl_space_free(dim);
422 return NULL;
425 __isl_give isl_set *isl_union_set_extract_set(__isl_keep isl_union_set *uset,
426 __isl_take isl_space *dim)
428 return (isl_set *)isl_union_map_extract_map(uset, dim);
431 /* Check if umap contains a map in the given space.
433 __isl_give int isl_union_map_contains(__isl_keep isl_union_map *umap,
434 __isl_keep isl_space *dim)
436 uint32_t hash;
437 struct isl_hash_table_entry *entry;
439 if (!umap || !dim)
440 return -1;
442 hash = isl_space_get_hash(dim);
443 entry = isl_hash_table_find(umap->dim->ctx, &umap->table, hash,
444 &has_dim, dim, 0);
445 return !!entry;
448 __isl_give int isl_union_set_contains(__isl_keep isl_union_set *uset,
449 __isl_keep isl_space *dim)
451 return isl_union_map_contains(uset, dim);
454 int isl_union_set_foreach_set(__isl_keep isl_union_set *uset,
455 int (*fn)(__isl_take isl_set *set, void *user), void *user)
457 return isl_union_map_foreach_map(uset,
458 (int(*)(__isl_take isl_map *, void*))fn, user);
461 struct isl_union_set_foreach_point_data {
462 int (*fn)(__isl_take isl_point *pnt, void *user);
463 void *user;
466 static int foreach_point(__isl_take isl_set *set, void *user)
468 struct isl_union_set_foreach_point_data *data = user;
469 int r;
471 r = isl_set_foreach_point(set, data->fn, data->user);
472 isl_set_free(set);
474 return r;
477 int isl_union_set_foreach_point(__isl_keep isl_union_set *uset,
478 int (*fn)(__isl_take isl_point *pnt, void *user), void *user)
480 struct isl_union_set_foreach_point_data data = { fn, user };
481 return isl_union_set_foreach_set(uset, &foreach_point, &data);
484 struct isl_union_map_gen_bin_data {
485 isl_union_map *umap2;
486 isl_union_map *res;
489 static int subtract_entry(void **entry, void *user)
491 struct isl_union_map_gen_bin_data *data = user;
492 uint32_t hash;
493 struct isl_hash_table_entry *entry2;
494 isl_map *map = *entry;
496 hash = isl_space_get_hash(map->dim);
497 entry2 = isl_hash_table_find(data->umap2->dim->ctx, &data->umap2->table,
498 hash, &has_dim, map->dim, 0);
499 map = isl_map_copy(map);
500 if (entry2) {
501 int empty;
502 map = isl_map_subtract(map, isl_map_copy(entry2->data));
504 empty = isl_map_is_empty(map);
505 if (empty < 0) {
506 isl_map_free(map);
507 return -1;
509 if (empty) {
510 isl_map_free(map);
511 return 0;
514 data->res = isl_union_map_add_map(data->res, map);
516 return 0;
519 static __isl_give isl_union_map *gen_bin_op(__isl_take isl_union_map *umap1,
520 __isl_take isl_union_map *umap2, int (*fn)(void **, void *))
522 struct isl_union_map_gen_bin_data data = { NULL, NULL };
524 umap1 = isl_union_map_align_params(umap1, isl_union_map_get_space(umap2));
525 umap2 = isl_union_map_align_params(umap2, isl_union_map_get_space(umap1));
527 if (!umap1 || !umap2)
528 goto error;
530 data.umap2 = umap2;
531 data.res = isl_union_map_alloc(isl_space_copy(umap1->dim),
532 umap1->table.n);
533 if (isl_hash_table_foreach(umap1->dim->ctx, &umap1->table,
534 fn, &data) < 0)
535 goto error;
537 isl_union_map_free(umap1);
538 isl_union_map_free(umap2);
539 return data.res;
540 error:
541 isl_union_map_free(umap1);
542 isl_union_map_free(umap2);
543 isl_union_map_free(data.res);
544 return NULL;
547 __isl_give isl_union_map *isl_union_map_subtract(
548 __isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2)
550 return gen_bin_op(umap1, umap2, &subtract_entry);
553 __isl_give isl_union_set *isl_union_set_subtract(
554 __isl_take isl_union_set *uset1, __isl_take isl_union_set *uset2)
556 return isl_union_map_subtract(uset1, uset2);
559 struct isl_union_map_match_bin_data {
560 isl_union_map *umap2;
561 isl_union_map *res;
562 __isl_give isl_map *(*fn)(__isl_take isl_map*, __isl_take isl_map*);
565 static int match_bin_entry(void **entry, void *user)
567 struct isl_union_map_match_bin_data *data = user;
568 uint32_t hash;
569 struct isl_hash_table_entry *entry2;
570 isl_map *map = *entry;
571 int empty;
573 hash = isl_space_get_hash(map->dim);
574 entry2 = isl_hash_table_find(data->umap2->dim->ctx, &data->umap2->table,
575 hash, &has_dim, map->dim, 0);
576 if (!entry2)
577 return 0;
579 map = isl_map_copy(map);
580 map = data->fn(map, isl_map_copy(entry2->data));
582 empty = isl_map_is_empty(map);
583 if (empty < 0) {
584 isl_map_free(map);
585 return -1;
587 if (empty) {
588 isl_map_free(map);
589 return 0;
592 data->res = isl_union_map_add_map(data->res, map);
594 return 0;
597 static __isl_give isl_union_map *match_bin_op(__isl_take isl_union_map *umap1,
598 __isl_take isl_union_map *umap2,
599 __isl_give isl_map *(*fn)(__isl_take isl_map*, __isl_take isl_map*))
601 struct isl_union_map_match_bin_data data = { NULL, NULL, fn };
603 umap1 = isl_union_map_align_params(umap1, isl_union_map_get_space(umap2));
604 umap2 = isl_union_map_align_params(umap2, isl_union_map_get_space(umap1));
606 if (!umap1 || !umap2)
607 goto error;
609 data.umap2 = umap2;
610 data.res = isl_union_map_alloc(isl_space_copy(umap1->dim),
611 umap1->table.n);
612 if (isl_hash_table_foreach(umap1->dim->ctx, &umap1->table,
613 &match_bin_entry, &data) < 0)
614 goto error;
616 isl_union_map_free(umap1);
617 isl_union_map_free(umap2);
618 return data.res;
619 error:
620 isl_union_map_free(umap1);
621 isl_union_map_free(umap2);
622 isl_union_map_free(data.res);
623 return NULL;
626 __isl_give isl_union_map *isl_union_map_intersect(
627 __isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2)
629 return match_bin_op(umap1, umap2, &isl_map_intersect);
632 __isl_give isl_union_set *isl_union_set_intersect(
633 __isl_take isl_union_set *uset1, __isl_take isl_union_set *uset2)
635 return isl_union_map_intersect(uset1, uset2);
638 __isl_give isl_union_map *isl_union_map_gist(__isl_take isl_union_map *umap,
639 __isl_take isl_union_map *context)
641 return match_bin_op(umap, context, &isl_map_gist);
644 __isl_give isl_union_set *isl_union_set_gist(__isl_take isl_union_set *uset,
645 __isl_take isl_union_set *context)
647 return isl_union_map_gist(uset, context);
650 static __isl_give isl_map *lex_le_set(__isl_take isl_map *set1,
651 __isl_take isl_map *set2)
653 return isl_set_lex_le_set((isl_set *)set1, (isl_set *)set2);
656 static __isl_give isl_map *lex_lt_set(__isl_take isl_map *set1,
657 __isl_take isl_map *set2)
659 return isl_set_lex_lt_set((isl_set *)set1, (isl_set *)set2);
662 __isl_give isl_union_map *isl_union_set_lex_lt_union_set(
663 __isl_take isl_union_set *uset1, __isl_take isl_union_set *uset2)
665 return match_bin_op(uset1, uset2, &lex_lt_set);
668 __isl_give isl_union_map *isl_union_set_lex_le_union_set(
669 __isl_take isl_union_set *uset1, __isl_take isl_union_set *uset2)
671 return match_bin_op(uset1, uset2, &lex_le_set);
674 __isl_give isl_union_map *isl_union_set_lex_gt_union_set(
675 __isl_take isl_union_set *uset1, __isl_take isl_union_set *uset2)
677 return isl_union_map_reverse(isl_union_set_lex_lt_union_set(uset2, uset1));
680 __isl_give isl_union_map *isl_union_set_lex_ge_union_set(
681 __isl_take isl_union_set *uset1, __isl_take isl_union_set *uset2)
683 return isl_union_map_reverse(isl_union_set_lex_le_union_set(uset2, uset1));
686 __isl_give isl_union_map *isl_union_map_lex_gt_union_map(
687 __isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2)
689 return isl_union_map_reverse(isl_union_map_lex_lt_union_map(umap2, umap1));
692 __isl_give isl_union_map *isl_union_map_lex_ge_union_map(
693 __isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2)
695 return isl_union_map_reverse(isl_union_map_lex_le_union_map(umap2, umap1));
698 static int intersect_domain_entry(void **entry, void *user)
700 struct isl_union_map_gen_bin_data *data = user;
701 uint32_t hash;
702 struct isl_hash_table_entry *entry2;
703 isl_space *dim;
704 isl_map *map = *entry;
705 int empty;
707 dim = isl_map_get_space(map);
708 dim = isl_space_domain(dim);
709 hash = isl_space_get_hash(dim);
710 entry2 = isl_hash_table_find(data->umap2->dim->ctx, &data->umap2->table,
711 hash, &has_dim, dim, 0);
712 isl_space_free(dim);
713 if (!entry2)
714 return 0;
716 map = isl_map_copy(map);
717 map = isl_map_intersect_domain(map, isl_set_copy(entry2->data));
719 empty = isl_map_is_empty(map);
720 if (empty < 0) {
721 isl_map_free(map);
722 return -1;
724 if (empty) {
725 isl_map_free(map);
726 return 0;
729 data->res = isl_union_map_add_map(data->res, map);
731 return 0;
734 __isl_give isl_union_map *isl_union_map_intersect_domain(
735 __isl_take isl_union_map *umap, __isl_take isl_union_set *uset)
737 return gen_bin_op(umap, uset, &intersect_domain_entry);
740 static int intersect_range_entry(void **entry, void *user)
742 struct isl_union_map_gen_bin_data *data = user;
743 uint32_t hash;
744 struct isl_hash_table_entry *entry2;
745 isl_space *dim;
746 isl_map *map = *entry;
747 int empty;
749 dim = isl_map_get_space(map);
750 dim = isl_space_range(dim);
751 hash = isl_space_get_hash(dim);
752 entry2 = isl_hash_table_find(data->umap2->dim->ctx, &data->umap2->table,
753 hash, &has_dim, dim, 0);
754 isl_space_free(dim);
755 if (!entry2)
756 return 0;
758 map = isl_map_copy(map);
759 map = isl_map_intersect_range(map, isl_set_copy(entry2->data));
761 empty = isl_map_is_empty(map);
762 if (empty < 0) {
763 isl_map_free(map);
764 return -1;
766 if (empty) {
767 isl_map_free(map);
768 return 0;
771 data->res = isl_union_map_add_map(data->res, map);
773 return 0;
776 __isl_give isl_union_map *isl_union_map_intersect_range(
777 __isl_take isl_union_map *umap, __isl_take isl_union_set *uset)
779 return gen_bin_op(umap, uset, &intersect_range_entry);
782 struct isl_union_map_bin_data {
783 isl_union_map *umap2;
784 isl_union_map *res;
785 isl_map *map;
786 int (*fn)(void **entry, void *user);
789 static int apply_range_entry(void **entry, void *user)
791 struct isl_union_map_bin_data *data = user;
792 isl_map *map2 = *entry;
793 int empty;
795 if (!isl_space_tuple_match(data->map->dim, isl_dim_out,
796 map2->dim, isl_dim_in))
797 return 0;
799 map2 = isl_map_apply_range(isl_map_copy(data->map), isl_map_copy(map2));
801 empty = isl_map_is_empty(map2);
802 if (empty < 0) {
803 isl_map_free(map2);
804 return -1;
806 if (empty) {
807 isl_map_free(map2);
808 return 0;
811 data->res = isl_union_map_add_map(data->res, map2);
813 return 0;
816 static int bin_entry(void **entry, void *user)
818 struct isl_union_map_bin_data *data = user;
819 isl_map *map = *entry;
821 data->map = map;
822 if (isl_hash_table_foreach(data->umap2->dim->ctx, &data->umap2->table,
823 data->fn, data) < 0)
824 return -1;
826 return 0;
829 static __isl_give isl_union_map *bin_op(__isl_take isl_union_map *umap1,
830 __isl_take isl_union_map *umap2, int (*fn)(void **entry, void *user))
832 struct isl_union_map_bin_data data = { NULL, NULL, NULL, fn };
834 umap1 = isl_union_map_align_params(umap1, isl_union_map_get_space(umap2));
835 umap2 = isl_union_map_align_params(umap2, isl_union_map_get_space(umap1));
837 if (!umap1 || !umap2)
838 goto error;
840 data.umap2 = umap2;
841 data.res = isl_union_map_alloc(isl_space_copy(umap1->dim),
842 umap1->table.n);
843 if (isl_hash_table_foreach(umap1->dim->ctx, &umap1->table,
844 &bin_entry, &data) < 0)
845 goto error;
847 isl_union_map_free(umap1);
848 isl_union_map_free(umap2);
849 return data.res;
850 error:
851 isl_union_map_free(umap1);
852 isl_union_map_free(umap2);
853 isl_union_map_free(data.res);
854 return NULL;
857 __isl_give isl_union_map *isl_union_map_apply_range(
858 __isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2)
860 return bin_op(umap1, umap2, &apply_range_entry);
863 __isl_give isl_union_map *isl_union_map_apply_domain(
864 __isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2)
866 umap1 = isl_union_map_reverse(umap1);
867 umap1 = isl_union_map_apply_range(umap1, umap2);
868 return isl_union_map_reverse(umap1);
871 __isl_give isl_union_set *isl_union_set_apply(
872 __isl_take isl_union_set *uset, __isl_take isl_union_map *umap)
874 return isl_union_map_apply_range(uset, umap);
877 static int map_lex_lt_entry(void **entry, void *user)
879 struct isl_union_map_bin_data *data = user;
880 isl_map *map2 = *entry;
882 if (!isl_space_tuple_match(data->map->dim, isl_dim_out,
883 map2->dim, isl_dim_out))
884 return 0;
886 map2 = isl_map_lex_lt_map(isl_map_copy(data->map), isl_map_copy(map2));
888 data->res = isl_union_map_add_map(data->res, map2);
890 return 0;
893 __isl_give isl_union_map *isl_union_map_lex_lt_union_map(
894 __isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2)
896 return bin_op(umap1, umap2, &map_lex_lt_entry);
899 static int map_lex_le_entry(void **entry, void *user)
901 struct isl_union_map_bin_data *data = user;
902 isl_map *map2 = *entry;
904 if (!isl_space_tuple_match(data->map->dim, isl_dim_out,
905 map2->dim, isl_dim_out))
906 return 0;
908 map2 = isl_map_lex_le_map(isl_map_copy(data->map), isl_map_copy(map2));
910 data->res = isl_union_map_add_map(data->res, map2);
912 return 0;
915 __isl_give isl_union_map *isl_union_map_lex_le_union_map(
916 __isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2)
918 return bin_op(umap1, umap2, &map_lex_le_entry);
921 static int product_entry(void **entry, void *user)
923 struct isl_union_map_bin_data *data = user;
924 isl_map *map2 = *entry;
926 map2 = isl_map_product(isl_map_copy(data->map), isl_map_copy(map2));
928 data->res = isl_union_map_add_map(data->res, map2);
930 return 0;
933 __isl_give isl_union_map *isl_union_map_product(__isl_take isl_union_map *umap1,
934 __isl_take isl_union_map *umap2)
936 return bin_op(umap1, umap2, &product_entry);
939 __isl_give isl_union_set *isl_union_set_product(__isl_take isl_union_set *uset1,
940 __isl_take isl_union_set *uset2)
942 return isl_union_map_product(uset1, uset2);
945 static int range_product_entry(void **entry, void *user)
947 struct isl_union_map_bin_data *data = user;
948 isl_map *map2 = *entry;
950 if (!isl_space_tuple_match(data->map->dim, isl_dim_in,
951 map2->dim, isl_dim_in))
952 return 0;
954 map2 = isl_map_range_product(isl_map_copy(data->map),
955 isl_map_copy(map2));
957 data->res = isl_union_map_add_map(data->res, map2);
959 return 0;
962 __isl_give isl_union_map *isl_union_map_range_product(
963 __isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2)
965 return bin_op(umap1, umap2, &range_product_entry);
968 static int flat_range_product_entry(void **entry, void *user)
970 struct isl_union_map_bin_data *data = user;
971 isl_map *map2 = *entry;
973 if (!isl_space_tuple_match(data->map->dim, isl_dim_in,
974 map2->dim, isl_dim_in))
975 return 0;
977 map2 = isl_map_flat_range_product(isl_map_copy(data->map),
978 isl_map_copy(map2));
980 data->res = isl_union_map_add_map(data->res, map2);
982 return 0;
985 __isl_give isl_union_map *isl_union_map_flat_range_product(
986 __isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2)
988 return bin_op(umap1, umap2, &flat_range_product_entry);
991 static __isl_give isl_union_set *cond_un_op(__isl_take isl_union_map *umap,
992 int (*fn)(void **, void *))
994 isl_union_set *res;
996 if (!umap)
997 return NULL;
999 res = isl_union_map_alloc(isl_space_copy(umap->dim), umap->table.n);
1000 if (isl_hash_table_foreach(umap->dim->ctx, &umap->table, fn, &res) < 0)
1001 goto error;
1003 isl_union_map_free(umap);
1004 return res;
1005 error:
1006 isl_union_map_free(umap);
1007 isl_union_set_free(res);
1008 return NULL;
1011 static int from_range_entry(void **entry, void *user)
1013 isl_map *set = *entry;
1014 isl_union_set **res = user;
1016 *res = isl_union_map_add_map(*res,
1017 isl_map_from_range(isl_set_copy(set)));
1019 return 0;
1022 __isl_give isl_union_map *isl_union_map_from_range(
1023 __isl_take isl_union_set *uset)
1025 return cond_un_op(uset, &from_range_entry);
1028 __isl_give isl_union_map *isl_union_map_from_domain(
1029 __isl_take isl_union_set *uset)
1031 return isl_union_map_reverse(isl_union_map_from_range(uset));
1034 __isl_give isl_union_map *isl_union_map_from_domain_and_range(
1035 __isl_take isl_union_set *domain, __isl_take isl_union_set *range)
1037 return isl_union_map_apply_range(isl_union_map_from_domain(domain),
1038 isl_union_map_from_range(range));
1041 static __isl_give isl_union_map *un_op(__isl_take isl_union_map *umap,
1042 int (*fn)(void **, void *))
1044 umap = isl_union_map_cow(umap);
1045 if (!umap)
1046 return NULL;
1048 if (isl_hash_table_foreach(umap->dim->ctx, &umap->table, fn, NULL) < 0)
1049 goto error;
1051 return umap;
1052 error:
1053 isl_union_map_free(umap);
1054 return NULL;
1057 static int affine_entry(void **entry, void *user)
1059 isl_map **map = (isl_map **)entry;
1061 *map = isl_map_from_basic_map(isl_map_affine_hull(*map));
1063 return *map ? 0 : -1;
1066 __isl_give isl_union_map *isl_union_map_affine_hull(
1067 __isl_take isl_union_map *umap)
1069 return un_op(umap, &affine_entry);
1072 __isl_give isl_union_set *isl_union_set_affine_hull(
1073 __isl_take isl_union_set *uset)
1075 return isl_union_map_affine_hull(uset);
1078 static int polyhedral_entry(void **entry, void *user)
1080 isl_map **map = (isl_map **)entry;
1082 *map = isl_map_from_basic_map(isl_map_polyhedral_hull(*map));
1084 return *map ? 0 : -1;
1087 __isl_give isl_union_map *isl_union_map_polyhedral_hull(
1088 __isl_take isl_union_map *umap)
1090 return un_op(umap, &polyhedral_entry);
1093 __isl_give isl_union_set *isl_union_set_polyhedral_hull(
1094 __isl_take isl_union_set *uset)
1096 return isl_union_map_polyhedral_hull(uset);
1099 static int simple_entry(void **entry, void *user)
1101 isl_map **map = (isl_map **)entry;
1103 *map = isl_map_from_basic_map(isl_map_simple_hull(*map));
1105 return *map ? 0 : -1;
1108 __isl_give isl_union_map *isl_union_map_simple_hull(
1109 __isl_take isl_union_map *umap)
1111 return un_op(umap, &simple_entry);
1114 __isl_give isl_union_set *isl_union_set_simple_hull(
1115 __isl_take isl_union_set *uset)
1117 return isl_union_map_simple_hull(uset);
1120 static int inplace_entry(void **entry, void *user)
1122 __isl_give isl_map *(*fn)(__isl_take isl_map *);
1123 isl_map **map = (isl_map **)entry;
1124 isl_map *copy;
1126 fn = *(__isl_give isl_map *(**)(__isl_take isl_map *)) user;
1127 copy = fn(isl_map_copy(*map));
1128 if (!copy)
1129 return -1;
1131 isl_map_free(*map);
1132 *map = copy;
1134 return 0;
1137 static __isl_give isl_union_map *inplace(__isl_take isl_union_map *umap,
1138 __isl_give isl_map *(*fn)(__isl_take isl_map *))
1140 if (!umap)
1141 return NULL;
1143 if (isl_hash_table_foreach(umap->dim->ctx, &umap->table,
1144 &inplace_entry, &fn) < 0)
1145 goto error;
1147 return umap;
1148 error:
1149 isl_union_map_free(umap);
1150 return NULL;
1153 __isl_give isl_union_map *isl_union_map_coalesce(
1154 __isl_take isl_union_map *umap)
1156 return inplace(umap, &isl_map_coalesce);
1159 __isl_give isl_union_set *isl_union_set_coalesce(
1160 __isl_take isl_union_set *uset)
1162 return isl_union_map_coalesce(uset);
1165 __isl_give isl_union_map *isl_union_map_detect_equalities(
1166 __isl_take isl_union_map *umap)
1168 return inplace(umap, &isl_map_detect_equalities);
1171 __isl_give isl_union_set *isl_union_set_detect_equalities(
1172 __isl_take isl_union_set *uset)
1174 return isl_union_map_detect_equalities(uset);
1177 __isl_give isl_union_map *isl_union_map_compute_divs(
1178 __isl_take isl_union_map *umap)
1180 return inplace(umap, &isl_map_compute_divs);
1183 __isl_give isl_union_set *isl_union_set_compute_divs(
1184 __isl_take isl_union_set *uset)
1186 return isl_union_map_compute_divs(uset);
1189 static int lexmin_entry(void **entry, void *user)
1191 isl_map **map = (isl_map **)entry;
1193 *map = isl_map_lexmin(*map);
1195 return *map ? 0 : -1;
1198 __isl_give isl_union_map *isl_union_map_lexmin(
1199 __isl_take isl_union_map *umap)
1201 return un_op(umap, &lexmin_entry);
1204 __isl_give isl_union_set *isl_union_set_lexmin(
1205 __isl_take isl_union_set *uset)
1207 return isl_union_map_lexmin(uset);
1210 static int lexmax_entry(void **entry, void *user)
1212 isl_map **map = (isl_map **)entry;
1214 *map = isl_map_lexmax(*map);
1216 return *map ? 0 : -1;
1219 __isl_give isl_union_map *isl_union_map_lexmax(
1220 __isl_take isl_union_map *umap)
1222 return un_op(umap, &lexmax_entry);
1225 __isl_give isl_union_set *isl_union_set_lexmax(
1226 __isl_take isl_union_set *uset)
1228 return isl_union_map_lexmax(uset);
1231 static int universe_entry(void **entry, void *user)
1233 isl_map *map = *entry;
1234 isl_union_map **res = user;
1236 map = isl_map_universe(isl_map_get_space(map));
1237 *res = isl_union_map_add_map(*res, map);
1239 return 0;
1242 __isl_give isl_union_map *isl_union_map_universe(__isl_take isl_union_map *umap)
1244 return cond_un_op(umap, &universe_entry);
1247 __isl_give isl_union_set *isl_union_set_universe(__isl_take isl_union_set *uset)
1249 return isl_union_map_universe(uset);
1252 static int reverse_entry(void **entry, void *user)
1254 isl_map *map = *entry;
1255 isl_union_map **res = user;
1257 *res = isl_union_map_add_map(*res, isl_map_reverse(isl_map_copy(map)));
1259 return 0;
1262 __isl_give isl_union_map *isl_union_map_reverse(__isl_take isl_union_map *umap)
1264 return cond_un_op(umap, &reverse_entry);
1267 static int domain_entry(void **entry, void *user)
1269 isl_map *map = *entry;
1270 isl_union_set **res = user;
1272 *res = isl_union_set_add_set(*res, isl_map_domain(isl_map_copy(map)));
1274 return 0;
1277 __isl_give isl_union_set *isl_union_map_domain(__isl_take isl_union_map *umap)
1279 return cond_un_op(umap, &domain_entry);
1282 static int range_entry(void **entry, void *user)
1284 isl_map *map = *entry;
1285 isl_union_set **res = user;
1287 *res = isl_union_set_add_set(*res, isl_map_range(isl_map_copy(map)));
1289 return 0;
1292 __isl_give isl_union_set *isl_union_map_range(__isl_take isl_union_map *umap)
1294 return cond_un_op(umap, &range_entry);
1297 static int domain_map_entry(void **entry, void *user)
1299 isl_map *map = *entry;
1300 isl_union_set **res = user;
1302 *res = isl_union_map_add_map(*res,
1303 isl_map_domain_map(isl_map_copy(map)));
1305 return 0;
1308 __isl_give isl_union_map *isl_union_map_domain_map(
1309 __isl_take isl_union_map *umap)
1311 return cond_un_op(umap, &domain_map_entry);
1314 static int range_map_entry(void **entry, void *user)
1316 isl_map *map = *entry;
1317 isl_union_set **res = user;
1319 *res = isl_union_map_add_map(*res,
1320 isl_map_range_map(isl_map_copy(map)));
1322 return 0;
1325 __isl_give isl_union_map *isl_union_map_range_map(
1326 __isl_take isl_union_map *umap)
1328 return cond_un_op(umap, &range_map_entry);
1331 static int deltas_entry(void **entry, void *user)
1333 isl_map *map = *entry;
1334 isl_union_set **res = user;
1336 if (!isl_space_tuple_match(map->dim, isl_dim_in, map->dim, isl_dim_out))
1337 return 0;
1339 *res = isl_union_set_add_set(*res, isl_map_deltas(isl_map_copy(map)));
1341 return 0;
1344 __isl_give isl_union_set *isl_union_map_deltas(__isl_take isl_union_map *umap)
1346 return cond_un_op(umap, &deltas_entry);
1349 static int deltas_map_entry(void **entry, void *user)
1351 isl_map *map = *entry;
1352 isl_union_map **res = user;
1354 if (!isl_space_tuple_match(map->dim, isl_dim_in, map->dim, isl_dim_out))
1355 return 0;
1357 *res = isl_union_map_add_map(*res,
1358 isl_map_deltas_map(isl_map_copy(map)));
1360 return 0;
1363 __isl_give isl_union_map *isl_union_map_deltas_map(
1364 __isl_take isl_union_map *umap)
1366 return cond_un_op(umap, &deltas_map_entry);
1369 static int identity_entry(void **entry, void *user)
1371 isl_set *set = *entry;
1372 isl_union_map **res = user;
1374 *res = isl_union_map_add_map(*res, isl_set_identity(isl_set_copy(set)));
1376 return 0;
1379 __isl_give isl_union_map *isl_union_set_identity(__isl_take isl_union_set *uset)
1381 return cond_un_op(uset, &identity_entry);
1384 static int unwrap_entry(void **entry, void *user)
1386 isl_set *set = *entry;
1387 isl_union_set **res = user;
1389 if (!isl_set_is_wrapping(set))
1390 return 0;
1392 *res = isl_union_map_add_map(*res, isl_set_unwrap(isl_set_copy(set)));
1394 return 0;
1397 __isl_give isl_union_map *isl_union_set_unwrap(__isl_take isl_union_set *uset)
1399 return cond_un_op(uset, &unwrap_entry);
1402 static int wrap_entry(void **entry, void *user)
1404 isl_map *map = *entry;
1405 isl_union_set **res = user;
1407 *res = isl_union_set_add_set(*res, isl_map_wrap(isl_map_copy(map)));
1409 return 0;
1412 __isl_give isl_union_set *isl_union_map_wrap(__isl_take isl_union_map *umap)
1414 return cond_un_op(umap, &wrap_entry);
1417 struct isl_union_map_is_subset_data {
1418 isl_union_map *umap2;
1419 int is_subset;
1422 static int is_subset_entry(void **entry, void *user)
1424 struct isl_union_map_is_subset_data *data = user;
1425 uint32_t hash;
1426 struct isl_hash_table_entry *entry2;
1427 isl_map *map = *entry;
1429 hash = isl_space_get_hash(map->dim);
1430 entry2 = isl_hash_table_find(data->umap2->dim->ctx, &data->umap2->table,
1431 hash, &has_dim, map->dim, 0);
1432 if (!entry2) {
1433 data->is_subset = 0;
1434 return -1;
1437 data->is_subset = isl_map_is_subset(map, entry2->data);
1438 if (data->is_subset < 0 || !data->is_subset)
1439 return -1;
1441 return 0;
1444 int isl_union_map_is_subset(__isl_keep isl_union_map *umap1,
1445 __isl_keep isl_union_map *umap2)
1447 struct isl_union_map_is_subset_data data = { NULL, 1 };
1449 umap1 = isl_union_map_copy(umap1);
1450 umap2 = isl_union_map_copy(umap2);
1451 umap1 = isl_union_map_align_params(umap1, isl_union_map_get_space(umap2));
1452 umap2 = isl_union_map_align_params(umap2, isl_union_map_get_space(umap1));
1454 if (!umap1 || !umap2)
1455 goto error;
1457 data.umap2 = umap2;
1458 if (isl_hash_table_foreach(umap1->dim->ctx, &umap1->table,
1459 &is_subset_entry, &data) < 0 &&
1460 data.is_subset)
1461 goto error;
1463 isl_union_map_free(umap1);
1464 isl_union_map_free(umap2);
1466 return data.is_subset;
1467 error:
1468 isl_union_map_free(umap1);
1469 isl_union_map_free(umap2);
1470 return -1;
1473 int isl_union_set_is_subset(__isl_keep isl_union_set *uset1,
1474 __isl_keep isl_union_set *uset2)
1476 return isl_union_map_is_subset(uset1, uset2);
1479 int isl_union_map_is_equal(__isl_keep isl_union_map *umap1,
1480 __isl_keep isl_union_map *umap2)
1482 int is_subset;
1484 if (!umap1 || !umap2)
1485 return -1;
1486 is_subset = isl_union_map_is_subset(umap1, umap2);
1487 if (is_subset != 1)
1488 return is_subset;
1489 is_subset = isl_union_map_is_subset(umap2, umap1);
1490 return is_subset;
1493 int isl_union_set_is_equal(__isl_keep isl_union_set *uset1,
1494 __isl_keep isl_union_set *uset2)
1496 return isl_union_map_is_equal(uset1, uset2);
1499 int isl_union_map_is_strict_subset(__isl_keep isl_union_map *umap1,
1500 __isl_keep isl_union_map *umap2)
1502 int is_subset;
1504 if (!umap1 || !umap2)
1505 return -1;
1506 is_subset = isl_union_map_is_subset(umap1, umap2);
1507 if (is_subset != 1)
1508 return is_subset;
1509 is_subset = isl_union_map_is_subset(umap2, umap1);
1510 if (is_subset == -1)
1511 return is_subset;
1512 return !is_subset;
1515 int isl_union_set_is_strict_subset(__isl_keep isl_union_set *uset1,
1516 __isl_keep isl_union_set *uset2)
1518 return isl_union_map_is_strict_subset(uset1, uset2);
1521 static int sample_entry(void **entry, void *user)
1523 isl_basic_map **sample = (isl_basic_map **)user;
1524 isl_map *map = *entry;
1526 *sample = isl_map_sample(isl_map_copy(map));
1527 if (!*sample)
1528 return -1;
1529 if (!isl_basic_map_plain_is_empty(*sample))
1530 return -1;
1531 return 0;
1534 __isl_give isl_basic_map *isl_union_map_sample(__isl_take isl_union_map *umap)
1536 isl_basic_map *sample = NULL;
1538 if (!umap)
1539 return NULL;
1541 if (isl_hash_table_foreach(umap->dim->ctx, &umap->table,
1542 &sample_entry, &sample) < 0 &&
1543 !sample)
1544 goto error;
1546 if (!sample)
1547 sample = isl_basic_map_empty(isl_union_map_get_space(umap));
1549 isl_union_map_free(umap);
1551 return sample;
1552 error:
1553 isl_union_map_free(umap);
1554 return NULL;
1557 __isl_give isl_basic_set *isl_union_set_sample(__isl_take isl_union_set *uset)
1559 return (isl_basic_set *)isl_union_map_sample(uset);
1562 struct isl_forall_data {
1563 int res;
1564 int (*fn)(__isl_keep isl_map *map);
1567 static int forall_entry(void **entry, void *user)
1569 struct isl_forall_data *data = user;
1570 isl_map *map = *entry;
1572 data->res = data->fn(map);
1573 if (data->res < 0)
1574 return -1;
1576 if (!data->res)
1577 return -1;
1579 return 0;
1582 static int union_map_forall(__isl_keep isl_union_map *umap,
1583 int (*fn)(__isl_keep isl_map *map))
1585 struct isl_forall_data data = { 1, fn };
1587 if (!umap)
1588 return -1;
1590 if (isl_hash_table_foreach(umap->dim->ctx, &umap->table,
1591 &forall_entry, &data) < 0 && data.res)
1592 return -1;
1594 return data.res;
1597 struct isl_forall_user_data {
1598 int res;
1599 int (*fn)(__isl_keep isl_map *map, void *user);
1600 void *user;
1603 static int forall_user_entry(void **entry, void *user)
1605 struct isl_forall_user_data *data = user;
1606 isl_map *map = *entry;
1608 data->res = data->fn(map, data->user);
1609 if (data->res < 0)
1610 return -1;
1612 if (!data->res)
1613 return -1;
1615 return 0;
1618 /* Check if fn(map, user) returns true for all maps "map" in umap.
1620 static int union_map_forall_user(__isl_keep isl_union_map *umap,
1621 int (*fn)(__isl_keep isl_map *map, void *user), void *user)
1623 struct isl_forall_user_data data = { 1, fn, user };
1625 if (!umap)
1626 return -1;
1628 if (isl_hash_table_foreach(umap->dim->ctx, &umap->table,
1629 &forall_user_entry, &data) < 0 && data.res)
1630 return -1;
1632 return data.res;
1635 int isl_union_map_is_empty(__isl_keep isl_union_map *umap)
1637 return union_map_forall(umap, &isl_map_is_empty);
1640 int isl_union_set_is_empty(__isl_keep isl_union_set *uset)
1642 return isl_union_map_is_empty(uset);
1645 static int is_subset_of_identity(__isl_keep isl_map *map)
1647 int is_subset;
1648 isl_space *dim;
1649 isl_map *id;
1651 if (!map)
1652 return -1;
1654 if (!isl_space_tuple_match(map->dim, isl_dim_in, map->dim, isl_dim_out))
1655 return 0;
1657 dim = isl_map_get_space(map);
1658 id = isl_map_identity(dim);
1660 is_subset = isl_map_is_subset(map, id);
1662 isl_map_free(id);
1664 return is_subset;
1667 /* Check if the given map is single-valued.
1668 * We simply compute
1670 * M \circ M^-1
1672 * and check if the result is a subset of the identity mapping.
1674 int isl_union_map_is_single_valued(__isl_keep isl_union_map *umap)
1676 isl_union_map *test;
1677 int sv;
1679 if (isl_union_map_n_map(umap) == 1) {
1680 isl_map *map;
1681 umap = isl_union_map_copy(umap);
1682 map = isl_map_from_union_map(umap);
1683 sv = isl_map_is_single_valued(map);
1684 isl_map_free(map);
1685 return sv;
1688 test = isl_union_map_reverse(isl_union_map_copy(umap));
1689 test = isl_union_map_apply_range(test, isl_union_map_copy(umap));
1691 sv = union_map_forall(test, &is_subset_of_identity);
1693 isl_union_map_free(test);
1695 return sv;
1698 int isl_union_map_is_injective(__isl_keep isl_union_map *umap)
1700 int in;
1702 umap = isl_union_map_copy(umap);
1703 umap = isl_union_map_reverse(umap);
1704 in = isl_union_map_is_single_valued(umap);
1705 isl_union_map_free(umap);
1707 return in;
1710 /* Represents a map that has a fixed value (v) for one of its
1711 * range dimensions.
1712 * The map in this structure is not reference counted, so it
1713 * is only valid while the isl_union_map from which it was
1714 * obtained is still alive.
1716 struct isl_fixed_map {
1717 isl_int v;
1718 isl_map *map;
1721 static struct isl_fixed_map *alloc_isl_fixed_map_array(isl_ctx *ctx,
1722 int n)
1724 int i;
1725 struct isl_fixed_map *v;
1727 v = isl_calloc_array(ctx, struct isl_fixed_map, n);
1728 if (!v)
1729 return NULL;
1730 for (i = 0; i < n; ++i)
1731 isl_int_init(v[i].v);
1732 return v;
1735 static void free_isl_fixed_map_array(struct isl_fixed_map *v, int n)
1737 int i;
1739 if (!v)
1740 return;
1741 for (i = 0; i < n; ++i)
1742 isl_int_clear(v[i].v);
1743 free(v);
1746 /* Compare the "v" field of two isl_fixed_map structs.
1748 static int qsort_fixed_map_cmp(const void *p1, const void *p2)
1750 const struct isl_fixed_map *e1 = (const struct isl_fixed_map *) p1;
1751 const struct isl_fixed_map *e2 = (const struct isl_fixed_map *) p2;
1753 return isl_int_cmp(e1->v, e2->v);
1756 /* Internal data structure used while checking whether all maps
1757 * in a union_map have a fixed value for a given output dimension.
1758 * v is the list of maps, with the fixed value for the dimension
1759 * n is the number of maps considered so far
1760 * pos is the output dimension under investigation
1762 struct isl_fixed_dim_data {
1763 struct isl_fixed_map *v;
1764 int n;
1765 int pos;
1768 static int fixed_at_pos(__isl_keep isl_map *map, void *user)
1770 struct isl_fixed_dim_data *data = user;
1772 data->v[data->n].map = map;
1773 return isl_map_plain_is_fixed(map, isl_dim_out, data->pos,
1774 &data->v[data->n++].v);
1777 static int plain_injective_on_range(__isl_take isl_union_map *umap,
1778 int first, int n_range);
1780 /* Given a list of the maps, with their fixed values at output dimension "pos",
1781 * check whether the ranges of the maps form an obvious partition.
1783 * We first sort the maps according to their fixed values.
1784 * If all maps have a different value, then we know the ranges form
1785 * a partition.
1786 * Otherwise, we collect the maps with the same fixed value and
1787 * check whether each such collection is obviously injective
1788 * based on later dimensions.
1790 static int separates(struct isl_fixed_map *v, int n,
1791 __isl_take isl_space *dim, int pos, int n_range)
1793 int i;
1795 if (!v)
1796 goto error;
1798 qsort(v, n, sizeof(*v), &qsort_fixed_map_cmp);
1800 for (i = 0; i + 1 < n; ++i) {
1801 int j, k;
1802 isl_union_map *part;
1803 int injective;
1805 for (j = i + 1; j < n; ++j)
1806 if (isl_int_ne(v[i].v, v[j].v))
1807 break;
1809 if (j == i + 1)
1810 continue;
1812 part = isl_union_map_alloc(isl_space_copy(dim), j - i);
1813 for (k = i; k < j; ++k)
1814 part = isl_union_map_add_map(part,
1815 isl_map_copy(v[k].map));
1817 injective = plain_injective_on_range(part, pos + 1, n_range);
1818 if (injective < 0)
1819 goto error;
1820 if (!injective)
1821 break;
1823 i = j - 1;
1826 isl_space_free(dim);
1827 free_isl_fixed_map_array(v, n);
1828 return i + 1 >= n;
1829 error:
1830 isl_space_free(dim);
1831 free_isl_fixed_map_array(v, n);
1832 return -1;
1835 /* Check whether the maps in umap have obviously distinct ranges.
1836 * In particular, check for an output dimension in the range
1837 * [first,n_range) for which all maps have a fixed value
1838 * and then check if these values, possibly along with fixed values
1839 * at later dimensions, entail distinct ranges.
1841 static int plain_injective_on_range(__isl_take isl_union_map *umap,
1842 int first, int n_range)
1844 isl_ctx *ctx;
1845 int n;
1846 struct isl_fixed_dim_data data = { NULL };
1848 ctx = isl_union_map_get_ctx(umap);
1850 if (!umap)
1851 goto error;
1853 n = isl_union_map_n_map(umap);
1854 if (n <= 1) {
1855 isl_union_map_free(umap);
1856 return 1;
1859 if (first >= n_range) {
1860 isl_union_map_free(umap);
1861 return 0;
1864 data.v = alloc_isl_fixed_map_array(ctx, n);
1865 if (!data.v)
1866 goto error;
1868 for (data.pos = first; data.pos < n_range; ++data.pos) {
1869 int fixed;
1870 int injective;
1871 isl_space *dim;
1873 data.n = 0;
1874 fixed = union_map_forall_user(umap, &fixed_at_pos, &data);
1875 if (fixed < 0)
1876 goto error;
1877 if (!fixed)
1878 continue;
1879 dim = isl_union_map_get_space(umap);
1880 injective = separates(data.v, n, dim, data.pos, n_range);
1881 isl_union_map_free(umap);
1882 return injective;
1885 free_isl_fixed_map_array(data.v, n);
1886 isl_union_map_free(umap);
1888 return 0;
1889 error:
1890 free_isl_fixed_map_array(data.v, n);
1891 isl_union_map_free(umap);
1892 return -1;
1895 /* Check whether the maps in umap that map to subsets of "ran"
1896 * have obviously distinct ranges.
1898 static int plain_injective_on_range_wrap(__isl_keep isl_set *ran, void *user)
1900 isl_union_map *umap = user;
1902 umap = isl_union_map_copy(umap);
1903 umap = isl_union_map_intersect_range(umap,
1904 isl_union_set_from_set(isl_set_copy(ran)));
1905 return plain_injective_on_range(umap, 0, isl_set_dim(ran, isl_dim_set));
1908 /* Check if the given union_map is obviously injective.
1910 * In particular, we first check if all individual maps are obviously
1911 * injective and then check if all the ranges of these maps are
1912 * obviously disjoint.
1914 int isl_union_map_plain_is_injective(__isl_keep isl_union_map *umap)
1916 int in;
1917 isl_union_map *univ;
1918 isl_union_set *ran;
1920 in = union_map_forall(umap, &isl_map_plain_is_injective);
1921 if (in < 0)
1922 return -1;
1923 if (!in)
1924 return 0;
1926 univ = isl_union_map_universe(isl_union_map_copy(umap));
1927 ran = isl_union_map_range(univ);
1929 in = union_map_forall_user(ran, &plain_injective_on_range_wrap, umap);
1931 isl_union_set_free(ran);
1933 return in;
1936 int isl_union_map_is_bijective(__isl_keep isl_union_map *umap)
1938 int sv;
1940 sv = isl_union_map_is_single_valued(umap);
1941 if (sv < 0 || !sv)
1942 return sv;
1944 return isl_union_map_is_injective(umap);
1947 static int zip_entry(void **entry, void *user)
1949 isl_map *map = *entry;
1950 isl_union_map **res = user;
1952 if (!isl_map_can_zip(map))
1953 return 0;
1955 *res = isl_union_map_add_map(*res, isl_map_zip(isl_map_copy(map)));
1957 return 0;
1960 __isl_give isl_union_map *isl_union_map_zip(__isl_take isl_union_map *umap)
1962 return cond_un_op(umap, &zip_entry);
1965 static int lift_entry(void **entry, void *user)
1967 isl_set *set = *entry;
1968 isl_union_set **res = user;
1970 *res = isl_union_set_add_set(*res, isl_set_lift(isl_set_copy(set)));
1972 return 0;
1975 __isl_give isl_union_set *isl_union_set_lift(__isl_take isl_union_set *uset)
1977 return cond_un_op(uset, &lift_entry);
1980 static int coefficients_entry(void **entry, void *user)
1982 isl_set *set = *entry;
1983 isl_union_set **res = user;
1985 set = isl_set_copy(set);
1986 set = isl_set_from_basic_set(isl_set_coefficients(set));
1987 *res = isl_union_set_add_set(*res, set);
1989 return 0;
1992 __isl_give isl_union_set *isl_union_set_coefficients(
1993 __isl_take isl_union_set *uset)
1995 isl_ctx *ctx;
1996 isl_space *dim;
1997 isl_union_set *res;
1999 if (!uset)
2000 return NULL;
2002 ctx = isl_union_set_get_ctx(uset);
2003 dim = isl_space_set_alloc(ctx, 0, 0);
2004 res = isl_union_map_alloc(dim, uset->table.n);
2005 if (isl_hash_table_foreach(uset->dim->ctx, &uset->table,
2006 &coefficients_entry, &res) < 0)
2007 goto error;
2009 isl_union_set_free(uset);
2010 return res;
2011 error:
2012 isl_union_set_free(uset);
2013 isl_union_set_free(res);
2014 return NULL;
2017 static int solutions_entry(void **entry, void *user)
2019 isl_set *set = *entry;
2020 isl_union_set **res = user;
2022 set = isl_set_copy(set);
2023 set = isl_set_from_basic_set(isl_set_solutions(set));
2024 if (!*res)
2025 *res = isl_union_set_from_set(set);
2026 else
2027 *res = isl_union_set_add_set(*res, set);
2029 if (!*res)
2030 return -1;
2032 return 0;
2035 __isl_give isl_union_set *isl_union_set_solutions(
2036 __isl_take isl_union_set *uset)
2038 isl_union_set *res = NULL;
2040 if (!uset)
2041 return NULL;
2043 if (uset->table.n == 0) {
2044 res = isl_union_set_empty(isl_union_set_get_space(uset));
2045 isl_union_set_free(uset);
2046 return res;
2049 if (isl_hash_table_foreach(uset->dim->ctx, &uset->table,
2050 &solutions_entry, &res) < 0)
2051 goto error;
2053 isl_union_set_free(uset);
2054 return res;
2055 error:
2056 isl_union_set_free(uset);
2057 isl_union_set_free(res);
2058 return NULL;