add isl_union_map_preimage_domain_multi_aff
authorSven Verdoolaege <skimo@kotnet.org>
Fri, 12 Apr 2013 16:18:31 +0000 (18:18 +0200)
committerSven Verdoolaege <skimo@kotnet.org>
Mon, 22 Apr 2013 07:38:19 +0000 (09:38 +0200)
Signed-off-by: Sven Verdoolaege <skimo@kotnet.org>
doc/user.pod
include/isl/union_map.h
isl_test.c
isl_union_map.c

index 344532e..c8bd428 100644 (file)
@@ -2820,6 +2820,10 @@ a parametric set as well.
        __isl_give isl_map *isl_map_preimage_domain_multi_aff(
                __isl_take isl_map *map,
                __isl_take isl_multi_aff *ma);
        __isl_give isl_map *isl_map_preimage_domain_multi_aff(
                __isl_take isl_map *map,
                __isl_take isl_multi_aff *ma);
+       __isl_give isl_union_map *
+       isl_union_map_preimage_domain_multi_aff(
+               __isl_take isl_union_map *umap,
+               __isl_take isl_multi_aff *ma);
 
 These functions compute the preimage of the given set or map domain under
 the given function.  In other words, the expression is plugged
 
 These functions compute the preimage of the given set or map domain under
 the given function.  In other words, the expression is plugged
index 8eb7b2f..2ea5876 100644 (file)
@@ -109,6 +109,8 @@ __isl_give isl_union_map *isl_union_map_apply_domain(
 __isl_export
 __isl_give isl_union_map *isl_union_map_apply_range(
        __isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2);
 __isl_export
 __isl_give isl_union_map *isl_union_map_apply_range(
        __isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2);
+__isl_give isl_union_map *isl_union_map_preimage_domain_multi_aff(
+       __isl_take isl_union_map *umap, __isl_take isl_multi_aff *ma);
 __isl_export
 __isl_give isl_union_map *isl_union_map_reverse(__isl_take isl_union_map *umap);
 __isl_give isl_union_map *isl_union_map_from_domain_and_range(
 __isl_export
 __isl_give isl_union_map *isl_union_map_reverse(__isl_take isl_union_map *umap);
 __isl_give isl_union_map *isl_union_map_from_domain_and_range(
index bc8b748..fa26538 100644 (file)
@@ -3332,7 +3332,7 @@ struct {
          "{ A[i,j] : j = [(i)/6] and exists a : i = 3 a }" },
 };
 
          "{ A[i,j] : j = [(i)/6] and exists a : i = 3 a }" },
 };
 
-int test_preimage(isl_ctx *ctx)
+static int test_preimage_basic_set(isl_ctx *ctx)
 {
        int i;
        isl_basic_set *bset1, *bset2;
 {
        int i;
        isl_basic_set *bset1, *bset2;
@@ -3358,6 +3358,76 @@ int test_preimage(isl_ctx *ctx)
 }
 
 struct {
 }
 
 struct {
+       const char *map;
+       const char *ma;
+       const char *res;
+} preimage_domain_tests[] = {
+       { "{ B[i,j] -> C[2i + 3j] : 0 <= i < 10 and 0 <= j < 100 }",
+         "{ A[j,i] -> B[i,j] }",
+         "{ A[j,i] -> C[2i + 3j] : 0 <= i < 10 and 0 <= j < 100 }" },
+       { "{ B[i] -> C[i]; D[i] -> E[i] }",
+         "{ A[i] -> B[i + 1] }",
+         "{ A[i] -> C[i + 1] }" },
+       { "{ B[i] -> C[i]; B[i] -> E[i] }",
+         "{ A[i] -> B[i + 1] }",
+         "{ A[i] -> C[i + 1]; A[i] -> E[i + 1] }" },
+       { "{ B[i] -> C[([i/2])] }",
+         "{ A[i] -> B[2i] }",
+         "{ A[i] -> C[i] }" },
+       { "{ B[i,j] -> C[([i/2]), ([(i+j)/3])] }",
+         "{ A[i] -> B[([i/5]), ([i/7])] }",
+         "{ A[i] -> C[([([i/5])/2]), ([(([i/5])+([i/7]))/3])] }" },
+       { "[N] -> { B[i] -> C[([N/2]), i, ([N/3])] }",
+         "[N] -> { A[] -> B[([N/5])] }",
+         "[N] -> { A[] -> C[([N/2]), ([N/5]), ([N/3])] }" },
+       { "{ B[i] -> C[i] : exists a : i = 5 a }",
+         "{ A[i] -> B[2i] }",
+         "{ A[i] -> C[2i] : exists a : 2i = 5 a }" },
+       { "{ B[i] -> C[i] : exists a : i = 2 a; "
+           "B[i] -> D[i] : exists a : i = 2 a + 1 }",
+         "{ A[i] -> B[2i] }",
+         "{ A[i] -> C[2i] }" },
+};
+
+static int test_preimage_union_map(isl_ctx *ctx)
+{
+       int i;
+       isl_union_map *umap1, *umap2;
+       isl_multi_aff *ma;
+       int equal;
+
+       for (i = 0; i < ARRAY_SIZE(preimage_domain_tests); ++i) {
+               umap1 = isl_union_map_read_from_str(ctx,
+                                               preimage_domain_tests[i].map);
+               ma = isl_multi_aff_read_from_str(ctx,
+                                               preimage_domain_tests[i].ma);
+               umap2 = isl_union_map_read_from_str(ctx,
+                                               preimage_domain_tests[i].res);
+               umap1 = isl_union_map_preimage_domain_multi_aff(umap1, ma);
+               equal = isl_union_map_is_equal(umap1, umap2);
+               isl_union_map_free(umap1);
+               isl_union_map_free(umap2);
+               if (equal < 0)
+                       return -1;
+               if (!equal)
+                       isl_die(ctx, isl_error_unknown, "bad preimage",
+                               return -1);
+       }
+
+       return 0;
+}
+
+static int test_preimage(isl_ctx *ctx)
+{
+       if (test_preimage_basic_set(ctx) < 0)
+               return -1;
+       if (test_preimage_union_map(ctx) < 0)
+               return -1;
+
+       return 0;
+}
+
+struct {
        const char *ma1;
        const char *ma;
        const char *res;
        const char *ma1;
        const char *ma;
        const char *res;
index ed6639f..0edaf55 100644 (file)
@@ -12,6 +12,7 @@
 #include <isl_map_private.h>
 #include <isl/ctx.h>
 #include <isl/hash.h>
 #include <isl_map_private.h>
 #include <isl/ctx.h>
 #include <isl/hash.h>
+#include <isl/aff.h>
 #include <isl/map.h>
 #include <isl/set.h>
 #include <isl_space_private.h>
 #include <isl/map.h>
 #include <isl/set.h>
 #include <isl_space_private.h>
@@ -2532,3 +2533,84 @@ error:
        isl_union_set_free(res);
        return NULL;
 }
        isl_union_set_free(res);
        return NULL;
 }
