isl_printer_print_map: make printing order of disjuncts platform independent
[platform/upstream/isl.git] / isl_aff.c
index de1a0ca..3b2d20e 100644 (file)
--- a/isl_aff.c
+++ b/isl_aff.c
@@ -22,6 +22,7 @@
 #include <isl/constraint.h>
 #include <isl/seq.h>
 #include <isl/set.h>
+#include <isl_val_private.h>
 #include <isl_config.h>
 
 #undef BASE
@@ -408,6 +409,19 @@ int isl_aff_get_denominator(__isl_keep isl_aff *aff, isl_int *v)
        return 0;
 }
 
+/* Return the common denominator of "aff".
+ */
+__isl_give isl_val *isl_aff_get_denominator_val(__isl_keep isl_aff *aff)
+{
+       isl_ctx *ctx;
+
+       if (!aff)
+               return NULL;
+
+       ctx = isl_aff_get_ctx(aff);
+       return isl_val_int_from_isl_int(ctx, aff->v->el[0]);
+}
+
 int isl_aff_get_constant(__isl_keep isl_aff *aff, isl_int *v)
 {
        if (!aff)
@@ -416,6 +430,21 @@ int isl_aff_get_constant(__isl_keep isl_aff *aff, isl_int *v)
        return 0;
 }
 
+/* Return the constant term of "aff".
+ */
+__isl_give isl_val *isl_aff_get_constant_val(__isl_keep isl_aff *aff)
+{
+       isl_ctx *ctx;
+       isl_val *v;
+
+       if (!aff)
+               return NULL;
+
+       ctx = isl_aff_get_ctx(aff);
+       v = isl_val_rat_from_isl_int(ctx, aff->v->el[1], aff->v->el[0]);
+       return isl_val_normalize(v);
+}
+
 int isl_aff_get_coefficient(__isl_keep isl_aff *aff,
        enum isl_dim_type type, int pos, isl_int *v)
 {
@@ -439,6 +468,35 @@ int isl_aff_get_coefficient(__isl_keep isl_aff *aff,
        return 0;
 }
 
+/* Return the coefficient of the variable of type "type" at position "pos"
+ * of "aff".
+ */
+__isl_give isl_val *isl_aff_get_coefficient_val(__isl_keep isl_aff *aff,
+       enum isl_dim_type type, int pos)
+{
+       isl_ctx *ctx;
+       isl_val *v;
+
+       if (!aff)
+               return NULL;
+
+       ctx = isl_aff_get_ctx(aff);
+       if (type == isl_dim_out)
+               isl_die(ctx, isl_error_invalid,
+                       "output/set dimension does not have a coefficient",
+                       return NULL);
+       if (type == isl_dim_in)
+               type = isl_dim_set;
+
+       if (pos >= isl_local_space_dim(aff->ls, type))
+               isl_die(ctx, isl_error_invalid,
+                       "position out of bounds", return NULL);
+
+       pos += isl_local_space_offset(aff->ls, type);
+       v = isl_val_rat_from_isl_int(ctx, aff->v->el[1 + pos], aff->v->el[0]);
+       return isl_val_normalize(v);
+}
+
 __isl_give isl_aff *isl_aff_set_denominator(__isl_take isl_aff *aff, isl_int v)
 {
        aff = isl_aff_cow(aff);
@@ -469,6 +527,53 @@ __isl_give isl_aff *isl_aff_set_constant(__isl_take isl_aff *aff, isl_int v)
        return aff;
 }
 
+/* Replace the constant term of "aff" by "v".
+ */
+__isl_give isl_aff *isl_aff_set_constant_val(__isl_take isl_aff *aff,
+       __isl_take isl_val *v)
+{
+       if (!aff || !v)
+               goto error;
+
+       if (!isl_val_is_rat(v))
+               isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
+                       "expecting rational value", goto error);
+
+       if (isl_int_eq(aff->v->el[1], v->n) &&
+           isl_int_eq(aff->v->el[0], v->d)) {
+               isl_val_free(v);
+               return aff;
+       }
+
+       aff = isl_aff_cow(aff);
+       if (!aff)
+               goto error;
+       aff->v = isl_vec_cow(aff->v);
+       if (!aff->v)
+               goto error;
+
+       if (isl_int_eq(aff->v->el[0], v->d)) {
+               isl_int_set(aff->v->el[1], v->n);
+       } else if (isl_int_is_one(v->d)) {
+               isl_int_mul(aff->v->el[1], aff->v->el[0], v->n);
+       } else {
+               isl_seq_scale(aff->v->el + 1,
+                               aff->v->el + 1, v->d, aff->v->size - 1);
+               isl_int_mul(aff->v->el[1], aff->v->el[0], v->n);
+               isl_int_mul(aff->v->el[0], aff->v->el[0], v->d);
+               aff->v = isl_vec_normalize(aff->v);
+               if (!aff->v)
+                       goto error;
+       }
+
+       isl_val_free(v);
+       return aff;
+error:
+       isl_aff_free(aff);
+       isl_val_free(v);
+       return NULL;
+}
+
 __isl_give isl_aff *isl_aff_add_constant(__isl_take isl_aff *aff, isl_int v)
 {
        if (isl_int_is_zero(v))
@@ -487,6 +592,56 @@ __isl_give isl_aff *isl_aff_add_constant(__isl_take isl_aff *aff, isl_int v)
        return aff;
 }
 
