add isl_pw_qpolynomial_split_dims
[platform/upstream/isl.git] / isl_map.c
index e290420..7df4bcf 100644 (file)
--- a/isl_map.c
+++ b/isl_map.c
@@ -1176,38 +1176,56 @@ void isl_basic_map_swap_div(struct isl_basic_map *bmap, int a, int b)
 }
 
 /* Eliminate the specified n dimensions starting at first from the
- * constraints using Fourier-Motzkin, The dimensions themselves
+ * constraints using Fourier-Motzkin The dimensions themselves
  * are not removed.
  */
-struct isl_set *isl_set_eliminate_dims(struct isl_set *set,
-       unsigned first, unsigned n)
+__isl_give isl_map *isl_map_eliminate(__isl_take isl_map *map,
+       enum isl_dim_type type, unsigned first, unsigned n)
 {
        int i;
-       unsigned nparam;
 
-       if (!set)
+       if (!map)
                return NULL;
        if (n == 0)
-               return set;
+               return map;
 
-       set = isl_set_cow(set);
-       if (!set)
+       map = isl_map_cow(map);
+       if (!map)
                return NULL;
-       isl_assert(set->ctx, first+n <= isl_set_n_dim(set), goto error);
-       nparam = isl_set_n_param(set);
+       isl_assert(map->ctx, first + n <= isl_map_dim(map, type), goto error);
+       first += pos(map->dim, type) - 1;
        
-       for (i = 0; i < set->n; ++i) {
-               set->p[i] = isl_basic_set_eliminate_vars(set->p[i],
-                                                           nparam + first, n);
-               if (!set->p[i])
+       for (i = 0; i < map->n; ++i) {
+               map->p[i] = isl_basic_map_eliminate_vars(map->p[i], first, n);
+               if (!map->p[i])
                        goto error;
        }
-       return set;
+       return map;
 error:
-       isl_set_free(set);
+       isl_map_free(map);
        return NULL;
 }
 
+/* Eliminate the specified n dimensions starting at first from the
+ * constraints using Fourier-Motzkin.  The dimensions themselves
+ * are not removed.
+ */
+__isl_give isl_set *isl_set_eliminate(__isl_take isl_set *set,
+       enum isl_dim_type type, unsigned first, unsigned n)
+{
+       return (isl_set *)isl_map_eliminate((isl_map *)set, type, first, n);
+}
+
+/* Eliminate the specified n dimensions starting at first from the
+ * constraints using Fourier-Motzkin.  The dimensions themselves
+ * are not removed.
+ */
+__isl_give isl_set *isl_set_eliminate_dims(__isl_take isl_set *set,
+       unsigned first, unsigned n)
+{
+       return isl_set_eliminate(set, isl_dim_set, first, n);
+}
+
 /* Project out n dimensions starting at first using Fourier-Motzkin */
 struct isl_set *isl_set_remove_dims(struct isl_set *set,
        unsigned first, unsigned n)
@@ -1971,13 +1989,14 @@ struct isl_basic_map *isl_basic_map_reverse(struct isl_basic_map *bmap)
        return isl_basic_map_from_basic_set(bset, dim);
 }
 
