isl_tab_pip.c: sol_map_add: fix double free on error path
[platform/upstream/isl.git] / isl_constraint.c
index 1cce16e..7c4b778 100644 (file)
  * ZAC des vignes, 4 rue Jacques Monod, 91893 Orsay, France 
  */
 
-#include <isl_constraint.h>
+#include <isl_map_private.h>
+#include <isl_constraint_private.h>
 #include <isl_dim_private.h>
-#include "isl_seq.h"
-#include "isl_map_private.h"
+#include <isl_div_private.h>
+#include <isl/seq.h>
+#include <isl_aff_private.h>
+
+isl_ctx *isl_constraint_get_ctx(__isl_keep isl_constraint *c)
+{
+       return c ? c->ctx : NULL;
+}
 
 static unsigned n(struct isl_constraint *c, enum isl_dim_type type)
 {
@@ -276,6 +283,23 @@ struct isl_basic_set *isl_basic_set_add_constraint(
                                                constraint);
 }
 
+__isl_give isl_map *isl_map_add_constraint(__isl_take isl_map *map,
+       __isl_take isl_constraint *constraint)
+{
+       isl_basic_map *bmap;
+
+       bmap = isl_basic_map_from_constraint(constraint);
+       map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
+
+       return map;
+}
+
+__isl_give isl_set *isl_set_add_constraint(__isl_take isl_set *set,
+       __isl_take isl_constraint *constraint)
+{
+       return isl_map_add_constraint(set, constraint);
+}
+
 struct isl_constraint *isl_constraint_add_div(struct isl_constraint *constraint,
        struct isl_div *div, int *pos)
 {
@@ -306,6 +330,12 @@ error:
        return NULL;
 }
 
