From 92cc4b47eff95ceb7de386b76f8fdb213c8ad957 Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Mon, 8 Mar 2010 15:04:57 +0100 Subject: [PATCH] add isl_pw_qpolynomial_fold --- Makefile.am | 1 + include/isl_polynomial.h | 51 ++++++ isl_output.c | 61 +++++++ isl_polynomial.c | 438 ++++++++++++++++++++--------------------------- isl_polynomial_private.h | 28 +++ isl_pw_templ.c | 236 +++++++++++++++++++++++++ 6 files changed, 567 insertions(+), 248 deletions(-) create mode 100644 isl_pw_templ.c diff --git a/Makefile.am b/Makefile.am index 0d2ab50..1688c95 100644 --- a/Makefile.am +++ b/Makefile.am @@ -169,6 +169,7 @@ pkginclude_HEADERS = \ EXTRA_DIST = \ basis_reduction_templ.c \ + isl_pw_templ.c \ doc/mypod2latex \ doc/manual.tex \ doc/user.pod \ diff --git a/include/isl_polynomial.h b/include/isl_polynomial.h index 7820ce0..fea6c84 100644 --- a/include/isl_polynomial.h +++ b/include/isl_polynomial.h @@ -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 diff --git a/isl_output.c b/isl_output.c index 4a3d838..eabd02c 100644 --- a/isl_output.c +++ b/isl_output.c @@ -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"); +} diff --git a/isl_polynomial.c b/isl_polynomial.c index 0b2e3c0..23e42e1 100644 --- a/isl_polynomial.c +++ b/isl_polynomial.c @@ -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 + +#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 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; +} diff --git a/isl_polynomial_private.h b/isl_polynomial_private.h index 9052d96..d3d3f2f 100644 --- a/isl_polynomial_private.h +++ b/isl_polynomial_private.h @@ -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 index 0000000..0262a89 --- /dev/null +++ b/isl_pw_templ.c @@ -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; +} -- 2.7.4