+/* Add "v" to the constant term of "aff".
+ */
+__isl_give isl_aff *isl_aff_add_constant_val(__isl_take isl_aff *aff,
+       __isl_take isl_val *v)
+{
+       if (!aff || !v)
+               goto error;
+
+       if (isl_val_is_zero(v)) {
+               isl_val_free(v);
+               return aff;
+       }
+
+       if (!isl_val_is_rat(v))
+               isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
+                       "expecting rational value", goto error);
+
+       aff = isl_aff_cow(aff);
+       if (!aff)
+               goto error;
+
+       aff->v = isl_vec_cow(aff->v);
+       if (!aff->v)
+               goto error;
+
+       if (isl_int_is_one(v->d)) {
+               isl_int_addmul(aff->v->el[1], aff->v->el[0], v->n);
+       } else if (isl_int_eq(aff->v->el[0], v->d)) {
+               isl_int_add(aff->v->el[1], aff->v->el[1], v->n);
+               aff->v = isl_vec_normalize(aff->v);
+               if (!aff->v)
+                       goto error;
+       } else {
+               isl_seq_scale(aff->v->el + 1,
+                               aff->v->el + 1, v->d, aff->v->size - 1);
+               isl_int_addmul(aff->v->el[1], aff->v->el[0], v->n);
+               isl_int_mul(aff->v->el[0], aff->v->el[0], v->d);
+               aff->v = isl_vec_normalize(aff->v);
+               if (!aff->v)
+                       goto error;
+       }
+
+       isl_val_free(v);
+       return aff;
+error:
+       isl_aff_free(aff);
+       isl_val_free(v);
+       return NULL;
+}
+
 __isl_give isl_aff *isl_aff_add_constant_si(__isl_take isl_aff *aff, int v)
 {
        isl_int t;
@@ -613,6 +768,66 @@ __isl_give isl_aff *isl_aff_set_coefficient_si(__isl_take isl_aff *aff,
        return aff;
 }
 
+/* Replace the coefficient of the variable of type "type" at position "pos"
+ * of "aff" by "v".
+ */
+__isl_give isl_aff *isl_aff_set_coefficient_val(__isl_take isl_aff *aff,
+       enum isl_dim_type type, int pos, __isl_take isl_val *v)
+{
+       if (!aff || !v)
+               goto error;
+
+       if (type == isl_dim_out)
+               isl_die(aff->v->ctx, isl_error_invalid,
+                       "output/set dimension does not have a coefficient",
+                       goto error);
+       if (type == isl_dim_in)
+               type = isl_dim_set;
+
+       if (pos >= isl_local_space_dim(aff->ls, type))
+               isl_die(aff->v->ctx, isl_error_invalid,
+                       "position out of bounds", goto error);
+
+       if (!isl_val_is_rat(v))
+               isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
+                       "expecting rational value", goto error);
+
+       pos += isl_local_space_offset(aff->ls, type);
+       if (isl_int_eq(aff->v->el[1 + pos], v->n) &&
+           isl_int_eq(aff->v->el[0], v->d)) {
+               isl_val_free(v);
+               return aff;
+       }
+
+       aff = isl_aff_cow(aff);
+       if (!aff)
+               goto error;
+       aff->v = isl_vec_cow(aff->v);
+       if (!aff->v)
+               goto error;
+
+       if (isl_int_eq(aff->v->el[0], v->d)) {
+               isl_int_set(aff->v->el[1 + pos], v->n);
+       } else if (isl_int_is_one(v->d)) {
+               isl_int_mul(aff->v->el[1 + pos], aff->v->el[0], v->n);
+       } else {
+               isl_seq_scale(aff->v->el + 1,
+                               aff->v->el + 1, v->d, aff->v->size - 1);
+               isl_int_mul(aff->v->el[1 + pos], aff->v->el[0], v->n);
+               isl_int_mul(aff->v->el[0], aff->v->el[0], v->d);
+               aff->v = isl_vec_normalize(aff->v);
+               if (!aff->v)
+                       goto error;
+       }
+
+       isl_val_free(v);
+       return aff;
+error:
+       isl_aff_free(aff);
+       isl_val_free(v);
+       return NULL;
+}
+
 __isl_give isl_aff *isl_aff_add_coefficient(__isl_take isl_aff *aff,
        enum isl_dim_type type, int pos, isl_int v)
 {
@@ -644,6 +859,69 @@ __isl_give isl_aff *isl_aff_add_coefficient(__isl_take isl_aff *aff,
        return aff;
 }
 
+/* Add "v" to the coefficient of the variable of type "type"
+ * at position "pos" of "aff".
+ */
+__isl_give isl_aff *isl_aff_add_coefficient_val(__isl_take isl_aff *aff,
+       enum isl_dim_type type, int pos, __isl_take isl_val *v)
+{
+       if (!aff || !v)
+               goto error;
+
+       if (isl_val_is_zero(v)) {
+               isl_val_free(v);
+               return aff;
+       }
+
+       if (type == isl_dim_out)
+               isl_die(aff->v->ctx, isl_error_invalid,
+                       "output/set dimension does not have a coefficient",
+                       goto error);
+       if (type == isl_dim_in)
+               type = isl_dim_set;
+
+       if (pos >= isl_local_space_dim(aff->ls, type))
+               isl_die(aff->v->ctx, isl_error_invalid,
+                       "position out of bounds", goto error);
+
+       if (!isl_val_is_rat(v))
+               isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
+                       "expecting rational value", goto error);
+
+       aff = isl_aff_cow(aff);
+       if (!aff)
+               goto error;
+
+       aff->v = isl_vec_cow(aff->v);
+       if (!aff->v)
+               goto error;
+
+       pos += isl_local_space_offset(aff->ls, type);
+       if (isl_int_is_one(v->d)) {
+               isl_int_addmul(aff->v->el[1 + pos], aff->v->el[0], v->n);
+       } else if (isl_int_eq(aff->v->el[0], v->d)) {
+               isl_int_add(aff->v->el[1 + pos], aff->v->el[1 + pos], v->n);
+               aff->v = isl_vec_normalize(aff->v);
+               if (!aff->v)
+                       goto error;
+       } else {
+               isl_seq_scale(aff->v->el + 1,
+                               aff->v->el + 1, v->d, aff->v->size - 1);
+               isl_int_addmul(aff->v->el[1 + pos], aff->v->el[0], v->n);
+               isl_int_mul(aff->v->el[0], aff->v->el[0], v->d);
+               aff->v = isl_vec_normalize(aff->v);
+               if (!aff->v)
+                       goto error;
+       }
+
+       isl_val_free(v);
+       return aff;
+error:
+       isl_aff_free(aff);
+       isl_val_free(v);
+       return NULL;
+}
+
 __isl_give isl_aff *isl_aff_add_coefficient_si(__isl_take isl_aff *aff,
        enum isl_dim_type type, int pos, int v)
 {
@@ -1033,6 +1311,37 @@ __isl_give isl_aff *isl_aff_mod(__isl_take isl_aff *aff, isl_int m)
 
 /* Compute
  *
+ *     aff mod m = aff - m * floor(aff/m)
+ *
+ * with m an integer value.
+ */
+__isl_give isl_aff *isl_aff_mod_val(__isl_take isl_aff *aff,
+       __isl_take isl_val *m)
+{
+       isl_aff *res;
+
+       if (!aff || !m)
+               goto error;
+
+       if (!isl_val_is_int(m))
+               isl_die(isl_val_get_ctx(m), isl_error_invalid,
+                       "expecting integer modulo", goto error);
+
+       res = isl_aff_copy(aff);
+       aff = isl_aff_scale_down_val(aff, isl_val_copy(m));
+       aff = isl_aff_floor(aff);
+       aff = isl_aff_scale_val(aff, m);
+       res = isl_aff_sub(res, aff);
+
+       return res;
+error:
+       isl_aff_free(aff);
+       isl_val_free(m);
+       return NULL;
+}
+
+/* Compute
+ *
  *     pwaff mod m = pwaff - m * floor(pwaff/m)
  */
 __isl_give isl_pw_aff *isl_pw_aff_mod(__isl_take isl_pw_aff *pwaff, isl_int m)
@@ -1048,6 +1357,29 @@ __isl_give isl_pw_aff *isl_pw_aff_mod(__isl_take isl_pw_aff *pwaff, isl_int m)
        return res;
 }
 