+__isl_give isl_dim *isl_constraint_get_dim(
+       __isl_keep isl_constraint *constraint)
+{
+       return constraint ? isl_basic_map_get_dim(constraint->bmap) : NULL;
+}
+
 int isl_constraint_dim(struct isl_constraint *constraint,
        enum isl_dim_type type)
 {
@@ -314,6 +344,24 @@ int isl_constraint_dim(struct isl_constraint *constraint,
        return n(constraint, type);
 }
 
+int isl_constraint_involves_dims(__isl_keep isl_constraint *constraint,
+       enum isl_dim_type type, unsigned first, unsigned n)
+{
+       if (!constraint)
+               return -1;
+
+       if (first + n > isl_basic_set_dim(constraint->bmap, type))
+               isl_die(constraint->ctx, isl_error_invalid,
+                       "index out of bounds", return -1);
+
+       first += isl_basic_map_offset(constraint->bmap, type);
+
+       if (isl_seq_first_non_zero(constraint->line[0] + first, n) >= 0)
+               return 1;
+
+       return 0;
+}
+
 const char *isl_constraint_get_dim_name(__isl_keep isl_constraint *constraint,
        enum isl_dim_type type, unsigned pos)
 {
@@ -357,6 +405,14 @@ void isl_constraint_set_constant(struct isl_constraint *constraint, isl_int v)
        isl_int_set(constraint->line[0][0], v);
 }
 
+void isl_constraint_set_constant_si(__isl_keep isl_constraint *constraint,
+       int v)
+{
+       if (!constraint)
+               return;
+       isl_int_set_si(constraint->line[0][0], v);
+}
+
 void isl_constraint_set_coefficient(struct isl_constraint *constraint,
        enum isl_dim_type type, int pos, isl_int v)
 {
@@ -367,6 +423,16 @@ void isl_constraint_set_coefficient(struct isl_constraint *constraint,
        isl_int_set(constraint->line[0][offset(constraint, type) + pos], v);
 }
 
+void isl_constraint_set_coefficient_si(__isl_keep isl_constraint *constraint,
+       enum isl_dim_type type, int pos, int v)
+{
+       if (!constraint)
+               return;
+
+       isl_assert(constraint->ctx, pos < n(constraint, type), return);
+       isl_int_set_si(constraint->line[0][offset(constraint, type) + pos], v);
+}
+
 void isl_constraint_clear(struct isl_constraint *constraint)
 {
        unsigned total;
@@ -377,6 +443,80 @@ void isl_constraint_clear(struct isl_constraint *constraint)
        isl_seq_clr(constraint->line[0], 1 + total);
 }
 
+/* Check whether the two basic maps have identical divs in the same order.
+ */
+static int equal_divs(__isl_keep isl_basic_map *bmap1,
+       __isl_keep isl_basic_map *bmap2)
+{
+       int i;
+       unsigned total;
+
+       if (!isl_basic_map_divs_known(bmap1))
+               return 0;
+       if (!isl_basic_map_divs_known(bmap2))
+               return 0;
+       if (bmap1->n_div != bmap2->n_div)
+               return 0;
+
+       total = isl_basic_map_total_dim(bmap1);
+       for (i = 0; i < bmap1->n_div; ++i)
+               if (!isl_seq_eq(bmap1->div[i], bmap2->div[i], 2 + total))
+                       return 0;
+
+       return 1;
+}
+
+/* Drop any constraint from "bset" that is identical to "constraint".
+ * In particular, this means that the local spaces of "bset" and
+ * "constraint" need to be the same.
+ *
+ * Since the given constraint may actually be a pointer into the bset,
+ * we have to be careful not to reorder the constraints as the user
+ * may be holding on to other constraints from the same bset.
+ * This should be cleaned up when the internal representation of
+ * isl_constraint is changed to use isl_aff.
+ */
+__isl_give isl_basic_set *isl_basic_set_drop_constraint(
+       __isl_take isl_basic_set *bset, __isl_take isl_constraint *constraint)
+{
+       int i;
+       unsigned n;
+       isl_int **row;
+       unsigned total;
+
+       if (!bset || !constraint)
+               goto error;
+
+       if (!isl_dim_equal(bset->dim, constraint->bmap->dim))
+               isl_die(bset->ctx, isl_error_invalid,
+                       "spaces don't match", goto error);
+
+       if (bset != constraint->bmap && !equal_divs(bset, constraint->bmap)) {
+               isl_constraint_free(constraint);
+               return bset;
+       }
+
+       if (isl_constraint_is_equality(constraint)) {
+               n = bset->n_eq;
+               row = bset->eq;
+       } else {
+               n = bset->n_ineq;
+               row = bset->ineq;
+       }
+
+       total = isl_basic_map_total_dim(constraint->bmap);
+       for (i = 0; i < n; ++i)
+               if (isl_seq_eq(row[i], constraint->line[0], 1 + total))
+                       isl_seq_clr(row[i], 1 + total);
+                       
+       isl_constraint_free(constraint);
+       return bset;
+error:
+       isl_constraint_free(constraint);
+       isl_basic_set_free(bset);
+       return NULL;
+}
+
 struct isl_constraint *isl_constraint_negate(struct isl_constraint *constraint)
 {
        unsigned total;
@@ -917,3 +1057,125 @@ error:
        isl_basic_set_free(context);
        return -1;
 }
+
+__isl_give isl_aff *isl_constraint_get_bound(
+       __isl_keep isl_constraint *constraint, enum isl_dim_type type, int pos)
+{
+       isl_aff *aff;
+       isl_local_space *ls;
+
+       if (!constraint)
+               return NULL;
+       if (pos >= isl_basic_set_dim(constraint->bmap, type))
+               isl_die(constraint->ctx, isl_error_invalid,
+                       "index out of bounds", return NULL);
+       if (!isl_basic_map_may_be_set(constraint->bmap))
+               isl_die(constraint->ctx, isl_error_invalid,
+                       "not a set constraint", return NULL);
+
+       pos += offset(constraint, type);
+       if (isl_int_is_zero(constraint->line[0][pos]))
+               isl_die(constraint->ctx, isl_error_invalid,
+                       "constraint does not define a bound on given dimension",
+                       return NULL);
+
+       ls = isl_basic_set_get_local_space(constraint->bmap);
+       aff = isl_aff_alloc(ls);
+       if (!aff)
+               return NULL;
+
+       if (isl_int_is_neg(constraint->line[0][pos]))
+               isl_seq_cpy(aff->v->el + 1, constraint->line[0],
+                           aff->v->size - 1);
+       else
+               isl_seq_neg(aff->v->el + 1, constraint->line[0],
+                           aff->v->size - 1);
+       isl_int_set_si(aff->v->el[1 + pos], 0);
+       isl_int_abs(aff->v->el[0], constraint->line[0][pos]);
+
+       return aff;
+}
+
+/* For an inequality constraint
+ *
+ *     f >= 0
+ *
+ * or an equality constraint
+ *
+ *     f = 0
+ *
+ * return the affine expression f.
+ */
+__isl_give isl_aff *isl_constraint_get_aff(
+       __isl_keep isl_constraint *constraint)
+{
+       isl_aff *aff;
+       isl_local_space *ls;
+
+       if (!constraint)
+               return NULL;
+
+       ls = isl_basic_set_get_local_space(constraint->bmap);
+       aff = isl_aff_alloc(ls);
+       if (!aff)
+               return NULL;
+
+       isl_seq_cpy(aff->v->el + 1, constraint->line[0], aff->v->size - 1);
+       isl_int_set_si(aff->v->el[0], 1);
+
+       return aff;
+}
+
+/* Construct an equality constraint equating the given affine expression
+ * to zero.
+ */
+__isl_give isl_constraint *isl_equality_from_aff(__isl_take isl_aff *aff)
+{
+       int k;
+       isl_basic_set *bset;
+
+       if (!aff)
+               return NULL;
+
+       bset = isl_basic_set_from_local_space(isl_aff_get_local_space(aff));
+       bset = isl_basic_set_extend_constraints(bset, 1, 0);
+       k = isl_basic_set_alloc_equality(bset);
+       if (k < 0)
+               goto error;
+
+       isl_seq_cpy(bset->eq[k], aff->v->el + 1, aff->v->size - 1);
+       isl_aff_free(aff);
+
+       return isl_basic_set_constraint(bset, &bset->eq[k]);
+error:
+       isl_aff_free(aff);
+       isl_basic_set_free(bset);
+       return NULL;
+}
+
+/* Construct an inequality constraint enforcing the given affine expression
+ * to be non-negative.
+ */
+__isl_give isl_constraint *isl_inequality_from_aff(__isl_take isl_aff *aff)
+{
+       int k;
+       isl_basic_set *bset;
+
+       if (!aff)
+               return NULL;
+
+       bset = isl_basic_set_from_local_space(isl_aff_get_local_space(aff));
+       bset = isl_basic_set_extend_constraints(bset, 0, 1);
+       k = isl_basic_set_alloc_inequality(bset);
+       if (k < 0)
+               goto error;
+
+       isl_seq_cpy(bset->ineq[k], aff->v->el + 1, aff->v->size - 1);
+       isl_aff_free(aff);
+
+       return isl_basic_set_constraint(bset, &bset->ineq[k]);
+error:
+       isl_aff_free(aff);
+       isl_basic_set_free(bset);
+       return NULL;
+}