add isl_pw_qpolynomial_fold
authorSven Verdoolaege <skimo@kotnet.org>
Mon, 8 Mar 2010 14:04:57 +0000 (15:04 +0100)
committerSven Verdoolaege <skimo@kotnet.org>
Tue, 9 Mar 2010 14:54:42 +0000 (15:54 +0100)
Makefile.am
include/isl_polynomial.h
isl_output.c
isl_polynomial.c
isl_polynomial_private.h
isl_pw_templ.c [new file with mode: 0644]

index 0d2ab50..1688c95 100644 (file)
@@ -169,6 +169,7 @@ pkginclude_HEADERS = \
 
 EXTRA_DIST = \
        basis_reduction_templ.c \
+       isl_pw_templ.c \
        doc/mypod2latex \
        doc/manual.tex \
        doc/user.pod \
index 7820ce0..fea6c84 100644 (file)
@@ -102,6 +102,57 @@ int isl_pw_qpolynomial_foreach_lifted_piece(__isl_keep isl_pw_qpolynomial *pwqp,
 void isl_pw_qpolynomial_print(__isl_keep isl_pw_qpolynomial *pwqp, FILE *out,
        unsigned output_format);
 
+enum isl_fold {
+       isl_fold_min,
+       isl_fold_max,
+       isl_fold_list
+};
+
+struct isl_qpolynomial_fold;
+typedef struct isl_qpolynomial_fold isl_qpolynomial_fold;
+
+__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_empty(enum isl_fold type,
+       __isl_take isl_dim *dim);
+__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_alloc(
+       enum isl_fold type, __isl_take isl_qpolynomial *qp);
+__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_copy(
+       __isl_keep isl_qpolynomial_fold *fold);
+void isl_qpolynomial_fold_free(__isl_take isl_qpolynomial_fold *fold);
+
+int isl_qpolynomial_fold_is_empty(__isl_keep isl_qpolynomial_fold *fold);
+
+__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_fold(
+       __isl_take isl_qpolynomial_fold *fold1,
+       __isl_take isl_qpolynomial_fold *fold2);
+
+void isl_qpolynomial_fold_print(__isl_keep isl_qpolynomial_fold *fold, FILE *out,
+       unsigned output_format);
+
+struct isl_pw_qpolynomial_fold;
+typedef struct isl_pw_qpolynomial_fold isl_pw_qpolynomial_fold;
+
+__isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_from_pw_qpolynomial(
+       enum isl_fold type, __isl_take isl_pw_qpolynomial *pwqp);
+
+__isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_alloc(
+       __isl_take isl_set *set, __isl_take isl_qpolynomial_fold *fold);
+__isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_copy(
+       __isl_keep isl_pw_qpolynomial_fold *pwf);
+void isl_pw_qpolynomial_fold_free(__isl_take isl_pw_qpolynomial_fold *pwf);
+
+__isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_zero(
+       __isl_take isl_dim *dim);
+
+__isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_add(
+       __isl_take isl_pw_qpolynomial_fold *pwf1,
+       __isl_take isl_pw_qpolynomial_fold *pwf2);
+__isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_add_disjoint(
+       __isl_take isl_pw_qpolynomial_fold *pwf1,
+       __isl_take isl_pw_qpolynomial_fold *pwf2);
+
+void isl_pw_qpolynomial_fold_print(__isl_keep isl_pw_qpolynomial_fold *pwf,
+       FILE *out, unsigned output_format);
+
 #if defined(__cplusplus)
 }
 #endif
index 4a3d838..eabd02c 100644 (file)
@@ -693,6 +693,34 @@ void isl_qpolynomial_print(__isl_keep isl_qpolynomial *qp, FILE *out,
        fprintf(out, "\n");
 }
 
