add isl_multi_aff_pullback_multi_aff
authorSven Verdoolaege <skimo@kotnet.org>
Fri, 20 Jul 2012 12:07:37 +0000 (14:07 +0200)
committerSven Verdoolaege <skimo@kotnet.org>
Tue, 18 Sep 2012 13:08:21 +0000 (15:08 +0200)
Signed-off-by: Sven Verdoolaege <skimo@kotnet.org>
doc/user.pod
include/isl/aff.h
isl_aff.c
isl_test.c

index 426a943..521773a 100644 (file)
@@ -3932,6 +3932,15 @@ If the C<ls> argument of C<isl_multi_aff_lift> is not C<NULL>,
 then it is assigned the local space that lies at the basis of
 the lifting applied.
 
+       #include <isl/aff.h>
+       __isl_give isl_multi_aff *isl_multi_aff_pullback_multi_aff(
+               __isl_take isl_multi_aff *ma1,
+               __isl_take isl_multi_aff *ma2);
+
+The function C<isl_multi_aff_pullback_multi_aff> precomposes C<ma1> by C<ma2>.
+In other words, C<ma2> is plugged
+into C<ma1>.
+
        __isl_give isl_set *isl_multi_aff_lex_le_set(
                __isl_take isl_multi_aff *ma1,
                __isl_take isl_multi_aff *ma2);
index d5527f9..3f548ff 100644 (file)
@@ -333,6 +333,9 @@ __isl_give isl_multi_aff *isl_multi_aff_gist(__isl_take isl_multi_aff *maff,
 __isl_give isl_multi_aff *isl_multi_aff_lift(__isl_take isl_multi_aff *maff,
        __isl_give isl_local_space **ls);
 
+__isl_give isl_multi_aff *isl_multi_aff_pullback_multi_aff(
+       __isl_take isl_multi_aff *ma1, __isl_take isl_multi_aff *ma2);
+
 __isl_give isl_set *isl_multi_aff_lex_le_set(__isl_take isl_multi_aff *ma1,
        __isl_take isl_multi_aff *ma2);
 __isl_give isl_set *isl_multi_aff_lex_ge_set(__isl_take isl_multi_aff *ma1,
index 1117f4d..cfd08a7 100644 (file)
--- a/isl_aff.c
+++ b/isl_aff.c
@@ -3552,6 +3552,40 @@ error:
        return NULL;
 }
 
+/* Compute the pullback of "ma1" by the function represented by "ma2".
+ * In other words, plug in "ma2" in "ma1".
+ */
+__isl_give isl_multi_aff *isl_multi_aff_pullback_multi_aff(
+       __isl_take isl_multi_aff *ma1, __isl_take isl_multi_aff *ma2)
+{
+       int i;
+       isl_space *space = NULL;
+
+       ma2 = isl_multi_aff_align_divs(ma2);
+       ma1 = isl_multi_aff_cow(ma1);
+       if (!ma1 || !ma2)
+               goto error;
+
+       space = isl_space_join(isl_multi_aff_get_space(ma2),
+                               isl_multi_aff_get_space(ma1));
+
+       for (i = 0; i < ma1->n; ++i) {
+               ma1->p[i] = isl_aff_pullback_multi_aff(ma1->p[i],
+                                                   isl_multi_aff_copy(ma2));
+               if (!ma1->p[i])
+                       goto error;
+       }
+
+       ma1 = isl_multi_aff_reset_space(ma1, space);
+       isl_multi_aff_free(ma2);
+       return ma1;
+error:
+       isl_space_free(space);
+       isl_multi_aff_free(ma2);
+       isl_multi_aff_free(ma1);
+       return NULL;
+}
+
 /* Extend the local space of "dst" to include the divs
  * in the local space of "src".
  */
index 60f70a5..17d9c83 100644 (file)
@@ -3239,12 +3239,60 @@ int test_preimage(isl_ctx *ctx)
 }
 
 struct {
+       const char *ma1;
+       const char *ma;
+       const char *res;
+} pullback_tests[] = {
+       { "{ B[i,j] -> C[i + 2j] }" , "{ A[a,b] -> B[b,a] }",
+         "{ A[a,b] -> C[b + 2a] }" },
+       { "{ B[i] -> C[2i] }", "{ A[a] -> B[(a)/2] }", "{ A[a] -> C[a] }" },
+       { "{ B[i] -> C[(i)/2] }", "{ A[a] -> B[2a] }", "{ A[a] -> C[a] }" },
+       { "{ B[i] -> C[(i)/2] }", "{ A[a] -> B[(a)/3] }",
+         "{ A[a] -> C[(a)/6] }" },
+       { "{ B[i] -> C[2i] }", "{ A[a] -> B[5a] }", "{ A[a] -> C[10a] }" },
+       { "{ B[i] -> C[2i] }", "{ A[a] -> B[(a)/3] }",
+         "{ A[a] -> C[(2a)/3] }" },
+       { "{ B[i,j] -> C[i + j] }", "{ A[a] -> B[a,a] }", "{ A[a] -> C[2a] }"},
+       { "{ B[a] -> C[a,a] }", "{ A[i,j] -> B[i + j] }",
+         "{ A[i,j] -> C[i + j, i + j] }"},
+       { "{ B[i] -> C[([i/2])] }", "{ B[5] }", "{ C[2] }" },
+       { "[n] -> { B[i,j] -> C[([i/2]) + 2j] }",
+         "[n] -> { B[n,[n/3]] }", "[n] -> { C[([n/2]) + 2*[n/3]] }", },
+};
+
+static int test_pullback(isl_ctx *ctx)
+{
+       int i;
+       isl_multi_aff *ma1, *ma2;
+       isl_multi_aff *ma;
+       int equal;
+
+       for (i = 0; i < ARRAY_SIZE(pullback_tests); ++i) {
+               ma1 = isl_multi_aff_read_from_str(ctx, pullback_tests[i].ma1);
+               ma = isl_multi_aff_read_from_str(ctx, pullback_tests[i].ma);
+               ma2 = isl_multi_aff_read_from_str(ctx, pullback_tests[i].res);
+               ma1 = isl_multi_aff_pullback_multi_aff(ma1, ma);
+               equal = isl_multi_aff_plain_is_equal(ma1, ma2);
+               isl_multi_aff_free(ma1);
+               isl_multi_aff_free(ma2);
+               if (equal < 0)
+                       return -1;
+               if (!equal)
+                       isl_die(ctx, isl_error_unknown, "bad pullback",
+                               return -1);
+       }
+
+       return 0;
+}
+
+struct {
        const char *name;
        int (*fn)(isl_ctx *ctx);
 } tests [] = {
        { "list", &test_list },
        { "align parameters", &test_align_parameters },
        { "preimage", &test_preimage },
+       { "pullback", &test_pullback },
        { "eliminate", &test_eliminate },
        { "reisdue class", &test_residue_class },
        { "div", &test_div },