isl_ast_codegen.c: fix typo in comment
[platform/upstream/isl.git] / isl_map.c
index a74324b..c011a94 100644 (file)
--- a/isl_map.c
+++ b/isl_map.c
@@ -33,6 +33,7 @@
 #include <isl_local_space_private.h>
 #include <isl_aff_private.h>
 #include <isl_options_private.h>
+#include <isl_morph.h>
 
 static unsigned n(__isl_keep isl_space *dim, enum isl_dim_type type)
 {
@@ -6061,19 +6062,33 @@ __isl_give isl_set *isl_set_partial_lexmax(
                        dom, empty);
 }
 
+/* Compute the lexicographic minimum (or maximum if "max" is set)
+ * of "bmap" over its domain.
+ *
+ * Since we are not interested in the part of the domain space where
+ * there is no solution, we initialize the domain to those constraints
+ * of "bmap" that only involve the parameters and the input dimensions.
+ * This relieves the parametric programming engine from detecting those
+ * inequalities and transferring them to the context.  More importantly,
+ * it ensures that those inequalities are transferred first and not
+ * intermixed with inequalities that actually split the domain.
+ */
 __isl_give isl_map *isl_basic_map_lexopt(__isl_take isl_basic_map *bmap, int max)
 {
-       struct isl_basic_set *dom = NULL;
-       isl_space *dom_dim;
+       int n_div;
+       int n_out;
+       isl_basic_map *copy;
+       isl_basic_set *dom;
 
-       if (!bmap)
-               goto error;
-       dom_dim = isl_space_domain(isl_space_copy(bmap->dim));
-       dom = isl_basic_set_universe(dom_dim);
+       n_div = isl_basic_map_dim(bmap, isl_dim_div);
+       n_out = isl_basic_map_dim(bmap, isl_dim_out);
+       copy = isl_basic_map_copy(bmap);
+       copy = isl_basic_map_drop_constraints_involving_dims(copy,
+                                                       isl_dim_div, 0, n_div);
+       copy = isl_basic_map_drop_constraints_involving_dims(copy,
+                                                       isl_dim_out, 0, n_out);
+       dom = isl_basic_map_domain(copy);
        return isl_basic_map_partial_lexopt(bmap, dom, NULL, max);
-error:
-       isl_basic_map_free(bmap);
-       return NULL;
 }
 
 __isl_give isl_map *isl_basic_map_lexmin(__isl_take isl_basic_map *bmap)
