add isl_union_pw_multi_aff_scale_vec
[platform/upstream/isl.git] / isl_aff.c
index dadc332..6ff07ad 100644 (file)
--- a/isl_aff.c
+++ b/isl_aff.c
@@ -1,7 +1,7 @@
 /*
  * Copyright 2011      INRIA Saclay
  * Copyright 2011      Sven Verdoolaege
- * Copyright 2012      Ecole Normale Superieure
+ * Copyright 2012-2013 Ecole Normale Superieure
  *
  * Use of this software is governed by the MIT license
  *
@@ -2680,6 +2680,14 @@ __isl_give isl_multi_aff *isl_multi_aff_add(__isl_take isl_multi_aff *maff1,
        return isl_multi_aff_bin_op(maff1, maff2, &isl_aff_add);
 }
 
+/* Subtract "ma2" from "ma1" and return the result.
+ */
+__isl_give isl_multi_aff *isl_multi_aff_sub(__isl_take isl_multi_aff *ma1,
+       __isl_take isl_multi_aff *ma2)
+{
+       return isl_multi_aff_bin_op(ma1, ma2, &isl_aff_sub);
+}
+
 /* Given two multi-affine expressions A -> B and C -> D,
  * construct a multi-affine expression [A -> C] -> [B -> D].
  */
@@ -3038,6 +3046,22 @@ __isl_give isl_pw_multi_aff *isl_pw_multi_aff_add(
                                                &pw_multi_aff_add);
 }
 
+static __isl_give isl_pw_multi_aff *pw_multi_aff_sub(
+       __isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2)
+{
+       return isl_pw_multi_aff_on_shared_domain(pma1, pma2,
+                                               &isl_multi_aff_sub);
+}
+
+/* Subtract "pma2" from "pma1" and return the result.
+ */
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_sub(
+       __isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2)
+{
+       return isl_pw_multi_aff_align_params_pw_pw_and(pma1, pma2,
+                                               &pw_multi_aff_sub);
+}
+
 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_union_add(
        __isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2)
 {
@@ -4621,3 +4645,101 @@ error:
 #define BASE pw_aff
 
 #include <isl_multi_templ.c>
+
+/* Scale the first elements of "ma" by the corresponding elements of "vec".
+ */
+__isl_give isl_multi_aff *isl_multi_aff_scale_vec(__isl_take isl_multi_aff *ma,
+       __isl_take isl_vec *vec)
+{
+       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_vec_get_element(vec, i, &v);
+
+               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);
+
+       isl_vec_free(vec);
+       return ma;
+error:
+       isl_vec_free(vec);
+       isl_multi_aff_free(ma);
+       return NULL;
+}
+
+/* Scale the first elements of "pma" by the corresponding elements of "vec".
+ */
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_scale_vec(
+       __isl_take isl_pw_multi_aff *pma, __isl_take isl_vec *v)
+{
+       int i;
+
+       pma = isl_pw_multi_aff_cow(pma);
+       if (!pma || !v)
+               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));
+               if (!pma->p[i].maff)
+                       goto error;
+       }
+
+       isl_vec_free(v);
+       return pma;
+error:
+       isl_vec_free(v);
+       isl_pw_multi_aff_free(pma);
+       return NULL;
+}
+
+/* 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.
+ */
+static int union_pw_multi_aff_scale_vec_entry(void **entry, void *user)
+{
+       isl_pw_multi_aff **pma = (isl_pw_multi_aff **) entry;
+       isl_vec *v = user;
+
+       *pma = isl_pw_multi_aff_scale_vec(*pma, isl_vec_copy(v));
+       if (!*pma)
+               return -1;
+
+       return 0;
+}
+
+/* Scale the first elements of "upma" by the corresponding elements of "vec".
+ */
+__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)
+{
+       upma = isl_union_pw_multi_aff_cow(upma);
+       if (!upma || !v)
+               goto error;
+
+       if (isl_hash_table_foreach(upma->dim->ctx, &upma->table,
+                                  &union_pw_multi_aff_scale_vec_entry, v) < 0)
+               goto error;
+
+       isl_vec_free(v);
+       return upma;
+error:
+       isl_vec_free(v);
+       isl_union_pw_multi_aff_free(upma);
+       return NULL;
+}