diff options
Diffstat (limited to 'cloog-0.17.0/isl/isl_bernstein.c')
-rw-r--r-- | cloog-0.17.0/isl/isl_bernstein.c | 554 |
1 files changed, 0 insertions, 554 deletions
diff --git a/cloog-0.17.0/isl/isl_bernstein.c b/cloog-0.17.0/isl/isl_bernstein.c deleted file mode 100644 index 0e528e5..0000000 --- a/cloog-0.17.0/isl/isl_bernstein.c +++ /dev/null @@ -1,554 +0,0 @@ -/* - * Copyright 2006-2007 Universiteit Leiden - * Copyright 2008-2009 Katholieke Universiteit Leuven - * Copyright 2010 INRIA Saclay - * - * Use of this software is governed by the GNU LGPLv2.1 license - * - * Written by Sven Verdoolaege, Leiden Institute of Advanced Computer Science, - * Universiteit Leiden, Niels Bohrweg 1, 2333 CA Leiden, The Netherlands - * and K.U.Leuven, Departement Computerwetenschappen, Celestijnenlaan 200A, - * B-3001 Leuven, Belgium - * and INRIA Saclay - Ile-de-France, Parc Club Orsay Universite, - * ZAC des vignes, 4 rue Jacques Monod, 91893 Orsay, France - */ - -#include <isl_ctx_private.h> -#include <isl_map_private.h> -#include <isl/set.h> -#include <isl/seq.h> -#include <isl_morph.h> -#include <isl_factorization.h> -#include <isl_vertices_private.h> -#include <isl_polynomial_private.h> -#include <isl_options_private.h> -#include <isl_bernstein.h> - -struct bernstein_data { - enum isl_fold type; - isl_qpolynomial *poly; - int check_tight; - - isl_cell *cell; - - isl_qpolynomial_fold *fold; - isl_qpolynomial_fold *fold_tight; - isl_pw_qpolynomial_fold *pwf; - isl_pw_qpolynomial_fold *pwf_tight; -}; - -static int vertex_is_integral(__isl_keep isl_basic_set *vertex) -{ - unsigned nvar; - unsigned nparam; - int i; - - nvar = isl_basic_set_dim(vertex, isl_dim_set); - nparam = isl_basic_set_dim(vertex, isl_dim_param); - for (i = 0; i < nvar; ++i) { - int r = nvar - 1 - i; - if (!isl_int_is_one(vertex->eq[r][1 + nparam + i]) && - !isl_int_is_negone(vertex->eq[r][1 + nparam + i])) - return 0; - } - - return 1; -} - -static __isl_give isl_qpolynomial *vertex_coordinate( - __isl_keep isl_basic_set *vertex, int i, __isl_take isl_space *dim) -{ - unsigned nvar; - unsigned nparam; - int r; - isl_int denom; - isl_qpolynomial *v; - - nvar = isl_basic_set_dim(vertex, isl_dim_set); - nparam = isl_basic_set_dim(vertex, isl_dim_param); - r = nvar - 1 - i; - - isl_int_init(denom); - isl_int_set(denom, vertex->eq[r][1 + nparam + i]); - isl_assert(vertex->ctx, !isl_int_is_zero(denom), goto error); - - if (isl_int_is_pos(denom)) - isl_seq_neg(vertex->eq[r], vertex->eq[r], - 1 + isl_basic_set_total_dim(vertex)); - else - isl_int_neg(denom, denom); - - v = isl_qpolynomial_from_affine(dim, vertex->eq[r], denom); - isl_int_clear(denom); - - return v; -error: - isl_space_free(dim); - isl_int_clear(denom); - return NULL; -} - -/* Check whether the bound associated to the selection "k" is tight, - * which is the case if we select exactly one vertex and if that vertex - * is integral for all values of the parameters. - */ -static int is_tight(int *k, int n, int d, isl_cell *cell) -{ - int i; - - for (i = 0; i < n; ++i) { - int v; - if (k[i] != d) { - if (k[i]) - return 0; - continue; - } - v = cell->ids[n - 1 - i]; - return vertex_is_integral(cell->vertices->v[v].vertex); - } - - return 0; -} - -static void add_fold(__isl_take isl_qpolynomial *b, __isl_keep isl_set *dom, - int *k, int n, int d, struct bernstein_data *data) -{ - isl_qpolynomial_fold *fold; - - fold = isl_qpolynomial_fold_alloc(data->type, b); - - if (data->check_tight && is_tight(k, n, d, data->cell)) - data->fold_tight = isl_qpolynomial_fold_fold_on_domain(dom, - data->fold_tight, fold); - else - data->fold = isl_qpolynomial_fold_fold_on_domain(dom, - data->fold, fold); -} - -/* Extract the coefficients of the Bernstein base polynomials and store - * them in data->fold and data->fold_tight. - * - * In particular, the coefficient of each monomial - * of multi-degree (k[0], k[1], ..., k[n-1]) is divided by the corresponding - * multinomial coefficient d!/k[0]! k[1]! ... k[n-1]! - * - * c[i] contains the coefficient of the selected powers of the first i+1 vars. - * multinom[i] contains the partial multinomial coefficient. - */ -static void extract_coefficients(isl_qpolynomial *poly, - __isl_keep isl_set *dom, struct bernstein_data *data) -{ - int i; - int d; - int n; - isl_ctx *ctx; - isl_qpolynomial **c = NULL; - int *k = NULL; - int *left = NULL; - isl_vec *multinom = NULL; - - if (!poly) - return; - - ctx = isl_qpolynomial_get_ctx(poly); - n = isl_qpolynomial_dim(poly, isl_dim_in); - d = isl_qpolynomial_degree(poly); - isl_assert(ctx, n >= 2, return); - - c = isl_calloc_array(ctx, isl_qpolynomial *, n); - k = isl_alloc_array(ctx, int, n); - left = isl_alloc_array(ctx, int, n); - multinom = isl_vec_alloc(ctx, n); - if (!c || !k || !left || !multinom) - goto error; - - isl_int_set_si(multinom->el[0], 1); - for (k[0] = d; k[0] >= 0; --k[0]) { - int i = 1; - isl_qpolynomial_free(c[0]); - c[0] = isl_qpolynomial_coeff(poly, isl_dim_in, n - 1, k[0]); - left[0] = d - k[0]; - k[1] = -1; - isl_int_set(multinom->el[1], multinom->el[0]); - while (i > 0) { - if (i == n - 1) { - int j; - isl_space *dim; - isl_qpolynomial *b; - isl_qpolynomial *f; - for (j = 2; j <= left[i - 1]; ++j) - isl_int_divexact_ui(multinom->el[i], - multinom->el[i], j); - b = isl_qpolynomial_coeff(c[i - 1], isl_dim_in, - n - 1 - i, left[i - 1]); - b = isl_qpolynomial_project_domain_on_params(b); - dim = isl_qpolynomial_get_domain_space(b); - f = isl_qpolynomial_rat_cst_on_domain(dim, ctx->one, - multinom->el[i]); - b = isl_qpolynomial_mul(b, f); - k[n - 1] = left[n - 2]; - add_fold(b, dom, k, n, d, data); - --i; - continue; - } - if (k[i] >= left[i - 1]) { - --i; - continue; - } - ++k[i]; - if (k[i]) - isl_int_divexact_ui(multinom->el[i], - multinom->el[i], k[i]); - isl_qpolynomial_free(c[i]); - c[i] = isl_qpolynomial_coeff(c[i - 1], isl_dim_in, - n - 1 - i, k[i]); - left[i] = left[i - 1] - k[i]; - k[i + 1] = -1; - isl_int_set(multinom->el[i + 1], multinom->el[i]); - ++i; - } - isl_int_mul_ui(multinom->el[0], multinom->el[0], k[0]); - } - - for (i = 0; i < n; ++i) - isl_qpolynomial_free(c[i]); - - isl_vec_free(multinom); - free(left); - free(k); - free(c); - return; -error: - isl_vec_free(multinom); - free(left); - free(k); - if (c) - for (i = 0; i < n; ++i) - isl_qpolynomial_free(c[i]); - free(c); - return; -} - -/* Perform bernstein expansion on the parametric vertices that are active - * on "cell". - * - * data->poly has been homogenized in the calling function. - * - * We plug in the barycentric coordinates for the set variables - * - * \vec x = \sum_i \alpha_i v_i(\vec p) - * - * and the constant "1 = \sum_i \alpha_i" for the homogeneous dimension. - * Next, we extract the coefficients of the Bernstein base polynomials. - */ -static int bernstein_coefficients_cell(__isl_take isl_cell *cell, void *user) -{ - int i, j; - struct bernstein_data *data = (struct bernstein_data *)user; - isl_space *dim_param; - isl_space *dim_dst; - isl_qpolynomial *poly = data->poly; - unsigned nvar; - int n_vertices; - isl_qpolynomial **subs; - isl_pw_qpolynomial_fold *pwf; - isl_set *dom; - isl_ctx *ctx; - - if (!poly) - goto error; - - nvar = isl_qpolynomial_dim(poly, isl_dim_in) - 1; - n_vertices = cell->n_vertices; - - ctx = isl_qpolynomial_get_ctx(poly); - if (n_vertices > nvar + 1 && ctx->opt->bernstein_triangulate) - return isl_cell_foreach_simplex(cell, - &bernstein_coefficients_cell, user); - - subs = isl_alloc_array(ctx, isl_qpolynomial *, 1 + nvar); - if (!subs) - goto error; - - dim_param = isl_basic_set_get_space(cell->dom); - dim_dst = isl_qpolynomial_get_domain_space(poly); - dim_dst = isl_space_add_dims(dim_dst, isl_dim_set, n_vertices); - - for (i = 0; i < 1 + nvar; ++i) - subs[i] = isl_qpolynomial_zero_on_domain(isl_space_copy(dim_dst)); - - for (i = 0; i < n_vertices; ++i) { - isl_qpolynomial *c; - c = isl_qpolynomial_var_on_domain(isl_space_copy(dim_dst), isl_dim_set, - 1 + nvar + i); - for (j = 0; j < nvar; ++j) { - int k = cell->ids[i]; - isl_qpolynomial *v; - v = vertex_coordinate(cell->vertices->v[k].vertex, j, - isl_space_copy(dim_param)); - v = isl_qpolynomial_add_dims(v, isl_dim_in, - 1 + nvar + n_vertices); - v = isl_qpolynomial_mul(v, isl_qpolynomial_copy(c)); - subs[1 + j] = isl_qpolynomial_add(subs[1 + j], v); - } - subs[0] = isl_qpolynomial_add(subs[0], c); - } - isl_space_free(dim_dst); - - poly = isl_qpolynomial_copy(poly); - - poly = isl_qpolynomial_add_dims(poly, isl_dim_in, n_vertices); - poly = isl_qpolynomial_substitute(poly, isl_dim_in, 0, 1 + nvar, subs); - poly = isl_qpolynomial_drop_dims(poly, isl_dim_in, 0, 1 + nvar); - - data->cell = cell; - dom = isl_set_from_basic_set(isl_basic_set_copy(cell->dom)); - data->fold = isl_qpolynomial_fold_empty(data->type, isl_space_copy(dim_param)); - data->fold_tight = isl_qpolynomial_fold_empty(data->type, dim_param); - extract_coefficients(poly, dom, data); - - pwf = isl_pw_qpolynomial_fold_alloc(data->type, isl_set_copy(dom), - data->fold); - data->pwf = isl_pw_qpolynomial_fold_fold(data->pwf, pwf); - pwf = isl_pw_qpolynomial_fold_alloc(data->type, dom, data->fold_tight); - data->pwf_tight = isl_pw_qpolynomial_fold_fold(data->pwf_tight, pwf); - - isl_qpolynomial_free(poly); - isl_cell_free(cell); - for (i = 0; i < 1 + nvar; ++i) - isl_qpolynomial_free(subs[i]); - free(subs); - return 0; -error: - isl_cell_free(cell); - return -1; -} - -/* Base case of applying bernstein expansion. - * - * We compute the chamber decomposition of the parametric polytope "bset" - * and then perform bernstein expansion on the parametric vertices - * that are active on each chamber. - */ -static __isl_give isl_pw_qpolynomial_fold *bernstein_coefficients_base( - __isl_take isl_basic_set *bset, - __isl_take isl_qpolynomial *poly, struct bernstein_data *data, int *tight) -{ - unsigned nvar; - isl_space *dim; - isl_pw_qpolynomial_fold *pwf; - isl_vertices *vertices; - int covers; - - nvar = isl_basic_set_dim(bset, isl_dim_set); - if (nvar == 0) { - isl_set *dom; - isl_qpolynomial_fold *fold; - - fold = isl_qpolynomial_fold_alloc(data->type, poly); - dom = isl_set_from_basic_set(bset); - if (tight) - *tight = 1; - pwf = isl_pw_qpolynomial_fold_alloc(data->type, dom, fold); - return isl_pw_qpolynomial_fold_project_domain_on_params(pwf); - } - - if (isl_qpolynomial_is_zero(poly)) { - isl_set *dom; - isl_qpolynomial_fold *fold; - fold = isl_qpolynomial_fold_alloc(data->type, poly); - dom = isl_set_from_basic_set(bset); - pwf = isl_pw_qpolynomial_fold_alloc(data->type, dom, fold); - if (tight) - *tight = 1; - return isl_pw_qpolynomial_fold_project_domain_on_params(pwf); - } - - dim = isl_basic_set_get_space(bset); - dim = isl_space_params(dim); - dim = isl_space_from_domain(dim); - dim = isl_space_add_dims(dim, isl_dim_set, 1); - data->pwf = isl_pw_qpolynomial_fold_zero(isl_space_copy(dim), data->type); - data->pwf_tight = isl_pw_qpolynomial_fold_zero(dim, data->type); - data->poly = isl_qpolynomial_homogenize(isl_qpolynomial_copy(poly)); - vertices = isl_basic_set_compute_vertices(bset); - isl_vertices_foreach_disjoint_cell(vertices, - &bernstein_coefficients_cell, data); - isl_vertices_free(vertices); - isl_qpolynomial_free(data->poly); - - isl_basic_set_free(bset); - isl_qpolynomial_free(poly); - - covers = isl_pw_qpolynomial_fold_covers(data->pwf_tight, data->pwf); - if (covers < 0) - goto error; - - if (tight) - *tight = covers; - - if (covers) { - isl_pw_qpolynomial_fold_free(data->pwf); - return data->pwf_tight; - } - - data->pwf = isl_pw_qpolynomial_fold_fold(data->pwf, data->pwf_tight); - - return data->pwf; -error: - isl_pw_qpolynomial_fold_free(data->pwf_tight); - isl_pw_qpolynomial_fold_free(data->pwf); - return NULL; -} - -/* Apply bernstein expansion recursively by working in on len[i] - * set variables at a time, with i ranging from n_group - 1 to 0. - */ -static __isl_give isl_pw_qpolynomial_fold *bernstein_coefficients_recursive( - __isl_take isl_pw_qpolynomial *pwqp, - int n_group, int *len, struct bernstein_data *data, int *tight) -{ - int i; - unsigned nparam; - unsigned nvar; - isl_pw_qpolynomial_fold *pwf; - - if (!pwqp) - return NULL; - - nparam = isl_pw_qpolynomial_dim(pwqp, isl_dim_param); - nvar = isl_pw_qpolynomial_dim(pwqp, isl_dim_in); - - pwqp = isl_pw_qpolynomial_move_dims(pwqp, isl_dim_param, nparam, - isl_dim_in, 0, nvar - len[n_group - 1]); - pwf = isl_pw_qpolynomial_bound(pwqp, data->type, tight); - - for (i = n_group - 2; i >= 0; --i) { - nparam = isl_pw_qpolynomial_fold_dim(pwf, isl_dim_param); - pwf = isl_pw_qpolynomial_fold_move_dims(pwf, isl_dim_in, 0, - isl_dim_param, nparam - len[i], len[i]); - if (tight && !*tight) - tight = NULL; - pwf = isl_pw_qpolynomial_fold_bound(pwf, tight); - } - - return pwf; -} - -static __isl_give isl_pw_qpolynomial_fold *bernstein_coefficients_factors( - __isl_take isl_basic_set *bset, - __isl_take isl_qpolynomial *poly, struct bernstein_data *data, int *tight) -{ - isl_factorizer *f; - isl_set *set; - isl_pw_qpolynomial *pwqp; - isl_pw_qpolynomial_fold *pwf; - - f = isl_basic_set_factorizer(bset); - if (!f) - goto error; - if (f->n_group == 0) { - isl_factorizer_free(f); - return bernstein_coefficients_base(bset, poly, data, tight); - } - - set = isl_set_from_basic_set(bset); - pwqp = isl_pw_qpolynomial_alloc(set, poly); - pwqp = isl_pw_qpolynomial_morph_domain(pwqp, isl_morph_copy(f->morph)); - - pwf = bernstein_coefficients_recursive(pwqp, f->n_group, f->len, data, - tight); - - isl_factorizer_free(f); - - return pwf; -error: - isl_basic_set_free(bset); - isl_qpolynomial_free(poly); - return NULL; -} - -static __isl_give isl_pw_qpolynomial_fold *bernstein_coefficients_full_recursive( - __isl_take isl_basic_set *bset, - __isl_take isl_qpolynomial *poly, struct bernstein_data *data, int *tight) -{ - int i; - int *len; - unsigned nvar; - isl_pw_qpolynomial_fold *pwf; - isl_set *set; - isl_pw_qpolynomial *pwqp; - - if (!bset || !poly) - goto error; - - nvar = isl_basic_set_dim(bset, isl_dim_set); - - len = isl_alloc_array(bset->ctx, int, nvar); - if (!len) - goto error; - - for (i = 0; i < nvar; ++i) - len[i] = 1; - - set = isl_set_from_basic_set(bset); - pwqp = isl_pw_qpolynomial_alloc(set, poly); - - pwf = bernstein_coefficients_recursive(pwqp, nvar, len, data, tight); - - free(len); - - return pwf; -error: - isl_basic_set_free(bset); - isl_qpolynomial_free(poly); - return NULL; -} - -/* Compute a bound on the polynomial defined over the parametric polytope - * using bernstein expansion and store the result - * in bound->pwf and bound->pwf_tight. - * - * If bernstein_recurse is set to ISL_BERNSTEIN_FACTORS, we check if - * the polytope can be factorized and apply bernstein expansion recursively - * on the factors. - * If bernstein_recurse is set to ISL_BERNSTEIN_INTERVALS, we apply - * bernstein expansion recursively on each dimension. - * Otherwise, we apply bernstein expansion on the entire polytope. - */ -int isl_qpolynomial_bound_on_domain_bernstein(__isl_take isl_basic_set *bset, - __isl_take isl_qpolynomial *poly, struct isl_bound *bound) -{ - struct bernstein_data data; - isl_pw_qpolynomial_fold *pwf; - unsigned nvar; - int tight = 0; - int *tp = bound->check_tight ? &tight : NULL; - - if (!bset || !poly) - goto error; - - data.type = bound->type; - data.check_tight = bound->check_tight; - - nvar = isl_basic_set_dim(bset, isl_dim_set); - - if (bset->ctx->opt->bernstein_recurse & ISL_BERNSTEIN_FACTORS) - pwf = bernstein_coefficients_factors(bset, poly, &data, tp); - else if (nvar > 1 && - (bset->ctx->opt->bernstein_recurse & ISL_BERNSTEIN_INTERVALS)) - pwf = bernstein_coefficients_full_recursive(bset, poly, &data, tp); - else - pwf = bernstein_coefficients_base(bset, poly, &data, tp); - - if (tight) - bound->pwf_tight = isl_pw_qpolynomial_fold_fold(bound->pwf_tight, pwf); - else - bound->pwf = isl_pw_qpolynomial_fold_fold(bound->pwf, pwf); - - return 0; -error: - isl_basic_set_free(bset); - isl_qpolynomial_free(poly); - return -1; -} |