add isl_aff_scale_down_val
[platform/upstream/isl.git] / isl_aff.c
index de1a0ca..13060f0 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)
 {
@@ -1238,6 +1516,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 +1574,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;
@@ -2659,6 +2996,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 +5050,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