add isl_map_fixed_power and isl_union_map_fixed_power
authorSven Verdoolaege <skimo@kotnet.org>
Wed, 7 Mar 2012 09:08:50 +0000 (10:08 +0100)
committerSven Verdoolaege <skimo@kotnet.org>
Wed, 7 Mar 2012 10:50:43 +0000 (11:50 +0100)
Signed-off-by: Sven Verdoolaege <skimo@kotnet.org>
Makefile.am
doc/user.pod
include/isl/map.h
include/isl/union_map.h
isl_power_templ.c [new file with mode: 0644]
isl_test.c
isl_transitive_closure.c

index 5a8d307..35e1dbd 100644 (file)
@@ -240,6 +240,7 @@ EXTRA_DIST = \
        isl_multi_templ.c \
        isl_multi_templ.h \
        print_templ.c \
+       isl_power_templ.c \
        isl_pw_templ.c \
        isl_union_templ.c \
        isl.py \
index bfd40c8..bd3b0d8 100644 (file)
@@ -2121,6 +2121,15 @@ dualization algorithms or skip the elimination step.
 
 =item * Power
 
+       __isl_give isl_map *isl_map_fixed_power(
+               __isl_take isl_map *map, isl_int exp);
+       __isl_give isl_union_map *isl_union_map_fixed_power(
+               __isl_take isl_union_map *umap, isl_int exp);
+
+Compute the given power of C<map>, where C<exp> is assumed to be non-zero.
+If the exponent C<exp> is negative, then the -C<exp> th power of the inverse
+of C<map> is computed.
+
        __isl_give isl_map *isl_map_power(__isl_take isl_map *map,
                int *exact);
        __isl_give isl_union_map *isl_union_map_power(
index a4969e6..b99b73c 100644 (file)
@@ -549,6 +549,7 @@ int isl_map_foreach_basic_map(__isl_keep isl_map *map,
 
 __isl_give isl_map *isl_set_lifting(__isl_take isl_set *set);
 
+__isl_give isl_map *isl_map_fixed_power(__isl_take isl_map *map, isl_int exp);
 __isl_give isl_map *isl_map_power(__isl_take isl_map *map, int *exact);
 __isl_give isl_map *isl_map_reaching_path_lengths(__isl_take isl_map *map,
        int *exact);
index 8054d9d..bec5a9c 100644 (file)
@@ -150,6 +150,8 @@ __isl_give isl_map *isl_map_from_union_map(__isl_take isl_union_map *umap);
 
 __isl_give isl_basic_map *isl_union_map_sample(__isl_take isl_union_map *umap);
 
+__isl_give isl_union_map *isl_union_map_fixed_power(
+       __isl_take isl_union_map *umap, isl_int exp);
 __isl_give isl_union_map *isl_union_map_power(__isl_take isl_union_map *umap,
        int *exact);
 __isl_give isl_union_map *isl_union_map_transitive_closure(
diff --git a/isl_power_templ.c b/isl_power_templ.c
new file mode 100644 (file)
index 0000000..b9fc559
--- /dev/null
@@ -0,0 +1,58 @@
+#define xFN(TYPE,NAME) TYPE ## _ ## NAME
+#define FN(TYPE,NAME) xFN(TYPE,NAME)
+
+/* Compute the given non-zero power of "map" and return the result.
+ * If the exponent "exp" is negative, then the -exp th power of the inverse
+ * relation is computed.
+ */
+__isl_give TYPE *FN(TYPE,fixed_power)(__isl_take TYPE *map, isl_int exp)
+{
+       isl_ctx *ctx;
+       TYPE *res = NULL;
+       isl_int r;
+
+       if (!map)
+               return NULL;
+
+       ctx = FN(TYPE,get_ctx)(map);
+       if (isl_int_is_zero(exp))
+               isl_die(ctx, isl_error_invalid,
+                       "expecting non-zero exponent", goto error);
+
+       if (isl_int_is_neg(exp)) {
+               isl_int_neg(exp, exp);
+               map = FN(TYPE,reverse)(map);
+               return FN(TYPE,fixed_power)(map, exp);
+       }
+
+       isl_int_init(r);
+       for (;;) {
+               isl_int_fdiv_r(r, exp, ctx->two);
+
+               if (!isl_int_is_zero(r)) {
+                       if (!res)
+                               res = FN(TYPE,copy)(map);
+                       else {
+                               res = FN(TYPE,apply_range)(res,
+                                                         FN(TYPE,copy)(map));
+                               res = FN(TYPE,coalesce)(res);
+                       }
+                       if (!res)
+                               break;
+               }
+
+               isl_int_fdiv_q(exp, exp, ctx->two);
+               if (isl_int_is_zero(exp))
+                       break;
+
+               map = FN(TYPE,apply_range)(map, FN(TYPE,copy)(map));
+               map = FN(TYPE,coalesce)(map);
+       }
+       isl_int_clear(r);
+
+       FN(TYPE,free)(map);
+       return res;
+error:
+       FN(TYPE,free)(map);
+       return NULL;
+}
index 4cb7de3..88ba123 100644 (file)
@@ -1455,6 +1455,19 @@ static int map_is_equal(__isl_keep isl_map *map, const char *str)
        return equal;
 }
 
+static int map_check_equal(__isl_keep isl_map *map, const char *str)
+{
+       int equal;
+
+       equal = map_is_equal(map, str);
+       if (equal < 0)
+               return -1;
+       if (!equal)
+               isl_die(isl_map_get_ctx(map), isl_error_unknown,
+                       "result not as expected", return -1);
+       return 0;
+}
+
 void test_dep(struct isl_ctx *ctx)
 {
        const char *str;
@@ -2756,6 +2769,27 @@ int test_sample(isl_ctx *ctx)
        return 0;
 }
 
+int test_fixed_power(isl_ctx *ctx)
+{
+       const char *str;
+       isl_map *map;
+       isl_int exp;
+       int equal;
+
+       isl_int_init(exp);
+       str = "{ [i] -> [i + 1] }";
+       map = isl_map_read_from_str(ctx, str);
+       isl_int_set_si(exp, 23);
+       map = isl_map_fixed_power(map, exp);
+       equal = map_check_equal(map, "{ [i] -> [i + 23] }");
+       isl_int_clear(exp);
+       isl_map_free(map);
+       if (equal < 0)
+               return -1;
+
+       return 0;
+}
+
 int main()
 {
        struct isl_ctx *ctx;
@@ -2764,6 +2798,8 @@ int main()
        assert(srcdir);
 
        ctx = isl_ctx_alloc();
+       if (test_fixed_power(ctx) < 0)
+               goto error;
        if (test_sample(ctx) < 0)
                goto error;
        if (test_output(ctx) < 0)
index 20e020e..59cb8bd 100644 (file)
@@ -3102,3 +3102,11 @@ __isl_give isl_union_map *isl_union_map_power(__isl_take isl_union_map *umap,
        
        return umap;
 }
+
+#undef TYPE
+#define TYPE isl_map
+#include "isl_power_templ.c"
+
+#undef TYPE
+#define TYPE isl_union_map
+#include "isl_power_templ.c"