/* Construct a morphism that first does morph2 and then morph1. */ __isl_give isl_morph *isl_morph_compose(__isl_take isl_morph *morph1, __isl_take isl_morph *morph2) { isl_mat *map, *inv; isl_basic_set *dom, *ran; if (!morph1 || !morph2) goto error; map = isl_mat_product(isl_mat_copy(morph1->map), isl_mat_copy(morph2->map)); inv = isl_mat_product(isl_mat_copy(morph2->inv), isl_mat_copy(morph1->inv)); dom = isl_morph_basic_set(isl_morph_inverse(isl_morph_copy(morph2)), isl_basic_set_copy(morph1->dom)); dom = isl_basic_set_intersect(dom, isl_basic_set_copy(morph2->dom)); ran = isl_morph_basic_set(isl_morph_copy(morph1), isl_basic_set_copy(morph2->ran)); ran = isl_basic_set_intersect(ran, isl_basic_set_copy(morph1->ran)); isl_morph_free(morph1); isl_morph_free(morph2); return isl_morph_alloc(dom, ran, map, inv); error: isl_morph_free(morph1); isl_morph_free(morph2); return NULL; }
Param_Polyhedron *ISL_P2PP(Polyhedron *P, Polyhedron *C, struct barvinok_options *options) { int i, j; isl_ctx *ctx = isl_ctx_alloc(); isl_space *dim; isl_basic_set *bset, *context; isl_vertices *vertices; unsigned nparam = C->Dimension; unsigned nvar = P->Dimension - nparam; Param_Polyhedron *PP = isl_calloc_type(ctx, Param_Polyhedron); Param_Vertices **next_V; struct bv_add_chamber_data data; dim = isl_space_set_alloc(ctx, nparam, nvar); bset = isl_basic_set_new_from_polylib(P, dim); dim = isl_space_set_alloc(ctx, nparam, 0); context = isl_basic_set_new_from_polylib(C, dim); bset = isl_basic_set_intersect(bset, context); vertices = isl_basic_set_compute_vertices(bset); isl_basic_set_free(bset); PP->Rays = NULL; PP->nbV = isl_vertices_get_n_vertices(vertices); PP->Constraints = Polyhedron2Constraints(P); next_V = &PP->V; isl_vertices_foreach_vertex(vertices, &add_vertex, &next_V); data.next_D = &PP->D; data.vertex_len = (PP->nbV + INT_BITS - 1)/INT_BITS; isl_vertices_foreach_cell(vertices, &add_chamber, &data); isl_vertices_free(vertices); isl_ctx_free(ctx); return PP; }
/* 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; }
/** * Reduce the modulo guard expressed by "constraints" using equalities * found in outer nesting levels (stored in "equal"). * The modulo guard may be an equality or a pair of inequalities. * In case of a pair of inequalities, *bound contains the bound on the * corresponding modulo expression. If any reduction is performed * then this bound is recomputed. * * "level" may not correspond to an existentially quantified variable. * * We first check if there are any equalities we can use. If not, * there is again nothing to reduce. * For the actual reduction, we use isl_basic_set_gist, but this * function will only perform the reduction we want here if the * the variable that imposes the modulo constraint has been projected * out (i.e., turned into an existentially quantified variable). * After the call to isl_basic_set_gist, we need to move the * existential variable back into the position where the calling * function expects it (assuming there are any constraints left). * We do this by adding an equality between the given dimension and * the existentially quantified variable. * * If there are no existentially quantified variables left, then * we don't need to add this equality. * If, on the other hand, the resulting basic set involves more * than one existentially quantified variable, then the caller * will not be able to handle the result, so we just return the * original input instead. */ CloogConstraintSet *cloog_constraint_set_reduce(CloogConstraintSet *constraints, int level, CloogEqualities *equal, int nb_par, cloog_int_t *bound) { int j; isl_space *idim; struct isl_basic_set *eq; struct isl_basic_map *id; struct cloog_isl_dim dim; struct isl_constraint *c; unsigned constraints_dim; unsigned n_div; isl_basic_set *bset, *orig; bset = cloog_constraints_set_to_isl(constraints); orig = isl_basic_set_copy(bset); dim = set_cloog_dim_to_isl_dim(constraints, level - 1); assert(dim.type == isl_dim_set); eq = NULL; for (j = 0; j < level - 1; ++j) { isl_basic_set *bset_j; if (equal->types[j] != EQTYPE_EXAFFINE) continue; bset_j = equality_to_basic_set(equal, j); if (!eq) eq = bset_j; else eq = isl_basic_set_intersect(eq, bset_j); } if (!eq) { isl_basic_set_free(orig); return cloog_constraint_set_from_isl_basic_set(bset); } idim = isl_space_map_from_set(isl_basic_set_get_space(bset)); id = isl_basic_map_identity(idim); id = isl_basic_map_remove_dims(id, isl_dim_out, dim.pos, 1); bset = isl_basic_set_apply(bset, isl_basic_map_copy(id)); bset = isl_basic_set_apply(bset, isl_basic_map_reverse(id)); constraints_dim = isl_basic_set_dim(bset, isl_dim_set); eq = isl_basic_set_remove_dims(eq, isl_dim_set, constraints_dim, isl_basic_set_dim(eq, isl_dim_set) - constraints_dim); bset = isl_basic_set_gist(bset, eq); n_div = isl_basic_set_dim(bset, isl_dim_div); if (n_div > 1) { isl_basic_set_free(bset); return cloog_constraint_set_from_isl_basic_set(orig); } if (n_div < 1) { isl_basic_set_free(orig); return cloog_constraint_set_from_isl_basic_set(bset); } c = isl_equality_alloc(isl_basic_set_get_local_space(bset)); c = isl_constraint_set_coefficient_si(c, isl_dim_div, 0, 1); c = isl_constraint_set_coefficient_si(c, isl_dim_set, dim.pos, -1); bset = isl_basic_set_add_constraint(bset, c); isl_int_set_si(*bound, 0); constraints = cloog_constraint_set_from_isl_basic_set(bset); cloog_constraint_set_foreach_constraint(constraints, add_constant_term, bound); isl_basic_set_free(orig); return cloog_constraint_set_from_isl_basic_set(bset); }