add isl_map_{lexmin,lexmax}_pw_multi_aff
authorSven Verdoolaege <skimo@kotnet.org>
Thu, 19 Apr 2012 19:55:09 +0000 (21:55 +0200)
committerSven Verdoolaege <skimo@kotnet.org>
Thu, 2 Aug 2012 10:20:09 +0000 (12:20 +0200)
Signed-off-by: Sven Verdoolaege <skimo@kotnet.org>
Makefile.am
doc/user.pod
include/isl/map.h
isl_map.c
isl_map_lexopt_templ.c [new file with mode: 0644]

index c650752..e1f26b3 100644 (file)
@@ -239,6 +239,7 @@ EXTRA_DIST = \
        basis_reduction_templ.c \
        isl_list_templ.c \
        isl_list_templ.h \
+       isl_map_lexopt_templ.c \
        isl_multi_templ.c \
        isl_multi_templ.h \
        print_templ.c \
index 12e5470..46e5a4c 100644 (file)
@@ -2859,6 +2859,10 @@ returning a basic set or relation.
                __isl_take isl_basic_map *bmap,
                __isl_take isl_basic_set *dom,
                __isl_give isl_set **empty);
+       __isl_give isl_pw_multi_aff *isl_map_lexmin_pw_multi_aff(
+               __isl_take isl_map *map);
+       __isl_give isl_pw_multi_aff *isl_map_lexmax_pw_multi_aff(
+               __isl_take isl_map *map);
 
 =head2 Lists
 
index ecba464..7613b06 100644 (file)
@@ -257,6 +257,10 @@ __isl_give isl_pw_multi_aff *isl_basic_map_partial_lexmax_pw_multi_aff(
        __isl_give isl_set **empty);
 __isl_give isl_pw_multi_aff *isl_basic_map_lexmin_pw_multi_aff(
        __isl_take isl_basic_map *bmap);
+__isl_give isl_pw_multi_aff *isl_map_lexmin_pw_multi_aff(
+       __isl_take isl_map *map);
+__isl_give isl_pw_multi_aff *isl_map_lexmax_pw_multi_aff(
+       __isl_take isl_map *map);
 
 void isl_basic_map_print_internal(__isl_keep isl_basic_map *bmap,
        FILE *out, int indent);
index c1ab54a..290ee4e 100644 (file)
--- a/isl_map.c
+++ b/isl_map.c
@@ -5618,58 +5618,93 @@ __isl_give isl_pw_multi_aff *isl_basic_map_lexmin_pw_multi_aff(
        return isl_basic_map_lexopt_pw_multi_aff(bmap, 0);
 }
 
-/* Given a basic map "bmap", compute the lexicographically minimal
- * (or maximal) image element for each domain element in dom.
+#undef TYPE
+#define TYPE   isl_pw_multi_aff
+#undef SUFFIX
+#define SUFFIX _pw_multi_aff
+#undef EMPTY
+#define EMPTY  isl_pw_multi_aff_empty
+#undef ADD
+#define ADD    isl_pw_multi_aff_union_add
+#include "isl_map_lexopt_templ.c"
+
+/* Given a map "map", compute the lexicographically minimal
+ * (or maximal) image element for each domain element in dom,
+ * in the form of an isl_pw_multi_aff.
  * Set *empty to those elements in dom that do not have an image element.
  *
- * We first make sure the basic sets in dom are disjoint and then
- * simply collect the results over each of the basic sets separately.
- * We could probably improve the efficiency a bit by moving the union
- * domain down into the parametric integer programming.
+ * We first compute the lexicographically minimal or maximal element
+ * in the first basic map.  This results in a partial solution "res"
+ * and a subset "todo" of dom that still need to be handled.
+ * We then consider each of the remaining maps in "map" and successively
+ * update both "res" and "todo".
  */
