align parameters of arguments to binary isl_map and isl_pw_aff functions
authorSven Verdoolaege <skimo@kotnet.org>
Wed, 20 Jul 2011 08:06:21 +0000 (10:06 +0200)
committerSven Verdoolaege <skimo@kotnet.org>
Wed, 20 Jul 2011 15:37:26 +0000 (17:37 +0200)
Signed-off-by: Sven Verdoolaege <skimo@kotnet.org>
doc/user.pod
isl_aff.c
isl_map.c
isl_map_private.h
isl_map_simplify.c
isl_map_subtract.c
isl_pw_templ.c

index f5f2429..b4c7381 100644 (file)
@@ -555,9 +555,9 @@ Also note that every function that operates on two sets or relations
 requires that both arguments have the same parameters.  This also
 means that if one of the arguments has named parameters, then the
 other needs to have named parameters too and the names need to match.
-Pairs of C<isl_union_set> and/or C<isl_union_map> arguments may
-have different parameters (as long as they are named), in which case
-the result will have as parameters the union of the parameters of
+Pairs of C<isl_set>, C<isl_map>, C<isl_union_set> and/or C<isl_union_map>
+arguments may have different parameters (as long as they are named),
+in which case the result will have as parameters the union of the parameters of
 the arguments.
 
 Given the identifier of a dimension (typically a parameter),