+static void qpolynomial_fold_print(__isl_keep isl_qpolynomial_fold *fold,
+       FILE *out)
+{
+       int i;
+
+       if (fold->type == isl_fold_min)
+               fprintf(out, "min");
+       else if (fold->type == isl_fold_max)
+               fprintf(out, "max");
+       fprintf(out, "(");
+       for (i = 0; i < fold->n; ++i) {
+               if (i)
+                       fprintf(out, ", ");
+               qpolynomial_print(fold->qp[i], out);
+       }
+       fprintf(out, ")");
+}
+
+void isl_qpolynomial_fold_print(__isl_keep isl_qpolynomial_fold *fold, FILE *out,
+       unsigned output_format)
+{
+       if  (!fold)
+               return;
+       isl_assert(fold->dim->ctx, output_format == ISL_FORMAT_ISL, return);
+       qpolynomial_fold_print(fold, out);
+       fprintf(out, "\n");
+}
+
 void isl_pw_qpolynomial_print(__isl_keep isl_pw_qpolynomial *pwqp, FILE *out,
        unsigned output_format)
 {
@@ -725,3 +753,36 @@ void isl_pw_qpolynomial_print(__isl_keep isl_pw_qpolynomial *pwqp, FILE *out,
        }
        fprintf(out, " }\n");
 }
+
+void isl_pw_qpolynomial_fold_print(__isl_keep isl_pw_qpolynomial_fold *pwf,
+       FILE *out, unsigned output_format)
+{
+       int i = 0;
+
+       if (!pwf)
+               return;
+       isl_assert(pwf->dim->ctx, output_format == ISL_FORMAT_ISL, return);
+       if (isl_dim_size(pwf->dim, isl_dim_param) > 0) {
+               print_tuple(pwf->dim, out, isl_dim_param, 0);
+               fprintf(out, " -> ");
+       }
+       fprintf(out, "{ ");
+       if (pwf->n == 0) {
+               if (isl_dim_size(pwf->dim, isl_dim_set) > 0) {
+                       print_tuple(pwf->dim, out, isl_dim_set, 0);
+                       fprintf(out, " -> ");
+               }
+               fprintf(out, "0");
+       }
+       for (i = 0; i < pwf->n; ++i) {
+               if (i)
+                       fprintf(out, "; ");
+               if (isl_dim_size(pwf->p[i].set->dim, isl_dim_set) > 0) {
+                       print_tuple(pwf->p[i].set->dim, out, isl_dim_set, 0);
+                       fprintf(out, " -> ");
+               }
+               qpolynomial_fold_print(pwf->p[i].fold, out);
+               print_disjuncts((isl_map *)pwf->p[i].set, out, 1);
+       }
+       fprintf(out, " }\n");
+}
index 0b2e3c0..23e42e1 100644 (file)
@@ -1279,87 +1279,31 @@ error:
        return NULL;
 }
 