+/* Compute
+ *
+ *     pa mod m = pa - m * floor(pa/m)
+ *
+ * with m an integer value.
+ */
+__isl_give isl_pw_aff *isl_pw_aff_mod_val(__isl_take isl_pw_aff *pa,
+       __isl_take isl_val *m)
+{
+       if (!pa || !m)
+               goto error;
+       if (!isl_val_is_int(m))
+               isl_die(isl_pw_aff_get_ctx(pa), isl_error_invalid,
+                       "expecting integer modulo", goto error);
+       pa = isl_pw_aff_mod(pa, m->n);
+       isl_val_free(m);
+       return pa;
+error:
+       isl_pw_aff_free(pa);
+       isl_val_free(m);
+       return NULL;
+}
+
 /* Given f, return ceil(f).
  * If f is an integer expression, then just return f.
  * Otherwise, let f be the expression
@@ -1238,6 +1570,34 @@ __isl_give isl_aff *isl_aff_scale(__isl_take isl_aff *aff, isl_int f)
        return aff;
 }
 
+/* Multiple "aff" by "v".
+ */
+__isl_give isl_aff *isl_aff_scale_val(__isl_take isl_aff *aff,
+       __isl_take isl_val *v)
+{
+       if (!aff || !v)
+               goto error;
+
+       if (isl_val_is_one(v)) {
+               isl_val_free(v);
+               return aff;
+       }
+
+       if (!isl_val_is_rat(v))
+               isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
+                       "expecting rational factor", goto error);
+
+       aff = isl_aff_scale(aff, v->n);
+       aff = isl_aff_scale_down(aff, v->d);
+
+       isl_val_free(v);
+       return aff;
+error:
+       isl_aff_free(aff);
+       isl_val_free(v);
+       return NULL;
+}
+
 __isl_give isl_aff *isl_aff_scale_down(__isl_take isl_aff *aff, isl_int f)
 {
        isl_int gcd;
@@ -1268,6 +1628,37 @@ __isl_give isl_aff *isl_aff_scale_down(__isl_take isl_aff *aff, isl_int f)
        return aff;
 }
 
