/* 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; }
/* 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_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)); }
/* 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; }