+
+/* Internal data structure for isl_union_map_preimage_domain_multi_aff.
+ *
+ * "ma" is the function under which the preimage should be taken.
+ * "space" is the space of "ma".
+ * "res" collects the results.
+ */
+struct isl_union_map_preimage_domain_data {
+       isl_space *space;
+       isl_multi_aff *ma;
+       isl_union_map *res;
+};
+
+/* Compute the preimage of the domain of *entry under the function
+ * represented by data->ma, provided the domain space of *entry
+ * match the target space of data->ma, and add the result to data->res.
+ */
+static int preimage_domain_entry(void **entry, void *user)
+{
+       int m;
+       isl_map *map = *entry;
+       struct isl_union_map_preimage_domain_data *data = user;
+       int empty;
+
+       m = isl_space_tuple_match(map->dim, isl_dim_in,
+                                       data->space, isl_dim_out);
+       if (m < 0)
+               return -1;
+       if (!m)
+               return 0;
+
+       map = isl_map_copy(map);
+       map = isl_map_preimage_domain_multi_aff(map,
+                                               isl_multi_aff_copy(data->ma));
+
+       empty = isl_map_is_empty(map);
+       if (empty < 0 || empty) {
+               isl_map_free(map);
+               return empty < 0 ? -1 : 0;
+       }
+
+       data->res = isl_union_map_add_map(data->res, map);
+
+       return 0;
+}
+
+/* Compute the preimage of the domain of "umap" under the function
+ * represented by "ma".
+ * In other words, plug in "ma" in the domain of "umap".
+ * The result contains maps that live in the same spaces as the maps of "umap"
+ * with domain space equal to the target space of "ma",
+ * except that the domain has been replaced by the domain space of "ma".
+ */
+__isl_give isl_union_map *isl_union_map_preimage_domain_multi_aff(
+       __isl_take isl_union_map *umap, __isl_take isl_multi_aff *ma)
+{
+       isl_ctx *ctx;
+       isl_space *space;
+       struct isl_union_map_preimage_domain_data data;
+
+       if (!umap || !ma)
+               goto error;
+
+       ctx = isl_union_map_get_ctx(umap);
+       space = isl_union_map_get_space(umap);
+       data.space = isl_multi_aff_get_space(ma);
+       data.ma = ma;
+       data.res = isl_union_map_alloc(space, umap->table.n);
+       if (isl_hash_table_foreach(ctx, &umap->table, &preimage_domain_entry,
+                                       &data) < 0)
+               data.res = isl_union_map_free(data.res);
+
+       isl_space_free(data.space);
+       isl_union_map_free(umap);
+       isl_multi_aff_free(ma);
+       return data.res;
+error:
+       isl_union_map_free(umap);
+       isl_multi_aff_free(ma);
+       return NULL;
+}