+/* Divide "aff" by "v".
+ */
+__isl_give isl_aff *isl_aff_scale_down_val(__isl_take isl_aff *aff,
+       __isl_take isl_val *v)
+{
+       if (!aff || !v)
+               goto error;
+
+       if (isl_val_is_one(v)) {
+               isl_val_free(v);
+               return aff;
+       }
+
+       if (!isl_val_is_rat(v))
+               isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
+                       "expecting rational factor", goto error);
+       if (!isl_val_is_pos(v))
+               isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
+                       "factor needs to be positive", goto error);
+
+       aff = isl_aff_scale(aff, v->d);
+       aff = isl_aff_scale_down(aff, v->n);
+
+       isl_val_free(v);
+       return aff;
+error:
+       isl_aff_free(aff);
+       isl_val_free(v);
+       return NULL;
+}
+
 __isl_give isl_aff *isl_aff_scale_down_ui(__isl_take isl_aff *aff, unsigned f)
 {
        isl_int v;
@@ -2245,6 +2636,49 @@ __isl_give isl_pw_aff *isl_pw_aff_scale_down(__isl_take isl_pw_aff *pwaff,
        return pwaff;
 }
 
+/* Divide "pa" by "f".
+ */
+__isl_give isl_pw_aff *isl_pw_aff_scale_down_val(__isl_take isl_pw_aff *pa,
+       __isl_take isl_val *f)
+{
+       int i;
+
+       if (!pa || !f)
+               goto error;
+
+       if (isl_val_is_one(f)) {
+               isl_val_free(f);
+               return pa;
+       }
+
+       if (!isl_val_is_rat(f))
+               isl_die(isl_pw_aff_get_ctx(pa), isl_error_invalid,
+                       "expecting rational factor", goto error);
+       if (!isl_val_is_pos(f))
+               isl_die(isl_pw_aff_get_ctx(pa), isl_error_invalid,
+                       "factor needs to be positive", goto error);
+
+       pa = isl_pw_aff_cow(pa);
+       if (!pa)
+               return NULL;
+       if (pa->n == 0)
+               return pa;
+
+       for (i = 0; i < pa->n; ++i) {
+               pa->p[i].aff = isl_aff_scale_down_val(pa->p[i].aff,
+                                                       isl_val_copy(f));
+               if (!pa->p[i].aff)
+                       goto error;
+       }
+
+       isl_val_free(f);
+       return pa;
+error:
+       isl_pw_aff_free(pa);
+       isl_val_free(f);
+       return NULL;
+}
+
 __isl_give isl_pw_aff *isl_pw_aff_floor(__isl_take isl_pw_aff *pwaff)
 {
        int i;
@@ -2659,6 +3093,41 @@ __isl_give isl_pw_aff_list *isl_pw_aff_list_set_rational(
        return list;
 }
 
+/* Check that the domain space of "aff" matches "space".
+ *
+ * Return 0 on success and -1 on error.
+ */
+int isl_aff_check_match_domain_space(__isl_keep isl_aff *aff,
+       __isl_keep isl_space *space)
+{
+       isl_space *aff_space;
+       int match;
+
+       if (!aff || !space)
+               return -1;
+
+       aff_space = isl_aff_get_domain_space(aff);
+
+       match = isl_space_match(space, isl_dim_param, aff_space, isl_dim_param);
+       if (match < 0)
+               goto error;
+       if (!match)
+               isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
+                       "parameters don't match", goto error);
+       match = isl_space_tuple_match(space, isl_dim_in,
+                                       aff_space, isl_dim_set);
+       if (match < 0)
+               goto error;
+       if (!match)
+               isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
+                       "domains don't match", goto error);
+       isl_space_free(aff_space);
+       return 0;
+error:
+       isl_space_free(aff_space);
+       return -1;
+}
+
 #undef BASE
 #define BASE aff
 
