isl_qpolynomial_div_pow: normalize given div
[platform/upstream/isl.git] / isl_polynomial.c
index 052318a..050f666 100644 (file)
@@ -1641,6 +1641,27 @@ error:
        return NULL;
 }
 
+/* Remove common factor of non-constant terms and denominator.
+ */
+static void normalize_div(__isl_keep isl_qpolynomial *qp, int div)
+{
+       isl_ctx *ctx = qp->div->ctx;
+       unsigned total = qp->div->n_col - 2;
+
+       isl_seq_gcd(qp->div->row[div] + 2, total, &ctx->normalize_gcd);
+       isl_int_gcd(ctx->normalize_gcd,
+                   ctx->normalize_gcd, qp->div->row[div][0]);
+       if (isl_int_is_one(ctx->normalize_gcd))
+               return;
+
+       isl_seq_scale_down(qp->div->row[div] + 2, qp->div->row[div] + 2,
+                           ctx->normalize_gcd, total);
+       isl_int_divexact(qp->div->row[div][0], qp->div->row[div][0],
+                           ctx->normalize_gcd);
+       isl_int_fdiv_q(qp->div->row[div][1], qp->div->row[div][1],
+                           ctx->normalize_gcd);
+}
+
 __isl_give isl_qpolynomial *isl_qpolynomial_div_pow(__isl_take isl_div *div,
        int power)
 {
@@ -1662,8 +1683,10 @@ __isl_give isl_qpolynomial *isl_qpolynomial_div_pow(__isl_take isl_div *div,
        if (!qp)
                goto error;
 
-       for (i = 0; i < div->bmap->n_div; ++i)
+       for (i = 0; i < div->bmap->n_div; ++i) {
                isl_seq_cpy(qp->div->row[i], div->bmap->div[i], qp->div->n_col);
+               normalize_div(qp, i);
+       }
 
        for (i = 0; i < 1 + power; ++i) {
                rec->p[i] = isl_upoly_zero(div->ctx);
@@ -1941,27 +1964,6 @@ __isl_give struct isl_upoly *isl_upoly_from_affine(isl_ctx *ctx, isl_int *f,
        return up;
 }
 
-/* Remove common factor of non-constant terms and denominator.
- */
-static void normalize_div(__isl_keep isl_qpolynomial *qp, int div)
-{
-       isl_ctx *ctx = qp->div->ctx;
-       unsigned total = qp->div->n_col - 2;
-
-       isl_seq_gcd(qp->div->row[div] + 2, total, &ctx->normalize_gcd);
-       isl_int_gcd(ctx->normalize_gcd,
-                   ctx->normalize_gcd, qp->div->row[div][0]);
-       if (isl_int_is_one(ctx->normalize_gcd))
-               return;
-
-       isl_seq_scale_down(qp->div->row[div] + 2, qp->div->row[div] + 2,
-                           ctx->normalize_gcd, total);
-       isl_int_divexact(qp->div->row[div][0], qp->div->row[div][0],
-                           ctx->normalize_gcd);
-       isl_int_fdiv_q(qp->div->row[div][1], qp->div->row[div][1],
-                           ctx->normalize_gcd);
-}
-
 /* Replace the integer division identified by "div" by the polynomial "s".
  * The integer division is assumed not to appear in the definition
  * of any other integer divisions.
@@ -2111,6 +2113,62 @@ error:
        return NULL;
 }
 
+static __isl_give isl_basic_set *add_div_constraints(
+       __isl_take isl_basic_set *bset, __isl_take isl_mat *div)
+{
+       int i;
+       unsigned total;
+
+       if (!bset || !div)
+               goto error;
+
+       bset = isl_basic_set_extend_constraints(bset, 0, 2 * div->n_row);
+       if (!bset)
+               goto error;
+       total = isl_basic_set_total_dim(bset);
+       for (i = 0; i < div->n_row; ++i)
+               if (isl_basic_set_add_div_constraints_var(bset,
+                                   total - div->n_row + i, div->row[i]) < 0)
+                       goto error;
+
+       isl_mat_free(div);
+       return bset;
+error:
+       isl_mat_free(div);
+       isl_basic_set_free(bset);
+       return NULL;
+}
+
+/* Look for equalities among the variables shared by context and qp
+ * and the integer divisions of qp, if any.
+ * The equalities are then used to eliminate variables and/or integer
+ * divisions from qp.
+ */
+__isl_give isl_qpolynomial *isl_qpolynomial_gist(
+       __isl_take isl_qpolynomial *qp, __isl_take isl_set *context)
+{
+       isl_basic_set *aff;
+
+       if (!qp)
+               goto error;
+       if (qp->div->n_row > 0) {
+               isl_basic_set *bset;
+               context = isl_set_add_dims(context, isl_dim_set,
+                                           qp->div->n_row);
+               bset = isl_basic_set_universe(isl_set_get_dim(context));
+               bset = add_div_constraints(bset, isl_mat_copy(qp->div));
+               context = isl_set_intersect(context,
+                                           isl_set_from_basic_set(bset));
+       }
+
+       aff = isl_set_affine_hull(context);
+       return isl_qpolynomial_substitute_equalities(qp, aff);
+error:
+       isl_qpolynomial_free(qp);
+       isl_set_free(context);
+       return NULL;
+}
+
 #undef PW
 #define PW isl_pw_qpolynomial
 #undef EL
@@ -2667,32 +2725,6 @@ error:
        return NULL;
 }
 
-__isl_give isl_basic_set *add_div_constraints(__isl_take isl_basic_set *bset,
-       __isl_take isl_mat *div)
-{
-       int i;
-       unsigned total;
-
-       if (!bset || !div)
-               goto error;
-
-       bset = isl_basic_set_extend_constraints(bset, 0, 2 * div->n_row);
-       if (!bset)
-               goto error;
-       total = isl_basic_set_total_dim(bset);
-       for (i = 0; i < div->n_row; ++i)
-               if (isl_basic_set_add_div_constraints_var(bset,
-                                   total - div->n_row + i, div->row[i]) < 0)
-                       goto error;
-
-       isl_mat_free(div);
-       return bset;
-error:
-       isl_mat_free(div);
-       isl_basic_set_free(bset);
-       return NULL;
-}
-
 /* Extend "bset" with extra set dimensions for each integer division
  * in "qp" and then call "fn" with the extended bset and the polynomial
  * that results from replacing each of the integer divisions by the