-__isl_give isl_basic_map *isl_basic_map_add(__isl_take isl_basic_map *bmap,
-               enum isl_dim_type type, unsigned n)
+__isl_give isl_basic_map *isl_basic_map_insert(__isl_take isl_basic_map *bmap,
+               enum isl_dim_type type, unsigned pos, unsigned n)
 {
        struct isl_dim *res_dim;
        struct isl_basic_map *res;
        struct isl_dim_map *dim_map;
-       unsigned total, pos;
+       unsigned total, off;
+       enum isl_dim_type t;
 
        if (n == 0)
                return bmap;
@@ -1985,18 +2004,24 @@ __isl_give isl_basic_map *isl_basic_map_add(__isl_take isl_basic_map *bmap,
        if (!bmap)
                return NULL;
 
-       res_dim = isl_dim_add(isl_basic_map_get_dim(bmap), type, n);
+       res_dim = isl_dim_insert(isl_basic_map_get_dim(bmap), type, pos, n);
 
        total = isl_basic_map_total_dim(bmap) + n;
        dim_map = isl_dim_map_alloc(bmap->ctx, total);
-       pos = 0;
-       isl_dim_map_dim(dim_map, bmap->dim, isl_dim_param, pos);
-       pos += isl_dim_size(res_dim, isl_dim_param);
-       isl_dim_map_dim(dim_map, bmap->dim, isl_dim_in, pos);
-       pos += isl_dim_size(res_dim, isl_dim_in);
-       isl_dim_map_dim(dim_map, bmap->dim, isl_dim_out, pos);
-       pos += isl_dim_size(res_dim, isl_dim_out);
-       isl_dim_map_div(dim_map, bmap, pos);
+       off = 0;
+       for (t = isl_dim_param; t <= isl_dim_out; ++t) {
+               if (t != type) {
+                       isl_dim_map_dim(dim_map, bmap->dim, t, off);
+               } else {
+                       unsigned size = isl_basic_map_dim(bmap, t);
+                       isl_dim_map_dim_range(dim_map, bmap->dim, t,
+                                               0, pos, off);
+                       isl_dim_map_dim_range(dim_map, bmap->dim, t,
+                                               pos, size - pos, off + pos + n);
+               }
+               off += isl_dim_size(res_dim, t);
+       }
+       isl_dim_map_div(dim_map, bmap, off);
 
        res = isl_basic_map_alloc_dim(res_dim,
                        bmap->n_div, bmap->n_eq, bmap->n_ineq);
@@ -2005,6 +2030,15 @@ __isl_give isl_basic_map *isl_basic_map_add(__isl_take isl_basic_map *bmap,
        return isl_basic_map_finalize(res);
 }
 
+__isl_give isl_basic_map *isl_basic_map_add(__isl_take isl_basic_map *bmap,
+               enum isl_dim_type type, unsigned n)
+{
+       if (!bmap)
+               return NULL;
+       return isl_basic_map_insert(bmap, type,
+                                       isl_basic_map_dim(bmap, type), n);
+}
+
 __isl_give isl_basic_set *isl_basic_set_add(__isl_take isl_basic_set *bset,
                enum isl_dim_type type, unsigned n)
 {
@@ -2017,8 +2051,8 @@ error:
        return NULL;
 }
 
-__isl_give isl_map *isl_map_add(__isl_take isl_map *map,
-               enum isl_dim_type type, unsigned n)
+__isl_give isl_map *isl_map_insert(__isl_take isl_map *map,
+               enum isl_dim_type type, unsigned pos, unsigned n)
 {
        int i;
 
@@ -2029,12 +2063,12 @@ __isl_give isl_map *isl_map_add(__isl_take isl_map *map,
        if (!map)
                return NULL;
 
-       map->dim = isl_dim_add(map->dim, type, n);
+       map->dim = isl_dim_insert(map->dim, type, pos, n);
        if (!map->dim)
                goto error;
 
        for (i = 0; i < map->n; ++i) {
-               map->p[i] = isl_basic_map_add(map->p[i], type, n);
+               map->p[i] = isl_basic_map_insert(map->p[i], type, pos, n);
                if (!map->p[i])
                        goto error;
        }
@@ -2045,6 +2079,14 @@ error:
        return NULL;
 }
 
+__isl_give isl_map *isl_map_add(__isl_take isl_map *map,
+               enum isl_dim_type type, unsigned n)
+{
+       if (!map)
+               return NULL;
+       return isl_map_insert(map, type, isl_map_dim(map, type), n);
+}
+
 __isl_give isl_set *isl_set_add(__isl_take isl_set *set,
                enum isl_dim_type type, unsigned n)
 {
@@ -2057,6 +2099,143 @@ error:
        return NULL;
 }
 
+__isl_give isl_basic_map *isl_basic_map_move(__isl_take isl_basic_map *bmap,
+       enum isl_dim_type dst_type, unsigned dst_pos,
+       enum isl_dim_type src_type, unsigned src_pos, unsigned n)
+{
+       int i;
+       struct isl_dim_map *dim_map;
+       struct isl_basic_map *res;
+       enum isl_dim_type t;
+       unsigned total, off;
+
+       if (!bmap)
+               return NULL;
+       if (n == 0)
+               return bmap;
+
+       isl_assert(bmap->ctx, src_pos + n <= isl_basic_map_dim(bmap, src_type),
+               goto error);
+
+       if (dst_type == src_type && dst_pos == src_pos)
+               return bmap;
+
+       isl_assert(bmap->ctx, dst_type != src_type, goto error);
+
+       if (pos(bmap->dim, dst_type) + dst_pos ==
+           pos(bmap->dim, src_type) + src_pos +
+                                           ((src_type < dst_type) ? n : 0)) {
+               bmap = isl_basic_map_cow(bmap);
+               if (!bmap)
+                       return NULL;
+
+               bmap->dim = isl_dim_move(bmap->dim, dst_type, dst_pos,
+                                               src_type, src_pos, n);
+               if (!bmap->dim)
+                       goto error;
+
+               return bmap;
+       }
+
+       total = isl_basic_map_total_dim(bmap);
+       dim_map = isl_dim_map_alloc(bmap->ctx, total);
+
+       off = 0;
+       for (t = isl_dim_param; t <= isl_dim_out; ++t) {
+               unsigned size = isl_dim_size(bmap->dim, t);
+               if (t == dst_type) {
+                       isl_dim_map_dim_range(dim_map, bmap->dim, t,
+                                           0, dst_pos, off);
+                       off += dst_pos;
+                       isl_dim_map_dim_range(dim_map, bmap->dim, src_type,
+                                           src_pos, n, off);
+                       off += n;
+                       isl_dim_map_dim_range(dim_map, bmap->dim, t,
+                                           dst_pos, size - dst_pos, off);
+                       off += size - dst_pos;
+               } else if (t == src_type) {
+                       isl_dim_map_dim_range(dim_map, bmap->dim, t,
+                                           0, src_pos, off);
+                       off += src_pos;
+                       isl_dim_map_dim_range(dim_map, bmap->dim, t,
+                                       src_pos + n, size - src_pos - n, off);
+                       off += size - src_pos - n;
+               } else {
+                       isl_dim_map_dim(dim_map, bmap->dim, t, off);
+                       off += size;
+               }
+       }
+       isl_dim_map_div(dim_map, bmap, off + n);
+
+       res = isl_basic_map_alloc_dim(isl_basic_map_get_dim(bmap),
+                       bmap->n_div, bmap->n_eq, bmap->n_ineq);
+       bmap = add_constraints_dim_map(res, bmap, dim_map);
+
+       bmap->dim = isl_dim_move(bmap->dim, dst_type, dst_pos,
+                                       src_type, src_pos, n);
+       if (!bmap->dim)
+               goto error;
+
+       return bmap;
+error:
+       isl_basic_map_free(bmap);
+       return NULL;
+}
+
+__isl_give isl_set *isl_set_move(__isl_take isl_set *set,
+       enum isl_dim_type dst_type, unsigned dst_pos,
+       enum isl_dim_type src_type, unsigned src_pos, unsigned n)
+{
+       if (!set)
+               return NULL;
+       isl_assert(set->ctx, dst_type != isl_dim_in, goto error);
+       return (isl_set *)isl_map_move((isl_map *)set, dst_type, dst_pos,
+                                       src_type, src_pos, n);
+error:
+       isl_set_free(set);
+       return NULL;
+}
+
+__isl_give isl_map *isl_map_move(__isl_take isl_map *map,
+       enum isl_dim_type dst_type, unsigned dst_pos,
+       enum isl_dim_type src_type, unsigned src_pos, unsigned n)
+{
+       int i;
+
+       if (!map)
+               return NULL;
+       if (n == 0)
+               return map;
+
+       isl_assert(map->ctx, src_pos + n <= isl_map_dim(map, src_type),
+               goto error);
+
+       if (dst_type == src_type && dst_pos == src_pos)
+               return map;
+
+       isl_assert(map->ctx, dst_type != src_type, goto error);
+
+       map = isl_map_cow(map);
+       if (!map)
+               return NULL;
+
+       map->dim = isl_dim_move(map->dim, dst_type, dst_pos, src_type, src_pos, n);
+       if (!map->dim)
+               goto error;
+
+       for (i = 0; i < map->n; ++i) {
+               map->p[i] = isl_basic_map_move(map->p[i], dst_type, dst_pos,
+                                               src_type, src_pos, n);
+               if (!map->p[i])
+                       goto error;
+       }
+
+       return map;
+error:
+       isl_map_free(map);
+       return NULL;
+}
+
 /* Move the specified dimensions to the last columns right before
  * the divs.  Don't change the dimension specification of bmap.
  * That's the responsibility of the caller.
@@ -2986,16 +3165,17 @@ struct isl_set *isl_map_range(struct isl_map *map)
 
        if (!map)
                goto error;
+       if (isl_map_dim(map, isl_dim_in) == 0)
+               return (isl_set *)map;
+
        map = isl_map_cow(map);
        if (!map)
                goto error;
 
        set = (struct isl_set *) map;
-       if (set->dim->n_in != 0) {
-               set->dim = isl_dim_drop_inputs(set->dim, 0, set->dim->n_in);
-               if (!set->dim)
-                       goto error;
-       }
+       set->dim = isl_dim_drop_inputs(set->dim, 0, set->dim->n_in);
+       if (!set->dim)
+               goto error;
        for (i = 0; i < map->n; ++i) {
                set->p[i] = isl_basic_map_range(map->p[i]);
                if (!set->p[i])
@@ -4657,6 +4837,50 @@ error:
        return NULL;
 }
 
+__isl_give isl_set *isl_set_split_dims(__isl_take isl_set *set,
+       enum isl_dim_type type, unsigned first, unsigned n)
+{
+       int i;
+       isl_basic_set *nonneg = NULL;
+       isl_basic_set *neg = NULL;
+
+       if (!set)
+               return NULL;
+       if (n == 0)
+               return set;
+
+       isl_assert(set->ctx, first + n <= isl_set_dim(set, type), goto error);
+
+       for (i = 0; i < n; ++i) {
+               int k;
+
+               neg = NULL;
+               nonneg = isl_basic_set_alloc_dim(isl_set_get_dim(set), 0, 0, 1);
+               k = isl_basic_set_alloc_inequality(nonneg);
+               if (k < 0)
+                       goto error;
+               isl_seq_clr(nonneg->ineq[k], 1 + isl_basic_set_total_dim(nonneg));
+               isl_int_set_si(nonneg->ineq[k][pos(set->dim, type) + first + i], 1);
+
+               neg = isl_basic_set_alloc_dim(isl_set_get_dim(set), 0, 0, 1);
+               k = isl_basic_set_alloc_inequality(neg);
+               if (k < 0)
+                       goto error;
+               isl_seq_clr(neg->ineq[k], 1 + isl_basic_set_total_dim(neg));
+               isl_int_set_si(neg->ineq[k][0], -1);
+               isl_int_set_si(neg->ineq[k][pos(set->dim, type) + first + i], -1);
+
+               set = isl_set_intersect(set, isl_basic_set_union(nonneg, neg));
+       }
+
+       return set;
+error:
+       isl_basic_set_free(nonneg);
+       isl_basic_set_free(neg);
+       isl_set_free(set);
+       return NULL;
+}
+
 int isl_set_is_equal(struct isl_set *set1, struct isl_set *set2)
 {
        return isl_map_is_equal((struct isl_map *)set1, (struct isl_map *)set2);
@@ -6009,6 +6233,71 @@ int isl_set_foreach_basic_set(__isl_keep isl_set *set,
        return 0;
 }
 
+__isl_give isl_basic_set *isl_basic_set_lift(__isl_take isl_basic_set *bset)
+{
+       struct isl_dim *dim;
+
+       if (!bset)
+               return NULL;
+
+       if (bset->n_div == 0)
+               return bset;
+
+       bset = isl_basic_set_cow(bset);
+       if (!bset)
+               return NULL;
+
+       dim = isl_basic_set_get_dim(bset);
+       dim = isl_dim_add(dim, isl_dim_set, bset->n_div);
+       if (!dim)
+               goto error;
+       isl_dim_free(bset->dim);
+       bset->dim = dim;
+       bset->n_div = 0;
+
+       return bset;
+error:
+       isl_basic_set_free(bset);
+       return NULL;
+}
+
+__isl_give isl_set *isl_set_lift(__isl_take isl_set *set)
+{
+       int i;
+       struct isl_dim *dim;
+       unsigned n_div;
+
+       set = isl_set_align_divs(set);
+
+       if (!set)
+               return NULL;
+       if (set->n == 0 || set->p[0]->n_div == 0)
+               return set;
+
+       set = isl_set_cow(set);
+       if (!set)
+               return NULL;
+
+       n_div = set->p[0]->n_div;
+       dim = isl_set_get_dim(set);
+       dim = isl_dim_add(dim, isl_dim_set, n_div);
+       if (!dim)
+               goto error;
+       isl_dim_free(set->dim);
+       set->dim = dim;
+
+       for (i = 0; i < set->n; ++i) {
+               set->p[i] = isl_basic_set_lift(set->p[i]);
+               if (!set->p[i])
+                       goto error;
+       }
+
+       return set;
+error:
+       isl_set_free(set);
+       return NULL;
+}
+
 __isl_give isl_map *isl_set_lifting(__isl_take isl_set *set)
 {
        struct isl_dim *dim;