Merge commit 'isl-0.05.1'
[platform/upstream/isl.git] / isl_map.c
index 89be7b2..c8b15aa 100644 (file)
--- a/isl_map.c
+++ b/isl_map.c
@@ -1721,7 +1721,8 @@ static void dump(struct isl_basic_map *bmap, FILE *out, int indent)
        }
 }
 
-void isl_basic_set_dump(struct isl_basic_set *bset, FILE *out, int indent)
+void isl_basic_set_print_internal(struct isl_basic_set *bset,
+       FILE *out, int indent)
 {
        if (!bset) {
                fprintf(out, "null basic set\n");
@@ -1735,7 +1736,8 @@ void isl_basic_set_dump(struct isl_basic_set *bset, FILE *out, int indent)
        dump((struct isl_basic_map *)bset, out, indent);
 }
 
-void isl_basic_map_dump(struct isl_basic_map *bmap, FILE *out, int indent)
+void isl_basic_map_print_internal(struct isl_basic_map *bmap,
+       FILE *out, int indent)
 {
        if (!bmap) {
                fprintf(out, "null basic map\n");
@@ -1911,7 +1913,7 @@ void isl_set_free(struct isl_set *set)
        free(set);
 }
 
-void isl_set_dump(struct isl_set *set, FILE *out, int indent)
+void isl_set_print_internal(struct isl_set *set, FILE *out, int indent)
 {
        int i;
 
@@ -1927,11 +1929,11 @@ void isl_set_dump(struct isl_set *set, FILE *out, int indent)
        for (i = 0; i < set->n; ++i) {
                fprintf(out, "%*s", indent, "");
                fprintf(out, "basic set %d:\n", i);
-               isl_basic_set_dump(set->p[i], out, indent+4);
+               isl_basic_set_print_internal(set->p[i], out, indent+4);
        }
 }
 
-void isl_map_dump(struct isl_map *map, FILE *out, int indent)
+void isl_map_print_internal(struct isl_map *map, FILE *out, int indent)
 {
        int i;
 
@@ -1948,7 +1950,7 @@ void isl_map_dump(struct isl_map *map, FILE *out, int indent)
        for (i = 0; i < map->n; ++i) {
                fprintf(out, "%*s", indent, "");
                fprintf(out, "basic map %d:\n", i);
-               isl_basic_map_dump(map->p[i], out, indent+4);
+               isl_basic_map_print_internal(map->p[i], out, indent+4);
        }
 }
 
@@ -4592,7 +4594,7 @@ struct isl_set *isl_basic_set_partial_lexmax(
                        dom, empty);
 }
 
-/* Given a basic map "bmap", compute the lexicograhically minimal
+/* 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.
  *
@@ -4644,7 +4646,7 @@ error:
        return NULL;
 }
 
-/* Given a map "map", compute the lexicograhically minimal
+/* 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.
  *
@@ -4656,16 +4658,46 @@ error:
  *
  * Let res^k and todo^k be the results after k steps and let i = k + 1.
  * Assume we are computing the lexicographical maximum.
- * We first intersect basic map i with a relation that maps elements
- * to elements that are lexicographically larger than the image elements
- * in res^k and the compute the maximum image element of this intersection.
- * The result ("better") corresponds to those image elements in basic map i
- * that are better than what we had before.  The remainder ("keep") are the
- * domain elements for which the image element in res_k was better.
- * We also compute the lexicographical maximum of basic map i in todo^k.
- * res^i is the result of the operation + better + those elements in
- *             res^k that we should keep
- * todo^i is the remainder of the maximum operation on todo^k.
+ * We first compute the lexicographically maximal element in basic map i.
+ * This results in a partial solution res_i and a subset todo_i.
+ * Then we combine these results with those obtain for the first k basic maps
+ * to obtain a result that is valid for the first k+1 basic maps.
+ * In particular, the set where there is no solution is the set where
+ * there is no solution for the first k basic maps and also no solution
+ * for the ith basic map, i.e.,
+ *
+ *     todo^i = todo^k * todo_i
+ *
+ * On dom(res^k) * dom(res_i), we need to pick the larger of the two
+ * solutions, arbitrarily breaking ties in favor of res^k.
+ * That is, when res^k(a) >= res_i(a), we pick res^k and
+ * when res^k(a) < res_i(a), we pick res_i.  (Here, ">=" and "<" denote
+ * the lexicographic order.)
+ * In practice, we compute
+ *
+ *     res^k * (res_i . "<=")
+ *
+ * and
+ *
+ *     res_i * (res^k . "<")
+ *
+ * Finally, we consider the symmetric difference of dom(res^k) and dom(res_i),
+ * where only one of res^k and res_i provides a solution and we simply pick
+ * that one, i.e.,
+ *
+ *     res^k * todo_i
+ * and
+ *     res_i * todo^k
+ *
+ * Note that we only compute these intersections when dom(res^k) intersects
+ * dom(res_i).  Otherwise, the only effect of these intersections is to
+ * potentially break up res^k and res_i into smaller pieces.
+ * We want to avoid such splintering as much as possible.
+ * In fact, an earlier implementation of this function would look for
+ * better results in the domain of res^k and for extra results in todo^k,
+ * but this would always result in a splintering according to todo^k,
+ * even when the domain of basic map i is disjoint from the domains of
+ * the previous basic maps.
  */
 static __isl_give isl_map *isl_map_partial_lexopt(
                __isl_take isl_map *map, __isl_take isl_set *dom,
@@ -4690,32 +4722,38 @@ static __isl_give isl_map *isl_map_partial_lexopt(
                                        isl_set_copy(dom), &todo, max);
 
        for (i = 1; i < map->n; ++i) {
-               struct isl_map *lt;
-               struct isl_map *better;
-               struct isl_set *keep;
-               struct isl_map *res_i;
-               struct isl_set *todo_i;
-               struct isl_dim *dim = isl_map_get_dim(res);
-
-               dim = isl_dim_range(dim);
-               if (max)
-                       lt = isl_map_lex_lt(dim);
-               else
-                       lt = isl_map_lex_gt(dim);
-               lt = isl_map_apply_range(isl_map_copy(res), lt);
-               lt = isl_map_intersect(lt,
-                       isl_map_from_basic_map(isl_basic_map_copy(map->p[i])));
-               better = isl_map_partial_lexopt(lt,
-                       isl_map_domain(isl_map_copy(res)),
-                       &keep, max);
+               isl_map *lt, *le;
+               isl_map *res_i;
+               isl_set *todo_i;
+               isl_dim *dim = isl_dim_range(isl_map_get_dim(res));
 
                res_i = basic_map_partial_lexopt(isl_basic_map_copy(map->p[i]),
-                                               todo, &todo_i, max);
+                                       isl_set_copy(dom), &todo_i, max);
+
+               if (max) {
+                       lt = isl_map_lex_lt(isl_dim_copy(dim));
+                       le = isl_map_lex_le(dim);
+               } else {
+                       lt = isl_map_lex_gt(isl_dim_copy(dim));
+                       le = isl_map_lex_ge(dim);
+               }
+               lt = isl_map_apply_range(isl_map_copy(res), lt);
+               lt = isl_map_intersect(lt, isl_map_copy(res_i));
+               le = isl_map_apply_range(isl_map_copy(res_i), le);
+               le = isl_map_intersect(le, isl_map_copy(res));
+
+               if (!isl_map_is_empty(lt) || !isl_map_is_empty(le)) {
+                       res = isl_map_intersect_domain(res,
+                                                       isl_set_copy(todo_i));
+                       res_i = isl_map_intersect_domain(res_i,
+                                                       isl_set_copy(todo));
+               }
 
-               res = isl_map_intersect_domain(res, keep);
                res = isl_map_union_disjoint(res, res_i);
-               res = isl_map_union_disjoint(res, better);
-               todo = todo_i;
+               res = isl_map_union_disjoint(res, lt);
+               res = isl_map_union_disjoint(res, le);
+
+               todo = isl_set_intersect(todo, todo_i);
        }
 
        isl_set_free(dom);