X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=isl_sample.c;h=c6a0f314425b0bc2d4683589997a3034b652abe0;hb=de51a9bc4da5dd3f1f9f57c2362da6f9752c44e0;hp=13faa3b08060047da9cbe3ecfb85f16248d1c115;hpb=e18f50ef6f40c2325dcf07da8fc2f960e6f0f9b9;p=platform%2Fupstream%2Fisl.git diff --git a/isl_sample.c b/isl_sample.c index 13faa3b..c6a0f31 100644 --- a/isl_sample.c +++ b/isl_sample.c @@ -1,22 +1,25 @@ /* * Copyright 2008-2009 Katholieke Universiteit Leuven * - * Use of this software is governed by the GNU LGPLv2.1 license + * Use of this software is governed by the MIT license * * Written by Sven Verdoolaege, K.U.Leuven, Departement * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium */ +#include +#include #include "isl_sample.h" #include "isl_sample_piplib.h" -#include "isl_vec.h" -#include "isl_mat.h" -#include "isl_seq.h" -#include "isl_map_private.h" +#include +#include +#include #include "isl_equalities.h" #include "isl_tab.h" #include "isl_basis_reduction.h" +#include #include +#include static struct isl_vec *empty_sample(struct isl_basic_set *bset) { @@ -55,12 +58,16 @@ static struct isl_vec *interval_sample(struct isl_basic_set *bset) bset = isl_basic_set_simplify(bset); if (!bset) return NULL; - if (isl_basic_set_fast_is_empty(bset)) + if (isl_basic_set_plain_is_empty(bset)) return empty_sample(bset); if (bset->n_eq == 0 && bset->n_ineq == 0) return zero_sample(bset); sample = isl_vec_alloc(bset->ctx, 2); + if (!sample) + goto error; + if (!bset) + return NULL; isl_int_set_si(sample->block.data[0], 1); if (bset->n_eq > 0) { @@ -340,6 +347,105 @@ static struct isl_mat *initial_basis(struct isl_tab *tab) return Q; } +/* Compute the minimum of the current ("level") basis row over "tab" + * and store the result in position "level" of "min". + */ +static enum isl_lp_result compute_min(isl_ctx *ctx, struct isl_tab *tab, + __isl_keep isl_vec *min, int level) +{ + return isl_tab_min(tab, tab->basis->row[1 + level], + ctx->one, &min->el[level], NULL, 0); +} + +/* Compute the maximum of the current ("level") basis row over "tab" + * and store the result in position "level" of "max". + */ +static enum isl_lp_result compute_max(isl_ctx *ctx, struct isl_tab *tab, + __isl_keep isl_vec *max, int level) +{ + enum isl_lp_result res; + unsigned dim = tab->n_var; + + isl_seq_neg(tab->basis->row[1 + level] + 1, + tab->basis->row[1 + level] + 1, dim); + res = isl_tab_min(tab, tab->basis->row[1 + level], + ctx->one, &max->el[level], NULL, 0); + isl_seq_neg(tab->basis->row[1 + level] + 1, + tab->basis->row[1 + level] + 1, dim); + isl_int_neg(max->el[level], max->el[level]); + + return res; +} + +/* Perform a greedy search for an integer point in the set represented + * by "tab", given that the minimal rational value (rounded up to the + * nearest integer) at "level" is smaller than the maximal rational + * value (rounded down to the nearest integer). + * + * Return 1 if we have found an integer point (if tab->n_unbounded > 0 + * then we may have only found integer values for the bounded dimensions + * and it is the responsibility of the caller to extend this solution + * to the unbounded dimensions). + * Return 0 if greedy search did not result in a solution. + * Return -1 if some error occurred. + * + * We assign a value half-way between the minimum and the maximum + * to the current dimension and check if the minimal value of the + * next dimension is still smaller than (or equal) to the maximal value. + * We continue this process until either + * - the minimal value (rounded up) is greater than the maximal value + * (rounded down). In this case, greedy search has failed. + * - we have exhausted all bounded dimensions, meaning that we have + * found a solution. + * - the sample value of the tableau is integral. + * - some error has occurred. + */ +static int greedy_search(isl_ctx *ctx, struct isl_tab *tab, + __isl_keep isl_vec *min, __isl_keep isl_vec *max, int level) +{ + struct isl_tab_undo *snap; + enum isl_lp_result res; + + snap = isl_tab_snap(tab); + + do { + isl_int_add(tab->basis->row[1 + level][0], + min->el[level], max->el[level]); + isl_int_fdiv_q_ui(tab->basis->row[1 + level][0], + tab->basis->row[1 + level][0], 2); + isl_int_neg(tab->basis->row[1 + level][0], + tab->basis->row[1 + level][0]); + if (isl_tab_add_valid_eq(tab, tab->basis->row[1 + level]) < 0) + return -1; + isl_int_set_si(tab->basis->row[1 + level][0], 0); + + if (++level >= tab->n_var - tab->n_unbounded) + return 1; + if (isl_tab_sample_is_integer(tab)) + return 1; + + res = compute_min(ctx, tab, min, level); + if (res == isl_lp_error) + return -1; + if (res != isl_lp_ok) + isl_die(ctx, isl_error_internal, + "expecting bounded rational solution", + return -1); + res = compute_max(ctx, tab, max, level); + if (res == isl_lp_error) + return -1; + if (res != isl_lp_ok) + isl_die(ctx, isl_error_internal, + "expecting bounded rational solution", + return -1); + } while (isl_int_le(min->el[level], max->el[level])); + + if (isl_tab_rollback(tab, snap) < 0) + return -1; + + return 0; +} + /* Given a tableau representing a set, find and return * an integer point in the set, if there is any. * @@ -379,6 +485,9 @@ static struct isl_mat *initial_basis(struct isl_tab *tab) * basis vector. "init" is true if we want the first value at the current * level and false if we want the next value. * + * At the start of each level, we first check if we can find a solution + * using greedy search. If not, we continue with the exhaustive search. + * * The initial basis is the identity matrix. If the range in some direction * contains more than one integer value, we perform basis reduction based * on the value of ctx->opt->gbr @@ -448,34 +557,38 @@ struct isl_vec *isl_tab_sample(struct isl_tab *tab) reduced = 0; while (level >= 0) { - int empty = 0; if (init) { - res = isl_tab_min(tab, tab->basis->row[1 + level], - ctx->one, &min->el[level], NULL, 0); - if (res == isl_lp_empty) - empty = 1; - isl_assert(ctx, res != isl_lp_unbounded, goto error); + int choice; + + res = compute_min(ctx, tab, min, level); if (res == isl_lp_error) goto error; - if (!empty && isl_tab_sample_is_integer(tab)) + if (res != isl_lp_ok) + isl_die(ctx, isl_error_internal, + "expecting bounded rational solution", + goto error); + if (isl_tab_sample_is_integer(tab)) break; - isl_seq_neg(tab->basis->row[1 + level] + 1, - tab->basis->row[1 + level] + 1, dim); - res = isl_tab_min(tab, tab->basis->row[1 + level], - ctx->one, &max->el[level], NULL, 0); - isl_seq_neg(tab->basis->row[1 + level] + 1, - tab->basis->row[1 + level] + 1, dim); - isl_int_neg(max->el[level], max->el[level]); - if (res == isl_lp_empty) - empty = 1; - isl_assert(ctx, res != isl_lp_unbounded, goto error); + res = compute_max(ctx, tab, max, level); if (res == isl_lp_error) goto error; - if (!empty && isl_tab_sample_is_integer(tab)) + if (res != isl_lp_ok) + isl_die(ctx, isl_error_internal, + "expecting bounded rational solution", + goto error); + if (isl_tab_sample_is_integer(tab)) break; - if (!empty && !reduced && - ctx->opt->gbr != ISL_GBR_NEVER && - isl_int_lt(min->el[level], max->el[level])) { + choice = isl_int_lt(min->el[level], max->el[level]); + if (choice) { + int g; + g = greedy_search(ctx, tab, min, max, level); + if (g < 0) + goto error; + if (g) + break; + } + if (!reduced && choice && + ctx->opt->gbr != ISL_GBR_NEVER) { unsigned gbr_only_first; if (ctx->opt->gbr == ISL_GBR_ONCE) ctx->opt->gbr = ISL_GBR_NEVER; @@ -495,7 +608,7 @@ struct isl_vec *isl_tab_sample(struct isl_tab *tab) } else isl_int_add_ui(min->el[level], min->el[level], 1); - if (empty || isl_int_gt(min->el[level], max->el[level])) { + if (isl_int_gt(min->el[level], max->el[level])) { level--; init = 0; if (level >= 0) @@ -504,7 +617,8 @@ struct isl_vec *isl_tab_sample(struct isl_tab *tab) continue; } isl_int_neg(tab->basis->row[1 + level][0], min->el[level]); - tab = isl_tab_add_valid_eq(tab, tab->basis->row[1 + level]); + if (isl_tab_add_valid_eq(tab, tab->basis->row[1 + level]) < 0) + goto error; isl_int_set_si(tab->basis->row[1 + level][0], 0); if (level + tab->n_unbounded < dim - 1) { ++level; @@ -541,6 +655,76 @@ error: return NULL; } +static struct isl_vec *sample_bounded(struct isl_basic_set *bset); + +/* Compute a sample point of the given basic set, based on the given, + * non-trivial factorization. + */ +static __isl_give isl_vec *factored_sample(__isl_take isl_basic_set *bset, + __isl_take isl_factorizer *f) +{ + int i, n; + isl_vec *sample = NULL; + isl_ctx *ctx; + unsigned nparam; + unsigned nvar; + + ctx = isl_basic_set_get_ctx(bset); + if (!ctx) + goto error; + + nparam = isl_basic_set_dim(bset, isl_dim_param); + nvar = isl_basic_set_dim(bset, isl_dim_set); + + sample = isl_vec_alloc(ctx, 1 + isl_basic_set_total_dim(bset)); + if (!sample) + goto error; + isl_int_set_si(sample->el[0], 1); + + bset = isl_morph_basic_set(isl_morph_copy(f->morph), bset); + + for (i = 0, n = 0; i < f->n_group; ++i) { + isl_basic_set *bset_i; + isl_vec *sample_i; + + bset_i = isl_basic_set_copy(bset); + bset_i = isl_basic_set_drop_constraints_involving(bset_i, + nparam + n + f->len[i], nvar - n - f->len[i]); + bset_i = isl_basic_set_drop_constraints_involving(bset_i, + nparam, n); + bset_i = isl_basic_set_drop(bset_i, isl_dim_set, + n + f->len[i], nvar - n - f->len[i]); + bset_i = isl_basic_set_drop(bset_i, isl_dim_set, 0, n); + + sample_i = sample_bounded(bset_i); + if (!sample_i) + goto error; + if (sample_i->size == 0) { + isl_basic_set_free(bset); + isl_factorizer_free(f); + isl_vec_free(sample); + return sample_i; + } + isl_seq_cpy(sample->el + 1 + nparam + n, + sample_i->el + 1, f->len[i]); + isl_vec_free(sample_i); + + n += f->len[i]; + } + + f->morph = isl_morph_inverse(f->morph); + sample = isl_morph_vec(isl_morph_copy(f->morph), sample); + + isl_basic_set_free(bset); + isl_factorizer_free(f); + return sample; +error: + isl_basic_set_free(bset); + isl_factorizer_free(f); + isl_vec_free(sample); + return NULL; +} + /* Given a basic set that is known to be bounded, find and return * an integer point in the basic set, if there is any. * @@ -554,11 +738,12 @@ static struct isl_vec *sample_bounded(struct isl_basic_set *bset) struct isl_ctx *ctx; struct isl_vec *sample; struct isl_tab *tab = NULL; + isl_factorizer *f; if (!bset) return NULL; - if (isl_basic_set_fast_is_empty(bset)) + if (isl_basic_set_plain_is_empty(bset)) return empty_sample(bset); dim = isl_basic_set_total_dim(bset); @@ -569,9 +754,16 @@ static struct isl_vec *sample_bounded(struct isl_basic_set *bset) if (bset->n_eq > 0) return sample_eq(bset, sample_bounded); + f = isl_basic_set_factorizer(bset); + if (!f) + goto error; + if (f->n_group != 0) + return factored_sample(bset, f); + isl_factorizer_free(f); + ctx = bset->ctx; - tab = isl_tab_from_basic_set(bset); + tab = isl_tab_from_basic_set(bset, 1); if (tab && tab->empty) { isl_tab_free(tab); ISL_F_SET(bset, ISL_BASIC_SET_EMPTY); @@ -580,12 +772,9 @@ static struct isl_vec *sample_bounded(struct isl_basic_set *bset) return sample; } - if (isl_tab_track_bset(tab, isl_basic_set_copy(bset)) < 0) - goto error; if (!ISL_F_ISSET(bset, ISL_BASIC_SET_NO_IMPLICIT)) - tab = isl_tab_detect_implicit_equalities(tab); - if (!tab) - goto error; + if (isl_tab_detect_implicit_equalities(tab) < 0) + goto error; sample = isl_tab_sample(tab); if (!sample) @@ -661,7 +850,7 @@ static struct isl_vec *rational_sample(struct isl_basic_set *bset) if (!bset) return NULL; - tab = isl_tab_from_basic_set(bset); + tab = isl_tab_from_basic_set(bset, 0); sample = isl_tab_get_sample_value(tab); isl_tab_free(tab); @@ -718,7 +907,7 @@ static struct isl_basic_set *shift_cone(struct isl_basic_set *cone, total = isl_basic_set_total_dim(cone); - shift = isl_basic_set_alloc_dim(isl_basic_set_get_dim(cone), + shift = isl_basic_set_alloc_space(isl_basic_set_get_space(cone), 0, 0, cone->n_ineq); for (i = 0; i < cone->n_ineq; ++i) { @@ -778,7 +967,8 @@ static struct isl_vec *round_up_in_cone(struct isl_vec *vec, total = isl_basic_set_total_dim(cone); cone = isl_basic_set_preimage(cone, U); - cone = isl_basic_set_remove_dims(cone, 0, total - (vec->size - 1)); + cone = isl_basic_set_remove_dims(cone, isl_dim_set, + 0, total - (vec->size - 1)); cone = shift_cone(cone, vec); @@ -823,28 +1013,6 @@ error: return NULL; } -/* Drop all constraints in bset that involve any of the dimensions - * first to first+n-1. - */ -static struct isl_basic_set *drop_constraints_involving - (struct isl_basic_set *bset, unsigned first, unsigned n) -{ - int i; - - if (!bset) - return NULL; - - bset = isl_basic_set_cow(bset); - - for (i = bset->n_ineq - 1; i >= 0; --i) { - if (isl_seq_first_non_zero(bset->ineq[i] + 1 + first, n) == -1) - continue; - isl_basic_set_drop_inequality(bset, i); - } - - return bset; -} - /* Give a basic set "bset" with recession cone "cone", compute and * return an integer point in bset, if any. * @@ -900,7 +1068,7 @@ __isl_give isl_vec *isl_basic_set_sample_with_cone( total = isl_basic_set_total_dim(cone); cone_dim = total - cone->n_eq; - M = isl_mat_sub_alloc(bset->ctx, cone->eq, 0, cone->n_eq, 1, total); + M = isl_mat_sub_alloc6(bset->ctx, cone->eq, 0, cone->n_eq, 1, total); M = isl_mat_left_hermite(M, 0, &U, NULL); if (!M) goto error; @@ -910,7 +1078,8 @@ __isl_give isl_vec *isl_basic_set_sample_with_cone( bset = isl_basic_set_preimage(bset, isl_mat_copy(U)); bounded = isl_basic_set_copy(bset); - bounded = drop_constraints_involving(bounded, total - cone_dim, cone_dim); + bounded = isl_basic_set_drop_constraints_involving(bounded, + total - cone_dim, cone_dim); bounded = isl_basic_set_drop_dims(bounded, total - cone_dim, cone_dim); sample = sample_bounded(bounded); if (!sample || sample->size == 0) { @@ -1072,12 +1241,17 @@ static struct isl_vec *gbr_sample(struct isl_basic_set *bset) dim = isl_basic_set_total_dim(bset); cone = isl_basic_set_recession_cone(isl_basic_set_copy(bset)); + if (!cone) + goto error; if (cone->n_eq < dim) return isl_basic_set_sample_with_cone(bset, cone); isl_basic_set_free(cone); return sample_bounded(bset); +error: + isl_basic_set_free(bset); + return NULL; } static struct isl_vec *pip_sample(struct isl_basic_set *bset) @@ -1109,7 +1283,7 @@ static struct isl_vec *basic_set_sample(struct isl_basic_set *bset, int bounded) return NULL; ctx = bset->ctx; - if (isl_basic_set_fast_is_empty(bset)) + if (isl_basic_set_plain_is_empty(bset)) return empty_sample(bset); dim = isl_basic_set_n_dim(bset); @@ -1219,6 +1393,11 @@ error: return NULL; } +__isl_give isl_basic_set *isl_basic_set_sample(__isl_take isl_basic_set *bset) +{ + return isl_basic_map_sample(bset); +} + __isl_give isl_basic_map *isl_map_sample(__isl_take isl_map *map) { int i; @@ -1252,9 +1431,9 @@ __isl_give isl_basic_set *isl_set_sample(__isl_take isl_set *set) __isl_give isl_point *isl_basic_set_sample_point(__isl_take isl_basic_set *bset) { isl_vec *vec; - isl_dim *dim; + isl_space *dim; - dim = isl_basic_set_get_dim(bset); + dim = isl_basic_set_get_space(bset); bset = isl_basic_set_underlying_set(bset); vec = isl_basic_set_sample_vec(bset); @@ -1278,7 +1457,7 @@ __isl_give isl_point *isl_set_sample_point(__isl_take isl_set *set) isl_point_free(pnt); } if (i == set->n) - pnt = isl_point_void(isl_set_get_dim(set)); + pnt = isl_point_void(isl_set_get_space(set)); isl_set_free(set); return pnt;