/// @brief Create an isl map from a OpenScop matrix. /// /// @param m The OpenScop matrix to translate. /// @param Space The dimensions that are contained in the OpenScop matrix. /// /// @return An isl map representing m. isl_map *mapFromMatrix(scoplib_matrix_p m, __isl_take isl_space *Space, unsigned scatteringDims) { isl_basic_map *bmap = isl_basic_map_universe(isl_space_copy(Space)); for (unsigned i = 0; i < m->NbRows; ++i) { isl_constraint *c; c = constraintFromMatrixRow(m->p[i], isl_space_copy(Space)); mpz_t minusOne; mpz_init(minusOne); mpz_set_si(minusOne, -1); isl_constraint_set_coefficient(c, isl_dim_out, i, minusOne); bmap = isl_basic_map_add_constraint(bmap, c); } for (unsigned i = m->NbRows; i < scatteringDims; i++) { isl_constraint *c; c = isl_equality_alloc(isl_local_space_from_space(isl_space_copy(Space))); mpz_t One; mpz_init(One); mpz_set_si(One, 1); isl_constraint_set_coefficient(c, isl_dim_out, i, One); bmap = isl_basic_map_add_constraint(bmap, c); } isl_space_free(Space); return isl_map_from_basic_map(bmap); }
static isl_map* build_access_function (scoplib_scop_p scop, scoplib_statement_p s, scoplib_matrix_p m, isl_space* space, isl_ctx* ctxt, int* row_pos, int array_id) { isl_map* ret = NULL; int i; isl_val* tmp = isl_val_int_from_si (ctxt, 0); for (i = *row_pos; i < m->NbRows; ++i) { if (SCOPVAL_get_si(m->p[i][0]) == array_id) { ret = isl_map_universe (isl_space_copy (space)); int pos = 0; do { isl_local_space* ls = isl_local_space_from_space (isl_space_copy (space)); isl_constraint* cst = isl_equality_alloc (isl_local_space_copy (ls)); // Set input dimensions. int k; for (k = 0; k < s->nb_iterators; ++k) { tmp = isl_val_set_si (tmp, SCOPVAL_get_si(m->p[i][k+1])); cst = isl_constraint_set_coefficient_val (cst, isl_dim_in, k, isl_val_copy(tmp)); } for (k = 0; k < scop->nb_parameters; ++k) { tmp = isl_val_set_si (tmp, SCOPVAL_get_si(m->p[i][k+1+s->nb_iterators])); cst = isl_constraint_set_coefficient_val (cst, isl_dim_param, k, isl_val_copy (tmp)); } tmp = isl_val_set_si (tmp, SCOPVAL_get_si(m->p[i][m->NbColumns - 1])); cst = isl_constraint_set_constant_val (cst, isl_val_copy(tmp)); // Set output dimension. tmp = isl_val_set_si (tmp, -1); isl_constraint_set_coefficient_val (cst, isl_dim_out, pos++, isl_val_copy (tmp)); // Insert constraint. ret = isl_map_add_constraint (ret, cst); ++i; } while (i < m->NbRows && SCOPVAL_get_si(m->p[i][0]) == 0); *row_pos = i; break; } } isl_val_free (tmp); return ret; }
/* Construct a parameter compression for "bset". * We basically just call isl_mat_parameter_compression with the right input * and then extend the resulting matrix to include the variables. * * Let the equalities be given as * * B(p) + A x = 0 * * and let [H 0] be the Hermite Normal Form of A, then * * H^-1 B(p) * * needs to be integer, so we impose that each row is divisible by * the denominator. */ __isl_give isl_morph *isl_basic_set_parameter_compression( __isl_keep isl_basic_set *bset) { unsigned nparam; unsigned nvar; int n_eq; isl_mat *H, *B; isl_vec *d; isl_mat *map, *inv; isl_basic_set *dom, *ran; if (!bset) return NULL; if (isl_basic_set_plain_is_empty(bset)) return isl_morph_empty(bset); if (bset->n_eq == 0) return isl_morph_identity(bset); isl_assert(bset->ctx, bset->n_div == 0, return NULL); n_eq = bset->n_eq; nparam = isl_basic_set_dim(bset, isl_dim_param); nvar = isl_basic_set_dim(bset, isl_dim_set); isl_assert(bset->ctx, n_eq <= nvar, return NULL); d = isl_vec_alloc(bset->ctx, n_eq); B = isl_mat_sub_alloc6(bset->ctx, bset->eq, 0, n_eq, 0, 1 + nparam); H = isl_mat_sub_alloc6(bset->ctx, bset->eq, 0, n_eq, 1 + nparam, nvar); H = isl_mat_left_hermite(H, 0, NULL, NULL); H = isl_mat_drop_cols(H, n_eq, nvar - n_eq); H = isl_mat_lin_to_aff(H); H = isl_mat_right_inverse(H); if (!H || !d) goto error; isl_seq_set(d->el, H->row[0][0], d->size); H = isl_mat_drop_rows(H, 0, 1); H = isl_mat_drop_cols(H, 0, 1); B = isl_mat_product(H, B); inv = isl_mat_parameter_compression(B, d); inv = isl_mat_diagonal(inv, isl_mat_identity(bset->ctx, nvar)); map = isl_mat_right_inverse(isl_mat_copy(inv)); dom = isl_basic_set_universe(isl_space_copy(bset->dim)); ran = isl_basic_set_universe(isl_space_copy(bset->dim)); return isl_morph_alloc(dom, ran, map, inv); error: isl_mat_free(H); isl_mat_free(B); isl_vec_free(d); return NULL; }
/// @brief Create an isl map from a OpenScop matrix. /// /// @param m The OpenScop matrix to translate. /// @param Space The dimensions that are contained in the OpenScop matrix. /// /// @return An isl map representing m. isl_map *mapFromMatrix(scoplib_matrix_p m, __isl_take isl_space *Space) { isl_basic_map *bmap = isl_basic_map_universe(isl_space_copy(Space)); for (unsigned i = 0; i < m->NbRows; ++i) { isl_constraint *c; c = constraintFromMatrixRowFull(m->p[i], isl_space_copy(Space)); bmap = isl_basic_map_add_constraint(bmap, c); } isl_space_free(Space); return isl_map_from_basic_map(bmap); }
/* Create a graft for "node" with no guards and no enforced conditions. */ __isl_give isl_ast_graft *isl_ast_graft_alloc( __isl_take isl_ast_node *node, __isl_keep isl_ast_build *build) { isl_ctx *ctx; isl_space *space; isl_ast_graft *graft; if (!node) return NULL; ctx = isl_ast_node_get_ctx(node); graft = isl_calloc_type(ctx, isl_ast_graft); if (!graft) goto error; space = isl_ast_build_get_space(build, 1); graft->ref = 1; graft->node = node; graft->guard = isl_set_universe(isl_space_copy(space)); graft->enforced = isl_basic_set_universe(space); if (!graft->guard || !graft->enforced) return isl_ast_graft_free(graft); return graft; error: isl_ast_node_free(node); return NULL; }
__isl_give isl_space *isl_morph_get_ran_space(__isl_keep isl_morph *morph) { if (!morph) return NULL; return isl_space_copy(morph->ran->dim); }
/* Apply the morphism to the set. */ __isl_give isl_set *isl_morph_set(__isl_take isl_morph *morph, __isl_take isl_set *set) { int i; if (!morph || !set) goto error; isl_assert(set->ctx, isl_space_is_equal(set->dim, morph->dom->dim), goto error); set = isl_set_cow(set); if (!set) goto error; isl_space_free(set->dim); set->dim = isl_space_copy(morph->ran->dim); if (!set->dim) goto error; for (i = 0; i < set->n; ++i) { set->p[i] = isl_morph_basic_set(isl_morph_copy(morph), set->p[i]); if (!set->p[i]) goto error; } isl_morph_free(morph); ISL_F_CLR(set, ISL_SET_NORMALIZED); return set; error: isl_set_free(set); isl_morph_free(morph); return NULL; }
/* Given a lower and upper bound on the final variable and constraints * on the remaining variables where these bounds are active, * eliminate the variable from data->poly based on these bounds. * If the polynomial has been determined to be monotonic * in the variable, then simply plug in the appropriate bound. * If the current polynomial is tight and if this bound is integer, * then the result is still tight. In all other cases, the results * may not be tight. * Otherwise, plug in the largest bound (in absolute value) in * the positive terms (if an upper bound is wanted) or the negative terms * (if a lower bounded is wanted) and the other bound in the other terms. * * If all variables have been eliminated, then record the result. * Ohterwise, recurse on the next variable. */ static isl_stat propagate_on_bound_pair(__isl_take isl_constraint *lower, __isl_take isl_constraint *upper, __isl_take isl_basic_set *bset, void *user) { struct range_data *data = (struct range_data *)user; int save_tight = data->tight; isl_qpolynomial *poly; isl_stat r; unsigned nvar; nvar = isl_basic_set_dim(bset, isl_dim_set); if (data->monotonicity) { isl_qpolynomial *sub; isl_space *dim = isl_qpolynomial_get_domain_space(data->poly); if (data->monotonicity * data->sign > 0) { if (data->tight) data->tight = bound_is_integer(upper, nvar); sub = bound2poly(upper, dim, nvar, 1); isl_constraint_free(lower); } else { if (data->tight) data->tight = bound_is_integer(lower, nvar); sub = bound2poly(lower, dim, nvar, -1); isl_constraint_free(upper); } poly = isl_qpolynomial_copy(data->poly); poly = plug_in_at_pos(poly, nvar, sub, data); poly = isl_qpolynomial_drop_dims(poly, isl_dim_in, nvar, 1); } else { isl_qpolynomial *l, *u; isl_qpolynomial *pos, *neg; isl_space *dim = isl_qpolynomial_get_domain_space(data->poly); unsigned nparam = isl_basic_set_dim(bset, isl_dim_param); int sign = data->sign * data->signs[nparam + nvar]; data->tight = 0; u = bound2poly(upper, isl_space_copy(dim), nvar, 1); l = bound2poly(lower, dim, nvar, -1); pos = isl_qpolynomial_terms_of_sign(data->poly, data->signs, sign); neg = isl_qpolynomial_terms_of_sign(data->poly, data->signs, -sign); pos = plug_in_at_pos(pos, nvar, u, data); neg = plug_in_at_pos(neg, nvar, l, data); poly = isl_qpolynomial_add(pos, neg); poly = isl_qpolynomial_drop_dims(poly, isl_dim_in, nvar, 1); } if (isl_basic_set_dim(bset, isl_dim_set) == 0) r = add_guarded_poly(bset, poly, data); else r = propagate_on_domain(bset, poly, data); data->tight = save_tight; return r; }
/* Construct a basic set described by the "n" equalities of "bset" starting * at "first". */ static __isl_give isl_basic_set *copy_equalities(__isl_keep isl_basic_set *bset, unsigned first, unsigned n) { int i, k; isl_basic_set *eq; unsigned total; isl_assert(bset->ctx, bset->n_div == 0, return NULL); total = isl_basic_set_total_dim(bset); eq = isl_basic_set_alloc_space(isl_space_copy(bset->dim), 0, n, 0); if (!eq) return NULL; for (i = 0; i < n; ++i) { k = isl_basic_set_alloc_equality(eq); if (k < 0) goto error; isl_seq_cpy(eq->eq[k], bset->eq[first + k], 1 + total); } return eq; error: isl_basic_set_free(eq); return NULL; }
// Init void init_solver (void) { context = isl_ctx_alloc (); isl_space * vars = isl_space_set_alloc (context, 0, v_nb ()); ls = isl_local_space_from_space (isl_space_copy (vars)); solutions = isl_set_universe (vars); solution = 0; next_max_var = 0; }
enum lp_result isl_constraints_opt(Matrix *C, Value *obj, Value denom, enum lp_dir dir, Value *opt) { int i; isl_ctx *ctx = isl_ctx_alloc(); isl_space *dim; isl_local_space *ls; isl_mat *eq, *ineq; isl_basic_set *bset; isl_aff *aff; isl_val *v; enum isl_lp_result res; int max = dir == lp_max; eq = extract_equalities(ctx, C); ineq = extract_inequalities(ctx, C); dim = isl_space_set_alloc(ctx, 0, C->NbColumns - 2); ls = isl_local_space_from_space(isl_space_copy(dim)); bset = isl_basic_set_from_constraint_matrices(dim, eq, ineq, isl_dim_set, isl_dim_div, isl_dim_param, isl_dim_cst); aff = isl_aff_zero_on_domain(ls); for (i = 0; i < C->NbColumns - 2; ++i) { v = isl_val_int_from_gmp(ctx, obj[i]); aff = isl_aff_set_coefficient_val(aff, isl_dim_in, i, v); } v = isl_val_int_from_gmp(ctx, obj[C->NbColumns - 2]); aff = isl_aff_set_constant_val(aff, v); v = isl_val_int_from_gmp(ctx, denom); aff = isl_aff_scale_down_val(aff, v); if (max) v = isl_val_floor(isl_basic_set_max_lp_val(bset, aff)); else v = isl_val_ceil(isl_basic_set_min_lp_val(bset, aff)); if (!v) res = isl_lp_error; else if (isl_val_is_nan(v)) res = isl_lp_empty; else if (!isl_val_is_rat(v)) res = isl_lp_unbounded; else { res = isl_lp_ok; isl_val_get_num_gmp(v, *opt); } isl_val_free(v); isl_aff_free(aff); isl_basic_set_free(bset); isl_ctx_free(ctx); return isl_lp_result2lp_result(res); }
/* Create a(n identity) morphism between empty sets of the same dimension * a "bset". */ __isl_give isl_morph *isl_morph_empty(__isl_keep isl_basic_set *bset) { isl_mat *id; isl_basic_set *empty; unsigned total; if (!bset) return NULL; total = isl_basic_set_total_dim(bset); id = isl_mat_identity(bset->ctx, 1 + total); empty = isl_basic_set_empty(isl_space_copy(bset->dim)); return isl_morph_alloc(empty, isl_basic_set_copy(empty), id, isl_mat_copy(id)); }
__isl_give isl_morph *isl_morph_identity(__isl_keep isl_basic_set *bset) { isl_mat *id; isl_basic_set *universe; unsigned total; if (!bset) return NULL; total = isl_basic_set_total_dim(bset); id = isl_mat_identity(bset->ctx, 1 + total); universe = isl_basic_set_universe(isl_space_copy(bset->dim)); return isl_morph_alloc(universe, isl_basic_set_copy(universe), id, isl_mat_copy(id)); }
/* Return 1 if poly is monotonically increasing in the last set variable, * -1 if poly is monotonically decreasing in the last set variable, * 0 if no conclusion, * -2 on error. * * We simply check the sign of p(x+1)-p(x) */ static int monotonicity(__isl_keep isl_basic_set *bset, __isl_keep isl_qpolynomial *poly, struct range_data *data) { isl_ctx *ctx; isl_space *dim; isl_qpolynomial *sub = NULL; isl_qpolynomial *diff = NULL; int result = 0; int s; unsigned nvar; ctx = isl_qpolynomial_get_ctx(poly); dim = isl_qpolynomial_get_domain_space(poly); nvar = isl_basic_set_dim(bset, isl_dim_set); sub = isl_qpolynomial_var_on_domain(isl_space_copy(dim), isl_dim_set, nvar - 1); sub = isl_qpolynomial_add(sub, isl_qpolynomial_rat_cst_on_domain(dim, ctx->one, ctx->one)); diff = isl_qpolynomial_substitute(isl_qpolynomial_copy(poly), isl_dim_in, nvar - 1, 1, &sub); diff = isl_qpolynomial_sub(diff, isl_qpolynomial_copy(poly)); s = has_sign(bset, diff, 1, data->signs); if (s < 0) goto error; if (s) result = 1; else { s = has_sign(bset, diff, -1, data->signs); if (s < 0) goto error; if (s) result = -1; } isl_qpolynomial_free(diff); isl_qpolynomial_free(sub); return result; error: isl_qpolynomial_free(diff); isl_qpolynomial_free(sub); return -2; }
static isl_set* build_iteration_domain (scoplib_scop_p scop, scoplib_statement_p s, isl_space* space, isl_ctx* ctxt) { isl_set* ret = isl_set_universe (isl_space_domain (isl_space_copy (space))); int i; isl_val* tmp = isl_val_int_from_si (ctxt, 0); scoplib_matrix_p m = s->domain->elt; for (i = 0; i < m->NbRows; ++i) { isl_local_space* ls = isl_local_space_from_space (isl_set_get_space (ret)); isl_constraint* cst; if (SCOPVAL_get_si(m->p[i][0]) == 0) cst = isl_equality_alloc (isl_local_space_copy (ls)); else cst = isl_inequality_alloc (isl_local_space_copy (ls)); // Set input dimensions. int k; for (k = 0; k < s->nb_iterators; ++k) { tmp = isl_val_set_si (tmp, SCOPVAL_get_si(m->p[i][k+1])); cst = isl_constraint_set_coefficient_val (cst, isl_dim_set, k, isl_val_copy (tmp)); } for (k = 0; k < scop->nb_parameters; ++k) { tmp = isl_val_set_si (tmp, SCOPVAL_get_si(m->p[i][k+1+s->nb_iterators])); cst = isl_constraint_set_coefficient_val (cst, isl_dim_param, k, isl_val_copy (tmp)); } tmp = isl_val_set_si (tmp, SCOPVAL_get_si(m->p[i][m->NbColumns - 1])); cst = isl_constraint_set_constant_val (cst, isl_val_copy (tmp)); // Insert constraint. ret = isl_set_add_constraint (ret, cst); } isl_val_free (tmp); return ret; }
__isl_give isl_val *FN(UNION,eval)(__isl_take UNION *u, __isl_take isl_point *pnt) { uint32_t hash; struct isl_hash_table_entry *entry; isl_bool is_void; isl_space *space; isl_val *v; if (!u || !pnt) goto error; is_void = isl_point_is_void(pnt); if (is_void < 0) goto error; if (is_void) return FN(UNION,eval_void)(u, pnt); space = isl_space_copy(pnt->dim); if (!space) goto error; hash = isl_space_get_hash(space); entry = isl_hash_table_find(u->space->ctx, &u->table, hash, &FN(UNION,has_domain_space), space, 0); isl_space_free(space); if (!entry) { v = isl_val_zero(isl_point_get_ctx(pnt)); isl_point_free(pnt); } else { v = FN(PART,eval)(FN(PART,copy)(entry->data), pnt); } FN(UNION,free)(u); return v; error: FN(UNION,free)(u); isl_point_free(pnt); return NULL; }
/* Construct a unique identifier for a group in "grouping". * * The name is of the form G_n, with n the first value starting at * grouping->group_id that does not result in an identifier * that is already in use in the domain of the original schedule * constraints. */ static isl_id *construct_group_id(struct ppcg_grouping *grouping, __isl_take isl_space *space) { isl_ctx *ctx; isl_id *id; isl_bool empty; isl_union_set *domain; if (!space) return NULL; ctx = isl_space_get_ctx(space); domain = isl_schedule_constraints_get_domain(grouping->sc); do { char buffer[20]; isl_id *id; isl_set *set; snprintf(buffer, sizeof(buffer), "G_%d", grouping->group_id); grouping->group_id++; id = isl_id_alloc(ctx, buffer, NULL); space = isl_space_set_tuple_id(space, isl_dim_set, id); set = isl_union_set_extract_set(domain, isl_space_copy(space)); empty = isl_set_plain_is_empty(set); isl_set_free(set); } while (empty >= 0 && !empty); if (empty < 0) space = isl_space_free(space); id = isl_space_get_tuple_id(space, isl_dim_set); isl_space_free(space); isl_union_set_free(domain); return id; }
/* Apply the morphism to the basic set. * We basically just compute the preimage of "bset" under the inverse mapping * in morph, add in stride constraints and intersect with the range * of the morphism. */ __isl_give isl_basic_set *isl_morph_basic_set(__isl_take isl_morph *morph, __isl_take isl_basic_set *bset) { isl_basic_set *res = NULL; isl_mat *mat = NULL; int i, k; int max_stride; if (!morph || !bset) goto error; isl_assert(bset->ctx, isl_space_is_equal(bset->dim, morph->dom->dim), goto error); max_stride = morph->inv->n_row - 1; if (isl_int_is_one(morph->inv->row[0][0])) max_stride = 0; res = isl_basic_set_alloc_space(isl_space_copy(morph->ran->dim), bset->n_div + max_stride, bset->n_eq + max_stride, bset->n_ineq); for (i = 0; i < bset->n_div; ++i) if (isl_basic_set_alloc_div(res) < 0) goto error; mat = isl_mat_sub_alloc6(bset->ctx, bset->eq, 0, bset->n_eq, 0, morph->inv->n_row); mat = isl_mat_product(mat, isl_mat_copy(morph->inv)); if (!mat) goto error; for (i = 0; i < bset->n_eq; ++i) { k = isl_basic_set_alloc_equality(res); if (k < 0) goto error; isl_seq_cpy(res->eq[k], mat->row[i], mat->n_col); isl_seq_scale(res->eq[k] + mat->n_col, bset->eq[i] + mat->n_col, morph->inv->row[0][0], bset->n_div); } isl_mat_free(mat); mat = isl_mat_sub_alloc6(bset->ctx, bset->ineq, 0, bset->n_ineq, 0, morph->inv->n_row); mat = isl_mat_product(mat, isl_mat_copy(morph->inv)); if (!mat) goto error; for (i = 0; i < bset->n_ineq; ++i) { k = isl_basic_set_alloc_inequality(res); if (k < 0) goto error; isl_seq_cpy(res->ineq[k], mat->row[i], mat->n_col); isl_seq_scale(res->ineq[k] + mat->n_col, bset->ineq[i] + mat->n_col, morph->inv->row[0][0], bset->n_div); } isl_mat_free(mat); mat = isl_mat_sub_alloc6(bset->ctx, bset->div, 0, bset->n_div, 1, morph->inv->n_row); mat = isl_mat_product(mat, isl_mat_copy(morph->inv)); if (!mat) goto error; for (i = 0; i < bset->n_div; ++i) { isl_int_mul(res->div[i][0], morph->inv->row[0][0], bset->div[i][0]); isl_seq_cpy(res->div[i] + 1, mat->row[i], mat->n_col); isl_seq_scale(res->div[i] + 1 + mat->n_col, bset->div[i] + 1 + mat->n_col, morph->inv->row[0][0], bset->n_div); } isl_mat_free(mat); res = add_strides(res, morph); if (isl_basic_set_is_rational(bset)) res = isl_basic_set_set_rational(res); res = isl_basic_set_simplify(res); res = isl_basic_set_finalize(res); res = isl_basic_set_intersect(res, isl_basic_set_copy(morph->ran)); isl_morph_free(morph); isl_basic_set_free(bset); return res; error: isl_mat_free(mat); isl_morph_free(morph); isl_basic_set_free(bset); isl_basic_set_free(res); return NULL; }
/* Given a basic set, exploit the equalties in the a basic set to construct * a morphishm that maps the basic set to a lower-dimensional space. * Specifically, the morphism reduces the number of dimensions of type "type". * * This function is a slight generalization of isl_mat_variable_compression * in that it allows the input to be parametric and that it allows for the * compression of either parameters or set variables. * * We first select the equalities of interest, that is those that involve * variables of type "type" and no later variables. * Denote those equalities as * * -C(p) + M x = 0 * * where C(p) depends on the parameters if type == isl_dim_set and * is a constant if type == isl_dim_param. * * First compute the (left) Hermite normal form of M, * * M [U1 U2] = M U = H = [H1 0] * or * M = H Q = [H1 0] [Q1] * [Q2] * * with U, Q unimodular, Q = U^{-1} (and H lower triangular). * Define the transformed variables as * * x = [U1 U2] [ x1' ] = [U1 U2] [Q1] x * [ x2' ] [Q2] * * The equalities then become * * -C(p) + H1 x1' = 0 or x1' = H1^{-1} C(p) = C'(p) * * If the denominator of the constant term does not divide the * the common denominator of the parametric terms, then every * integer point is mapped to a non-integer point and then the original set has no * integer solutions (since the x' are a unimodular transformation * of the x). In this case, an empty morphism is returned. * Otherwise, the transformation is given by * * x = U1 H1^{-1} C(p) + U2 x2' * * The inverse transformation is simply * * x2' = Q2 x * * Both matrices are extended to map the full original space to the full * compressed space. */ __isl_give isl_morph *isl_basic_set_variable_compression( __isl_keep isl_basic_set *bset, enum isl_dim_type type) { unsigned otype; unsigned ntype; unsigned orest; unsigned nrest; int f_eq, n_eq; isl_space *dim; isl_mat *H, *U, *Q, *C = NULL, *H1, *U1, *U2; isl_basic_set *dom, *ran; if (!bset) return NULL; if (isl_basic_set_plain_is_empty(bset)) return isl_morph_empty(bset); isl_assert(bset->ctx, bset->n_div == 0, return NULL); otype = 1 + isl_space_offset(bset->dim, type); ntype = isl_basic_set_dim(bset, type); orest = otype + ntype; nrest = isl_basic_set_total_dim(bset) - (orest - 1); for (f_eq = 0; f_eq < bset->n_eq; ++f_eq) if (isl_seq_first_non_zero(bset->eq[f_eq] + orest, nrest) == -1) break; for (n_eq = 0; f_eq + n_eq < bset->n_eq; ++n_eq) if (isl_seq_first_non_zero(bset->eq[f_eq + n_eq] + otype, ntype) == -1) break; if (n_eq == 0) return isl_morph_identity(bset); H = isl_mat_sub_alloc6(bset->ctx, bset->eq, f_eq, n_eq, otype, ntype); H = isl_mat_left_hermite(H, 0, &U, &Q); if (!H || !U || !Q) goto error; Q = isl_mat_drop_rows(Q, 0, n_eq); Q = isl_mat_diagonal(isl_mat_identity(bset->ctx, otype), Q); Q = isl_mat_diagonal(Q, isl_mat_identity(bset->ctx, nrest)); C = isl_mat_alloc(bset->ctx, 1 + n_eq, otype); if (!C) goto error; isl_int_set_si(C->row[0][0], 1); isl_seq_clr(C->row[0] + 1, otype - 1); isl_mat_sub_neg(C->ctx, C->row + 1, bset->eq + f_eq, n_eq, 0, 0, otype); H1 = isl_mat_sub_alloc(H, 0, H->n_row, 0, H->n_row); H1 = isl_mat_lin_to_aff(H1); C = isl_mat_inverse_product(H1, C); if (!C) goto error; isl_mat_free(H); if (!isl_int_is_one(C->row[0][0])) { int i; isl_int g; isl_int_init(g); for (i = 0; i < n_eq; ++i) { isl_seq_gcd(C->row[1 + i] + 1, otype - 1, &g); isl_int_gcd(g, g, C->row[0][0]); if (!isl_int_is_divisible_by(C->row[1 + i][0], g)) break; } isl_int_clear(g); if (i < n_eq) { isl_mat_free(C); isl_mat_free(U); isl_mat_free(Q); return isl_morph_empty(bset); } C = isl_mat_normalize(C); } U1 = isl_mat_sub_alloc(U, 0, U->n_row, 0, n_eq); U1 = isl_mat_lin_to_aff(U1); U2 = isl_mat_sub_alloc(U, 0, U->n_row, n_eq, U->n_row - n_eq); U2 = isl_mat_lin_to_aff(U2); isl_mat_free(U); C = isl_mat_product(U1, C); C = isl_mat_aff_direct_sum(C, U2); C = insert_parameter_rows(C, otype - 1); C = isl_mat_diagonal(C, isl_mat_identity(bset->ctx, nrest)); dim = isl_space_copy(bset->dim); dim = isl_space_drop_dims(dim, type, 0, ntype); dim = isl_space_add_dims(dim, type, ntype - n_eq); ran = isl_basic_set_universe(dim); dom = copy_equalities(bset, f_eq, n_eq); return isl_morph_alloc(dom, ran, Q, C); error: isl_mat_free(C); isl_mat_free(H); isl_mat_free(U); isl_mat_free(Q); return NULL; }
static isl_map* build_schedule (scoplib_scop_p scop, scoplib_statement_p s, isl_space* sp, isl_ctx* ctxt) { // Set up the space. isl_space* space_in = isl_space_domain (isl_space_copy (sp)); int dout = s->schedule->NbRows; isl_space* space_out = isl_space_set_alloc(ctxt, scop->nb_parameters, dout); int i; char buffer[32]; char* name; for (i = 0; i < dout; ++i) { sprintf (buffer, "t%d", i); name = strdup (buffer); space_out = isl_space_set_dim_name (space_out, isl_dim_set, i, name); } for (i = 0; i < scop->nb_parameters; ++i) { name = strdup (((SgVariableSymbol*)(scop->parameters[i]))->get_name().str()); space_out = isl_space_set_dim_name (space_out, isl_dim_param, i, name); } isl_space* space = isl_space_map_from_domain_and_range (isl_space_copy (space_in), isl_space_copy (space_out)); isl_map* ret = isl_map_universe (isl_space_copy (space)); isl_val* tmp = isl_val_int_from_si (ctxt, 0); scoplib_matrix_p m = s->schedule; for (i = 0; i < m->NbRows; ++i) { isl_local_space* ls = isl_local_space_from_space (isl_space_copy (space)); isl_constraint* cst; if (SCOPVAL_get_si(m->p[i][0]) == 0) cst = isl_equality_alloc (isl_local_space_copy (ls)); else cst = isl_inequality_alloc (isl_local_space_copy (ls)); // Set input dimensions. int k; for (k = 0; k < s->nb_iterators; ++k) { tmp = isl_val_set_si (tmp, SCOPVAL_get_si(m->p[i][k+1])); cst = isl_constraint_set_coefficient_val (cst, isl_dim_in, k, isl_val_copy (tmp)); } for (k = 0; k < scop->nb_parameters; ++k) { tmp = isl_val_set_si (tmp, SCOPVAL_get_si(m->p[i][k+1+s->nb_iterators])); cst = isl_constraint_set_coefficient_val (cst, isl_dim_param, k, isl_val_copy (tmp)); } tmp = isl_val_set_si (tmp, SCOPVAL_get_si(m->p[i][m->NbColumns - 1])); cst = isl_constraint_set_constant_val (cst, isl_val_copy (tmp)); // Set output dimension. tmp = isl_val_set_si (tmp, -1); isl_constraint_set_coefficient_val (cst, isl_dim_out, i, isl_val_copy (tmp)); // Insert constraint. ret = isl_map_add_constraint (ret, cst); } isl_val_free (tmp); return ret; }
enum order_sign isl_polyhedron_affine_sign(Polyhedron *D, Matrix *T, struct barvinok_options *options) { int i; isl_ctx *ctx = isl_ctx_alloc(); isl_space *dim; isl_local_space *ls; isl_aff *aff; isl_basic_set *bset; isl_val *min, *max = NULL; isl_val *v; enum order_sign sign = order_undefined; assert(D->Dimension == T->NbColumns - 1); dim = isl_space_set_alloc(ctx, 0, D->Dimension); ls = isl_local_space_from_space(isl_space_copy(dim)); bset = isl_basic_set_new_from_polylib(D, dim); aff = isl_aff_zero_on_domain(ls); for (i = 0; i < D->Dimension; ++i) { v = isl_val_int_from_gmp(ctx, T->p[0][i]); aff = isl_aff_set_coefficient_val(aff, isl_dim_in, i, v); } v = isl_val_int_from_gmp(ctx, T->p[0][D->Dimension]); aff = isl_aff_set_constant_val(aff, v); v = isl_val_int_from_gmp(ctx, T->p[1][D->Dimension]); aff = isl_aff_scale_down_val(aff, v); min = isl_basic_set_min_lp_val(bset, aff); min = isl_val_ceil(min); assert(min); if (isl_val_is_nan(min)) sign = order_undefined; else if (isl_val_is_pos(min)) sign = order_gt; else { max = isl_basic_set_max_lp_val(bset, aff); max = isl_val_floor(max); assert(max); if (isl_val_is_neg(max)) sign = order_lt; else if (isl_val_is_zero(min) && isl_val_is_zero(max)) sign = order_eq; else if (isl_val_is_zero(min)) sign = order_ge; else if (isl_val_is_zero(max)) sign = order_le; else sign = order_unknown; } isl_basic_set_free(bset); isl_aff_free(aff); isl_val_free(min); isl_val_free(max); isl_ctx_free(ctx); return sign; }