@@ -4678,105 +5147,146 @@ error:
        return NULL;
 }
 
-#undef BASE
-#define BASE pw_aff
-
-#include <isl_multi_templ.c>
-
-/* Scale the first elements of "ma" by the corresponding elements of "vec".
+/* Check that the domain space of "pa" matches "space".
+ *
+ * Return 0 on success and -1 on error.
  */
-__isl_give isl_multi_aff *isl_multi_aff_scale_vec(__isl_take isl_multi_aff *ma,
-       __isl_take isl_vec *vec)
+int isl_pw_aff_check_match_domain_space(__isl_keep isl_pw_aff *pa,
+       __isl_keep isl_space *space)
 {
-       int i, n;
-       isl_int v;
-
-       if (!ma || !vec)
-               goto error;
-
-       n = isl_multi_aff_dim(ma, isl_dim_out);
-       if (isl_vec_size(vec) < n)
-               n = isl_vec_size(vec);
-
-       isl_int_init(v);
-       for (i = 0; i < n; ++i) {
-               isl_aff *aff;
+       isl_space *pa_space;
+       int match;
 
-               isl_vec_get_element(vec, i, &v);
+       if (!pa || !space)
+               return -1;
 
-               aff = isl_multi_aff_get_aff(ma, i);
-               aff = isl_aff_scale(aff, v);
-               ma = isl_multi_aff_set_aff(ma, i, aff);
-       }
-       isl_int_clear(v);
+       pa_space = isl_pw_aff_get_space(pa);
 
-       isl_vec_free(vec);
-       return ma;
+       match = isl_space_match(space, isl_dim_param, pa_space, isl_dim_param);
+       if (match < 0)
+               goto error;
+       if (!match)
+               isl_die(isl_pw_aff_get_ctx(pa), isl_error_invalid,
+                       "parameters don't match", goto error);
+       match = isl_space_tuple_match(space, isl_dim_in, pa_space, isl_dim_in);
+       if (match < 0)
+               goto error;
+       if (!match)
+               isl_die(isl_pw_aff_get_ctx(pa), isl_error_invalid,
+                       "domains don't match", goto error);
+       isl_space_free(pa_space);
+       return 0;
 error:
-       isl_vec_free(vec);
-       isl_multi_aff_free(ma);
-       return NULL;
+       isl_space_free(pa_space);
+       return -1;
 }
 
