isl_map_transitive_closure: break early if input map doesn't compose with itself
authorSven Verdoolaege <skimo@kotnet.org>
Wed, 31 Mar 2010 19:37:00 +0000 (21:37 +0200)
committerSven Verdoolaege <skimo@kotnet.org>
Thu, 1 Apr 2010 17:54:09 +0000 (19:54 +0200)
doc/implementation.tex
isl_test.c
isl_transitive_closure.c

index 13d35d0..3e3468a 100644 (file)
@@ -182,6 +182,12 @@ $$
 
 \subsection{Computing an Approximation of $R^k$}
 
+There are some special cases where the computation of $R^k$ is very easy.
+One such case is that where $R$ does not compose with itself,
+i.e., $R \circ R = \emptyset$ or $\domain R \cap \range R = \emptyset$.
+In this case, $R^k$ is only non-empty for $k=1$ where it is equal
+to $R$ itself.
+
 In general, it is impossible to construct a closed form
 of $R^k$ as a polyhedral relation.
 We will therefore need to make some approximations.
index a1fccdd..70bcfc2 100644 (file)
@@ -696,6 +696,7 @@ void test_coalesce(struct isl_ctx *ctx)
 
 void test_closure(struct isl_ctx *ctx)
 {
+       const char *str;
        isl_set *dom;
        isl_map *up, *right;
        isl_map *map, *map2;
@@ -879,6 +880,18 @@ void test_closure(struct isl_ctx *ctx)
        assert(isl_map_is_equal(map, map2));
        isl_map_free(map);
        isl_map_free(map2);
+
+       str = "[n, m] -> { [i0, i1, i2, i3] -> [o0, o1, o2, o3] : "
+           "i3 = 1 and o0 = i0 and o1 = -1 + i1 and o2 = -1 + i2 and "
+           "o3 = -2 + i2 and i1 <= -1 + i0 and i1 >= 1 - m + i0 and "
+           "i1 >= 2 and i1 <= n and i2 >= 3 and i2 <= 1 + n and i2 <= m }";
+       map = isl_map_read_from_str(ctx, str, -1);
+       map = isl_map_transitive_closure(map, &exact);
+       assert(exact);
+       map2 = isl_map_read_from_str(ctx, str, -1);
+       assert(isl_map_is_equal(map, map2));
+       isl_map_free(map);
+       isl_map_free(map2);
 }
 
 int main()
index 369d0fb..ba7153b 100644 (file)
@@ -610,6 +610,7 @@ static __isl_give isl_map *construct_component(__isl_take isl_dim *dim,
 {
        struct isl_set *domain = NULL;
        struct isl_set *range = NULL;
+       struct isl_set *overlap;
        struct isl_map *app = NULL;
        struct isl_map *path = NULL;
 
@@ -617,6 +618,20 @@ static __isl_give isl_map *construct_component(__isl_take isl_dim *dim,
        domain = isl_set_coalesce(domain);
        range = isl_map_range(isl_map_copy(map));
        range = isl_set_coalesce(range);
+       overlap = isl_set_intersect(isl_set_copy(domain), isl_set_copy(range));
+       if (isl_set_is_empty(overlap) == 1) {
+               isl_set_free(domain);
+               isl_set_free(range);
+               isl_set_free(overlap);
+               isl_dim_free(dim);
+
+               map = isl_map_copy(map);
+               map = isl_map_add(map, isl_dim_in, 1);
+               map = isl_map_add(map, isl_dim_out, 1);
+               map = set_path_length(map, 1, 1);
+               return map;
+       }
+       isl_set_free(overlap);
        app = isl_map_from_domain_and_range(domain, range);
        app = isl_map_add(app, isl_dim_in, 1);
        app = isl_map_add(app, isl_dim_out, 1);