add isl_aff_mod_val
[platform/upstream/isl.git] / isl_map_subtract.c
index 452af60..2c958c7 100644 (file)
@@ -1,19 +1,30 @@
 /*
  * Copyright 2008-2009 Katholieke Universiteit Leuven
  *
- * Use of this software is governed by the GNU LGPLv2.1 license
+ * Use of this software is governed by the MIT license
  *
  * Written by Sven Verdoolaege, K.U.Leuven, Departement
  * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
  */
 
+#include <isl_map_private.h>
 #include <isl/seq.h>
 #include <isl/set.h>
 #include <isl/map.h>
-#include "isl_map_private.h"
 #include "isl_tab.h"
 #include <isl_point_private.h>
 
+/* Expand the constraint "c" into "v".  The initial "dim" dimensions
+ * are the same, but "v" may have more divs than "c" and the divs of "c"
+ * may appear in different positions in "v".
+ * The number of divs in "c" is given by "n_div" and the mapping
+ * of divs in "c" to divs in "v" is given by "div_map".
+ *
+ * Although it shouldn't happen in practice, it is theoretically
+ * possible that two or more divs in "c" are mapped to the same div in "v".
+ * These divs are then necessarily the same, so we simply add their
+ * coefficients.
+ */
 static void expand_constraint(isl_vec *v, unsigned dim,
        isl_int *c, int *div_map, unsigned n_div)
 {
@@ -22,8 +33,10 @@ static void expand_constraint(isl_vec *v, unsigned dim,
        isl_seq_cpy(v->el, c, 1 + dim);
        isl_seq_clr(v->el + 1 + dim, v->size - (1 + dim));
 
-       for (i = 0; i < n_div; ++i)
-               isl_int_set(v->el[1 + dim + div_map[i]], c[1 + dim + i]);
+       for (i = 0; i < n_div; ++i) {
+               int pos = 1 + dim + div_map[i];
+               isl_int_add(v->el[pos], v->el[pos], c[1 + dim + i]);
+       }
 }
 
 /* Add all constraints of bmap to tab.  The equalities of bmap
@@ -43,7 +56,7 @@ static int tab_add_constraints(struct isl_tab *tab,
 
        tab_total = isl_basic_map_total_dim(tab->bmap);
        bmap_total = isl_basic_map_total_dim(bmap);
-       dim = isl_dim_total(tab->bmap->dim);
+       dim = isl_space_dim(tab->bmap->dim, isl_dim_all);
 
        if (isl_tab_extend_cons(tab, 2 * bmap->n_eq + bmap->n_ineq) < 0)
                return -1;
@@ -99,7 +112,7 @@ static int tab_add_constraint(struct isl_tab *tab,
 
        tab_total = isl_basic_map_total_dim(tab->bmap);
        bmap_total = isl_basic_map_total_dim(bmap);
-       dim = isl_dim_total(tab->bmap->dim);
+       dim = isl_space_dim(tab->bmap->dim, isl_dim_all);
 
        v = isl_vec_alloc(bmap->ctx, 1 + tab_total);
        if (!v)
@@ -206,7 +219,8 @@ static int tab_freeze_constraints(struct isl_tab *tab)
  * Put the indices of the redundant constraints in index
  * and return the number of redundant constraints.
  */
-static int n_non_redundant(struct isl_tab *tab, int offset, int **index)
+static int n_non_redundant(isl_ctx *ctx, struct isl_tab *tab,
+       int offset, int **index)
 {
        int i, n;
        int n_test = tab->n_con - offset;
@@ -215,7 +229,7 @@ static int n_non_redundant(struct isl_tab *tab, int offset, int **index)
                return -1;
 
        if (!*index)
-               *index = isl_alloc_array(tab->mat->ctx, int, n_test);
+               *index = isl_alloc_array(ctx, int, n_test);
        if (!*index)
                return -1;
 
@@ -278,6 +292,7 @@ static int basic_map_collect_diff(__isl_take isl_basic_map *bmap,
        int level;
        int init;
        int empty;
+       isl_ctx *ctx;
        struct isl_tab *tab = NULL;
        struct isl_tab_undo **snap = NULL;
        int *k = NULL;
@@ -298,6 +313,7 @@ static int basic_map_collect_diff(__isl_take isl_basic_map *bmap,
        if (!bmap || !map)
                goto error;
 
+       ctx = map->ctx;
        snap = isl_alloc_array(map->ctx, struct isl_tab_undo *, map->n);
        k = isl_alloc_array(map->ctx, int, map->n);
        n = isl_alloc_array(map->ctx, int, map->n);
@@ -309,8 +325,8 @@ static int basic_map_collect_diff(__isl_take isl_basic_map *bmap,
        bmap = isl_basic_map_order_divs(bmap);
        map = isl_map_order_divs(map);
 
-       tab = isl_tab_from_basic_map(bmap);
-       if (isl_tab_track_bmap(tab, isl_basic_map_copy(bmap)) < 0)
+       tab = isl_tab_from_basic_map(bmap, 1);
+       if (!tab)
                goto error;
 
        modified = 0;
@@ -365,7 +381,8 @@ static int basic_map_collect_diff(__isl_take isl_basic_map *bmap,
                                continue;
                        }
                        modified = 1;
-                       n[level] = n_non_redundant(tab, offset, &index[level]);
+                       n[level] = n_non_redundant(ctx, tab, offset,
+                                                   &index[level]);
                        if (n[level] < 0)
                                goto error;
                        if (n[level] == 0) {
@@ -474,7 +491,8 @@ static __isl_give isl_map *basic_map_subtract(__isl_take isl_basic_map *bmap,
 /* Return the set difference between map1 and map2.
  * (U_i A_i) \ (U_j B_j) is computed as U_i (A_i \ (U_j B_j))
  */
-struct isl_map *isl_map_subtract(struct isl_map *map1, struct isl_map *map2)
+static __isl_give isl_map *map_subtract( __isl_take isl_map *map1,
+       __isl_take isl_map *map2)
 {
        int i;
        struct isl_map *diff;
@@ -482,7 +500,7 @@ struct isl_map *isl_map_subtract(struct isl_map *map1, struct isl_map *map2)
        if (!map1 || !map2)
                goto error;
 
-       isl_assert(map1->ctx, isl_dim_equal(map1->dim, map2->dim), goto error);
+       isl_assert(map1->ctx, isl_space_is_equal(map1->dim, map2->dim), goto error);
 
        if (isl_map_is_empty(map2)) {
                isl_map_free(map2);
@@ -518,6 +536,12 @@ error:
        return NULL;
 }
 
+__isl_give isl_map *isl_map_subtract( __isl_take isl_map *map1,
+       __isl_take isl_map *map2)
+{
+       return isl_map_align_params_map_map_and(map1, map2, &map_subtract);
+}
+
 struct isl_set *isl_set_subtract(struct isl_set *set1, struct isl_set *set2)
 {
        return (struct isl_set *)
@@ -525,6 +549,58 @@ struct isl_set *isl_set_subtract(struct isl_set *set1, struct isl_set *set2)
                        (struct isl_map *)set1, (struct isl_map *)set2);
 }
 
+/* Remove the elements of "dom" from the domain of "map".
+ */
+static __isl_give isl_map *map_subtract_domain(__isl_take isl_map *map,
+       __isl_take isl_set *dom)
+{
+       isl_map *ext_dom;
+
+       if (!isl_map_compatible_domain(map, dom))
+               isl_die(isl_set_get_ctx(dom), isl_error_invalid,
+                       "incompatible spaces", goto error);
+       
+       ext_dom = isl_map_universe(isl_map_get_space(map));
+       ext_dom = isl_map_intersect_domain(ext_dom, dom);
+       return isl_map_subtract(map, ext_dom);
+error:
+       isl_map_free(map);
+       isl_set_free(dom);
+       return NULL;
+}
+
+__isl_give isl_map *isl_map_subtract_domain(__isl_take isl_map *map,
+       __isl_take isl_set *dom)
+{
+       return isl_map_align_params_map_map_and(map, dom, &map_subtract_domain);
+}
+
+/* Remove the elements of "dom" from the range of "map".
+ */
+static __isl_give isl_map *map_subtract_range(__isl_take isl_map *map,
+       __isl_take isl_set *dom)
+{
+       isl_map *ext_dom;
+
+       if (!isl_map_compatible_range(map, dom))
+               isl_die(isl_set_get_ctx(dom), isl_error_invalid,
+                       "incompatible spaces", goto error);
+       
+       ext_dom = isl_map_universe(isl_map_get_space(map));
+       ext_dom = isl_map_intersect_range(ext_dom, dom);
+       return isl_map_subtract(map, ext_dom);
+error:
+       isl_map_free(map);
+       isl_set_free(dom);
+       return NULL;
+}
+
+__isl_give isl_map *isl_map_subtract_range(__isl_take isl_map *map,
+       __isl_take isl_set *dom)
+{
+       return isl_map_align_params_map_map_and(map, dom, &map_subtract_range);
+}
+
 /* A diff collector that aborts as soon as its add function is called,
  * setting empty to 0.
  */
@@ -556,7 +632,7 @@ static int basic_map_diff_is_empty(__isl_keep isl_basic_map *bmap,
        int r;
        struct isl_is_empty_diff_collector edc;
 
-       r = isl_basic_map_fast_is_empty(bmap);
+       r = isl_basic_map_plain_is_empty(bmap);
        if (r)
                return r;
 
@@ -592,7 +668,7 @@ static int map_diff_is_empty(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
 
 /* Return 1 if "bmap" contains a single element.
  */
-int isl_basic_map_fast_is_singleton(__isl_keep isl_basic_map *bmap)
+int isl_basic_map_plain_is_singleton(__isl_keep isl_basic_map *bmap)
 {
        if (!bmap)
                return -1;
@@ -605,14 +681,14 @@ int isl_basic_map_fast_is_singleton(__isl_keep isl_basic_map *bmap)
 
 /* Return 1 if "map" contains a single element.
  */
-int isl_map_fast_is_singleton(__isl_keep isl_map *map)
+int isl_map_plain_is_singleton(__isl_keep isl_map *map)
 {
        if (!map)
                return -1;
        if (map->n != 1)
                return 0;
 
-       return isl_basic_map_fast_is_singleton(map->p[0]);
+       return isl_basic_map_plain_is_singleton(map->p[0]);
 }
 
 /* Given a singleton basic map, extract the single element
@@ -621,7 +697,7 @@ int isl_map_fast_is_singleton(__isl_keep isl_map *map)
 static __isl_give isl_point *singleton_extract_point(
        __isl_keep isl_basic_map *bmap)
 {
-       int i, j;
+       int j;
        unsigned dim;
        struct isl_vec *point;
        isl_int m;
@@ -639,7 +715,6 @@ static __isl_give isl_point *singleton_extract_point(
 
        isl_int_set_si(point->el[0], 1);
        for (j = 0; j < bmap->n_eq; ++j) {
-               int s;
                int i = dim - 1 - j;
                isl_assert(bmap->ctx,
                    isl_seq_first_non_zero(bmap->eq[j] + 1, i) == -1,
@@ -662,7 +737,7 @@ static __isl_give isl_point *singleton_extract_point(
        }
 
        isl_int_clear(m);
-       return isl_point_alloc(isl_basic_map_get_dim(bmap), point);
+       return isl_point_alloc(isl_basic_map_get_space(bmap), point);
 error:
        isl_int_clear(m);
        isl_vec_free(point);
@@ -699,25 +774,42 @@ static int map_is_singleton_subset(__isl_keep isl_map *map1,
        return is_subset;
 }
 
-int isl_map_is_subset(struct isl_map *map1, struct isl_map *map2)
+static int map_is_subset(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
 {
        int is_subset = 0;
-       struct isl_map *diff;
+       int empty;
+       int rat1, rat2;
 
        if (!map1 || !map2)
                return -1;
 
-       if (isl_map_is_empty(map1))
+       if (!isl_map_has_equal_space(map1, map2))
+               return 0;
+
+       empty = isl_map_is_empty(map1);
+       if (empty < 0)
+               return -1;
+       if (empty)
                return 1;
 
-       if (isl_map_is_empty(map2))
+       empty = isl_map_is_empty(map2);
+       if (empty < 0)
+               return -1;
+       if (empty)
+               return 0;
+
+       rat1 = isl_map_has_rational(map1);
+       rat2 = isl_map_has_rational(map2);
+       if (rat1 < 0 || rat2 < 0)
+               return -1;
+       if (rat1 && !rat2)
                return 0;
 
-       if (isl_map_fast_is_universe(map2))
+       if (isl_map_plain_is_universe(map2))
                return 1;
 
        map2 = isl_map_compute_divs(isl_map_copy(map2));
-       if (isl_map_fast_is_singleton(map1)) {
+       if (isl_map_plain_is_singleton(map1)) {
                is_subset = map_is_singleton_subset(map1, map2);
                isl_map_free(map2);
                return is_subset;
@@ -728,6 +820,12 @@ int isl_map_is_subset(struct isl_map *map1, struct isl_map *map2)
        return is_subset;
 }
 
+int isl_map_is_subset(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
+{
+       return isl_map_align_params_map_map_and_test(map1, map2,
+                                                       &map_is_subset);
+}
+
 int isl_set_is_subset(struct isl_set *set1, struct isl_set *set2)
 {
        return isl_map_is_subset(
@@ -775,14 +873,19 @@ __isl_give isl_set *isl_set_make_disjoint(__isl_take isl_set *set)
        return (struct isl_set *)isl_map_make_disjoint((struct isl_map *)set);
 }
 
-__isl_give isl_set *isl_set_complement(__isl_take isl_set *set)
+__isl_give isl_map *isl_map_complement(__isl_take isl_map *map)
 {
-       isl_set *universe;
+       isl_map *universe;
 
-       if (!set)
+       if (!map)
                return NULL;
 
-       universe = isl_set_universe(isl_set_get_dim(set));
+       universe = isl_map_universe(isl_map_get_space(map));
+
+       return isl_map_subtract(universe, map);
+}
 
-       return isl_set_subtract(universe, set);
+__isl_give isl_set *isl_set_complement(__isl_take isl_set *set)
+{
+       return isl_map_complement(set);
 }