-/* Scale the first elements of "pma" by the corresponding elements of "vec".
+#undef BASE
+#define BASE pw_aff
+
+#include <isl_multi_templ.c>
+
+/* Scale the elements of "pma" by the corresponding elements of "mv".
  */
-__isl_give isl_pw_multi_aff *isl_pw_multi_aff_scale_vec(
-       __isl_take isl_pw_multi_aff *pma, __isl_take isl_vec *v)
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_scale_multi_val(
+       __isl_take isl_pw_multi_aff *pma, __isl_take isl_multi_val *mv)
 {
        int i;
 
        pma = isl_pw_multi_aff_cow(pma);
-       if (!pma || !v)
+       if (!pma || !mv)
                goto error;
+       if (!isl_space_tuple_match(pma->dim, isl_dim_out,
+                                       mv->space, isl_dim_set))
+               isl_die(isl_pw_multi_aff_get_ctx(pma), isl_error_invalid,
+                       "spaces don't match", goto error);
+       if (!isl_space_match(pma->dim, isl_dim_param,
+                                       mv->space, isl_dim_param)) {
+               pma = isl_pw_multi_aff_align_params(pma,
+                                           isl_multi_val_get_space(mv));
+               mv = isl_multi_val_align_params(mv,
+                                           isl_pw_multi_aff_get_space(pma));
+               if (!pma || !mv)
+                       goto error;
+       }
 
        for (i = 0; i < pma->n; ++i) {
-               pma->p[i].maff = isl_multi_aff_scale_vec(pma->p[i].maff,
-                                                       isl_vec_copy(v));
+               pma->p[i].maff = isl_multi_aff_scale_multi_val(pma->p[i].maff,
+                                                       isl_multi_val_copy(mv));
                if (!pma->p[i].maff)
                        goto error;
        }
 
-       isl_vec_free(v);
+       isl_multi_val_free(mv);
        return pma;
 error:
-       isl_vec_free(v);
+       isl_multi_val_free(mv);
        isl_pw_multi_aff_free(pma);
        return NULL;
 }
 