index 2835889..6d66733 100644 (file)
--- a/isl_aff.c
+++ b/isl_aff.c
@@ -1054,13 +1054,36 @@ __isl_give isl_pw_aff *isl_pw_aff_set_tuple_id(__isl_take isl_pw_aff *pwaff,
 
 #include <isl_pw_templ.c>
 
+static __isl_give isl_set *align_params_pw_pw_set_and(
+       __isl_take isl_pw_aff *pwaff1, __isl_take isl_pw_aff *pwaff2,
+       __isl_give isl_set *(*fn)(__isl_take isl_pw_aff *pwaff1,
+                                   __isl_take isl_pw_aff *pwaff2))
+{
+       if (!pwaff1 || !pwaff2)
+               goto error;
+       if (isl_dim_match(pwaff1->dim, isl_dim_param,
+                         pwaff2->dim, isl_dim_param))
+               return fn(pwaff1, pwaff2);
+       if (!isl_dim_has_named_params(pwaff1->dim) ||
+           !isl_dim_has_named_params(pwaff2->dim))
+               isl_die(isl_pw_aff_get_ctx(pwaff1), isl_error_invalid,
+                       "unaligned unnamed parameters", goto error);
+       pwaff1 = isl_pw_aff_align_params(pwaff1, isl_pw_aff_get_dim(pwaff2));
+       pwaff2 = isl_pw_aff_align_params(pwaff2, isl_pw_aff_get_dim(pwaff1));
+       return fn(pwaff1, pwaff2);
+error:
+       isl_pw_aff_free(pwaff1);
+       isl_pw_aff_free(pwaff2);
+       return NULL;
+}
+
 /* Compute a piecewise quasi-affine expression with a domain that
  * is the union of those of pwaff1 and pwaff2 and such that on each
  * cell, the quasi-affine expression is the maximum of those of pwaff1
  * and pwaff2.  If only one of pwaff1 or pwaff2 is defined on a given
  * cell, then the associated expression is the defined one.
  */
-__isl_give isl_pw_aff *isl_pw_aff_union_max(__isl_take isl_pw_aff *pwaff1,
+static __isl_give isl_pw_aff *pw_aff_union_max(__isl_take isl_pw_aff *pwaff1,
        __isl_take isl_pw_aff *pwaff2)
 {
        int i, j, n;
@@ -1134,6 +1157,12 @@ error:
        return NULL;
 }
 
+__isl_give isl_pw_aff *isl_pw_aff_union_max(__isl_take isl_pw_aff *pwaff1,
+       __isl_take isl_pw_aff *pwaff2)
+{
+       return align_params_pw_pw_and(pwaff1, pwaff2, &pw_aff_union_max);
+}
+
 /* Construct a map with as domain the domain of pwaff and
  * one-dimensional range corresponding to the affine expressions.
  */
@@ -1261,30 +1290,48 @@ static __isl_give isl_set *pw_aff_gte_set(__isl_take isl_pw_aff *pwaff1,
 /* Return a set containing those elements in the shared domain
  * of pwaff1 and pwaff2 where pwaff1 is equal to pwaff2.
  */
-__isl_give isl_set *isl_pw_aff_eq_set(__isl_take isl_pw_aff *pwaff1,
+static __isl_give isl_set *pw_aff_eq_set(__isl_take isl_pw_aff *pwaff1,
        __isl_take isl_pw_aff *pwaff2)
 {
        return pw_aff_gte_set(pwaff1, pwaff2, 0, 1);
 }
 
+__isl_give isl_set *isl_pw_aff_eq_set(__isl_take isl_pw_aff *pwaff1,
+       __isl_take isl_pw_aff *pwaff2)
+{
+       return align_params_pw_pw_set_and(pwaff1, pwaff2, &pw_aff_eq_set);
+}
+
 /* Return a set containing those elements in the shared domain
  * of pwaff1 and pwaff2 where pwaff1 is greater than or equal to pwaff2.
  */
-__isl_give isl_set *isl_pw_aff_ge_set(__isl_take isl_pw_aff *pwaff1,
+static __isl_give isl_set *pw_aff_ge_set(__isl_take isl_pw_aff *pwaff1,
        __isl_take isl_pw_aff *pwaff2)
 {
        return pw_aff_gte_set(pwaff1, pwaff2, 0, 0);
 }
 
+__isl_give isl_set *isl_pw_aff_ge_set(__isl_take isl_pw_aff *pwaff1,
+       __isl_take isl_pw_aff *pwaff2)
+{
+       return align_params_pw_pw_set_and(pwaff1, pwaff2, &pw_aff_ge_set);
+}
+
 /* Return a set containing those elements in the shared domain
  * of pwaff1 and pwaff2 where pwaff1 is strictly greater than pwaff2.
  */
-__isl_give isl_set *isl_pw_aff_gt_set(__isl_take isl_pw_aff *pwaff1,
+static __isl_give isl_set *pw_aff_gt_set(__isl_take isl_pw_aff *pwaff1,
        __isl_take isl_pw_aff *pwaff2)
 {
        return pw_aff_gte_set(pwaff1, pwaff2, 1, 0);
 }
 
+__isl_give isl_set *isl_pw_aff_gt_set(__isl_take isl_pw_aff *pwaff1,
+       __isl_take isl_pw_aff *pwaff2)
+{
+       return align_params_pw_pw_set_and(pwaff1, pwaff2, &pw_aff_gt_set);
+}
+
 __isl_give isl_set *isl_pw_aff_le_set(__isl_take isl_pw_aff *pwaff1,
        __isl_take isl_pw_aff *pwaff2)
 {
@@ -1300,7 +1347,7 @@ __isl_give isl_set *isl_pw_aff_lt_set(__isl_take isl_pw_aff *pwaff1,
 /* Return a set containing those elements in the shared domain
  * of pwaff1 and pwaff2 where pwaff1 is not equal to pwaff2.
  */
-__isl_give isl_set *isl_pw_aff_ne_set(__isl_take isl_pw_aff *pwaff1,
+static __isl_give isl_set *pw_aff_ne_set(__isl_take isl_pw_aff *pwaff1,
        __isl_take isl_pw_aff *pwaff2)
 {
        isl_set *set_lt, *set_gt;
@@ -1311,6 +1358,12 @@ __isl_give isl_set *isl_pw_aff_ne_set(__isl_take isl_pw_aff *pwaff1,
        return isl_set_union_disjoint(set_lt, set_gt);
 }
 
+__isl_give isl_set *isl_pw_aff_ne_set(__isl_take isl_pw_aff *pwaff1,
+       __isl_take isl_pw_aff *pwaff2)
+{
+       return align_params_pw_pw_set_and(pwaff1, pwaff2, &pw_aff_ne_set);
+}
+
 __isl_give isl_pw_aff *isl_pw_aff_scale_down(__isl_take isl_pw_aff *pwaff,
        isl_int v)
 {
@@ -1443,7 +1496,7 @@ error:
        return NULL;
 }
 
-__isl_give isl_pw_aff *isl_pw_aff_mul(__isl_take isl_pw_aff *pwaff1,
+static __isl_give isl_pw_aff *pw_aff_mul(__isl_take isl_pw_aff *pwaff1,
        __isl_take isl_pw_aff *pwaff2)
 {
        int i, j, n;
@@ -1483,7 +1536,13 @@ error:
        return NULL;
 }
 
-__isl_give isl_pw_aff *isl_pw_aff_min(__isl_take isl_pw_aff *pwaff1,
+__isl_give isl_pw_aff *isl_pw_aff_mul(__isl_take isl_pw_aff *pwaff1,
+       __isl_take isl_pw_aff *pwaff2)
+{
+       return align_params_pw_pw_and(pwaff1, pwaff2, &pw_aff_mul);
+}
+
+static __isl_give isl_pw_aff *pw_aff_min(__isl_take isl_pw_aff *pwaff1,
        __isl_take isl_pw_aff *pwaff2)
 {
        isl_set *le;
@@ -1493,7 +1552,13 @@ __isl_give isl_pw_aff *isl_pw_aff_min(__isl_take isl_pw_aff *pwaff1,
        return isl_pw_aff_cond(le, pwaff1, pwaff2);
 }
 
-__isl_give isl_pw_aff *isl_pw_aff_max(__isl_take isl_pw_aff *pwaff1,
+__isl_give isl_pw_aff *isl_pw_aff_min(__isl_take isl_pw_aff *pwaff1,
+       __isl_take isl_pw_aff *pwaff2)
+{
+       return align_params_pw_pw_and(pwaff1, pwaff2, &pw_aff_min);
+}
+
+static __isl_give isl_pw_aff *pw_aff_max(__isl_take isl_pw_aff *pwaff1,
        __isl_take isl_pw_aff *pwaff2)
 {
        isl_set *le;
@@ -1502,3 +1567,9 @@ __isl_give isl_pw_aff *isl_pw_aff_max(__isl_take isl_pw_aff *pwaff1,
                                isl_pw_aff_copy(pwaff2));
        return isl_pw_aff_cond(le, pwaff1, pwaff2);
 }
+
+__isl_give isl_pw_aff *isl_pw_aff_max(__isl_take isl_pw_aff *pwaff1,
+       __isl_take isl_pw_aff *pwaff2)
+{
+       return align_params_pw_pw_and(pwaff1, pwaff2, &pw_aff_max);
+}
index 12369e9..8ed3e44 100644 (file)
--- a/isl_map.c
+++ b/isl_map.c
@@ -811,6 +811,52 @@ static int room_for_con(struct isl_basic_map *bmap, unsigned n)
        return bmap->n_eq + bmap->n_ineq + n <= bmap->c_size;
 }
 
+__isl_give isl_map *isl_map_align_params_map_map_and(
+       __isl_take isl_map *map1, __isl_take isl_map *map2,
+       __isl_give isl_map *(*fn)(__isl_take isl_map *map1,
+                                   __isl_take isl_map *map2))
+{
+       if (!map1 || !map2)
+               goto error;
+       if (isl_dim_match(map1->dim, isl_dim_param, map2->dim, isl_dim_param))
+               return fn(map1, map2);
+       if (!isl_dim_has_named_params(map1->dim) ||
+           !isl_dim_has_named_params(map2->dim))
+               isl_die(map1->ctx, isl_error_invalid,
+                       "unaligned unnamed parameters", goto error);
+       map1 = isl_map_align_params(map1, isl_map_get_dim(map2));
+       map2 = isl_map_align_params(map2, isl_map_get_dim(map1));
+       return fn(map1, map2);
+error:
+       isl_map_free(map1);
+       isl_map_free(map2);
+       return NULL;
+}
+
+static int align_params_map_map_and_test(__isl_keep isl_map *map1,
+       __isl_keep isl_map *map2,
+       int (*fn)(__isl_keep isl_map *map1, __isl_keep isl_map *map2))
+{
+       int r;
+
+       if (!map1 || !map2)
+               return -1;
+       if (isl_dim_match(map1->dim, isl_dim_param, map2->dim, isl_dim_param))
+               return fn(map1, map2);
+       if (!isl_dim_has_named_params(map1->dim) ||
+           !isl_dim_has_named_params(map2->dim))
+               isl_die(map1->ctx, isl_error_invalid,
+                       "unaligned unnamed parameters", return -1);
+       map1 = isl_map_copy(map1);
+       map2 = isl_map_copy(map2);
+       map1 = isl_map_align_params(map1, isl_map_get_dim(map2));
+       map2 = isl_map_align_params(map2, isl_map_get_dim(map1));
+       r = fn(map1, map2);
+       isl_map_free(map1);
+       isl_map_free(map2);
+       return r;
+}
+
 int isl_basic_map_alloc_equality(struct isl_basic_map *bmap)
 {
        struct isl_ctx *ctx;
@@ -2356,7 +2402,8 @@ error:
        return NULL;
 }
 
-struct isl_map *isl_map_intersect(struct isl_map *map1, struct isl_map *map2)
+static __isl_give isl_map *map_intersect(__isl_take isl_map *map1,
+       __isl_take isl_map *map2)
 {
        unsigned flags = 0;
        struct isl_map *result;
@@ -2380,8 +2427,6 @@ struct isl_map *isl_map_intersect(struct isl_map *map1, struct isl_map *map2)
            (map1->p[0]->n_eq + map1->p[0]->n_ineq == 1 ||
             map2->p[0]->n_eq + map2->p[0]->n_ineq == 1))
                return map_intersect_add_constraint(map1, map2);
-       isl_assert(map1->ctx, isl_dim_match(map1->dim, isl_dim_param,
-                                        map2->dim, isl_dim_param), goto error);
        if (isl_dim_total(map1->dim) ==
                                isl_dim_size(map1->dim, isl_dim_param) &&
            isl_dim_total(map2->dim) != isl_dim_size(map2->dim, isl_dim_param))
@@ -2421,6 +2466,12 @@ error:
        return NULL;
 }
 
+__isl_give isl_map *isl_map_intersect(__isl_take isl_map *map1,
+       __isl_take isl_map *map2)
+{
+       return isl_map_align_params_map_map_and(map1, map2, &map_intersect);
+}
+
 struct isl_set *isl_set_intersect(struct isl_set *set1, struct isl_set *set2)
 {
        return (struct isl_set *)
@@ -2431,12 +2482,18 @@ struct isl_set *isl_set_intersect(struct isl_set *set1, struct isl_set *set2)
 /* The current implementation of isl_map_intersect accepts intersections
  * with parameter domains, so we can just call that for now.
  */
-__isl_give isl_map *isl_map_intersect_params(__isl_take isl_map *map,
+static __isl_give isl_map *map_intersect_params(__isl_take isl_map *map,
                __isl_take isl_set *params)
 {
        return isl_map_intersect(map, params);
 }
 
+__isl_give isl_map *isl_map_intersect_params(__isl_take isl_map *map1,
+       __isl_take isl_map *map2)
+{
+       return isl_map_align_params_map_map_and(map1, map2, &map_intersect_params);
+}
+
 __isl_give isl_set *isl_set_intersect_params(__isl_take isl_set *set,
                __isl_take isl_set *params)
 {
@@ -5633,8 +5690,8 @@ error:
        return NULL;
 }
 
-struct isl_map *isl_map_union_disjoint(
-                       struct isl_map *map1, struct isl_map *map2)
+static __isl_give isl_map *map_union_disjoint(__isl_take isl_map *map1,
+       __isl_take isl_map *map2)
 {
        int i;
        unsigned flags = 0;
@@ -5684,6 +5741,12 @@ error:
        return NULL;
 }
 
+__isl_give isl_map *isl_map_union_disjoint(__isl_take isl_map *map1,
+       __isl_take isl_map *map2)
+{
+       return isl_map_align_params_map_map_and(map1, map2, &map_union_disjoint);
+}
+
 struct isl_map *isl_map_union(struct isl_map *map1, struct isl_map *map2)
 {
        map1 = isl_map_union_disjoint(map1, map2);
@@ -5708,8 +5771,8 @@ struct isl_set *isl_set_union(struct isl_set *set1, struct isl_set *set2)
                isl_map_union((struct isl_map *)set1, (struct isl_map *)set2);
 }
 
-struct isl_map *isl_map_intersect_range(
-               struct isl_map *map, struct isl_set *set)
+static __isl_give isl_map *map_intersect_range(__isl_take isl_map *map,
+       __isl_take isl_set *set)
 {
        unsigned flags = 0;
        struct isl_map *result;
@@ -5758,6 +5821,12 @@ error:
        return NULL;
 }
 
+__isl_give isl_map *isl_map_intersect_range(__isl_take isl_map *map,
+       __isl_take isl_set *set)
+{
+       return isl_map_align_params_map_map_and(map, set, &map_intersect_range);
+}
+
 struct isl_map *isl_map_intersect_domain(
                struct isl_map *map, struct isl_set *set)
 {
@@ -5765,8 +5834,8 @@ struct isl_map *isl_map_intersect_domain(
                isl_map_intersect_range(isl_map_reverse(map), set));
 }
 
-struct isl_map *isl_map_apply_domain(
-               struct isl_map *map1, struct isl_map *map2)
+static __isl_give isl_map *map_apply_domain(__isl_take isl_map *map1,
+       __isl_take isl_map *map2)
 {
        if (!map1 || !map2)
                goto error;
@@ -5779,8 +5848,14 @@ error:
        return NULL;
 }
 
-struct isl_map *isl_map_apply_range(
-               struct isl_map *map1, struct isl_map *map2)
+__isl_give isl_map *isl_map_apply_domain(__isl_take isl_map *map1,
+       __isl_take isl_map *map2)
+{
+       return isl_map_align_params_map_map_and(map1, map2, &map_apply_domain);
+}
+
+static __isl_give isl_map *map_apply_range(__isl_take isl_map *map1,
+       __isl_take isl_map *map2)
 {
        struct isl_dim *dim_result;
        struct isl_map *result;
@@ -5815,6 +5890,12 @@ error:
        return NULL;
 }
 
+__isl_give isl_map *isl_map_apply_range(__isl_take isl_map *map1,
+       __isl_take isl_map *map2)
+{
+       return isl_map_align_params_map_map_and(map1, map2, &map_apply_range);
+}
+
 /*
  * returns range - domain
  */
@@ -6317,7 +6398,7 @@ int isl_set_has_equal_dim(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
        return isl_dim_equal(set1->dim, set2->dim);
 }
 
-int isl_map_is_equal(struct isl_map *map1, struct isl_map *map2)
+static int map_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
 {
        int is_subset;
 
@@ -6330,6 +6411,11 @@ int isl_map_is_equal(struct isl_map *map1, struct isl_map *map2)
        return is_subset;
 }
 
+int isl_map_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
+{
+       return align_params_map_map_and_test(map1, map2, &map_is_equal);
+}
+
 int isl_basic_map_is_strict_subset(
                struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
 {
@@ -6705,7 +6791,8 @@ struct isl_set *isl_set_align_divs(struct isl_set *set)
        return (struct isl_set *)isl_map_align_divs((struct isl_map *)set);
 }
 
-struct isl_set *isl_set_apply(struct isl_set *set, struct isl_map *map)
+static __isl_give isl_set *set_apply( __isl_take isl_set *set,
+       __isl_take isl_map *map)
 {
        if (!set || !map)
                goto error;
@@ -6719,6 +6806,12 @@ error:
        return NULL;
 }
 
+__isl_give isl_set *isl_set_apply( __isl_take isl_set *set,
+       __isl_take isl_map *map)
+{
+       return isl_map_align_params_map_map_and(set, map, &set_apply);
+}
+
 /* There is no need to cow as removing empty parts doesn't change
  * the meaning of the set.
  */
@@ -7656,11 +7749,18 @@ error:
 
 /* Given two maps A -> B and C -> D, construct a map [A -> C] -> [B -> D]
  */
-struct isl_map *isl_map_product(struct isl_map *map1, struct isl_map *map2)
+static __isl_give isl_map *map_product_aligned(__isl_take isl_map *map1,
+       __isl_take isl_map *map2)
 {
        return map_product(map1, map2, &isl_dim_product, &isl_basic_map_product);
 }
 
+__isl_give isl_map *isl_map_product(__isl_take isl_map *map1,
+       __isl_take isl_map *map2)
+{
+       return isl_map_align_params_map_map_and(map1, map2, &map_product_aligned);
+}
+
 /* Given two maps A -> B and C -> D, construct a map (A, C) -> (B, D)
  */
 __isl_give isl_map *isl_map_flat_product(__isl_take isl_map *map1,
@@ -7689,13 +7789,20 @@ __isl_give isl_set *isl_set_flat_product(__isl_take isl_set *set1,
 
 /* Given two maps A -> B and C -> D, construct a map (A * C) -> [B -> D]
  */
-__isl_give isl_map *isl_map_range_product(__isl_take isl_map *map1,
+static __isl_give isl_map *map_range_product_aligned(__isl_take isl_map *map1,
        __isl_take isl_map *map2)
 {
        return map_product(map1, map2, &isl_dim_range_product,
                                &isl_basic_map_range_product);
 }
 
+__isl_give isl_map *isl_map_range_product(__isl_take isl_map *map1,
+       __isl_take isl_map *map2)
+{
+       return isl_map_align_params_map_map_and(map1, map2,
+                                               &map_range_product_aligned);
+}
+
 /* Given two maps A -> B and C -> D, construct a map (A * C) -> (B, D)
  */
 __isl_give isl_map *isl_map_flat_range_product(__isl_take isl_map *map1,
index a3b106b..a978fc6 100644 (file)
@@ -308,4 +308,9 @@ int isl_basic_map_divs_known(__isl_keep isl_basic_map *bmap);
 __isl_give isl_map *isl_map_inline_foreach_basic_map(__isl_take isl_map *map,
        __isl_give isl_basic_map *(*fn)(__isl_take isl_basic_map *bmap));
 
+__isl_give isl_map *isl_map_align_params_map_map_and(
+       __isl_take isl_map *map1, __isl_take isl_map *map2,
+       __isl_give isl_map *(*fn)(__isl_take isl_map *map1,
+                                   __isl_take isl_map *map2));
+
 #endif
index 7a24c5b..9558a09 100644 (file)
@@ -1813,13 +1813,19 @@ error:
        return NULL;
 }
 
-__isl_give isl_map *isl_map_gist(__isl_take isl_map *map,
+static __isl_give isl_map *map_gist(__isl_take isl_map *map,
        __isl_take isl_map *context)
 {
        context = isl_map_compute_divs(context);
        return isl_map_gist_basic_map(map, isl_map_simple_hull(context));
 }
 
+__isl_give isl_map *isl_map_gist(__isl_take isl_map *map,
+       __isl_take isl_map *context)
+{
+       return isl_map_align_params_map_map_and(map, context, &map_gist);
+}
+
 struct isl_basic_set *isl_basic_set_gist(struct isl_basic_set *bset,
                                                struct isl_basic_set *context)
 {
index 0510657..509e0f8 100644 (file)
@@ -478,7 +478,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;
@@ -522,6 +523,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 *)
index a446c43..644d9e6 100644 (file)
@@ -181,7 +181,122 @@ int FN(PW,IS_ZERO)(__isl_keep PW *pw)
        return pw->n == 0;
 }
 
-__isl_give PW *FN(PW,add)(__isl_take PW *pw1, __isl_take PW *pw2)
+#ifndef NO_REALIGN
+__isl_give PW *FN(PW,realign)(__isl_take PW *pw, __isl_take isl_reordering *exp)
+{
+       int i;
+
+       pw = FN(PW,cow)(pw);
+       if (!pw || !exp)
+               return NULL;
+
+       for (i = 0; i < pw->n; ++i) {
+               pw->p[i].set = isl_set_realign(pw->p[i].set,
+                                                   isl_reordering_copy(exp));
+               if (!pw->p[i].set)
+                       goto error;
+               pw->p[i].FIELD = FN(EL,realign)(pw->p[i].FIELD,
+                                                   isl_reordering_copy(exp));
+               if (!pw->p[i].FIELD)
+                       goto error;
+       }
+
+       pw = FN(PW,reset_dim)(pw, isl_dim_copy(exp->dim));
+
+       isl_reordering_free(exp);
+       return pw;
+error:
+       isl_reordering_free(exp);
+       FN(PW,free)(pw);
+       return NULL;
+}
+
+/* Align the parameters of "pw" to those of "model".
+ */
+__isl_give PW *FN(PW,align_params)(__isl_take PW *pw, __isl_take isl_dim *model)
+{
+       isl_ctx *ctx;
+
+       if (!pw || !model)
+               goto error;
+
+       ctx = isl_dim_get_ctx(model);
+       if (!isl_dim_has_named_params(model))
+               isl_die(ctx, isl_error_invalid,
+                       "model has unnamed parameters", goto error);
+       if (!isl_dim_has_named_params(pw->dim))
+               isl_die(ctx, isl_error_invalid,
+                       "input has unnamed parameters", goto error);
+       if (!isl_dim_match(pw->dim, isl_dim_param, model, isl_dim_param)) {
+               isl_reordering *exp;
+
+               model = isl_dim_drop(model, isl_dim_in,
+                                       0, isl_dim_size(model, isl_dim_in));
+               model = isl_dim_drop(model, isl_dim_out,
+                                       0, isl_dim_size(model, isl_dim_out));
+               exp = isl_parameter_alignment_reordering(pw->dim, model);
+               exp = isl_reordering_extend_dim(exp, FN(PW,get_dim)(pw));
+               pw = FN(PW,realign)(pw, exp);
+       }
+
+       isl_dim_free(model);
+       return pw;
+error:
+       isl_dim_free(model);
+       FN(PW,free)(pw);
+       return NULL;
+}
+
+static __isl_give PW *align_params_pw_pw_and(__isl_take PW *pw1,
+       __isl_take PW *pw2,
+       __isl_give PW *(*fn)(__isl_take PW *pw1, __isl_take PW *pw2))
+{
+       isl_ctx *ctx;
+
+       if (!pw1 || !pw2)
+               goto error;
+       if (isl_dim_match(pw1->dim, isl_dim_param, pw2->dim, isl_dim_param))
+               return fn(pw1, pw2);
+       ctx = FN(PW,get_ctx)(pw1);
+       if (!isl_dim_has_named_params(pw1->dim) ||
+           !isl_dim_has_named_params(pw2->dim))
+               isl_die(ctx, isl_error_invalid,
+                       "unaligned unnamed parameters", goto error);
+       pw1 = FN(PW,align_params)(pw1, FN(PW,get_dim)(pw2));
+       pw2 = FN(PW,align_params)(pw2, FN(PW,get_dim)(pw1));
+       return fn(pw1, pw2);
+error:
+       FN(PW,free)(pw1);
+       FN(PW,free)(pw2);
+       return NULL;
+}
+
+static __isl_give PW *align_params_pw_set_and(__isl_take PW *pw,
+       __isl_take isl_set *set,
+       __isl_give PW *(*fn)(__isl_take PW *pw, __isl_take isl_set *set))
+{
+       isl_ctx *ctx;
+
+       if (!pw || !set)
+               goto error;
+       if (isl_dim_match(pw->dim, isl_dim_param, set->dim, isl_dim_param))
+               return fn(pw, set);
+       ctx = FN(PW,get_ctx)(pw);
+       if (!isl_dim_has_named_params(pw->dim) ||
+           !isl_dim_has_named_params(set->dim))
+               isl_die(ctx, isl_error_invalid,
+                       "unaligned unnamed parameters", goto error);
+       pw = FN(PW,align_params)(pw, isl_set_get_dim(set));
+       set = isl_set_align_params(set, FN(PW,get_dim)(pw));
+       return fn(pw, set);
+error:
+       FN(PW,free)(pw);
+       isl_set_free(set);
+       return NULL;
+}
+#endif
+
+static __isl_give PW *FN(PW,add_aligned)(__isl_take PW *pw1, __isl_take PW *pw2)
 {
        int i, j, n;
        struct PW *res;
@@ -257,7 +372,13 @@ error:
        return NULL;
 }
 
-__isl_give PW *FN(PW,add_disjoint)(__isl_take PW *pw1, __isl_take PW *pw2)
+__isl_give PW *FN(PW,add)(__isl_take PW *pw1, __isl_take PW *pw2)
+{
+       return align_params_pw_pw_and(pw1, pw2, &FN(PW,add_aligned));
+}
+
+static __isl_give PW *FN(PW,add_disjoint_aligned)(__isl_take PW *pw1,
+       __isl_take PW *pw2)
 {
        int i;
        isl_ctx *ctx;
@@ -310,6 +431,11 @@ error:
        return NULL;
 }
 
+__isl_give PW *FN(PW,add_disjoint)(__isl_take PW *pw1, __isl_take PW *pw2)
+{
+       return align_params_pw_pw_and(pw1, pw2, &FN(PW,add_disjoint_aligned));
+}
+
 #ifndef NO_NEG
 __isl_give PW *FN(PW,neg)(__isl_take PW *pw)
 {
@@ -397,7 +523,8 @@ __isl_give isl_set *FN(PW,domain)(__isl_take PW *pw)
        return dom;
 }
 
-__isl_give PW *FN(PW,intersect_domain)(__isl_take PW *pw, __isl_take isl_set *set)
+static __isl_give PW *FN(PW,intersect_domain_aligned)(__isl_take PW *pw,
+       __isl_take isl_set *set)
 {
        int i;
 
@@ -438,7 +565,15 @@ error:
        return NULL;
 }
 
-__isl_give PW *FN(PW,gist)(__isl_take PW *pw, __isl_take isl_set *context)
+__isl_give PW *FN(PW,intersect_domain)(__isl_take PW *pw,
+       __isl_take isl_set *context)
+{
+       return align_params_pw_set_and(pw, context,
+                                       &FN(PW,intersect_domain_aligned));
+}
+
+static __isl_give PW *FN(PW,gist_aligned)(__isl_take PW *pw,
+       __isl_take isl_set *context)
 {
        int i;
        isl_basic_set *hull = NULL;
@@ -451,6 +586,12 @@ __isl_give PW *FN(PW,gist)(__isl_take PW *pw, __isl_take isl_set *context)
                return pw;
        }
 
+       if (!isl_dim_match(pw->dim, isl_dim_param,
+                               context->dim, isl_dim_param)) {
+               pw = FN(PW,align_params)(pw, isl_set_get_dim(context));
+               context = isl_set_align_params(context, FN(PW,get_dim)(pw));
+       }
+
        context = isl_set_compute_divs(context);
        hull = isl_set_simple_hull(isl_set_copy(context));
 
@@ -489,6 +630,11 @@ error:
        return NULL;
 }
 
+__isl_give PW *FN(PW,gist)(__isl_take PW *pw, __isl_take isl_set *context)
+{
+       return align_params_pw_set_and(pw, context, &FN(PW,gist_aligned));
+}
+
 __isl_give PW *FN(PW,coalesce)(__isl_take PW *pw)
 {
        int i, j;
@@ -962,73 +1108,6 @@ error:
 }
 #endif
 
-#ifndef NO_REALIGN
-__isl_give PW *FN(PW,realign)(__isl_take PW *pw, __isl_take isl_reordering *exp)
-{
-       int i;
-
-       pw = FN(PW,cow)(pw);
-       if (!pw || !exp)
-               return NULL;
-
-       for (i = 0; i < pw->n; ++i) {
-               pw->p[i].set = isl_set_realign(pw->p[i].set,
-                                                   isl_reordering_copy(exp));
-               if (!pw->p[i].set)
-                       goto error;
-               pw->p[i].FIELD = FN(EL,realign)(pw->p[i].FIELD,
-                                                   isl_reordering_copy(exp));
-               if (!pw->p[i].FIELD)
-                       goto error;
-       }
-
-       pw = FN(PW,reset_dim)(pw, isl_dim_copy(exp->dim));
-
-       isl_reordering_free(exp);
-       return pw;
-error:
-       isl_reordering_free(exp);
-       FN(PW,free)(pw);
-       return NULL;
-}
-
-/* Align the parameters of "pw" to those of "model".
- */
-__isl_give PW *FN(PW,align_params)(__isl_take PW *pw, __isl_take isl_dim *model)
-{
-       isl_ctx *ctx;
-
-       if (!pw || !model)
-               goto error;
-
-       ctx = isl_dim_get_ctx(model);
-       if (!isl_dim_has_named_params(model))
-               isl_die(ctx, isl_error_invalid,
-                       "model has unnamed parameters", goto error);
-       if (!isl_dim_has_named_params(pw->dim))
-               isl_die(ctx, isl_error_invalid,
-                       "input has unnamed parameters", goto error);
-       if (!isl_dim_match(pw->dim, isl_dim_param, model, isl_dim_param)) {
-               isl_reordering *exp;
-
-               model = isl_dim_drop(model, isl_dim_in,
-                                       0, isl_dim_size(model, isl_dim_in));
-               model = isl_dim_drop(model, isl_dim_out,
-                                       0, isl_dim_size(model, isl_dim_out));
-               exp = isl_parameter_alignment_reordering(pw->dim, model);
-               exp = isl_reordering_extend_dim(exp, FN(PW,get_dim)(pw));
-               pw = FN(PW,realign)(pw, exp);
-       }
-
-       isl_dim_free(model);
-       return pw;
-error:
-       isl_dim_free(model);
-       FN(PW,free)(pw);
-       return NULL;
-}
-#endif
-
 __isl_give PW *FN(PW,mul_isl_int)(__isl_take PW *pw, isl_int v)
 {
        int i;