#include <isl_union_map_private.h>
#include <isl/union_set.h>
+/* Is this union set a parameter domain?
+ */
+int isl_union_set_is_params(__isl_keep isl_union_set *uset)
+{
+ isl_set *set;
+ int params;
+
+ if (!uset)
+ return -1;
+ if (uset->table.n != 1)
+ return 0;
+
+ set = isl_set_from_union_set(isl_union_set_copy(uset));
+ params = isl_set_is_params(set);
+ isl_set_free(set);
+ return params;
+}
+
static __isl_give isl_union_map *isl_union_map_alloc(__isl_take isl_space *dim,
int size)
{
return isl_union_map_subtract(uset1, uset2);
}
+struct isl_union_map_gen_bin_set_data {
+ isl_set *set;
+ isl_union_map *res;
+};
+
+static int intersect_params_entry(void **entry, void *user)
+{
+ struct isl_union_map_gen_bin_set_data *data = user;
+ isl_map *map = *entry;
+ int empty;
+
+ map = isl_map_copy(map);
+ map = isl_map_intersect_params(map, isl_set_copy(data->set));
+
+ empty = isl_map_is_empty(map);
+ if (empty < 0) {
+ isl_map_free(map);
+ return -1;
+ }
+
+ data->res = isl_union_map_add_map(data->res, map);
+
+ return 0;
+}
+
+static __isl_give isl_union_map *gen_bin_set_op(__isl_take isl_union_map *umap,
+ __isl_take isl_set *set, int (*fn)(void **, void *))
+{
+ struct isl_union_map_gen_bin_set_data data = { NULL, NULL };
+
+ umap = isl_union_map_align_params(umap, isl_set_get_space(set));
+ set = isl_set_align_params(set, isl_union_map_get_space(umap));
+
+ if (!umap || !set)
+ goto error;
+
+ data.set = set;
+ data.res = isl_union_map_alloc(isl_space_copy(umap->dim),
+ umap->table.n);
+ if (isl_hash_table_foreach(umap->dim->ctx, &umap->table,
+ fn, &data) < 0)
+ goto error;
+
+ isl_union_map_free(umap);
+ isl_set_free(set);
+ return data.res;
+error:
+ isl_union_map_free(umap);
+ isl_set_free(set);
+ isl_union_map_free(data.res);
+ return NULL;
+}
+
+__isl_give isl_union_map *isl_union_map_intersect_params(
+ __isl_take isl_union_map *umap, __isl_take isl_set *set)
+{
+ return gen_bin_set_op(umap, set, &intersect_params_entry);
+}
+
+__isl_give isl_union_set *isl_union_set_intersect_params(
+ __isl_take isl_union_set *uset, __isl_take isl_set *set)
+{
+ return isl_union_map_intersect_params(uset, set);
+}
+
+static __isl_give isl_union_map *union_map_intersect_params(
+ __isl_take isl_union_map *umap, __isl_take isl_union_set *uset)
+{
+ return isl_union_map_intersect_params(umap,
+ isl_set_from_union_set(uset));
+}
+
+static __isl_give isl_union_map *union_map_gist_params(
+ __isl_take isl_union_map *umap, __isl_take isl_union_set *uset)
+{
+ return isl_union_map_gist_params(umap, isl_set_from_union_set(uset));
+}
+
struct isl_union_map_match_bin_data {
isl_union_map *umap2;
isl_union_map *res;
return match_bin_op(umap1, umap2, &isl_map_intersect);
}
+/* Compute the intersection of the two union_sets.
+ * As a special case, if exactly one of the two union_sets
+ * is a parameter domain, then intersect the parameter domain
+ * of the other one with this set.
+ */
__isl_give isl_union_set *isl_union_set_intersect(
__isl_take isl_union_set *uset1, __isl_take isl_union_set *uset2)
{
+ int p1, p2;
+
+ p1 = isl_union_set_is_params(uset1);
+ p2 = isl_union_set_is_params(uset2);
+ if (p1 < 0 || p2 < 0)
+ goto error;
+ if (!p1 && p2)
+ return union_map_intersect_params(uset1, uset2);
+ if (p1 && !p2)
+ return union_map_intersect_params(uset2, uset1);
return isl_union_map_intersect(uset1, uset2);
+error:
+ isl_union_set_free(uset1);
+ isl_union_set_free(uset2);
+ return NULL;
+}
+
+static int gist_params_entry(void **entry, void *user)
+{
+ struct isl_union_map_gen_bin_set_data *data = user;
+ isl_map *map = *entry;
+ int empty;
+
+ map = isl_map_copy(map);
+ map = isl_map_gist_params(map, isl_set_copy(data->set));
+
+ empty = isl_map_is_empty(map);
+ if (empty < 0) {
+ isl_map_free(map);
+ return -1;
+ }
+
+ data->res = isl_union_map_add_map(data->res, map);
+
+ return 0;
+}
+
+__isl_give isl_union_map *isl_union_map_gist_params(
+ __isl_take isl_union_map *umap, __isl_take isl_set *set)
+{
+ return gen_bin_set_op(umap, set, &gist_params_entry);
+}
+
+__isl_give isl_union_set *isl_union_set_gist_params(
+ __isl_take isl_union_set *uset, __isl_take isl_set *set)
+{
+ return isl_union_map_gist_params(uset, set);
}
__isl_give isl_union_map *isl_union_map_gist(__isl_take isl_union_map *umap,
__isl_give isl_union_set *isl_union_set_gist(__isl_take isl_union_set *uset,
__isl_take isl_union_set *context)
{
+ if (isl_union_set_is_params(context))
+ return union_map_gist_params(uset, context);
return isl_union_map_gist(uset, context);
}
return 0;
}
+/* Intersect the domain of "umap" with "uset".
+ * If "uset" is a parameters domain, then intersect the parameter
+ * domain of "umap" with this set.
+ */
__isl_give isl_union_map *isl_union_map_intersect_domain(
__isl_take isl_union_map *umap, __isl_take isl_union_set *uset)
{
+ if (isl_union_set_is_params(uset))
+ return union_map_intersect_params(umap, uset);
return gen_bin_op(umap, uset, &intersect_domain_entry);
}
+static int gist_domain_entry(void **entry, void *user)
+{
+ struct isl_union_map_gen_bin_data *data = user;
+ uint32_t hash;
+ struct isl_hash_table_entry *entry2;
+ isl_space *dim;
+ isl_map *map = *entry;
+ int empty;
+
+ dim = isl_map_get_space(map);
+ dim = isl_space_domain(dim);
+ hash = isl_space_get_hash(dim);
+ entry2 = isl_hash_table_find(data->umap2->dim->ctx, &data->umap2->table,
+ hash, &has_dim, dim, 0);
+ isl_space_free(dim);
+ if (!entry2)
+ return 0;
+
+ map = isl_map_copy(map);
+ map = isl_map_gist_domain(map, isl_set_copy(entry2->data));
+
+ empty = isl_map_is_empty(map);
+ if (empty < 0) {
+ isl_map_free(map);
+ return -1;
+ }
+
+ data->res = isl_union_map_add_map(data->res, map);
+
+ return 0;
+}
+
+/* Compute the gist of "umap" with respect to the domain "uset".
+ * If "uset" is a parameters domain, then compute the gist
+ * with respect to this parameter domain.
+ */
+__isl_give isl_union_map *isl_union_map_gist_domain(
+ __isl_take isl_union_map *umap, __isl_take isl_union_set *uset)
+{
+ if (isl_union_set_is_params(uset))
+ return union_map_gist_params(umap, uset);
+ return gen_bin_op(umap, uset, &gist_domain_entry);
+}
+
+static int gist_range_entry(void **entry, void *user)
+{
+ struct isl_union_map_gen_bin_data *data = user;
+ uint32_t hash;
+ struct isl_hash_table_entry *entry2;
+ isl_space *space;
+ isl_map *map = *entry;
+ int empty;
+
+ space = isl_map_get_space(map);
+ space = isl_space_range(space);
+ hash = isl_space_get_hash(space);
+ entry2 = isl_hash_table_find(data->umap2->dim->ctx, &data->umap2->table,
+ hash, &has_dim, space, 0);
+ isl_space_free(space);
+ if (!entry2)
+ return 0;
+
+ map = isl_map_copy(map);
+ map = isl_map_gist_range(map, isl_set_copy(entry2->data));
+
+ empty = isl_map_is_empty(map);
+ if (empty < 0) {
+ isl_map_free(map);
+ return -1;
+ }
+
+ data->res = isl_union_map_add_map(data->res, map);
+
+ return 0;
+}
+
+/* Compute the gist of "umap" with respect to the range "uset".
+ */
+__isl_give isl_union_map *isl_union_map_gist_range(
+ __isl_take isl_union_map *umap, __isl_take isl_union_set *uset)
+{
+ return gen_bin_op(umap, uset, &gist_range_entry);
+}
+
static int intersect_range_entry(void **entry, void *user)
{
struct isl_union_map_gen_bin_data *data = user;
return bin_op(umap1, umap2, &product_entry);
}
+static int set_product_entry(void **entry, void *user)
+{
+ struct isl_union_map_bin_data *data = user;
+ isl_set *set2 = *entry;
+
+ set2 = isl_set_product(isl_set_copy(data->map), isl_set_copy(set2));
+
+ data->res = isl_union_set_add_set(data->res, set2);
+
+ return 0;
+}
+
__isl_give isl_union_set *isl_union_set_product(__isl_take isl_union_set *uset1,
__isl_take isl_union_set *uset2)
{
- return isl_union_map_product(uset1, uset2);
+ return bin_op(uset1, uset2, &set_product_entry);
}
static int range_product_entry(void **entry, void *user)
return bin_op(umap1, umap2, &flat_range_product_entry);
}
+static __isl_give isl_union_set *cond_un_op(__isl_take isl_union_map *umap,
+ int (*fn)(void **, void *))
+{
+ isl_union_set *res;
+
+ if (!umap)
+ return NULL;
+
+ res = isl_union_map_alloc(isl_space_copy(umap->dim), umap->table.n);
+ if (isl_hash_table_foreach(umap->dim->ctx, &umap->table, fn, &res) < 0)
+ goto error;
+
+ isl_union_map_free(umap);
+ return res;
+error:
+ isl_union_map_free(umap);
+ isl_union_set_free(res);
+ return NULL;
+}
+
+static int from_range_entry(void **entry, void *user)
+{
+ isl_map *set = *entry;
+ isl_union_set **res = user;
+
+ *res = isl_union_map_add_map(*res,
+ isl_map_from_range(isl_set_copy(set)));
+
+ return 0;
+}
+
__isl_give isl_union_map *isl_union_map_from_range(
__isl_take isl_union_set *uset)
{
- return uset;
+ return cond_un_op(uset, &from_range_entry);
}
__isl_give isl_union_map *isl_union_map_from_domain(
return isl_union_map_lexmax(uset);
}
-static __isl_give isl_union_set *cond_un_op(__isl_take isl_union_map *umap,
- int (*fn)(void **, void *))
-{
- isl_union_set *res;
-
- if (!umap)
- return NULL;
-
- res = isl_union_map_alloc(isl_space_copy(umap->dim), umap->table.n);
- if (isl_hash_table_foreach(umap->dim->ctx, &umap->table, fn, &res) < 0)
- goto error;
-
- isl_union_map_free(umap);
- return res;
-error:
- isl_union_map_free(umap);
- isl_union_set_free(res);
- return NULL;
-}
-
static int universe_entry(void **entry, void *user)
{
isl_map *map = *entry;
return cond_un_op(umap, &reverse_entry);
}
+static int params_entry(void **entry, void *user)
+{
+ isl_map *map = *entry;
+ isl_union_set **res = user;
+
+ *res = isl_union_set_add_set(*res, isl_map_params(isl_map_copy(map)));
+
+ return 0;
+}
+
+/* Compute the parameter domain of the given union map.
+ */
+__isl_give isl_set *isl_union_map_params(__isl_take isl_union_map *umap)
+{
+ int empty;
+
+ empty = isl_union_map_is_empty(umap);
+ if (empty < 0)
+ return isl_union_map_free(umap);
+ if (empty)
+ return isl_set_empty(isl_union_map_get_space(umap));
+ return isl_set_from_union_set(cond_un_op(umap, ¶ms_entry));
+}
+
+/* Compute the parameter domain of the given union set.
+ */
+__isl_give isl_set *isl_union_set_params(__isl_take isl_union_set *uset)
+{
+ return isl_union_map_params(uset);
+}
+
static int domain_entry(void **entry, void *user)
{
isl_map *map = *entry;
entry2 = isl_hash_table_find(data->umap2->dim->ctx, &data->umap2->table,
hash, &has_dim, map->dim, 0);
if (!entry2) {
+ int empty = isl_map_is_empty(map);
+ if (empty < 0)
+ return -1;
+ if (empty)
+ return 0;
data->is_subset = 0;
return -1;
}
return cond_un_op(umap, &zip_entry);
}
+static int curry_entry(void **entry, void *user)
+{
+ isl_map *map = *entry;
+ isl_union_map **res = user;
+
+ if (!isl_map_can_curry(map))
+ return 0;
+
+ *res = isl_union_map_add_map(*res, isl_map_curry(isl_map_copy(map)));
+
+ return 0;
+}
+
+/* Given a union map, take the maps of the form (A -> B) -> C and
+ * return the union of the corresponding maps A -> (B -> C).
+ */
+__isl_give isl_union_map *isl_union_map_curry(__isl_take isl_union_map *umap)
+{
+ return cond_un_op(umap, &curry_entry);
+}
+
static int lift_entry(void **entry, void *user)
{
isl_set *set = *entry;