+/* Internal data structure for isl_union_pw_multi_aff_scale_multi_val.
+ * mv contains the mv argument.
+ * res collects the results.
+ */
+struct isl_union_pw_multi_aff_scale_multi_val_data {
+       isl_multi_val *mv;
+       isl_union_pw_multi_aff *res;
+};
+
 /* This function is called for each entry of an isl_union_pw_multi_aff.
- * Replace the entry by the result of applying isl_pw_multi_aff_scale_vec
- * to the original entry with the isl_vec in "user" as extra argument.
+ * If the space of the entry matches that of data->mv,
+ * then apply isl_pw_multi_aff_scale_multi_val and add the result
+ * to data->res.
  */
-static int union_pw_multi_aff_scale_vec_entry(void **entry, void *user)
+static int union_pw_multi_aff_scale_multi_val_entry(void **entry, void *user)
 {
-       isl_pw_multi_aff **pma = (isl_pw_multi_aff **) entry;
-       isl_vec *v = user;
+       struct isl_union_pw_multi_aff_scale_multi_val_data *data = user;
+       isl_pw_multi_aff *pma = *entry;
 
-       *pma = isl_pw_multi_aff_scale_vec(*pma, isl_vec_copy(v));
-       if (!*pma)
+       if (!pma)
+               return -1;
+       if (!isl_space_tuple_match(pma->dim, isl_dim_out,
+                                   data->mv->space, isl_dim_set))
+               return 0;
+
+       pma = isl_pw_multi_aff_copy(pma);
+       pma = isl_pw_multi_aff_scale_multi_val(pma,
+                                               isl_multi_val_copy(data->mv));
+       data->res = isl_union_pw_multi_aff_add_pw_multi_aff(data->res, pma);
+       if (!data->res)
                return -1;
 
        return 0;
 }
 
-/* Scale the first elements of "upma" by the corresponding elements of "vec".
+/* Scale the elements of "upma" by the corresponding elements of "mv",
+ * for those entries that match the space of "mv".
  */
-__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_scale_vec(
-       __isl_take isl_union_pw_multi_aff *upma, __isl_take isl_vec *v)
+__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_scale_multi_val(
+       __isl_take isl_union_pw_multi_aff *upma, __isl_take isl_multi_val *mv)
 {
-       upma = isl_union_pw_multi_aff_cow(upma);
-       if (!upma || !v)
+       struct isl_union_pw_multi_aff_scale_multi_val_data data;
+
+       upma = isl_union_pw_multi_aff_align_params(upma,
+                                               isl_multi_val_get_space(mv));
+       mv = isl_multi_val_align_params(mv,
+                                       isl_union_pw_multi_aff_get_space(upma));
+       if (!upma || !mv)
                goto error;
 
+       data.mv = mv;
+       data.res = isl_union_pw_multi_aff_alloc(isl_space_copy(upma->dim),
+                                               upma->table.n);
        if (isl_hash_table_foreach(upma->dim->ctx, &upma->table,
-                                  &union_pw_multi_aff_scale_vec_entry, v) < 0)
+                      &union_pw_multi_aff_scale_multi_val_entry, &data) < 0)
                goto error;
 
-       isl_vec_free(v);
-       return upma;
+       isl_multi_val_free(mv);
+       isl_union_pw_multi_aff_free(upma);
+       return data.res;
 error:
-       isl_vec_free(v);
+       isl_multi_val_free(mv);
        isl_union_pw_multi_aff_free(upma);
        return NULL;
 }