-static __isl_give isl_map *basic_map_partial_lexopt(
-               __isl_take isl_basic_map *bmap, __isl_take isl_set *dom,
-               __isl_give isl_set **empty, int max)
+static __isl_give isl_pw_multi_aff *isl_map_partial_lexopt_aligned_pw_multi_aff(
+       __isl_take isl_map *map, __isl_take isl_set *dom,
+       __isl_give isl_set **empty, int max)
 {
        int i;
-       struct isl_map *res;
+       isl_pw_multi_aff *res;
+       isl_set *todo;
 
-       dom = isl_set_make_disjoint(dom);
-       if (!dom)
+       if (!map || !dom)
                goto error;
 
-       if (isl_set_plain_is_empty(dom)) {
-               res = isl_map_empty_like_basic_map(bmap);
-               *empty = isl_set_empty_like(dom);
-               isl_set_free(dom);
-               isl_basic_map_free(bmap);
-               return res;
+       if (isl_map_plain_is_empty(map)) {
+               if (empty)
+                       *empty = dom;
+               else
+                       isl_set_free(dom);
+               return isl_pw_multi_aff_from_map(map);
        }
 
-       res = isl_basic_map_partial_lexopt(isl_basic_map_copy(bmap),
-                       isl_basic_set_copy(dom->p[0]), empty, max);
-               
-       for (i = 1; i < dom->n; ++i) {
-               struct isl_map *res_i;
-               struct isl_set *empty_i;
+       res = basic_map_partial_lexopt_pw_multi_aff(
+                                           isl_basic_map_copy(map->p[0]),
+                                           isl_set_copy(dom), &todo, max);
 
-               res_i = isl_basic_map_partial_lexopt(isl_basic_map_copy(bmap),
-                               isl_basic_set_copy(dom->p[i]), &empty_i, max);
+       for (i = 1; i < map->n; ++i) {
+               isl_pw_multi_aff *res_i;
+               isl_set *todo_i;
 
-               res = isl_map_union_disjoint(res, res_i);
-               *empty = isl_set_union_disjoint(*empty, empty_i);
+               res_i = basic_map_partial_lexopt_pw_multi_aff(
+                                           isl_basic_map_copy(map->p[i]),
+                                           isl_set_copy(dom), &todo_i, max);
+
+               if (max)
+                       res = isl_pw_multi_aff_union_lexmax(res, res_i);
+               else
+                       res = isl_pw_multi_aff_union_lexmin(res, res_i);
+
+               todo = isl_set_intersect(todo, todo_i);
        }
 
        isl_set_free(dom);
-       isl_basic_map_free(bmap);
+       isl_map_free(map);
+
+       if (empty)
+               *empty = todo;
+       else
+               isl_set_free(todo);
+
        return res;
 error:
-       *empty = NULL;
+       if (empty)
+               *empty = NULL;
        isl_set_free(dom);
-       isl_basic_map_free(bmap);
+       isl_map_free(map);
        return NULL;
 }
 
+#undef TYPE
+#define TYPE   isl_map
+#undef SUFFIX
+#define SUFFIX
+#undef EMPTY
+#define EMPTY  isl_map_empty
+#undef ADD
+#define ADD    isl_map_union_disjoint
+#include "isl_map_lexopt_templ.c"
+
 /* Given a map "map", compute the lexicographically minimal
  * (or maximal) image element for each domain element in dom.
  * Set *empty to those elements in dom that do not have an image element.
@@ -5678,7 +5713,7 @@ error:
  * in the first basic map.  This results in a partial solution "res"
  * and a subset "todo" of dom that still need to be handled.
  * We then consider each of the remaining maps in "map" and successively
- * improve both "res" and "todo".
+ * update both "res" and "todo".
  *
  * Let res^k and todo^k be the results after k steps and let i = k + 1.
  * Assume we are computing the lexicographical maximum.
@@ -5797,35 +5832,6 @@ error:
        return NULL;
 }
 
-/* Given a map "map", compute the lexicographically minimal
- * (or maximal) image element for each domain element in dom.
- * Set *empty to those elements in dom that do not have an image element.
- *
- * Align parameters if needed and then call isl_map_partial_lexopt_aligned.
- */
-static __isl_give isl_map *isl_map_partial_lexopt(
-               __isl_take isl_map *map, __isl_take isl_set *dom,
-               __isl_give isl_set **empty, int max)
-{
-       if (!map || !dom)
-               goto error;
-       if (isl_space_match(map->dim, isl_dim_param, dom->dim, isl_dim_param))
-               return isl_map_partial_lexopt_aligned(map, dom, empty, max);
-       if (!isl_space_has_named_params(map->dim) ||
-           !isl_space_has_named_params(dom->dim))
-               isl_die(map->ctx, isl_error_invalid,
-                       "unaligned unnamed parameters", goto error);
-       map = isl_map_align_params(map, isl_map_get_space(dom));
-       dom = isl_map_align_params(dom, isl_map_get_space(map));
-       return isl_map_partial_lexopt_aligned(map, dom, empty, max);
-error:
-       if (empty)
-               *empty = NULL;
-       isl_set_free(dom);
-       isl_map_free(map);
-       return NULL;
-}
-
 __isl_give isl_map *isl_map_partial_lexmax(
                __isl_take isl_map *map, __isl_take isl_set *dom,
                __isl_give isl_set **empty)
@@ -5893,31 +5899,6 @@ __isl_give isl_set *isl_basic_set_lexmax(__isl_take isl_basic_set *bset)
        return (isl_set *)isl_basic_map_lexmax((isl_basic_map *)bset);
 }
 
-__isl_give isl_map *isl_map_lexopt(__isl_take isl_map *map, int max)
-{
-       struct isl_set *dom = NULL;
-       isl_space *dom_dim;
-
-       if (!map)
-               goto error;
-       dom_dim = isl_space_domain(isl_space_copy(map->dim));
-       dom = isl_set_universe(dom_dim);
-       return isl_map_partial_lexopt(map, dom, NULL, max);
-error:
-       isl_map_free(map);
-       return NULL;
-}
-
-__isl_give isl_map *isl_map_lexmin(__isl_take isl_map *map)
-{
-       return isl_map_lexopt(map, 0);
-}
-
-__isl_give isl_map *isl_map_lexmax(__isl_take isl_map *map)
-{
-       return isl_map_lexopt(map, 1);
-}
-
 __isl_give isl_set *isl_set_lexmin(__isl_take isl_set *set)
 {
        return (isl_set *)isl_map_lexmin((isl_map *)set);
diff --git a/isl_map_lexopt_templ.c b/isl_map_lexopt_templ.c
new file mode 100644 (file)
index 0000000..275c14f
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2010      INRIA Saclay
+ * Copyright 2012      Ecole Normale Superieure
+ *
+ * Use of this software is governed by the GNU LGPLv2.1 license
+ *
+ * Written by Sven Verdoolaege,
+ * INRIA Saclay - Ile-de-France, Parc Club Orsay Universite,
+ * ZAC des vignes, 4 rue Jacques Monod, 91893 Orsay, France
+ * and Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France
+ */
+
+/* Function for computing the lexicographic optimum of a map
+ * in the form of either an isl_map or an isl_pw_multi_aff.
+ */
+
+#define xSF(TYPE,SUFFIX) TYPE ## SUFFIX
+#define SF(TYPE,SUFFIX) xSF(TYPE,SUFFIX)
+
+/* Given a basic map "bmap", compute the lexicographically minimal
+ * (or maximal) image element for each domain element in dom.
+ * Set *empty to those elements in dom that do not have an image element.
+ *
+ * We first make sure the basic sets in dom are disjoint and then
+ * simply collect the results over each of the basic sets separately.
+ * We could probably improve the efficiency a bit by moving the union
+ * domain down into the parametric integer programming.
+ */
+static __isl_give TYPE *SF(basic_map_partial_lexopt,SUFFIX)(
+       __isl_take isl_basic_map *bmap, __isl_take isl_set *dom,
+       __isl_give isl_set **empty, int max)
+{
+       int i;
+       TYPE *res;
+
+       dom = isl_set_make_disjoint(dom);
+       if (!dom)
+               goto error;
+
+       if (isl_set_plain_is_empty(dom)) {
+               isl_space *space = isl_basic_map_get_space(bmap);
+               if (empty)
+                       *empty = dom;
+               else
+                       isl_set_free(dom);
+               isl_basic_map_free(bmap);
+               return EMPTY(space);
+       }
+
+       res = SF(isl_basic_map_partial_lexopt,SUFFIX)(isl_basic_map_copy(bmap),
+                       isl_basic_set_copy(dom->p[0]), empty, max);
+               
+       for (i = 1; i < dom->n; ++i) {
+               TYPE *res_i;
+               isl_set *empty_i;
+
+               res_i = SF(isl_basic_map_partial_lexopt,SUFFIX)(
+                               isl_basic_map_copy(bmap),
+                               isl_basic_set_copy(dom->p[i]), &empty_i, max);
+
+               res = ADD(res, res_i);
+               *empty = isl_set_union_disjoint(*empty, empty_i);
+       }
+
+       isl_set_free(dom);
+       isl_basic_map_free(bmap);
+       return res;
+error:
+       *empty = NULL;
+       isl_set_free(dom);
+       isl_basic_map_free(bmap);
+       return NULL;
+}
+
+static __isl_give TYPE *SF(isl_map_partial_lexopt_aligned,SUFFIX)(
+       __isl_take isl_map *map, __isl_take isl_set *dom,
+       __isl_give isl_set **empty, int max);
+
+/* Given a map "map", compute the lexicographically minimal
+ * (or maximal) image element for each domain element in dom.
+ * Set *empty to those elements in dom that do not have an image element.
+ *
+ * Align parameters if needed and then call isl_map_partial_lexopt_aligned.
+ */
+static __isl_give TYPE *SF(isl_map_partial_lexopt,SUFFIX)(
+       __isl_take isl_map *map, __isl_take isl_set *dom,
+       __isl_give isl_set **empty, int max)
+{
+       if (!map || !dom)
+               goto error;
+       if (isl_space_match(map->dim, isl_dim_param, dom->dim, isl_dim_param))
+               return SF(isl_map_partial_lexopt_aligned,SUFFIX)(map, dom,
+                                                               empty, max);
+       if (!isl_space_has_named_params(map->dim) ||
+           !isl_space_has_named_params(dom->dim))
+               isl_die(map->ctx, isl_error_invalid,
+                       "unaligned unnamed parameters", goto error);
+       map = isl_map_align_params(map, isl_map_get_space(dom));
+       dom = isl_map_align_params(dom, isl_map_get_space(map));
+       return SF(isl_map_partial_lexopt_aligned,SUFFIX)(map, dom, empty, max);
+error:
+       if (empty)
+               *empty = NULL;
+       isl_set_free(dom);
+       isl_map_free(map);
+       return NULL;
+}
+
+__isl_give TYPE *SF(isl_map_lexopt,SUFFIX)(__isl_take isl_map *map, int max)
+{
+       isl_set *dom = NULL;
+       isl_space *dom_space;
+
+       if (!map)
+               goto error;
+       dom_space = isl_space_domain(isl_space_copy(map->dim));
+       dom = isl_set_universe(dom_space);
+       return SF(isl_map_partial_lexopt,SUFFIX)(map, dom, NULL, max);
+error:
+       isl_map_free(map);
+       return NULL;
+}
+
+__isl_give TYPE *SF(isl_map_lexmin,SUFFIX)(__isl_take isl_map *map)
+{
+       return SF(isl_map_lexopt,SUFFIX)(map, 0);
+}
+
+__isl_give TYPE *SF(isl_map_lexmax,SUFFIX)(__isl_take isl_map *map)
+{
+       return SF(isl_map_lexopt,SUFFIX)(map, 1);
+}