isl_map_union: special case universal input
[platform/upstream/isl.git] / isl_aff.c
index dc519cb..675801f 100644 (file)
--- a/isl_aff.c
+++ b/isl_aff.c
@@ -2203,6 +2203,46 @@ error:
        return NULL;
 }
 
+/* Divide "aff1" by "aff2", assuming "aff2" is a piecewise constant.
+ */
+__isl_give isl_aff *isl_aff_div(__isl_take isl_aff *aff1,
+       __isl_take isl_aff *aff2)
+{
+       int is_cst;
+       int neg;
+
+       is_cst = isl_aff_is_cst(aff2);
+       if (is_cst < 0)
+               goto error;
+       if (!is_cst)
+               isl_die(isl_aff_get_ctx(aff2), isl_error_invalid,
+                       "second argument should be a constant", goto error);
+
+       if (!aff2)
+               goto error;
+
+       neg = isl_int_is_neg(aff2->v->el[1]);
+       if (neg) {
+               isl_int_neg(aff2->v->el[0], aff2->v->el[0]);
+               isl_int_neg(aff2->v->el[1], aff2->v->el[1]);
+       }
+
+       aff1 = isl_aff_scale(aff1, aff2->v->el[0]);
+       aff1 = isl_aff_scale_down(aff1, aff2->v->el[1]);
+
+       if (neg) {
+               isl_int_neg(aff2->v->el[0], aff2->v->el[0]);
+               isl_int_neg(aff2->v->el[1], aff2->v->el[1]);
+       }
+
+       isl_aff_free(aff2);
+       return aff1;
+error:
+       isl_aff_free(aff1);
+       isl_aff_free(aff2);
+       return NULL;
+}
+
 static __isl_give isl_pw_aff *pw_aff_add(__isl_take isl_pw_aff *pwaff1,
        __isl_take isl_pw_aff *pwaff2)
 {
@@ -2233,6 +2273,101 @@ __isl_give isl_pw_aff *isl_pw_aff_mul(__isl_take isl_pw_aff *pwaff1,
        return isl_pw_aff_align_params_pw_pw_and(pwaff1, pwaff2, &pw_aff_mul);
 }
 
+static __isl_give isl_pw_aff *pw_aff_div(__isl_take isl_pw_aff *pa1,
+       __isl_take isl_pw_aff *pa2)
+{
+       return isl_pw_aff_on_shared_domain(pa1, pa2, &isl_aff_div);
+}
+
+/* Divide "pa1" by "pa2", assuming "pa2" is a piecewise constant.
+ */
+__isl_give isl_pw_aff *isl_pw_aff_div(__isl_take isl_pw_aff *pa1,
+       __isl_take isl_pw_aff *pa2)
+{
+       int is_cst;
+
+       is_cst = isl_pw_aff_is_cst(pa2);
+       if (is_cst < 0)
+               goto error;
+       if (!is_cst)
+               isl_die(isl_pw_aff_get_ctx(pa2), isl_error_invalid,
+                       "second argument should be a piecewise constant",
+                       goto error);
+       return isl_pw_aff_align_params_pw_pw_and(pa1, pa2, &pw_aff_div);
+error:
+       isl_pw_aff_free(pa1);
+       isl_pw_aff_free(pa2);
+       return NULL;
+}
+
+/* Compute the quotient of the integer division of "pa1" by "pa2"
+ * with rounding towards zero.
+ * "pa2" is assumed to be a piecewise constant.
+ *
+ * In particular, return
+ *
+ *     pa1 >= 0 ? floor(pa1/pa2) : ceil(pa1/pa2)
+ *
+ */
+__isl_give isl_pw_aff *isl_pw_aff_tdiv_q(__isl_take isl_pw_aff *pa1,
+       __isl_take isl_pw_aff *pa2)
+{
+       int is_cst;
+       isl_set *cond;
+       isl_pw_aff *f, *c;
+
+       is_cst = isl_pw_aff_is_cst(pa2);
+       if (is_cst < 0)
+               goto error;
+       if (!is_cst)
+               isl_die(isl_pw_aff_get_ctx(pa2), isl_error_invalid,
+                       "second argument should be a piecewise constant",
+                       goto error);
+
+       pa1 = isl_pw_aff_div(pa1, pa2);
+
+       cond = isl_pw_aff_nonneg_set(isl_pw_aff_copy(pa1));
+       f = isl_pw_aff_floor(isl_pw_aff_copy(pa1));
+       c = isl_pw_aff_ceil(pa1);
+       return isl_pw_aff_cond(isl_set_indicator_function(cond), f, c);
+error:
+       isl_pw_aff_free(pa1);
+       isl_pw_aff_free(pa2);
+       return NULL;
+}
+
+/* Compute the remainder of the integer division of "pa1" by "pa2"
+ * with rounding towards zero.
+ * "pa2" is assumed to be a piecewise constant.
+ *
+ * In particular, return
+ *
+ *     pa1 - pa2 * (pa1 >= 0 ? floor(pa1/pa2) : ceil(pa1/pa2))
+ *
+ */
+__isl_give isl_pw_aff *isl_pw_aff_tdiv_r(__isl_take isl_pw_aff *pa1,
+       __isl_take isl_pw_aff *pa2)
+{
+       int is_cst;
+       isl_pw_aff *res;
+
+       is_cst = isl_pw_aff_is_cst(pa2);
+       if (is_cst < 0)
+               goto error;
+       if (!is_cst)
+               isl_die(isl_pw_aff_get_ctx(pa2), isl_error_invalid,
+                       "second argument should be a piecewise constant",
+                       goto error);
+       res = isl_pw_aff_tdiv_q(isl_pw_aff_copy(pa1), isl_pw_aff_copy(pa2));
+       res = isl_pw_aff_mul(pa2, res);
+       res = isl_pw_aff_sub(pa1, res);
+       return res;
+error:
+       isl_pw_aff_free(pa1);
+       isl_pw_aff_free(pa2);
+       return NULL;
+}
+
 static __isl_give isl_pw_aff *pw_aff_min(__isl_take isl_pw_aff *pwaff1,
        __isl_take isl_pw_aff *pwaff2)
 {
@@ -3075,7 +3210,7 @@ static __isl_give isl_pw_multi_aff *plain_pw_multi_aff_from_map(
 }
 
 /* Try and create an isl_pw_multi_aff that is equivalent to the given isl_map.
- * This obivously only works if the input "map" is single-valued.
+ * This obviously only works if the input "map" is single-valued.
  * If so, we compute the lexicographic minimum of the image in the form
  * of an isl_pw_multi_aff.  Since the image is unique, it is equal
  * to its lexicographic minimum.