add isl_pw_qpolynomial_project_out
[isl.git] / isl_union_map.c
blobb54b193b7de6ec3d7ce441dd217c70be1bb7c6cb
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_drop_dims(model, isl_dim_in,
159 0, isl_space_dim(model, isl_dim_in));
160 model = isl_space_drop_dims(model, isl_dim_out,
161 0, isl_space_dim(model, isl_dim_out));
163 data.exp = isl_parameter_alignment_reordering(umap->dim, model);
164 if (!data.exp)
165 goto error;
167 data.res = isl_union_map_alloc(isl_space_copy(data.exp->dim),
168 umap->table.n);
169 if (isl_hash_table_foreach(umap->dim->ctx, &umap->table,
170 &align_entry, &data) < 0)
171 goto error;
173 isl_reordering_free(data.exp);
174 isl_union_map_free(umap);
175 isl_space_free(model);
176 return data.res;
177 error:
178 isl_reordering_free(data.exp);
179 isl_union_map_free(umap);
180 isl_union_map_free(data.res);
181 isl_space_free(model);
182 return NULL;
185 __isl_give isl_union_set *isl_union_set_align_params(
186 __isl_take isl_union_set *uset, __isl_take isl_space *model)
188 return isl_union_map_align_params(uset, model);
191 __isl_give isl_union_map *isl_union_map_union(__isl_take isl_union_map *umap1,
192 __isl_take isl_union_map *umap2)
194 umap1 = isl_union_map_align_params(umap1, isl_union_map_get_space(umap2));
195 umap2 = isl_union_map_align_params(umap2, isl_union_map_get_space(umap1));
197 umap1 = isl_union_map_cow(umap1);
199 if (!umap1 || !umap2)
200 goto error;
202 if (isl_union_map_foreach_map(umap2, &add_map, &umap1) < 0)
203 goto error;
205 isl_union_map_free(umap2);
207 return umap1;
208 error:
209 isl_union_map_free(umap1);
210 isl_union_map_free(umap2);
211 return NULL;
214 __isl_give isl_union_set *isl_union_set_union(__isl_take isl_union_set *uset1,
215 __isl_take isl_union_set *uset2)
217 return isl_union_map_union(uset1, uset2);
220 __isl_give isl_union_map *isl_union_map_copy(__isl_keep isl_union_map *umap)
222 if (!umap)
223 return NULL;
225 umap->ref++;
226 return umap;
229 __isl_give isl_union_set *isl_union_set_copy(__isl_keep isl_union_set *uset)
231 return isl_union_map_copy(uset);
234 void *isl_union_map_free(__isl_take isl_union_map *umap)
236 if (!umap)
237 return NULL;
239 if (--umap->ref > 0)
240 return NULL;
242 isl_hash_table_foreach(umap->dim->ctx, &umap->table,
243 &free_umap_entry, NULL);
244 isl_hash_table_clear(&umap->table);
245 isl_space_free(umap->dim);
246 free(umap);
247 return NULL;
250 void *isl_union_set_free(__isl_take isl_union_set *uset)
252 return isl_union_map_free(uset);
255 static int has_dim(const void *entry, const void *val)
257 isl_map *map = (isl_map *)entry;
258 isl_space *dim = (isl_space *)val;
260 return isl_space_is_equal(map->dim, dim);
263 __isl_give isl_union_map *isl_union_map_add_map(__isl_take isl_union_map *umap,
264 __isl_take isl_map *map)
266 uint32_t hash;
267 struct isl_hash_table_entry *entry;
269 if (!map || !umap)
270 goto error;
272 if (isl_map_plain_is_empty(map)) {
273 isl_map_free(map);
274 return umap;
277 if (!isl_space_match(map->dim, isl_dim_param, umap->dim, isl_dim_param)) {
278 umap = isl_union_map_align_params(umap, isl_map_get_space(map));
279 map = isl_map_align_params(map, isl_union_map_get_space(umap));
282 umap = isl_union_map_cow(umap);
284 if (!map || !umap)
285 goto error;
287 hash = isl_space_get_hash(map->dim);
288 entry = isl_hash_table_find(umap->dim->ctx, &umap->table, hash,
289 &has_dim, map->dim, 1);
290 if (!entry)
291 goto error;
293 if (!entry->data)
294 entry->data = map;
295 else {
296 entry->data = isl_map_union(entry->data, isl_map_copy(map));
297 if (!entry->data)
298 goto error;
299 isl_map_free(map);
302 return umap;
303 error:
304 isl_map_free(map);
305 isl_union_map_free(umap);
306 return NULL;
309 __isl_give isl_union_set *isl_union_set_add_set(__isl_take isl_union_set *uset,
310 __isl_take isl_set *set)
312 return isl_union_map_add_map(uset, (isl_map *)set);
315 __isl_give isl_union_map *isl_union_map_from_map(__isl_take isl_map *map)
317 isl_space *dim;
318 isl_union_map *umap;
320 if (!map)
321 return NULL;
323 dim = isl_map_get_space(map);
324 dim = isl_space_drop_dims(dim, isl_dim_in, 0, isl_space_dim(dim, isl_dim_in));
325 dim = isl_space_drop_dims(dim, isl_dim_out, 0, isl_space_dim(dim, isl_dim_out));
326 umap = isl_union_map_empty(dim);
327 umap = isl_union_map_add_map(umap, map);
329 return umap;
332 __isl_give isl_union_set *isl_union_set_from_set(__isl_take isl_set *set)
334 return isl_union_map_from_map((isl_map *)set);
337 struct isl_union_map_foreach_data
339 int (*fn)(__isl_take isl_map *map, void *user);
340 void *user;
343 static int call_on_copy(void **entry, void *user)
345 isl_map *map = *entry;
346 struct isl_union_map_foreach_data *data;
347 data = (struct isl_union_map_foreach_data *)user;
349 return data->fn(isl_map_copy(map), data->user);
352 int isl_union_map_n_map(__isl_keep isl_union_map *umap)
354 return umap ? umap->table.n : 0;
357 int isl_union_set_n_set(__isl_keep isl_union_set *uset)
359 return uset ? uset->table.n : 0;
362 int isl_union_map_foreach_map(__isl_keep isl_union_map *umap,
363 int (*fn)(__isl_take isl_map *map, void *user), void *user)
365 struct isl_union_map_foreach_data data = { fn, user };
367 if (!umap)
368 return -1;
370 return isl_hash_table_foreach(umap->dim->ctx, &umap->table,
371 &call_on_copy, &data);
374 static int copy_map(void **entry, void *user)
376 isl_map *map = *entry;
377 isl_map **map_p = user;
379 *map_p = isl_map_copy(map);
381 return -1;
384 __isl_give isl_map *isl_map_from_union_map(__isl_take isl_union_map *umap)
386 isl_ctx *ctx;
387 isl_map *map = NULL;
389 if (!umap)
390 return NULL;
391 ctx = isl_union_map_get_ctx(umap);
392 if (umap->table.n != 1)
393 isl_die(ctx, isl_error_invalid,
394 "union map needs to contain elements in exactly "
395 "one space", return isl_union_map_free(umap));
397 isl_hash_table_foreach(ctx, &umap->table, &copy_map, &map);
399 isl_union_map_free(umap);
401 return map;
404 __isl_give isl_set *isl_set_from_union_set(__isl_take isl_union_set *uset)
406 return isl_map_from_union_map(uset);
409 __isl_give isl_map *isl_union_map_extract_map(__isl_keep isl_union_map *umap,
410 __isl_take isl_space *dim)
412 uint32_t hash;
413 struct isl_hash_table_entry *entry;
415 if (!umap || !dim)
416 goto error;
418 hash = isl_space_get_hash(dim);
419 entry = isl_hash_table_find(umap->dim->ctx, &umap->table, hash,
420 &has_dim, dim, 0);
421 if (!entry)
422 return isl_map_empty(dim);
423 isl_space_free(dim);
424 return isl_map_copy(entry->data);
425 error:
426 isl_space_free(dim);
427 return NULL;
430 __isl_give isl_set *isl_union_set_extract_set(__isl_keep isl_union_set *uset,
431 __isl_take isl_space *dim)
433 return (isl_set *)isl_union_map_extract_map(uset, dim);
436 /* Check if umap contains a map in the given space.
438 __isl_give int isl_union_map_contains(__isl_keep isl_union_map *umap,
439 __isl_keep isl_space *dim)
441 uint32_t hash;
442 struct isl_hash_table_entry *entry;
444 if (!umap || !dim)
445 return -1;
447 hash = isl_space_get_hash(dim);
448 entry = isl_hash_table_find(umap->dim->ctx, &umap->table, hash,
449 &has_dim, dim, 0);
450 return !!entry;
453 __isl_give int isl_union_set_contains(__isl_keep isl_union_set *uset,
454 __isl_keep isl_space *dim)
456 return isl_union_map_contains(uset, dim);
459 int isl_union_set_foreach_set(__isl_keep isl_union_set *uset,
460 int (*fn)(__isl_take isl_set *set, void *user), void *user)
462 return isl_union_map_foreach_map(uset,
463 (int(*)(__isl_take isl_map *, void*))fn, user);
466 struct isl_union_set_foreach_point_data {
467 int (*fn)(__isl_take isl_point *pnt, void *user);
468 void *user;
471 static int foreach_point(__isl_take isl_set *set, void *user)
473 struct isl_union_set_foreach_point_data *data = user;
474 int r;
476 r = isl_set_foreach_point(set, data->fn, data->user);
477 isl_set_free(set);
479 return r;
482 int isl_union_set_foreach_point(__isl_keep isl_union_set *uset,
483 int (*fn)(__isl_take isl_point *pnt, void *user), void *user)
485 struct isl_union_set_foreach_point_data data = { fn, user };
486 return isl_union_set_foreach_set(uset, &foreach_point, &data);
489 struct isl_union_map_gen_bin_data {
490 isl_union_map *umap2;
491 isl_union_map *res;
494 static int subtract_entry(void **entry, void *user)
496 struct isl_union_map_gen_bin_data *data = user;
497 uint32_t hash;
498 struct isl_hash_table_entry *entry2;
499 isl_map *map = *entry;
501 hash = isl_space_get_hash(map->dim);
502 entry2 = isl_hash_table_find(data->umap2->dim->ctx, &data->umap2->table,
503 hash, &has_dim, map->dim, 0);
504 map = isl_map_copy(map);
505 if (entry2) {
506 int empty;
507 map = isl_map_subtract(map, isl_map_copy(entry2->data));
509 empty = isl_map_is_empty(map);
510 if (empty < 0) {
511 isl_map_free(map);
512 return -1;
514 if (empty) {
515 isl_map_free(map);
516 return 0;
519 data->res = isl_union_map_add_map(data->res, map);
521 return 0;
524 static __isl_give isl_union_map *gen_bin_op(__isl_take isl_union_map *umap1,
525 __isl_take isl_union_map *umap2, int (*fn)(void **, void *))
527 struct isl_union_map_gen_bin_data data = { NULL, NULL };
529 umap1 = isl_union_map_align_params(umap1, isl_union_map_get_space(umap2));
530 umap2 = isl_union_map_align_params(umap2, isl_union_map_get_space(umap1));
532 if (!umap1 || !umap2)
533 goto error;
535 data.umap2 = umap2;
536 data.res = isl_union_map_alloc(isl_space_copy(umap1->dim),
537 umap1->table.n);
538 if (isl_hash_table_foreach(umap1->dim->ctx, &umap1->table,
539 fn, &data) < 0)
540 goto error;
542 isl_union_map_free(umap1);
543 isl_union_map_free(umap2);
544 return data.res;
545 error:
546 isl_union_map_free(umap1);
547 isl_union_map_free(umap2);
548 isl_union_map_free(data.res);
549 return NULL;
552 __isl_give isl_union_map *isl_union_map_subtract(
553 __isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2)
555 return gen_bin_op(umap1, umap2, &subtract_entry);
558 __isl_give isl_union_set *isl_union_set_subtract(
559 __isl_take isl_union_set *uset1, __isl_take isl_union_set *uset2)
561 return isl_union_map_subtract(uset1, uset2);
564 struct isl_union_map_match_bin_data {
565 isl_union_map *umap2;
566 isl_union_map *res;
567 __isl_give isl_map *(*fn)(__isl_take isl_map*, __isl_take isl_map*);
570 static int match_bin_entry(void **entry, void *user)
572 struct isl_union_map_match_bin_data *data = user;
573 uint32_t hash;
574 struct isl_hash_table_entry *entry2;
575 isl_map *map = *entry;
576 int empty;
578 hash = isl_space_get_hash(map->dim);
579 entry2 = isl_hash_table_find(data->umap2->dim->ctx, &data->umap2->table,
580 hash, &has_dim, map->dim, 0);
581 if (!entry2)
582 return 0;
584 map = isl_map_copy(map);
585 map = data->fn(map, isl_map_copy(entry2->data));
587 empty = isl_map_is_empty(map);
588 if (empty < 0) {
589 isl_map_free(map);
590 return -1;
592 if (empty) {
593 isl_map_free(map);
594 return 0;
597 data->res = isl_union_map_add_map(data->res, map);
599 return 0;
602 static __isl_give isl_union_map *match_bin_op(__isl_take isl_union_map *umap1,
603 __isl_take isl_union_map *umap2,
604 __isl_give isl_map *(*fn)(__isl_take isl_map*, __isl_take isl_map*))
606 struct isl_union_map_match_bin_data data = { NULL, NULL, fn };
608 umap1 = isl_union_map_align_params(umap1, isl_union_map_get_space(umap2));
609 umap2 = isl_union_map_align_params(umap2, isl_union_map_get_space(umap1));
611 if (!umap1 || !umap2)
612 goto error;
614 data.umap2 = umap2;
615 data.res = isl_union_map_alloc(isl_space_copy(umap1->dim),
616 umap1->table.n);
617 if (isl_hash_table_foreach(umap1->dim->ctx, &umap1->table,
618 &match_bin_entry, &data) < 0)
619 goto error;
621 isl_union_map_free(umap1);
622 isl_union_map_free(umap2);
623 return data.res;
624 error:
625 isl_union_map_free(umap1);
626 isl_union_map_free(umap2);
627 isl_union_map_free(data.res);
628 return NULL;
631 __isl_give isl_union_map *isl_union_map_intersect(
632 __isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2)
634 return match_bin_op(umap1, umap2, &isl_map_intersect);
637 __isl_give isl_union_set *isl_union_set_intersect(
638 __isl_take isl_union_set *uset1, __isl_take isl_union_set *uset2)
640 return isl_union_map_intersect(uset1, uset2);
643 __isl_give isl_union_map *isl_union_map_gist(__isl_take isl_union_map *umap,
644 __isl_take isl_union_map *context)
646 return match_bin_op(umap, context, &isl_map_gist);
649 __isl_give isl_union_set *isl_union_set_gist(__isl_take isl_union_set *uset,
650 __isl_take isl_union_set *context)
652 return isl_union_map_gist(uset, context);
655 static __isl_give isl_map *lex_le_set(__isl_take isl_map *set1,
656 __isl_take isl_map *set2)
658 return isl_set_lex_le_set((isl_set *)set1, (isl_set *)set2);
661 static __isl_give isl_map *lex_lt_set(__isl_take isl_map *set1,
662 __isl_take isl_map *set2)
664 return isl_set_lex_lt_set((isl_set *)set1, (isl_set *)set2);
667 __isl_give isl_union_map *isl_union_set_lex_lt_union_set(
668 __isl_take isl_union_set *uset1, __isl_take isl_union_set *uset2)
670 return match_bin_op(uset1, uset2, &lex_lt_set);
673 __isl_give isl_union_map *isl_union_set_lex_le_union_set(
674 __isl_take isl_union_set *uset1, __isl_take isl_union_set *uset2)
676 return match_bin_op(uset1, uset2, &lex_le_set);
679 __isl_give isl_union_map *isl_union_set_lex_gt_union_set(
680 __isl_take isl_union_set *uset1, __isl_take isl_union_set *uset2)
682 return isl_union_map_reverse(isl_union_set_lex_lt_union_set(uset2, uset1));
685 __isl_give isl_union_map *isl_union_set_lex_ge_union_set(
686 __isl_take isl_union_set *uset1, __isl_take isl_union_set *uset2)
688 return isl_union_map_reverse(isl_union_set_lex_le_union_set(uset2, uset1));
691 __isl_give isl_union_map *isl_union_map_lex_gt_union_map(
692 __isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2)
694 return isl_union_map_reverse(isl_union_map_lex_lt_union_map(umap2, umap1));
697 __isl_give isl_union_map *isl_union_map_lex_ge_union_map(
698 __isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2)
700 return isl_union_map_reverse(isl_union_map_lex_le_union_map(umap2, umap1));
703 static int intersect_domain_entry(void **entry, void *user)
705 struct isl_union_map_gen_bin_data *data = user;
706 uint32_t hash;
707 struct isl_hash_table_entry *entry2;
708 isl_space *dim;
709 isl_map *map = *entry;
710 int empty;
712 dim = isl_map_get_space(map);
713 dim = isl_space_domain(dim);
714 hash = isl_space_get_hash(dim);
715 entry2 = isl_hash_table_find(data->umap2->dim->ctx, &data->umap2->table,
716 hash, &has_dim, dim, 0);
717 isl_space_free(dim);
718 if (!entry2)
719 return 0;
721 map = isl_map_copy(map);
722 map = isl_map_intersect_domain(map, isl_set_copy(entry2->data));
724 empty = isl_map_is_empty(map);
725 if (empty < 0) {
726 isl_map_free(map);
727 return -1;
729 if (empty) {
730 isl_map_free(map);
731 return 0;
734 data->res = isl_union_map_add_map(data->res, map);
736 return 0;
739 __isl_give isl_union_map *isl_union_map_intersect_domain(
740 __isl_take isl_union_map *umap, __isl_take isl_union_set *uset)
742 return gen_bin_op(umap, uset, &intersect_domain_entry);
745 static int intersect_range_entry(void **entry, void *user)
747 struct isl_union_map_gen_bin_data *data = user;
748 uint32_t hash;
749 struct isl_hash_table_entry *entry2;
750 isl_space *dim;
751 isl_map *map = *entry;
752 int empty;
754 dim = isl_map_get_space(map);
755 dim = isl_space_range(dim);
756 hash = isl_space_get_hash(dim);
757 entry2 = isl_hash_table_find(data->umap2->dim->ctx, &data->umap2->table,
758 hash, &has_dim, dim, 0);
759 isl_space_free(dim);
760 if (!entry2)
761 return 0;
763 map = isl_map_copy(map);
764 map = isl_map_intersect_range(map, isl_set_copy(entry2->data));
766 empty = isl_map_is_empty(map);
767 if (empty < 0) {
768 isl_map_free(map);
769 return -1;
771 if (empty) {
772 isl_map_free(map);
773 return 0;
776 data->res = isl_union_map_add_map(data->res, map);
778 return 0;
781 __isl_give isl_union_map *isl_union_map_intersect_range(
782 __isl_take isl_union_map *umap, __isl_take isl_union_set *uset)
784 return gen_bin_op(umap, uset, &intersect_range_entry);
787 struct isl_union_map_bin_data {
788 isl_union_map *umap2;
789 isl_union_map *res;
790 isl_map *map;
791 int (*fn)(void **entry, void *user);
794 static int apply_range_entry(void **entry, void *user)
796 struct isl_union_map_bin_data *data = user;
797 isl_map *map2 = *entry;
798 int empty;
800 if (!isl_space_tuple_match(data->map->dim, isl_dim_out,
801 map2->dim, isl_dim_in))
802 return 0;
804 map2 = isl_map_apply_range(isl_map_copy(data->map), isl_map_copy(map2));
806 empty = isl_map_is_empty(map2);
807 if (empty < 0) {
808 isl_map_free(map2);
809 return -1;
811 if (empty) {
812 isl_map_free(map2);
813 return 0;
816 data->res = isl_union_map_add_map(data->res, map2);
818 return 0;
821 static int bin_entry(void **entry, void *user)
823 struct isl_union_map_bin_data *data = user;
824 isl_map *map = *entry;
826 data->map = map;
827 if (isl_hash_table_foreach(data->umap2->dim->ctx, &data->umap2->table,
828 data->fn, data) < 0)
829 return -1;
831 return 0;
834 static __isl_give isl_union_map *bin_op(__isl_take isl_union_map *umap1,
835 __isl_take isl_union_map *umap2, int (*fn)(void **entry, void *user))
837 struct isl_union_map_bin_data data = { NULL, NULL, NULL, fn };
839 umap1 = isl_union_map_align_params(umap1, isl_union_map_get_space(umap2));
840 umap2 = isl_union_map_align_params(umap2, isl_union_map_get_space(umap1));
842 if (!umap1 || !umap2)
843 goto error;
845 data.umap2 = umap2;
846 data.res = isl_union_map_alloc(isl_space_copy(umap1->dim),
847 umap1->table.n);
848 if (isl_hash_table_foreach(umap1->dim->ctx, &umap1->table,
849 &bin_entry, &data) < 0)
850 goto error;
852 isl_union_map_free(umap1);
853 isl_union_map_free(umap2);
854 return data.res;
855 error:
856 isl_union_map_free(umap1);
857 isl_union_map_free(umap2);
858 isl_union_map_free(data.res);
859 return NULL;
862 __isl_give isl_union_map *isl_union_map_apply_range(
863 __isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2)
865 return bin_op(umap1, umap2, &apply_range_entry);
868 __isl_give isl_union_map *isl_union_map_apply_domain(
869 __isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2)
871 umap1 = isl_union_map_reverse(umap1);
872 umap1 = isl_union_map_apply_range(umap1, umap2);
873 return isl_union_map_reverse(umap1);
876 __isl_give isl_union_set *isl_union_set_apply(
877 __isl_take isl_union_set *uset, __isl_take isl_union_map *umap)
879 return isl_union_map_apply_range(uset, umap);
882 static int map_lex_lt_entry(void **entry, void *user)
884 struct isl_union_map_bin_data *data = user;
885 isl_map *map2 = *entry;
887 if (!isl_space_tuple_match(data->map->dim, isl_dim_out,
888 map2->dim, isl_dim_out))
889 return 0;
891 map2 = isl_map_lex_lt_map(isl_map_copy(data->map), isl_map_copy(map2));
893 data->res = isl_union_map_add_map(data->res, map2);
895 return 0;
898 __isl_give isl_union_map *isl_union_map_lex_lt_union_map(
899 __isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2)
901 return bin_op(umap1, umap2, &map_lex_lt_entry);
904 static int map_lex_le_entry(void **entry, void *user)
906 struct isl_union_map_bin_data *data = user;
907 isl_map *map2 = *entry;
909 if (!isl_space_tuple_match(data->map->dim, isl_dim_out,
910 map2->dim, isl_dim_out))
911 return 0;
913 map2 = isl_map_lex_le_map(isl_map_copy(data->map), isl_map_copy(map2));
915 data->res = isl_union_map_add_map(data->res, map2);
917 return 0;
920 __isl_give isl_union_map *isl_union_map_lex_le_union_map(
921 __isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2)
923 return bin_op(umap1, umap2, &map_lex_le_entry);
926 static int product_entry(void **entry, void *user)
928 struct isl_union_map_bin_data *data = user;
929 isl_map *map2 = *entry;
931 map2 = isl_map_product(isl_map_copy(data->map), isl_map_copy(map2));
933 data->res = isl_union_map_add_map(data->res, map2);
935 return 0;
938 __isl_give isl_union_map *isl_union_map_product(__isl_take isl_union_map *umap1,
939 __isl_take isl_union_map *umap2)
941 return bin_op(umap1, umap2, &product_entry);
944 __isl_give isl_union_set *isl_union_set_product(__isl_take isl_union_set *uset1,
945 __isl_take isl_union_set *uset2)
947 return isl_union_map_product(uset1, uset2);
950 static int range_product_entry(void **entry, void *user)
952 struct isl_union_map_bin_data *data = user;
953 isl_map *map2 = *entry;
955 if (!isl_space_tuple_match(data->map->dim, isl_dim_in,
956 map2->dim, isl_dim_in))
957 return 0;
959 map2 = isl_map_range_product(isl_map_copy(data->map),
960 isl_map_copy(map2));
962 data->res = isl_union_map_add_map(data->res, map2);
964 return 0;
967 __isl_give isl_union_map *isl_union_map_range_product(
968 __isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2)
970 return bin_op(umap1, umap2, &range_product_entry);
973 static int flat_range_product_entry(void **entry, void *user)
975 struct isl_union_map_bin_data *data = user;
976 isl_map *map2 = *entry;
978 if (!isl_space_tuple_match(data->map->dim, isl_dim_in,
979 map2->dim, isl_dim_in))
980 return 0;
982 map2 = isl_map_flat_range_product(isl_map_copy(data->map),
983 isl_map_copy(map2));
985 data->res = isl_union_map_add_map(data->res, map2);
987 return 0;
990 __isl_give isl_union_map *isl_union_map_flat_range_product(
991 __isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2)
993 return bin_op(umap1, umap2, &flat_range_product_entry);
996 __isl_give isl_union_map *isl_union_map_from_range(
997 __isl_take isl_union_set *uset)
999 return uset;
1002 __isl_give isl_union_map *isl_union_map_from_domain(
1003 __isl_take isl_union_set *uset)
1005 return isl_union_map_reverse(isl_union_map_from_range(uset));
1008 __isl_give isl_union_map *isl_union_map_from_domain_and_range(
1009 __isl_take isl_union_set *domain, __isl_take isl_union_set *range)
1011 return isl_union_map_apply_range(isl_union_map_from_domain(domain),
1012 isl_union_map_from_range(range));
1015 static __isl_give isl_union_map *un_op(__isl_take isl_union_map *umap,
1016 int (*fn)(void **, void *))
1018 umap = isl_union_map_cow(umap);
1019 if (!umap)
1020 return NULL;
1022 if (isl_hash_table_foreach(umap->dim->ctx, &umap->table, fn, NULL) < 0)
1023 goto error;
1025 return umap;
1026 error:
1027 isl_union_map_free(umap);
1028 return NULL;
1031 static int affine_entry(void **entry, void *user)
1033 isl_map **map = (isl_map **)entry;
1035 *map = isl_map_from_basic_map(isl_map_affine_hull(*map));
1037 return *map ? 0 : -1;
1040 __isl_give isl_union_map *isl_union_map_affine_hull(
1041 __isl_take isl_union_map *umap)
1043 return un_op(umap, &affine_entry);
1046 __isl_give isl_union_set *isl_union_set_affine_hull(
1047 __isl_take isl_union_set *uset)
1049 return isl_union_map_affine_hull(uset);
1052 static int polyhedral_entry(void **entry, void *user)
1054 isl_map **map = (isl_map **)entry;
1056 *map = isl_map_from_basic_map(isl_map_polyhedral_hull(*map));
1058 return *map ? 0 : -1;
1061 __isl_give isl_union_map *isl_union_map_polyhedral_hull(
1062 __isl_take isl_union_map *umap)
1064 return un_op(umap, &polyhedral_entry);
1067 __isl_give isl_union_set *isl_union_set_polyhedral_hull(
1068 __isl_take isl_union_set *uset)
1070 return isl_union_map_polyhedral_hull(uset);
1073 static int simple_entry(void **entry, void *user)
1075 isl_map **map = (isl_map **)entry;
1077 *map = isl_map_from_basic_map(isl_map_simple_hull(*map));
1079 return *map ? 0 : -1;
1082 __isl_give isl_union_map *isl_union_map_simple_hull(
1083 __isl_take isl_union_map *umap)
1085 return un_op(umap, &simple_entry);
1088 __isl_give isl_union_set *isl_union_set_simple_hull(
1089 __isl_take isl_union_set *uset)
1091 return isl_union_map_simple_hull(uset);
1094 static int inplace_entry(void **entry, void *user)
1096 __isl_give isl_map *(*fn)(__isl_take isl_map *);
1097 isl_map **map = (isl_map **)entry;
1098 isl_map *copy;
1100 fn = *(__isl_give isl_map *(**)(__isl_take isl_map *)) user;
1101 copy = fn(isl_map_copy(*map));
1102 if (!copy)
1103 return -1;
1105 isl_map_free(*map);
1106 *map = copy;
1108 return 0;
1111 static __isl_give isl_union_map *inplace(__isl_take isl_union_map *umap,
1112 __isl_give isl_map *(*fn)(__isl_take isl_map *))
1114 if (!umap)
1115 return NULL;
1117 if (isl_hash_table_foreach(umap->dim->ctx, &umap->table,
1118 &inplace_entry, &fn) < 0)
1119 goto error;
1121 return umap;
1122 error:
1123 isl_union_map_free(umap);
1124 return NULL;
1127 __isl_give isl_union_map *isl_union_map_coalesce(
1128 __isl_take isl_union_map *umap)
1130 return inplace(umap, &isl_map_coalesce);
1133 __isl_give isl_union_set *isl_union_set_coalesce(
1134 __isl_take isl_union_set *uset)
1136 return isl_union_map_coalesce(uset);
1139 __isl_give isl_union_map *isl_union_map_detect_equalities(
1140 __isl_take isl_union_map *umap)
1142 return inplace(umap, &isl_map_detect_equalities);
1145 __isl_give isl_union_set *isl_union_set_detect_equalities(
1146 __isl_take isl_union_set *uset)
1148 return isl_union_map_detect_equalities(uset);
1151 __isl_give isl_union_map *isl_union_map_compute_divs(
1152 __isl_take isl_union_map *umap)
1154 return inplace(umap, &isl_map_compute_divs);
1157 __isl_give isl_union_set *isl_union_set_compute_divs(
1158 __isl_take isl_union_set *uset)
1160 return isl_union_map_compute_divs(uset);
1163 static int lexmin_entry(void **entry, void *user)
1165 isl_map **map = (isl_map **)entry;
1167 *map = isl_map_lexmin(*map);
1169 return *map ? 0 : -1;
1172 __isl_give isl_union_map *isl_union_map_lexmin(
1173 __isl_take isl_union_map *umap)
1175 return un_op(umap, &lexmin_entry);
1178 __isl_give isl_union_set *isl_union_set_lexmin(
1179 __isl_take isl_union_set *uset)
1181 return isl_union_map_lexmin(uset);
1184 static int lexmax_entry(void **entry, void *user)
1186 isl_map **map = (isl_map **)entry;
1188 *map = isl_map_lexmax(*map);
1190 return *map ? 0 : -1;
1193 __isl_give isl_union_map *isl_union_map_lexmax(
1194 __isl_take isl_union_map *umap)
1196 return un_op(umap, &lexmax_entry);
1199 __isl_give isl_union_set *isl_union_set_lexmax(
1200 __isl_take isl_union_set *uset)
1202 return isl_union_map_lexmax(uset);
1205 static __isl_give isl_union_set *cond_un_op(__isl_take isl_union_map *umap,
1206 int (*fn)(void **, void *))
1208 isl_union_set *res;
1210 if (!umap)
1211 return NULL;
1213 res = isl_union_map_alloc(isl_space_copy(umap->dim), umap->table.n);
1214 if (isl_hash_table_foreach(umap->dim->ctx, &umap->table, fn, &res) < 0)
1215 goto error;
1217 isl_union_map_free(umap);
1218 return res;
1219 error:
1220 isl_union_map_free(umap);
1221 isl_union_set_free(res);
1222 return NULL;
1225 static int universe_entry(void **entry, void *user)
1227 isl_map *map = *entry;
1228 isl_union_map **res = user;
1230 map = isl_map_universe(isl_map_get_space(map));
1231 *res = isl_union_map_add_map(*res, map);
1233 return 0;
1236 __isl_give isl_union_map *isl_union_map_universe(__isl_take isl_union_map *umap)
1238 return cond_un_op(umap, &universe_entry);
1241 __isl_give isl_union_set *isl_union_set_universe(__isl_take isl_union_set *uset)
1243 return isl_union_map_universe(uset);
1246 static int reverse_entry(void **entry, void *user)
1248 isl_map *map = *entry;
1249 isl_union_map **res = user;
1251 *res = isl_union_map_add_map(*res, isl_map_reverse(isl_map_copy(map)));
1253 return 0;
1256 __isl_give isl_union_map *isl_union_map_reverse(__isl_take isl_union_map *umap)
1258 return cond_un_op(umap, &reverse_entry);
1261 static int domain_entry(void **entry, void *user)
1263 isl_map *map = *entry;
1264 isl_union_set **res = user;
1266 *res = isl_union_set_add_set(*res, isl_map_domain(isl_map_copy(map)));
1268 return 0;
1271 __isl_give isl_union_set *isl_union_map_domain(__isl_take isl_union_map *umap)
1273 return cond_un_op(umap, &domain_entry);
1276 static int range_entry(void **entry, void *user)
1278 isl_map *map = *entry;
1279 isl_union_set **res = user;
1281 *res = isl_union_set_add_set(*res, isl_map_range(isl_map_copy(map)));
1283 return 0;
1286 __isl_give isl_union_set *isl_union_map_range(__isl_take isl_union_map *umap)
1288 return cond_un_op(umap, &range_entry);
1291 static int domain_map_entry(void **entry, void *user)
1293 isl_map *map = *entry;
1294 isl_union_set **res = user;
1296 *res = isl_union_map_add_map(*res,
1297 isl_map_domain_map(isl_map_copy(map)));
1299 return 0;
1302 __isl_give isl_union_map *isl_union_map_domain_map(
1303 __isl_take isl_union_map *umap)
1305 return cond_un_op(umap, &domain_map_entry);
1308 static int range_map_entry(void **entry, void *user)
1310 isl_map *map = *entry;
1311 isl_union_set **res = user;
1313 *res = isl_union_map_add_map(*res,
1314 isl_map_range_map(isl_map_copy(map)));
1316 return 0;
1319 __isl_give isl_union_map *isl_union_map_range_map(
1320 __isl_take isl_union_map *umap)
1322 return cond_un_op(umap, &range_map_entry);
1325 static int deltas_entry(void **entry, void *user)
1327 isl_map *map = *entry;
1328 isl_union_set **res = user;
1330 if (!isl_space_tuple_match(map->dim, isl_dim_in, map->dim, isl_dim_out))
1331 return 0;
1333 *res = isl_union_set_add_set(*res, isl_map_deltas(isl_map_copy(map)));
1335 return 0;
1338 __isl_give isl_union_set *isl_union_map_deltas(__isl_take isl_union_map *umap)
1340 return cond_un_op(umap, &deltas_entry);
1343 static int deltas_map_entry(void **entry, void *user)
1345 isl_map *map = *entry;
1346 isl_union_map **res = user;
1348 if (!isl_space_tuple_match(map->dim, isl_dim_in, map->dim, isl_dim_out))
1349 return 0;
1351 *res = isl_union_map_add_map(*res,
1352 isl_map_deltas_map(isl_map_copy(map)));
1354 return 0;
1357 __isl_give isl_union_map *isl_union_map_deltas_map(
1358 __isl_take isl_union_map *umap)
1360 return cond_un_op(umap, &deltas_map_entry);
1363 static int identity_entry(void **entry, void *user)
1365 isl_set *set = *entry;
1366 isl_union_map **res = user;
1368 *res = isl_union_map_add_map(*res, isl_set_identity(isl_set_copy(set)));
1370 return 0;
1373 __isl_give isl_union_map *isl_union_set_identity(__isl_take isl_union_set *uset)
1375 return cond_un_op(uset, &identity_entry);
1378 static int unwrap_entry(void **entry, void *user)
1380 isl_set *set = *entry;
1381 isl_union_set **res = user;
1383 if (!isl_set_is_wrapping(set))
1384 return 0;
1386 *res = isl_union_map_add_map(*res, isl_set_unwrap(isl_set_copy(set)));
1388 return 0;
1391 __isl_give isl_union_map *isl_union_set_unwrap(__isl_take isl_union_set *uset)
1393 return cond_un_op(uset, &unwrap_entry);
1396 static int wrap_entry(void **entry, void *user)
1398 isl_map *map = *entry;
1399 isl_union_set **res = user;
1401 *res = isl_union_set_add_set(*res, isl_map_wrap(isl_map_copy(map)));
1403 return 0;
1406 __isl_give isl_union_set *isl_union_map_wrap(__isl_take isl_union_map *umap)
1408 return cond_un_op(umap, &wrap_entry);
1411 struct isl_union_map_is_subset_data {
1412 isl_union_map *umap2;
1413 int is_subset;
1416 static int is_subset_entry(void **entry, void *user)
1418 struct isl_union_map_is_subset_data *data = user;
1419 uint32_t hash;
1420 struct isl_hash_table_entry *entry2;
1421 isl_map *map = *entry;
1423 hash = isl_space_get_hash(map->dim);
1424 entry2 = isl_hash_table_find(data->umap2->dim->ctx, &data->umap2->table,
1425 hash, &has_dim, map->dim, 0);
1426 if (!entry2) {
1427 data->is_subset = 0;
1428 return -1;
1431 data->is_subset = isl_map_is_subset(map, entry2->data);
1432 if (data->is_subset < 0 || !data->is_subset)
1433 return -1;
1435 return 0;
1438 int isl_union_map_is_subset(__isl_keep isl_union_map *umap1,
1439 __isl_keep isl_union_map *umap2)
1441 struct isl_union_map_is_subset_data data = { NULL, 1 };
1443 umap1 = isl_union_map_copy(umap1);
1444 umap2 = isl_union_map_copy(umap2);
1445 umap1 = isl_union_map_align_params(umap1, isl_union_map_get_space(umap2));
1446 umap2 = isl_union_map_align_params(umap2, isl_union_map_get_space(umap1));
1448 if (!umap1 || !umap2)
1449 goto error;
1451 data.umap2 = umap2;
1452 if (isl_hash_table_foreach(umap1->dim->ctx, &umap1->table,
1453 &is_subset_entry, &data) < 0 &&
1454 data.is_subset)
1455 goto error;
1457 isl_union_map_free(umap1);
1458 isl_union_map_free(umap2);
1460 return data.is_subset;
1461 error:
1462 isl_union_map_free(umap1);
1463 isl_union_map_free(umap2);
1464 return -1;
1467 int isl_union_set_is_subset(__isl_keep isl_union_set *uset1,
1468 __isl_keep isl_union_set *uset2)
1470 return isl_union_map_is_subset(uset1, uset2);
1473 int isl_union_map_is_equal(__isl_keep isl_union_map *umap1,
1474 __isl_keep isl_union_map *umap2)
1476 int is_subset;
1478 if (!umap1 || !umap2)
1479 return -1;
1480 is_subset = isl_union_map_is_subset(umap1, umap2);
1481 if (is_subset != 1)
1482 return is_subset;
1483 is_subset = isl_union_map_is_subset(umap2, umap1);
1484 return is_subset;
1487 int isl_union_set_is_equal(__isl_keep isl_union_set *uset1,
1488 __isl_keep isl_union_set *uset2)
1490 return isl_union_map_is_equal(uset1, uset2);
1493 int isl_union_map_is_strict_subset(__isl_keep isl_union_map *umap1,
1494 __isl_keep isl_union_map *umap2)
1496 int is_subset;
1498 if (!umap1 || !umap2)
1499 return -1;
1500 is_subset = isl_union_map_is_subset(umap1, umap2);
1501 if (is_subset != 1)
1502 return is_subset;
1503 is_subset = isl_union_map_is_subset(umap2, umap1);
1504 if (is_subset == -1)
1505 return is_subset;
1506 return !is_subset;
1509 int isl_union_set_is_strict_subset(__isl_keep isl_union_set *uset1,
1510 __isl_keep isl_union_set *uset2)
1512 return isl_union_map_is_strict_subset(uset1, uset2);
1515 static int sample_entry(void **entry, void *user)
1517 isl_basic_map **sample = (isl_basic_map **)user;
1518 isl_map *map = *entry;
1520 *sample = isl_map_sample(isl_map_copy(map));
1521 if (!*sample)
1522 return -1;
1523 if (!isl_basic_map_plain_is_empty(*sample))
1524 return -1;
1525 return 0;
1528 __isl_give isl_basic_map *isl_union_map_sample(__isl_take isl_union_map *umap)
1530 isl_basic_map *sample = NULL;
1532 if (!umap)
1533 return NULL;
1535 if (isl_hash_table_foreach(umap->dim->ctx, &umap->table,
1536 &sample_entry, &sample) < 0 &&
1537 !sample)
1538 goto error;
1540 if (!sample)
1541 sample = isl_basic_map_empty(isl_union_map_get_space(umap));
1543 isl_union_map_free(umap);
1545 return sample;
1546 error:
1547 isl_union_map_free(umap);
1548 return NULL;
1551 __isl_give isl_basic_set *isl_union_set_sample(__isl_take isl_union_set *uset)
1553 return (isl_basic_set *)isl_union_map_sample(uset);
1556 struct isl_forall_data {
1557 int res;
1558 int (*fn)(__isl_keep isl_map *map);
1561 static int forall_entry(void **entry, void *user)
1563 struct isl_forall_data *data = user;
1564 isl_map *map = *entry;
1566 data->res = data->fn(map);
1567 if (data->res < 0)
1568 return -1;
1570 if (!data->res)
1571 return -1;
1573 return 0;
1576 static int union_map_forall(__isl_keep isl_union_map *umap,
1577 int (*fn)(__isl_keep isl_map *map))
1579 struct isl_forall_data data = { 1, fn };
1581 if (!umap)
1582 return -1;
1584 if (isl_hash_table_foreach(umap->dim->ctx, &umap->table,
1585 &forall_entry, &data) < 0 && data.res)
1586 return -1;
1588 return data.res;
1591 struct isl_forall_user_data {
1592 int res;
1593 int (*fn)(__isl_keep isl_map *map, void *user);
1594 void *user;
1597 static int forall_user_entry(void **entry, void *user)
1599 struct isl_forall_user_data *data = user;
1600 isl_map *map = *entry;
1602 data->res = data->fn(map, data->user);
1603 if (data->res < 0)
1604 return -1;
1606 if (!data->res)
1607 return -1;
1609 return 0;
1612 /* Check if fn(map, user) returns true for all maps "map" in umap.
1614 static int union_map_forall_user(__isl_keep isl_union_map *umap,
1615 int (*fn)(__isl_keep isl_map *map, void *user), void *user)
1617 struct isl_forall_user_data data = { 1, fn, user };
1619 if (!umap)
1620 return -1;
1622 if (isl_hash_table_foreach(umap->dim->ctx, &umap->table,
1623 &forall_user_entry, &data) < 0 && data.res)
1624 return -1;
1626 return data.res;
1629 int isl_union_map_is_empty(__isl_keep isl_union_map *umap)
1631 return union_map_forall(umap, &isl_map_is_empty);
1634 int isl_union_set_is_empty(__isl_keep isl_union_set *uset)
1636 return isl_union_map_is_empty(uset);
1639 static int is_subset_of_identity(__isl_keep isl_map *map)
1641 int is_subset;
1642 isl_space *dim;
1643 isl_map *id;
1645 if (!map)
1646 return -1;
1648 if (!isl_space_tuple_match(map->dim, isl_dim_in, map->dim, isl_dim_out))
1649 return 0;
1651 dim = isl_map_get_space(map);
1652 id = isl_map_identity(dim);
1654 is_subset = isl_map_is_subset(map, id);
1656 isl_map_free(id);
1658 return is_subset;
1661 /* Check if the given map is single-valued.
1662 * We simply compute
1664 * M \circ M^-1
1666 * and check if the result is a subset of the identity mapping.
1668 int isl_union_map_is_single_valued(__isl_keep isl_union_map *umap)
1670 isl_union_map *test;
1671 int sv;
1673 if (isl_union_map_n_map(umap) == 1) {
1674 isl_map *map;
1675 umap = isl_union_map_copy(umap);
1676 map = isl_map_from_union_map(umap);
1677 sv = isl_map_is_single_valued(map);
1678 isl_map_free(map);
1679 return sv;
1682 test = isl_union_map_reverse(isl_union_map_copy(umap));
1683 test = isl_union_map_apply_range(test, isl_union_map_copy(umap));
1685 sv = union_map_forall(test, &is_subset_of_identity);
1687 isl_union_map_free(test);
1689 return sv;
1692 int isl_union_map_is_injective(__isl_keep isl_union_map *umap)
1694 int in;
1696 umap = isl_union_map_copy(umap);
1697 umap = isl_union_map_reverse(umap);
1698 in = isl_union_map_is_single_valued(umap);
1699 isl_union_map_free(umap);
1701 return in;
1704 /* Represents a map that has a fixed value (v) for one of its
1705 * range dimensions.
1706 * The map in this structure is not reference counted, so it
1707 * is only valid while the isl_union_map from which it was
1708 * obtained is still alive.
1710 struct isl_fixed_map {
1711 isl_int v;
1712 isl_map *map;
1715 static struct isl_fixed_map *alloc_isl_fixed_map_array(isl_ctx *ctx,
1716 int n)
1718 int i;
1719 struct isl_fixed_map *v;
1721 v = isl_calloc_array(ctx, struct isl_fixed_map, n);
1722 if (!v)
1723 return NULL;
1724 for (i = 0; i < n; ++i)
1725 isl_int_init(v[i].v);
1726 return v;
1729 static void free_isl_fixed_map_array(struct isl_fixed_map *v, int n)
1731 int i;
1733 if (!v)
1734 return;
1735 for (i = 0; i < n; ++i)
1736 isl_int_clear(v[i].v);
1737 free(v);
1740 /* Compare the "v" field of two isl_fixed_map structs.
1742 static int qsort_fixed_map_cmp(const void *p1, const void *p2)
1744 const struct isl_fixed_map *e1 = (const struct isl_fixed_map *) p1;
1745 const struct isl_fixed_map *e2 = (const struct isl_fixed_map *) p2;
1747 return isl_int_cmp(e1->v, e2->v);
1750 /* Internal data structure used while checking whether all maps
1751 * in a union_map have a fixed value for a given output dimension.
1752 * v is the list of maps, with the fixed value for the dimension
1753 * n is the number of maps considered so far
1754 * pos is the output dimension under investigation
1756 struct isl_fixed_dim_data {
1757 struct isl_fixed_map *v;
1758 int n;
1759 int pos;
1762 static int fixed_at_pos(__isl_keep isl_map *map, void *user)
1764 struct isl_fixed_dim_data *data = user;
1766 data->v[data->n].map = map;
1767 return isl_map_plain_is_fixed(map, isl_dim_out, data->pos,
1768 &data->v[data->n++].v);
1771 static int plain_injective_on_range(__isl_take isl_union_map *umap,
1772 int first, int n_range);
1774 /* Given a list of the maps, with their fixed values at output dimension "pos",
1775 * check whether the ranges of the maps form an obvious partition.
1777 * We first sort the maps according to their fixed values.
1778 * If all maps have a different value, then we know the ranges form
1779 * a partition.
1780 * Otherwise, we collect the maps with the same fixed value and
1781 * check whether each such collection is obviously injective
1782 * based on later dimensions.
1784 static int separates(struct isl_fixed_map *v, int n,
1785 __isl_take isl_space *dim, int pos, int n_range)
1787 int i;
1789 if (!v)
1790 goto error;
1792 qsort(v, n, sizeof(*v), &qsort_fixed_map_cmp);
1794 for (i = 0; i + 1 < n; ++i) {
1795 int j, k;
1796 isl_union_map *part;
1797 int injective;
1799 for (j = i + 1; j < n; ++j)
1800 if (isl_int_ne(v[i].v, v[j].v))
1801 break;
1803 if (j == i + 1)
1804 continue;
1806 part = isl_union_map_alloc(isl_space_copy(dim), j - i);
1807 for (k = i; k < j; ++k)
1808 part = isl_union_map_add_map(part,
1809 isl_map_copy(v[k].map));
1811 injective = plain_injective_on_range(part, pos + 1, n_range);
1812 if (injective < 0)
1813 goto error;
1814 if (!injective)
1815 break;
1817 i = j - 1;
1820 isl_space_free(dim);
1821 free_isl_fixed_map_array(v, n);
1822 return i + 1 >= n;
1823 error:
1824 isl_space_free(dim);
1825 free_isl_fixed_map_array(v, n);
1826 return -1;
1829 /* Check whether the maps in umap have obviously distinct ranges.
1830 * In particular, check for an output dimension in the range
1831 * [first,n_range) for which all maps have a fixed value
1832 * and then check if these values, possibly along with fixed values
1833 * at later dimensions, entail distinct ranges.
1835 static int plain_injective_on_range(__isl_take isl_union_map *umap,
1836 int first, int n_range)
1838 isl_ctx *ctx;
1839 int n;
1840 struct isl_fixed_dim_data data = { NULL };
1842 ctx = isl_union_map_get_ctx(umap);
1844 if (!umap)
1845 goto error;
1847 n = isl_union_map_n_map(umap);
1848 if (n <= 1) {
1849 isl_union_map_free(umap);
1850 return 1;
1853 if (first >= n_range) {
1854 isl_union_map_free(umap);
1855 return 0;
1858 data.v = alloc_isl_fixed_map_array(ctx, n);
1859 if (!data.v)
1860 goto error;
1862 for (data.pos = first; data.pos < n_range; ++data.pos) {
1863 int fixed;
1864 int injective;
1865 isl_space *dim;
1867 data.n = 0;
1868 fixed = union_map_forall_user(umap, &fixed_at_pos, &data);
1869 if (fixed < 0)
1870 goto error;
1871 if (!fixed)
1872 continue;
1873 dim = isl_union_map_get_space(umap);
1874 injective = separates(data.v, n, dim, data.pos, n_range);
1875 isl_union_map_free(umap);
1876 return injective;
1879 free_isl_fixed_map_array(data.v, n);
1880 isl_union_map_free(umap);
1882 return 0;
1883 error:
1884 free_isl_fixed_map_array(data.v, n);
1885 isl_union_map_free(umap);
1886 return -1;
1889 /* Check whether the maps in umap that map to subsets of "ran"
1890 * have obviously distinct ranges.
1892 static int plain_injective_on_range_wrap(__isl_keep isl_set *ran, void *user)
1894 isl_union_map *umap = user;
1896 umap = isl_union_map_copy(umap);
1897 umap = isl_union_map_intersect_range(umap,
1898 isl_union_set_from_set(isl_set_copy(ran)));
1899 return plain_injective_on_range(umap, 0, isl_set_dim(ran, isl_dim_set));
1902 /* Check if the given union_map is obviously injective.
1904 * In particular, we first check if all individual maps are obviously
1905 * injective and then check if all the ranges of these maps are
1906 * obviously disjoint.
1908 int isl_union_map_plain_is_injective(__isl_keep isl_union_map *umap)
1910 int in;
1911 isl_union_map *univ;
1912 isl_union_set *ran;
1914 in = union_map_forall(umap, &isl_map_plain_is_injective);
1915 if (in < 0)
1916 return -1;
1917 if (!in)
1918 return 0;
1920 univ = isl_union_map_universe(isl_union_map_copy(umap));
1921 ran = isl_union_map_range(univ);
1923 in = union_map_forall_user(ran, &plain_injective_on_range_wrap, umap);
1925 isl_union_set_free(ran);
1927 return in;
1930 int isl_union_map_is_bijective(__isl_keep isl_union_map *umap)
1932 int sv;
1934 sv = isl_union_map_is_single_valued(umap);
1935 if (sv < 0 || !sv)
1936 return sv;
1938 return isl_union_map_is_injective(umap);
1941 static int zip_entry(void **entry, void *user)
1943 isl_map *map = *entry;
1944 isl_union_map **res = user;
1946 if (!isl_map_can_zip(map))
1947 return 0;
1949 *res = isl_union_map_add_map(*res, isl_map_zip(isl_map_copy(map)));
1951 return 0;
1954 __isl_give isl_union_map *isl_union_map_zip(__isl_take isl_union_map *umap)
1956 return cond_un_op(umap, &zip_entry);
1959 static int lift_entry(void **entry, void *user)
1961 isl_set *set = *entry;
1962 isl_union_set **res = user;
1964 *res = isl_union_set_add_set(*res, isl_set_lift(isl_set_copy(set)));
1966 return 0;
1969 __isl_give isl_union_set *isl_union_set_lift(__isl_take isl_union_set *uset)
1971 return cond_un_op(uset, &lift_entry);
1974 static int coefficients_entry(void **entry, void *user)
1976 isl_set *set = *entry;
1977 isl_union_set **res = user;
1979 set = isl_set_copy(set);
1980 set = isl_set_from_basic_set(isl_set_coefficients(set));
1981 *res = isl_union_set_add_set(*res, set);
1983 return 0;
1986 __isl_give isl_union_set *isl_union_set_coefficients(
1987 __isl_take isl_union_set *uset)
1989 isl_ctx *ctx;
1990 isl_space *dim;
1991 isl_union_set *res;
1993 if (!uset)
1994 return NULL;
1996 ctx = isl_union_set_get_ctx(uset);
1997 dim = isl_space_set_alloc(ctx, 0, 0);
1998 res = isl_union_map_alloc(dim, uset->table.n);
1999 if (isl_hash_table_foreach(uset->dim->ctx, &uset->table,
2000 &coefficients_entry, &res) < 0)
2001 goto error;
2003 isl_union_set_free(uset);
2004 return res;
2005 error:
2006 isl_union_set_free(uset);
2007 isl_union_set_free(res);
2008 return NULL;
2011 static int solutions_entry(void **entry, void *user)
2013 isl_set *set = *entry;
2014 isl_union_set **res = user;
2016 set = isl_set_copy(set);
2017 set = isl_set_from_basic_set(isl_set_solutions(set));
2018 if (!*res)
2019 *res = isl_union_set_from_set(set);
2020 else
2021 *res = isl_union_set_add_set(*res, set);
2023 if (!*res)
2024 return -1;
2026 return 0;
2029 __isl_give isl_union_set *isl_union_set_solutions(
2030 __isl_take isl_union_set *uset)
2032 isl_union_set *res = NULL;
2034 if (!uset)
2035 return NULL;
2037 if (uset->table.n == 0) {
2038 res = isl_union_set_empty(isl_union_set_get_space(uset));
2039 isl_union_set_free(uset);
2040 return res;
2043 if (isl_hash_table_foreach(uset->dim->ctx, &uset->table,
2044 &solutions_entry, &res) < 0)
2045 goto error;
2047 isl_union_set_free(uset);
2048 return res;
2049 error:
2050 isl_union_set_free(uset);
2051 isl_union_set_free(res);
2052 return NULL;