-static __isl_give isl_pw_qpolynomial *pw_qpolynomial_alloc(__isl_take isl_dim *dim,
-       int n)
-{
-       struct isl_pw_qpolynomial *pwqp;
-
-       if (!dim)
-               return NULL;
-       isl_assert(dim->ctx, n >= 0, return NULL);
-       pwqp = isl_alloc(dim->ctx, struct isl_pw_qpolynomial,
-                       sizeof(struct isl_pw_qpolynomial) +
-                       (n - 1) * sizeof(struct isl_pw_qpolynomial_piece));
-       if (!pwqp)
-               goto error;
-
-       pwqp->ref = 1;
-       pwqp->size = n;
-       pwqp->n = 0;
-       pwqp->dim = dim;
-       return pwqp;
-error:
-       isl_dim_free(dim);
-       return NULL;
-}
-
-__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_add_piece(
-       __isl_take isl_pw_qpolynomial *pwqp,
-       __isl_take isl_set *set, __isl_take isl_qpolynomial *qp)
-{
-       if (!pwqp || !set || !qp)
-               goto error;
-
-       if (isl_set_fast_is_empty(set) || isl_qpolynomial_is_zero(qp)) {
-               isl_set_free(set);
-               isl_qpolynomial_free(qp);
-               return pwqp;
-       }
-
-       isl_assert(set->ctx, isl_dim_equal(pwqp->dim, qp->dim), goto error);
-       isl_assert(set->ctx, pwqp->n < pwqp->size, goto error);
-
-       pwqp->p[pwqp->n].set = set;
-       pwqp->p[pwqp->n].qp = qp;
-       pwqp->n++;
-       
-       return pwqp;
-error:
-       isl_pw_qpolynomial_free(pwqp);
-       isl_set_free(set);
-       isl_qpolynomial_free(qp);
-       return NULL;
-}
-
-__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_alloc(__isl_take isl_set *set,
-       __isl_take isl_qpolynomial *qp)
-{
-       struct isl_pw_qpolynomial *pwqp;
-
-       if (!set || !qp)
-               goto error;
-
-       pwqp = pw_qpolynomial_alloc(isl_set_get_dim(set), 1);
-
-       return isl_pw_qpolynomial_add_piece(pwqp, set, qp);
-error:
-       isl_set_free(set);
-       isl_qpolynomial_free(qp);
-       return NULL;
-}
-
-__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_zero(__isl_take isl_dim *dim)
-{
-       return pw_qpolynomial_alloc(dim, 0);
-}
-
-int isl_pw_qpolynomial_is_zero(__isl_keep isl_pw_qpolynomial *pwqp)
-{
-       if (!pwqp)
-               return -1;
-
-       return pwqp->n == 0;
-}
+#undef PW
+#define PW isl_pw_qpolynomial
+#undef EL
+#define EL isl_qpolynomial
+#undef IS_ZERO
+#define IS_ZERO is_zero
+#undef FIELD
+#define FIELD qp
+#undef ADD
+#define ADD add
+
+#include <isl_pw_templ.c>
+
+#undef PW
+#define PW isl_pw_qpolynomial_fold
+#undef EL
+#define EL isl_qpolynomial_fold
+#undef IS_ZERO
+#define IS_ZERO is_empty
+#undef FIELD
+#define FIELD fold
+#undef ADD
+#define ADD fold
+
+#include <isl_pw_templ.c>
 
 int isl_pw_qpolynomial_is_one(__isl_keep isl_pw_qpolynomial *pwqp)
 {
@@ -1375,40 +1319,6 @@ int isl_pw_qpolynomial_is_one(__isl_keep isl_pw_qpolynomial *pwqp)
        return isl_qpolynomial_is_one(pwqp->p[0].qp);
 }
 
