add isl_pw_aff_scale_down_val
[platform/upstream/isl.git] / isl_aff.c
index de1a0ca..d9f0f71 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)
@@ -1238,6 +1547,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 +1605,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 +2613,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 +3070,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,6 +5124,40 @@ error:
        return NULL;
 }
 
+/* Check that the domain space of "pa" matches "space".
+ *
+ * Return 0 on success and -1 on error.
+ */
+int isl_pw_aff_check_match_domain_space(__isl_keep isl_pw_aff *pa,
+       __isl_keep isl_space *space)
+{
+       isl_space *pa_space;
+       int match;
+
+       if (!pa || !space)
+               return -1;
+
+       pa_space = isl_pw_aff_get_space(pa);
+
+       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_space_free(pa_space);
+       return -1;
+}
+
 #undef BASE
 #define BASE pw_aff