@@ -6096,16 +6111,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_set *isl_set_lexmin(__isl_take isl_set *set)
-{
-       return (isl_set *)isl_map_lexmin((isl_map *)set);
-}
-
-__isl_give isl_set *isl_set_lexmax(__isl_take isl_set *set)
-{
-       return (isl_set *)isl_map_lexmax((isl_map *)set);
-}
-
 /* Extract the first and only affine expression from list
  * and then add it to *pwaff with the given dom.
  * This domain is known to be disjoint from other domains
@@ -6377,6 +6382,72 @@ error:
        return NULL;
 }
 
+/* Given a basic set "bset" that only involves parameters and existentially
+ * quantified variables, return the index of the first equality
+ * that only involves parameters.  If there is no such equality then
+ * return bset->n_eq.
+ *
+ * This function assumes that isl_basic_set_gauss has been called on "bset".
+ */
+static int first_parameter_equality(__isl_keep isl_basic_set *bset)
+{
+       int i, j;
+       unsigned nparam, n_div;
+
+       if (!bset)
+               return -1;
+
+       nparam = isl_basic_set_dim(bset, isl_dim_param);
+       n_div = isl_basic_set_dim(bset, isl_dim_div);
+
+       for (i = 0, j = n_div - 1; i < bset->n_eq && j >= 0; --j) {
+               if (!isl_int_is_zero(bset->eq[i][1 + nparam + j]))
+                       ++i;
+       }
+
+       return i;
+}
+
+/* Compute an explicit representation for the existentially quantified
+ * variables in "bset" by computing the "minimal value" of the set
+ * variables.  Since there are no set variables, the computation of
+ * the minimal value essentially computes an explicit representation
+ * of the non-empty part(s) of "bset".
+ *
+ * The input only involves parameters and existentially quantified variables.
+ * All equalities among parameters have been removed.
+ *
+ * Since the existentially quantified variables in the result are in general
+ * going to be different from those in the input, we first replace
+ * them by the minimal number of variables based on their equalities.
+ * This should simplify the parametric integer programming.
+ */
+static __isl_give isl_set *base_compute_divs(__isl_take isl_basic_set *bset)
+{
+       isl_morph *morph1, *morph2;
+       isl_set *set;
+       unsigned n;
+
+       if (!bset)
+               return NULL;
+       if (bset->n_eq == 0)
+               return isl_basic_set_lexmin(bset);
+
+       morph1 = isl_basic_set_parameter_compression(bset);
+       bset = isl_morph_basic_set(isl_morph_copy(morph1), bset);
+       bset = isl_basic_set_lift(bset);
+       morph2 = isl_basic_set_variable_compression(bset, isl_dim_set);
+       bset = isl_morph_basic_set(morph2, bset);
+       n = isl_basic_set_dim(bset, isl_dim_set);
+       bset = isl_basic_set_project_out(bset, isl_dim_set, 0, n);
+
+       set = isl_basic_set_lexmin(bset);
+
+       set = isl_morph_set(isl_morph_inverse(morph1), set);
+
+       return set;
+}
+
 /* Project the given basic set onto its parameter domain, possibly introducing
  * new, explicit, existential variables in the constraints.
  * The input has parameters and (possibly implicit) existential variables.
@@ -6388,21 +6459,27 @@ error:
  * among the parameters by performing a variable compression on
  * the parameters.  Afterward, an inverse transformation is performed
  * and the equalities among the parameters are inserted back in.
+ *
+ * The variable compression on the parameters may uncover additional
+ * equalities that were only implicit before.  We therefore check
+ * if there are any new parameter equalities in the result and
+ * if so recurse.  The removal of parameter equalities is required
+ * for the parameter compression performed by base_compute_divs.
  */
 static struct isl_set *parameter_compute_divs(struct isl_basic_set *bset)
 {
-       int i, j;
+       int i;
        struct isl_mat *eq;
        struct isl_mat *T, *T2;
        struct isl_set *set;
-       unsigned nparam, n_div;
+       unsigned nparam;
 
        bset = isl_basic_set_cow(bset);
        if (!bset)
                return NULL;
 
        if (bset->n_eq == 0)
-               return isl_basic_set_lexmin(bset);
+               return base_compute_divs(bset);
 
        bset = isl_basic_set_gauss(bset, NULL);
        if (!bset)
@@ -6410,16 +6487,11 @@ static struct isl_set *parameter_compute_divs(struct isl_basic_set *bset)
        if (isl_basic_set_plain_is_empty(bset))
                return isl_set_from_basic_set(bset);
 
-       nparam = isl_basic_set_dim(bset, isl_dim_param);
-       n_div = isl_basic_set_dim(bset, isl_dim_div);
-
-       for (i = 0, j = n_div - 1; i < bset->n_eq && j >= 0; --j) {
-               if (!isl_int_is_zero(bset->eq[i][1 + nparam + j]))
-                       ++i;
-       }
+       i = first_parameter_equality(bset);
        if (i == bset->n_eq)
-               return isl_basic_set_lexmin(bset);
+               return base_compute_divs(bset);
 
+       nparam = isl_basic_set_dim(bset, isl_dim_param);
        eq = isl_mat_sub_alloc6(bset->ctx, bset->eq, i, bset->n_eq - i,
                0, 1 + nparam);
        eq = isl_mat_cow(eq);
@@ -6433,7 +6505,13 @@ static struct isl_set *parameter_compute_divs(struct isl_basic_set *bset)
        }
        bset = basic_set_parameter_preimage(bset, T);
 
-       set = isl_basic_set_lexmin(bset);
+       i = first_parameter_equality(bset);
+       if (!bset)
+               set = NULL;
+       else if (i == bset->n_eq)
+               set = base_compute_divs(bset);
+       else
+               set = parameter_compute_divs(bset);
        set = set_parameter_preimage(set, T2);
        set = set_append_equalities(set, eq);
        return set;