-__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_copy(
-       __isl_keep isl_pw_qpolynomial *pwqp)
-{
-       if (!pwqp)
-               return;
-
-       pwqp->ref++;
-       return pwqp;
-}
-
-__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_dup(
-       __isl_keep isl_pw_qpolynomial *pwqp)
-{
-       int i;
-       struct isl_pw_qpolynomial *dup;
-
-       if (!pwqp)
-               return NULL;
-
-       dup = pw_qpolynomial_alloc(isl_dim_copy(pwqp->dim), pwqp->n);
-       if (!dup)
-               return NULL;
-
-       for (i = 0; i < pwqp->n; ++i)
-               dup = isl_pw_qpolynomial_add_piece(dup,
-                                           isl_set_copy(pwqp->p[i].set),
-                                           isl_qpolynomial_copy(pwqp->p[i].qp));
-
-       return dup;
-error:
-       isl_pw_qpolynomial_free(dup);
-       return NULL;
-}
-
 __isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_cow(
        __isl_take isl_pw_qpolynomial *pwqp)
 {
@@ -1421,138 +1331,6 @@ __isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_cow(
        return isl_pw_qpolynomial_dup(pwqp);
 }
 
-void isl_pw_qpolynomial_free(__isl_take isl_pw_qpolynomial *pwqp)
-{
-       int i;
-
-       if (!pwqp)
-               return;
-       if (--pwqp->ref > 0)
-               return;
-
-       for (i = 0; i < pwqp->n; ++i) {
-               isl_set_free(pwqp->p[i].set);
-               isl_qpolynomial_free(pwqp->p[i].qp);
-       }
-       isl_dim_free(pwqp->dim);
-       free(pwqp);
-}
-
-__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_add(
-       __isl_take isl_pw_qpolynomial *pwqp1,
-       __isl_take isl_pw_qpolynomial *pwqp2)
-{
-       int i, j, n;
-       struct isl_pw_qpolynomial *res;
-       isl_set *set;
-
-       if (!pwqp1 || !pwqp2)
-               goto error;
-
-       isl_assert(pwqp1->dim->ctx, isl_dim_equal(pwqp1->dim, pwqp2->dim),
-                       goto error);
-
-       if (isl_pw_qpolynomial_is_zero(pwqp1)) {
-               isl_pw_qpolynomial_free(pwqp1);
-               return pwqp2;
-       }
-
-       if (isl_pw_qpolynomial_is_zero(pwqp2)) {
-               isl_pw_qpolynomial_free(pwqp2);
-               return pwqp1;
-       }
-
-       n = (pwqp1->n + 1) * (pwqp2->n + 1);
-       res = pw_qpolynomial_alloc(isl_dim_copy(pwqp1->dim), n);
-
-       for (i = 0; i < pwqp1->n; ++i) {
-               set = isl_set_copy(pwqp1->p[i].set);
-               for (j = 0; j < pwqp2->n; ++j) {
-                       struct isl_set *common;
-                       struct isl_qpolynomial *sum;
-                       set = isl_set_subtract(set,
-                                       isl_set_copy(pwqp2->p[j].set));
-                       common = isl_set_intersect(isl_set_copy(pwqp1->p[i].set),
-                                               isl_set_copy(pwqp2->p[j].set));
-                       if (isl_set_fast_is_empty(common)) {
-                               isl_set_free(common);
-                               continue;
-                       }
-
-                       sum = isl_qpolynomial_add(
-                               isl_qpolynomial_copy(pwqp1->p[i].qp),
-                               isl_qpolynomial_copy(pwqp2->p[j].qp));
-
-                       res = isl_pw_qpolynomial_add_piece(res, common, sum);
-               }
-               res = isl_pw_qpolynomial_add_piece(res, set,
-                       isl_qpolynomial_copy(pwqp1->p[i].qp));
-       }
-
-       for (j = 0; j < pwqp2->n; ++j) {
-               set = isl_set_copy(pwqp2->p[j].set);
-               for (i = 0; i < pwqp1->n; ++i)
-                       set = isl_set_subtract(set,
-                                       isl_set_copy(pwqp1->p[i].set));
-               res = isl_pw_qpolynomial_add_piece(res, set,
-                       isl_qpolynomial_copy(pwqp2->p[j].qp));
-       }
-
-       isl_pw_qpolynomial_free(pwqp1);
-       isl_pw_qpolynomial_free(pwqp2);
-
-       return res;
-error:
-       isl_pw_qpolynomial_free(pwqp1);
-       isl_pw_qpolynomial_free(pwqp2);
-       return NULL;
-}
-
-__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_add_disjoint(
-       __isl_take isl_pw_qpolynomial *pwqp1,
-       __isl_take isl_pw_qpolynomial *pwqp2)
-{
-       int i;
-       struct isl_pw_qpolynomial *res;
-
-       if (!pwqp1 || !pwqp2)
-               goto error;
-
-       isl_assert(pwqp1->dim->ctx, isl_dim_equal(pwqp1->dim, pwqp2->dim),
-                       goto error);
-
-       if (isl_pw_qpolynomial_is_zero(pwqp1)) {
-               isl_pw_qpolynomial_free(pwqp1);
-               return pwqp2;
-       }
-
-       if (isl_pw_qpolynomial_is_zero(pwqp2)) {
-               isl_pw_qpolynomial_free(pwqp2);
-               return pwqp1;
-       }
-
-       res = pw_qpolynomial_alloc(isl_dim_copy(pwqp1->dim), pwqp1->n + pwqp2->n);
-
-       for (i = 0; i < pwqp1->n; ++i)
-               res = isl_pw_qpolynomial_add_piece(res,
-                               isl_set_copy(pwqp1->p[i].set),
-                               isl_qpolynomial_copy(pwqp1->p[i].qp));
-
-       for (i = 0; i < pwqp2->n; ++i)
-               res = isl_pw_qpolynomial_add_piece(res,
-                               isl_set_copy(pwqp2->p[i].set),
-                               isl_qpolynomial_copy(pwqp2->p[i].qp));
-
-       isl_pw_qpolynomial_free(pwqp1);
-       isl_pw_qpolynomial_free(pwqp2);
-
-       return res;
-error:
-       isl_pw_qpolynomial_free(pwqp1);
-       isl_pw_qpolynomial_free(pwqp2);
-       return NULL;
-}
-
 __isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_mul(
        __isl_take isl_pw_qpolynomial *pwqp1,
        __isl_take isl_pw_qpolynomial *pwqp2)
@@ -1588,7 +1366,7 @@ __isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_mul(
        }
 
        n = pwqp1->n * pwqp2->n;
-       res = pw_qpolynomial_alloc(isl_dim_copy(pwqp1->dim), n);
+       res = isl_pw_qpolynomial_alloc_(isl_dim_copy(pwqp1->dim), n);
 
        for (i = 0; i < pwqp1->n; ++i) {
                for (j = 0; j < pwqp2->n; ++j) {
@@ -2223,3 +2001,167 @@ int isl_pw_qpolynomial_foreach_lifted_piece(__isl_keep isl_pw_qpolynomial *pwqp,
 
        return 0;
 }
+
+static __isl_give isl_qpolynomial_fold *qpolynomial_fold_alloc(
+       enum isl_fold type, __isl_take isl_dim *dim, int n)
+{
+       isl_qpolynomial_fold *fold;
+
+       if (!dim || !div)
+               goto error;
+
+       isl_assert(dim->ctx, n >= 0, goto error);
+       fold = isl_alloc(dim->ctx, struct isl_qpolynomial_fold,
+                       sizeof(struct isl_qpolynomial_fold) +
+                       (n - 1) * sizeof(struct isl_qpolynomial *));
+       if (!fold)
+               goto error;
+
+       fold->ref = 1;
+       fold->size = n;
+       fold->n = 0;
+       fold->type = type;
+       fold->dim = dim;
+
+       return fold;
+error:
+       isl_dim_free(dim);
+       return NULL;
+}
+
+__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_empty(enum isl_fold type,
+       __isl_take isl_dim *dim)
+{
+       return qpolynomial_fold_alloc(type, dim, 0);
+}
+
+__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_alloc(
+       enum isl_fold type, __isl_take isl_qpolynomial *qp)
+{
+       isl_qpolynomial_fold *fold;
+
+       if (!qp)
+               return NULL;
+
+       fold = qpolynomial_fold_alloc(type, isl_dim_copy(qp->dim), 1);
+       if (!fold)
+               goto error;
+
+       fold->qp[0] = qp;
+       fold->n++;
+
+       return fold;
+error:
+       isl_qpolynomial_fold_free(fold);
+       isl_qpolynomial_free(qp);
+       return NULL;
+}
+
+__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_copy(
+       __isl_keep isl_qpolynomial_fold *fold)
+{
+       if (!fold)
+               return NULL;
+
+       fold->ref++;
+       return fold;
+}
+
+void isl_qpolynomial_fold_free(__isl_take isl_qpolynomial_fold *fold)
+{
+       int i;
+
+       if (!fold)
+               return;
+       if (--fold->ref > 0)
+               return;
+
+       for (i = 0; i < fold->n; ++i)
+               isl_qpolynomial_free(fold->qp[i]);
+       isl_dim_free(fold->dim);
+       free(fold);
+}
+
+int isl_qpolynomial_fold_is_empty(__isl_keep isl_qpolynomial_fold *fold)
+{
+       if (!fold)
+               return -1;
+
+       return fold->n == 0;
+}
+
+__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_fold(
+       __isl_take isl_qpolynomial_fold *fold1,
+       __isl_take isl_qpolynomial_fold *fold2)
+{
+       int i;
+       struct isl_qpolynomial_fold *res = NULL;
+
+       if (!fold1 || !fold2)
+               goto error;
+
+       isl_assert(fold1->dim->ctx, fold1->type == fold2->type, goto error);
+       isl_assert(fold1->dim->ctx, isl_dim_equal(fold1->dim, fold2->dim),
+                       goto error);
+
+       if (isl_qpolynomial_fold_is_empty(fold1)) {
+               isl_qpolynomial_fold_free(fold1);
+               return fold2;
+       }
+
+       if (isl_qpolynomial_fold_is_empty(fold2)) {
+               isl_qpolynomial_fold_free(fold2);
+               return fold1;
+       }
+
+       res = qpolynomial_fold_alloc(fold1->type, isl_dim_copy(fold1->dim),
+                                       fold1->n + fold2->n);
+       if (!res)
+               goto error;
+
+       for (i = 0; i < fold1->n; ++i) {
+               res->qp[res->n] = isl_qpolynomial_copy(fold1->qp[i]);
+               if (!res->qp[res->n])
+                       goto error;
+               res->n++;
+       }
+
+       for (i = 0; i < fold2->n; ++i) {
+               res->qp[res->n] = isl_qpolynomial_copy(fold2->qp[i]);
+               if (!res->qp[res->n])
+                       goto error;
+               res->n++;
+       }
+
+       isl_qpolynomial_fold_free(fold1);
+       isl_qpolynomial_fold_free(fold2);
+
+       return res;
+error:
+       isl_qpolynomial_fold_free(res);
+       isl_qpolynomial_fold_free(fold1);
+       isl_qpolynomial_fold_free(fold2);
+       return NULL;
+}
+
+__isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_from_pw_qpolynomial(
+       enum isl_fold type, __isl_take isl_pw_qpolynomial *pwqp)
+{
+       int i;
+       isl_pw_qpolynomial_fold *pwf;
+
+       if (!pwqp)
+               return NULL;
+       
+       pwf = isl_pw_qpolynomial_fold_alloc_(isl_dim_copy(pwqp->dim), pwqp->n);
+
+       for (i = 0; i < pwqp->n; ++i)
+               pwf = isl_pw_qpolynomial_fold_add_piece(pwf,
+                       isl_set_copy(pwqp->p[i].set),
+                       isl_qpolynomial_fold_alloc(type,
+                               isl_qpolynomial_copy(pwqp->p[i].qp)));
+
+       isl_pw_qpolynomial_free(pwqp);
+
+       return pwf;
+}
index 9052d96..d3d3f2f 100644 (file)
@@ -61,6 +61,34 @@ struct isl_pw_qpolynomial {
        struct isl_pw_qpolynomial_piece p[1];
 };
 
+struct isl_qpolynomial_fold {
+       int ref;
+
+       enum isl_fold type;
+       struct isl_dim *dim;
+
+       int n;
+
+       size_t size;
+       struct isl_qpolynomial *qp[1];
+};
+
+struct isl_pw_qpolynomial_fold_piece {
+       struct isl_set *set;
+       struct isl_qpolynomial_fold *fold;
+};
+
+struct isl_pw_qpolynomial_fold {
+       int ref;
+
+       struct isl_dim *dim;
+
+       int n;
+
+       size_t size;
+       struct isl_pw_qpolynomial_fold_piece p[1];
+};
+
 __isl_give struct isl_upoly *isl_upoly_zero(struct isl_ctx *ctx);
 __isl_give struct isl_upoly *isl_upoly_copy(__isl_keep struct isl_upoly *up);
 __isl_give struct isl_upoly *isl_upoly_cow(__isl_take struct isl_upoly *up);
diff --git a/isl_pw_templ.c b/isl_pw_templ.c
new file mode 100644 (file)
index 0000000..0262a89
--- /dev/null
@@ -0,0 +1,236 @@
+#define xFN(TYPE,NAME) TYPE ## _ ## NAME
+#define FN(TYPE,NAME) xFN(TYPE,NAME)
+#define xS(TYPE,NAME) struct TYPE ## _ ## NAME
+#define S(TYPE,NAME) xS(TYPE,NAME)
+
+static __isl_give PW *FN(PW,alloc_)(__isl_take isl_dim *dim, int n)
+{
+       struct PW *pw;
+
+       if (!dim)
+               return NULL;
+       isl_assert(dim->ctx, n >= 0, goto error);
+       pw = isl_alloc(dim->ctx, struct PW,
+                       sizeof(struct PW) + (n - 1) * sizeof(S(PW,piece)));
+       if (!pw)
+               goto error;
+
+       pw->ref = 1;
+       pw->size = n;
+       pw->n = 0;
+       pw->dim = dim;
+       return pw;
+error:
+       isl_dim_free(dim);
+       return NULL;
+}
+
+__isl_give PW *FN(PW,zero)(__isl_take isl_dim *dim)
+{
+       return FN(PW,alloc_)(dim, 0);
+}
+
+__isl_give PW *FN(PW,add_piece)(__isl_take PW *pw,
+       __isl_take isl_set *set, __isl_take EL *el)
+{
+       if (!pw || !set || !el)
+               goto error;
+
+       if (isl_set_fast_is_empty(set) || FN(EL,IS_ZERO)(el)) {
+               isl_set_free(set);
+               FN(EL,free)(el);
+               return pw;
+       }
+
+       isl_assert(set->ctx, isl_dim_equal(pw->dim, el->dim), goto error);
+       isl_assert(set->ctx, pw->n < pw->size, goto error);
+
+       pw->p[pw->n].set = set;
+       pw->p[pw->n].FIELD = el;
+       pw->n++;
+       
+       return pw;
+error:
+       FN(PW,free)(pw);
+       isl_set_free(set);
+       FN(EL,free)(el);
+       return NULL;
+}
+
+__isl_give PW *FN(PW,alloc)(__isl_take isl_set *set, __isl_take EL *el)
+{
+       PW *pw;
+
+       if (!set || !el)
+               goto error;
+
+       pw = FN(PW,alloc_)(isl_set_get_dim(set), 1);
+
+       return FN(PW,add_piece)(pw, set, el);
+error:
+       isl_set_free(set);
+       FN(EL,free)(el);
+       return NULL;
+}
+
+__isl_give PW *FN(PW,dup)(__isl_keep PW *pw)
+{
+       int i;
+       PW *dup;
+
+       if (!pw)
+               return NULL;
+
+       dup = FN(PW,alloc_)(isl_dim_copy(pw->dim), pw->n);
+       if (!dup)
+               return NULL;
+
+       for (i = 0; i < pw->n; ++i)
+               dup = FN(PW,add_piece)(dup, isl_set_copy(pw->p[i].set),
+                                           FN(EL,copy)(pw->p[i].FIELD));
+
+       return dup;
+error:
+       FN(PW,free)(dup);
+       return NULL;
+}
+
+__isl_give PW *FN(PW,copy)(__isl_keep PW *pw)
+{
+       if (!pw)
+               return;
+
+       pw->ref++;
+       return pw;
+}
+
+void FN(PW,free)(__isl_take PW *pw)
+{
+       int i;
+
+       if (!pw)
+               return;
+       if (--pw->ref > 0)
+               return;
+
+       for (i = 0; i < pw->n; ++i) {
+               isl_set_free(pw->p[i].set);
+               FN(EL,free)(pw->p[i].FIELD);
+       }
+       isl_dim_free(pw->dim);
+       free(pw);
+}
+
+int FN(PW,is_zero)(__isl_keep PW *pw)
+{
+       if (!pw)
+               return -1;
+
+       return pw->n == 0;
+}
+
+__isl_give PW *FN(PW,add)(__isl_take PW *pw1, __isl_take PW *pw2)
+{
+       int i, j, n;
+       struct PW *res;
+       isl_set *set;
+
+       if (!pw1 || !pw2)
+               goto error;
+
+       isl_assert(pw1->dim->ctx, isl_dim_equal(pw1->dim, pw2->dim), goto error);
+
+       if (FN(PW,is_zero)(pw1)) {
+               FN(PW,free)(pw1);
+               return pw2;
+       }
+
+       if (FN(PW,is_zero)(pw2)) {
+               FN(PW,free)(pw2);
+               return pw1;
+       }
+
+       n = (pw1->n + 1) * (pw2->n + 1);
+       res = FN(PW,alloc_)(isl_dim_copy(pw1->dim), n);
+
+       for (i = 0; i < pw1->n; ++i) {
+               set = isl_set_copy(pw1->p[i].set);
+               for (j = 0; j < pw2->n; ++j) {
+                       struct isl_set *common;
+                       EL *sum;
+                       set = isl_set_subtract(set,
+                                       isl_set_copy(pw2->p[j].set));
+                       common = isl_set_intersect(isl_set_copy(pw1->p[i].set),
+                                               isl_set_copy(pw2->p[j].set));
+                       if (isl_set_fast_is_empty(common)) {
+                               isl_set_free(common);
+                               continue;
+                       }
+
+                       sum = FN(EL,ADD)(FN(EL,copy)(pw1->p[i].FIELD),
+                                        FN(EL,copy)(pw2->p[j].FIELD));
+
+                       res = FN(PW,add_piece)(res, common, sum);
+               }
+               res = FN(PW,add_piece)(res, set, FN(EL,copy)(pw1->p[i].FIELD));
+       }
+
+       for (j = 0; j < pw2->n; ++j) {
+               set = isl_set_copy(pw2->p[j].set);
+               for (i = 0; i < pw1->n; ++i)
+                       set = isl_set_subtract(set,
+                                       isl_set_copy(pw1->p[i].set));
+               res = FN(PW,add_piece)(res, set, FN(EL,copy)(pw2->p[j].FIELD));
+       }
+
+       FN(PW,free)(pw1);
+       FN(PW,free)(pw2);
+
+       return res;
+error:
+       FN(PW,free)(pw1);
+       FN(PW,free)(pw2);
+       return NULL;
+}
+
+__isl_give PW *FN(PW,add_disjoint)(__isl_take PW *pw1, __isl_take PW *pw2)
+{
+       int i;
+       PW *res;
+
+       if (!pw1 || !pw2)
+               goto error;
+
+       isl_assert(pw1->dim->ctx, isl_dim_equal(pw1->dim, pw2->dim), goto error);
+
+       if (FN(PW,is_zero)(pw1)) {
+               FN(PW,free)(pw1);
+               return pw2;
+       }
+
+       if (FN(PW,is_zero)(pw2)) {
+               FN(PW,free)(pw2);
+               return pw1;
+       }
+
+       res = FN(PW,alloc_)(isl_dim_copy(pw1->dim), pw1->n + pw2->n);
+
+       for (i = 0; i < pw1->n; ++i)
+               res = FN(PW,add_piece)(res,
+                               isl_set_copy(pw1->p[i].set),
+                               FN(EL,copy)(pw1->p[i].FIELD));
+
+       for (i = 0; i < pw2->n; ++i)
+               res = FN(PW,add_piece)(res,
+                               isl_set_copy(pw2->p[i].set),
+                               FN(EL,copy)(pw2->p[i].FIELD));
+
+       FN(PW,free)(pw1);
+       FN(PW,free)(pw2);
+
+       return res;
+error:
+       FN(PW,free)(pw1);
+       FN(PW,free)(pw2);
+       return NULL;
+}