1 1.1 mrg /* 2 1.1 mrg * Copyright 2010 INRIA Saclay 3 1.1 mrg * 4 1.1 mrg * Use of this software is governed by the MIT license 5 1.1 mrg * 6 1.1 mrg * Written by Sven Verdoolaege, INRIA Saclay - Ile-de-France, 7 1.1 mrg * Parc Club Orsay Universite, ZAC des vignes, 4 rue Jacques Monod, 8 1.1 mrg * 91893 Orsay, France 9 1.1 mrg */ 10 1.1 mrg 11 1.1 mrg #include <isl_map_private.h> 12 1.1 mrg #include <isl_aff_private.h> 13 1.1 mrg #include <isl/set.h> 14 1.1 mrg #include <isl_seq.h> 15 1.1 mrg #include <isl_tab.h> 16 1.1 mrg #include <isl_space_private.h> 17 1.1 mrg #include <isl_morph.h> 18 1.1 mrg #include <isl_vertices_private.h> 19 1.1 mrg #include <isl_mat_private.h> 20 1.1 mrg #include <isl_vec_private.h> 21 1.1 mrg 22 1.1 mrg #define SELECTED 1 23 1.1 mrg #define DESELECTED -1 24 1.1 mrg #define UNSELECTED 0 25 1.1 mrg 26 1.1 mrg static __isl_give isl_vertices *compute_chambers(__isl_take isl_basic_set *bset, 27 1.1 mrg __isl_take isl_vertices *vertices); 28 1.1 mrg 29 1.1 mrg __isl_give isl_vertices *isl_vertices_copy(__isl_keep isl_vertices *vertices) 30 1.1 mrg { 31 1.1 mrg if (!vertices) 32 1.1 mrg return NULL; 33 1.1 mrg 34 1.1 mrg vertices->ref++; 35 1.1 mrg return vertices; 36 1.1 mrg } 37 1.1 mrg 38 1.1 mrg __isl_null isl_vertices *isl_vertices_free(__isl_take isl_vertices *vertices) 39 1.1 mrg { 40 1.1 mrg int i; 41 1.1 mrg 42 1.1 mrg if (!vertices) 43 1.1 mrg return NULL; 44 1.1 mrg 45 1.1 mrg if (--vertices->ref > 0) 46 1.1 mrg return NULL; 47 1.1 mrg 48 1.1 mrg for (i = 0; i < vertices->n_vertices; ++i) { 49 1.1 mrg isl_basic_set_free(vertices->v[i].vertex); 50 1.1 mrg isl_basic_set_free(vertices->v[i].dom); 51 1.1 mrg } 52 1.1 mrg free(vertices->v); 53 1.1 mrg 54 1.1 mrg for (i = 0; i < vertices->n_chambers; ++i) { 55 1.1 mrg free(vertices->c[i].vertices); 56 1.1 mrg isl_basic_set_free(vertices->c[i].dom); 57 1.1 mrg } 58 1.1 mrg free(vertices->c); 59 1.1 mrg 60 1.1 mrg isl_basic_set_free(vertices->bset); 61 1.1 mrg free(vertices); 62 1.1 mrg 63 1.1 mrg return NULL; 64 1.1 mrg } 65 1.1 mrg 66 1.1 mrg struct isl_vertex_list { 67 1.1 mrg struct isl_vertex v; 68 1.1 mrg struct isl_vertex_list *next; 69 1.1 mrg }; 70 1.1 mrg 71 1.1 mrg static struct isl_vertex_list *free_vertex_list(struct isl_vertex_list *list) 72 1.1 mrg { 73 1.1 mrg struct isl_vertex_list *next; 74 1.1 mrg 75 1.1 mrg for (; list; list = next) { 76 1.1 mrg next = list->next; 77 1.1 mrg isl_basic_set_free(list->v.vertex); 78 1.1 mrg isl_basic_set_free(list->v.dom); 79 1.1 mrg free(list); 80 1.1 mrg } 81 1.1 mrg 82 1.1 mrg return NULL; 83 1.1 mrg } 84 1.1 mrg 85 1.1 mrg static __isl_give isl_vertices *vertices_from_list(__isl_keep isl_basic_set *bset, 86 1.1 mrg int n_vertices, struct isl_vertex_list *list) 87 1.1 mrg { 88 1.1 mrg int i; 89 1.1 mrg struct isl_vertex_list *next; 90 1.1 mrg isl_vertices *vertices; 91 1.1 mrg 92 1.1 mrg vertices = isl_calloc_type(bset->ctx, isl_vertices); 93 1.1 mrg if (!vertices) 94 1.1 mrg goto error; 95 1.1 mrg vertices->ref = 1; 96 1.1 mrg vertices->bset = isl_basic_set_copy(bset); 97 1.1 mrg vertices->v = isl_alloc_array(bset->ctx, struct isl_vertex, n_vertices); 98 1.1 mrg if (n_vertices && !vertices->v) 99 1.1 mrg goto error; 100 1.1 mrg vertices->n_vertices = n_vertices; 101 1.1 mrg 102 1.1 mrg for (i = 0; list; list = next, i++) { 103 1.1 mrg next = list->next; 104 1.1 mrg vertices->v[i] = list->v; 105 1.1 mrg free(list); 106 1.1 mrg } 107 1.1 mrg 108 1.1 mrg return vertices; 109 1.1 mrg error: 110 1.1 mrg isl_vertices_free(vertices); 111 1.1 mrg free_vertex_list(list); 112 1.1 mrg return NULL; 113 1.1 mrg } 114 1.1 mrg 115 1.1 mrg /* Prepend a vertex to the linked list "list" based on the equalities in "tab". 116 1.1 mrg * Return isl_bool_true if the vertex was actually added and 117 1.1 mrg * isl_bool_false otherwise. 118 1.1 mrg * In particular, vertices with a lower-dimensional activity domain are 119 1.1 mrg * not added to the list because they would not be included in any chamber. 120 1.1 mrg * Return isl_bool_error on error. 121 1.1 mrg */ 122 1.1 mrg static isl_bool add_vertex(struct isl_vertex_list **list, 123 1.1 mrg __isl_keep isl_basic_set *bset, struct isl_tab *tab) 124 1.1 mrg { 125 1.1 mrg isl_size nvar; 126 1.1 mrg struct isl_vertex_list *v = NULL; 127 1.1 mrg 128 1.1 mrg if (isl_tab_detect_implicit_equalities(tab) < 0) 129 1.1 mrg return isl_bool_error; 130 1.1 mrg 131 1.1 mrg nvar = isl_basic_set_dim(bset, isl_dim_set); 132 1.1 mrg if (nvar < 0) 133 1.1 mrg return isl_bool_error; 134 1.1 mrg 135 1.1 mrg v = isl_calloc_type(tab->mat->ctx, struct isl_vertex_list); 136 1.1 mrg if (!v) 137 1.1 mrg goto error; 138 1.1 mrg 139 1.1 mrg v->v.vertex = isl_basic_set_copy(bset); 140 1.1 mrg v->v.vertex = isl_basic_set_cow(v->v.vertex); 141 1.1 mrg v->v.vertex = isl_basic_set_update_from_tab(v->v.vertex, tab); 142 1.1 mrg v->v.vertex = isl_basic_set_simplify(v->v.vertex); 143 1.1 mrg v->v.vertex = isl_basic_set_finalize(v->v.vertex); 144 1.1 mrg if (!v->v.vertex) 145 1.1 mrg goto error; 146 1.1 mrg isl_assert(bset->ctx, v->v.vertex->n_eq >= nvar, goto error); 147 1.1 mrg v->v.dom = isl_basic_set_copy(v->v.vertex); 148 1.1 mrg v->v.dom = isl_basic_set_params(v->v.dom); 149 1.1 mrg if (!v->v.dom) 150 1.1 mrg goto error; 151 1.1 mrg 152 1.1 mrg if (v->v.dom->n_eq > 0) { 153 1.1 mrg free_vertex_list(v); 154 1.1 mrg return isl_bool_false; 155 1.1 mrg } 156 1.1 mrg 157 1.1 mrg v->next = *list; 158 1.1 mrg *list = v; 159 1.1 mrg 160 1.1 mrg return isl_bool_true; 161 1.1 mrg error: 162 1.1 mrg free_vertex_list(v); 163 1.1 mrg return isl_bool_error; 164 1.1 mrg } 165 1.1 mrg 166 1.1 mrg /* Compute the parametric vertices and the chamber decomposition 167 1.1 mrg * of an empty parametric polytope. 168 1.1 mrg */ 169 1.1 mrg static __isl_give isl_vertices *vertices_empty(__isl_keep isl_basic_set *bset) 170 1.1 mrg { 171 1.1 mrg isl_vertices *vertices; 172 1.1 mrg 173 1.1 mrg if (!bset) 174 1.1 mrg return NULL; 175 1.1 mrg 176 1.1 mrg vertices = isl_calloc_type(bset->ctx, isl_vertices); 177 1.1 mrg if (!vertices) 178 1.1 mrg return NULL; 179 1.1 mrg vertices->bset = isl_basic_set_copy(bset); 180 1.1 mrg vertices->ref = 1; 181 1.1 mrg 182 1.1 mrg vertices->n_vertices = 0; 183 1.1 mrg vertices->n_chambers = 0; 184 1.1 mrg 185 1.1 mrg return vertices; 186 1.1 mrg } 187 1.1 mrg 188 1.1 mrg /* Compute the parametric vertices and the chamber decomposition 189 1.1 mrg * of the parametric polytope defined using the same constraints 190 1.1 mrg * as "bset" in the 0D case. 191 1.1 mrg * There is exactly one 0D vertex and a single chamber containing 192 1.1 mrg * the vertex. 193 1.1 mrg */ 194 1.1 mrg static __isl_give isl_vertices *vertices_0D(__isl_keep isl_basic_set *bset) 195 1.1 mrg { 196 1.1 mrg isl_vertices *vertices; 197 1.1 mrg 198 1.1 mrg if (!bset) 199 1.1 mrg return NULL; 200 1.1 mrg 201 1.1 mrg vertices = isl_calloc_type(bset->ctx, isl_vertices); 202 1.1 mrg if (!vertices) 203 1.1 mrg return NULL; 204 1.1 mrg vertices->ref = 1; 205 1.1 mrg vertices->bset = isl_basic_set_copy(bset); 206 1.1 mrg 207 1.1 mrg vertices->v = isl_calloc_array(bset->ctx, struct isl_vertex, 1); 208 1.1 mrg if (!vertices->v) 209 1.1 mrg goto error; 210 1.1 mrg vertices->n_vertices = 1; 211 1.1 mrg vertices->v[0].vertex = isl_basic_set_copy(bset); 212 1.1 mrg vertices->v[0].dom = isl_basic_set_params(isl_basic_set_copy(bset)); 213 1.1 mrg if (!vertices->v[0].vertex || !vertices->v[0].dom) 214 1.1 mrg goto error; 215 1.1 mrg 216 1.1 mrg vertices->c = isl_calloc_array(bset->ctx, struct isl_chamber, 1); 217 1.1 mrg if (!vertices->c) 218 1.1 mrg goto error; 219 1.1 mrg vertices->n_chambers = 1; 220 1.1 mrg vertices->c[0].n_vertices = 1; 221 1.1 mrg vertices->c[0].vertices = isl_calloc_array(bset->ctx, int, 1); 222 1.1 mrg if (!vertices->c[0].vertices) 223 1.1 mrg goto error; 224 1.1 mrg vertices->c[0].dom = isl_basic_set_copy(vertices->v[0].dom); 225 1.1 mrg if (!vertices->c[0].dom) 226 1.1 mrg goto error; 227 1.1 mrg 228 1.1 mrg return vertices; 229 1.1 mrg error: 230 1.1 mrg isl_vertices_free(vertices); 231 1.1 mrg return NULL; 232 1.1 mrg } 233 1.1 mrg 234 1.1 mrg /* Is the row pointed to by "f" linearly independent of the "n" first 235 1.1 mrg * rows in "facets"? 236 1.1 mrg */ 237 1.1 mrg static isl_bool is_independent(__isl_keep isl_mat *facets, int n, isl_int *f) 238 1.1 mrg { 239 1.1 mrg isl_size rank; 240 1.1 mrg 241 1.1 mrg if (isl_seq_first_non_zero(f, facets->n_col) < 0) 242 1.1 mrg return isl_bool_false; 243 1.1 mrg 244 1.1 mrg isl_seq_cpy(facets->row[n], f, facets->n_col); 245 1.1 mrg facets->n_row = n + 1; 246 1.1 mrg rank = isl_mat_rank(facets); 247 1.1 mrg if (rank < 0) 248 1.1 mrg return isl_bool_error; 249 1.1 mrg 250 1.1 mrg return isl_bool_ok(rank == n + 1); 251 1.1 mrg } 252 1.1 mrg 253 1.1 mrg /* Check whether we can select constraint "level", given the current selection 254 1.1 mrg * reflected by facets in "tab", the rows of "facets" and the earlier 255 1.1 mrg * "selected" elements of "selection". 256 1.1 mrg * 257 1.1 mrg * If the constraint is (strictly) redundant in the tableau, selecting it would 258 1.1 mrg * result in an empty tableau, so it can't be selected. 259 1.1 mrg * If the set variable part of the constraint is not linearly independent 260 1.1 mrg * of the set variable parts of the already selected constraints, 261 1.1 mrg * the constraint cannot be selected. 262 1.1 mrg * If selecting the constraint results in an empty tableau, the constraint 263 1.1 mrg * cannot be selected. 264 1.1 mrg * Finally, if selecting the constraint results in some explicitly 265 1.1 mrg * deselected constraints turning into equalities, then the corresponding 266 1.1 mrg * vertices have already been generated, so the constraint cannot be selected. 267 1.1 mrg */ 268 1.1 mrg static isl_bool can_select(__isl_keep isl_basic_set *bset, int level, 269 1.1 mrg struct isl_tab *tab, __isl_keep isl_mat *facets, int selected, 270 1.1 mrg int *selection) 271 1.1 mrg { 272 1.1 mrg int i; 273 1.1 mrg isl_bool indep; 274 1.1 mrg isl_size ovar; 275 1.1 mrg struct isl_tab_undo *snap; 276 1.1 mrg 277 1.1 mrg if (isl_tab_is_redundant(tab, level)) 278 1.1 mrg return isl_bool_false; 279 1.1 mrg 280 1.1 mrg ovar = isl_space_offset(bset->dim, isl_dim_set); 281 1.1 mrg if (ovar < 0) 282 1.1 mrg return isl_bool_error; 283 1.1 mrg 284 1.1 mrg indep = is_independent(facets, selected, bset->ineq[level] + 1 + ovar); 285 1.1 mrg if (indep < 0 || !indep) 286 1.1 mrg return indep; 287 1.1 mrg 288 1.1 mrg snap = isl_tab_snap(tab); 289 1.1 mrg if (isl_tab_select_facet(tab, level) < 0) 290 1.1 mrg return isl_bool_error; 291 1.1 mrg 292 1.1 mrg if (tab->empty) { 293 1.1 mrg if (isl_tab_rollback(tab, snap) < 0) 294 1.1 mrg return isl_bool_error; 295 1.1 mrg return isl_bool_false; 296 1.1 mrg } 297 1.1 mrg 298 1.1 mrg for (i = 0; i < level; ++i) { 299 1.1 mrg int sgn; 300 1.1 mrg 301 1.1 mrg if (selection[i] != DESELECTED) 302 1.1 mrg continue; 303 1.1 mrg 304 1.1 mrg if (isl_tab_is_equality(tab, i)) 305 1.1 mrg sgn = 0; 306 1.1 mrg else if (isl_tab_is_redundant(tab, i)) 307 1.1 mrg sgn = 1; 308 1.1 mrg else 309 1.1 mrg sgn = isl_tab_sign_of_max(tab, i); 310 1.1 mrg if (sgn < -1) 311 1.1 mrg return isl_bool_error; 312 1.1 mrg if (sgn <= 0) { 313 1.1 mrg if (isl_tab_rollback(tab, snap) < 0) 314 1.1 mrg return isl_bool_error; 315 1.1 mrg return isl_bool_false; 316 1.1 mrg } 317 1.1 mrg } 318 1.1 mrg 319 1.1 mrg return isl_bool_true; 320 1.1 mrg } 321 1.1 mrg 322 1.1 mrg /* Compute the parametric vertices and the chamber decomposition 323 1.1 mrg * of a parametric polytope that is not full-dimensional. 324 1.1 mrg * 325 1.1 mrg * Simply map the parametric polytope to a lower dimensional space 326 1.1 mrg * and map the resulting vertices back. 327 1.1 mrg */ 328 1.1 mrg static __isl_give isl_vertices *lower_dim_vertices( 329 1.1 mrg __isl_take isl_basic_set *bset) 330 1.1 mrg { 331 1.1 mrg isl_morph *morph; 332 1.1 mrg isl_vertices *vertices; 333 1.1 mrg 334 1.1 mrg morph = isl_basic_set_full_compression(bset); 335 1.1 mrg bset = isl_morph_basic_set(isl_morph_copy(morph), bset); 336 1.1 mrg 337 1.1 mrg vertices = isl_basic_set_compute_vertices(bset); 338 1.1 mrg isl_basic_set_free(bset); 339 1.1 mrg 340 1.1 mrg morph = isl_morph_inverse(morph); 341 1.1 mrg 342 1.1 mrg vertices = isl_morph_vertices(morph, vertices); 343 1.1 mrg 344 1.1 mrg return vertices; 345 1.1 mrg } 346 1.1 mrg 347 1.1 mrg /* Compute the parametric vertices and the chamber decomposition 348 1.1 mrg * of a parametric polytope "bset" that is not full-dimensional. 349 1.1 mrg * Additionally, free both "copy" and "tab". 350 1.1 mrg */ 351 1.1 mrg static __isl_give isl_vertices *lower_dim_vertices_free( 352 1.1 mrg __isl_take isl_basic_set *bset, __isl_take isl_basic_set *copy, 353 1.1 mrg struct isl_tab *tab) 354 1.1 mrg { 355 1.1 mrg isl_basic_set_free(copy); 356 1.1 mrg isl_tab_free(tab); 357 1.1 mrg return lower_dim_vertices(bset); 358 1.1 mrg } 359 1.1 mrg 360 1.1 mrg /* Detect implicit equality constraints in "bset" using the tableau 361 1.1 mrg * representation "tab". 362 1.1 mrg * Return a copy of "bset" with the implicit equality constraints 363 1.1 mrg * made explicit, leaving the original "bset" unmodified. 364 1.1 mrg */ 365 1.1 mrg static __isl_give isl_basic_set *detect_implicit_equality_constraints( 366 1.1 mrg __isl_keep isl_basic_set *bset, struct isl_tab *tab) 367 1.1 mrg { 368 1.1 mrg if (isl_tab_detect_implicit_equalities(tab) < 0) 369 1.1 mrg return NULL; 370 1.1 mrg 371 1.1 mrg bset = isl_basic_set_copy(bset); 372 1.1 mrg bset = isl_basic_set_cow(bset); 373 1.1 mrg bset = isl_basic_set_update_from_tab(bset, tab); 374 1.1 mrg 375 1.1 mrg return bset; 376 1.1 mrg } 377 1.1 mrg 378 1.1 mrg /* Compute the parametric vertices and the chamber decomposition 379 1.1 mrg * of the parametric polytope defined using the same constraints 380 1.1 mrg * as "bset". "bset" is assumed to have no existentially quantified 381 1.1 mrg * variables. 382 1.1 mrg * 383 1.1 mrg * The vertices themselves are computed in a fairly simplistic way. 384 1.1 mrg * We simply run through all combinations of d constraints, 385 1.1 mrg * with d the number of set variables, and check if those d constraints 386 1.1 mrg * define a vertex. To avoid the generation of duplicate vertices, 387 1.1 mrg * which may happen if a vertex is defined by more than d constraints, 388 1.1 mrg * we make sure we only generate the vertex for the d constraints with 389 1.1 mrg * smallest index. 390 1.1 mrg * 391 1.1 mrg * Only potential vertices with a full-dimensional activity domain 392 1.1 mrg * are considered. However, if the input has (implicit) equality 393 1.1 mrg * constraints among the parameters, then activity domain 394 1.1 mrg * should be considered full-dimensional if it does not satisfy 395 1.1 mrg * any extra equality constraints beyond those of the input. 396 1.1 mrg * The implicit equality constraints of the input are therefore first detected. 397 1.1 mrg * If there are any, then the input is mapped to a lower dimensional space 398 1.1 mrg * such that the check for full-dimensional activity domains 399 1.1 mrg * can be performed with respect to a full-dimensional space. 400 1.1 mrg * Note that it is important to leave "bset" unmodified while detecting 401 1.1 mrg * equality constraints since the inequality constraints of "bset" 402 1.1 mrg * are assumed to correspond to those of the tableau. 403 1.1 mrg * 404 1.1 mrg * We set up a tableau and keep track of which facets have been 405 1.1 mrg * selected. The tableau is marked strict_redundant so that we can be 406 1.1 mrg * sure that any constraint that is marked redundant (and that is not 407 1.1 mrg * also marked zero) is not an equality. 408 1.1 mrg * If a constraint is marked DESELECTED, it means the constraint was 409 1.1 mrg * SELECTED before (in combination with the same selection of earlier 410 1.1 mrg * constraints). If such a deselected constraint turns out to be an 411 1.1 mrg * equality, then any vertex that may still be found with the current 412 1.1 mrg * selection has already been generated when the constraint was selected. 413 1.1 mrg * A constraint is marked UNSELECTED when there is no way selecting 414 1.1 mrg * the constraint could lead to a vertex (in combination with the current 415 1.1 mrg * selection of earlier constraints). 416 1.1 mrg * 417 1.1 mrg * The set variable coefficients of the selected constraints are stored 418 1.1 mrg * in the facets matrix. 419 1.1 mrg */ 420 1.1 mrg __isl_give isl_vertices *isl_basic_set_compute_vertices( 421 1.1 mrg __isl_keep isl_basic_set *bset) 422 1.1 mrg { 423 1.1 mrg struct isl_tab *tab; 424 1.1 mrg int level; 425 1.1 mrg int init; 426 1.1 mrg isl_size n_eq; 427 1.1 mrg isl_size nvar; 428 1.1 mrg int *selection = NULL; 429 1.1 mrg int selected; 430 1.1 mrg struct isl_tab_undo **snap = NULL; 431 1.1 mrg isl_mat *facets = NULL; 432 1.1 mrg struct isl_vertex_list *list = NULL; 433 1.1 mrg int n_vertices = 0; 434 1.1 mrg isl_vertices *vertices; 435 1.1 mrg isl_basic_set *copy; 436 1.1 mrg isl_basic_set *test; 437 1.1 mrg 438 1.1 mrg if (!bset) 439 1.1 mrg return NULL; 440 1.1 mrg 441 1.1 mrg if (isl_basic_set_plain_is_empty(bset)) 442 1.1 mrg return vertices_empty(bset); 443 1.1 mrg 444 1.1 mrg if (bset->n_eq != 0) 445 1.1 mrg return lower_dim_vertices(isl_basic_set_copy(bset)); 446 1.1 mrg 447 1.1 mrg if (isl_basic_set_check_no_locals(bset) < 0) 448 1.1 mrg return NULL; 449 1.1 mrg 450 1.1 mrg nvar = isl_basic_set_dim(bset, isl_dim_set); 451 1.1 mrg if (nvar < 0) 452 1.1 mrg return NULL; 453 1.1 mrg if (nvar == 0) 454 1.1 mrg return vertices_0D(bset); 455 1.1 mrg 456 1.1 mrg copy = isl_basic_set_copy(bset); 457 1.1 mrg copy = isl_basic_set_set_rational(copy); 458 1.1 mrg if (!copy) 459 1.1 mrg return NULL; 460 1.1 mrg 461 1.1 mrg tab = isl_tab_from_basic_set(copy, 0); 462 1.1 mrg if (!tab) 463 1.1 mrg goto error; 464 1.1 mrg tab->strict_redundant = 1; 465 1.1 mrg 466 1.1 mrg if (tab->empty) { 467 1.1 mrg vertices = vertices_empty(copy); 468 1.1 mrg isl_basic_set_free(copy); 469 1.1 mrg isl_tab_free(tab); 470 1.1 mrg return vertices; 471 1.1 mrg } 472 1.1 mrg 473 1.1 mrg test = detect_implicit_equality_constraints(bset, tab); 474 1.1 mrg n_eq = isl_basic_set_n_equality(test); 475 1.1 mrg if (n_eq < 0) 476 1.1 mrg test = isl_basic_set_free(test); 477 1.1 mrg if (n_eq < 0 || n_eq > 0) 478 1.1 mrg return lower_dim_vertices_free(test, copy, tab); 479 1.1 mrg isl_basic_set_free(test); 480 1.1 mrg 481 1.1 mrg selection = isl_alloc_array(copy->ctx, int, copy->n_ineq); 482 1.1 mrg snap = isl_alloc_array(copy->ctx, struct isl_tab_undo *, copy->n_ineq); 483 1.1 mrg facets = isl_mat_alloc(copy->ctx, nvar, nvar); 484 1.1 mrg if ((copy->n_ineq && (!selection || !snap)) || !facets) 485 1.1 mrg goto error; 486 1.1 mrg 487 1.1 mrg level = 0; 488 1.1 mrg init = 1; 489 1.1 mrg selected = 0; 490 1.1 mrg 491 1.1 mrg while (level >= 0) { 492 1.1 mrg if (level >= copy->n_ineq || 493 1.1 mrg (!init && selection[level] != SELECTED)) { 494 1.1 mrg --level; 495 1.1 mrg init = 0; 496 1.1 mrg continue; 497 1.1 mrg } 498 1.1 mrg if (init) { 499 1.1 mrg isl_bool ok; 500 1.1 mrg snap[level] = isl_tab_snap(tab); 501 1.1 mrg ok = can_select(copy, level, tab, facets, selected, 502 1.1 mrg selection); 503 1.1 mrg if (ok < 0) 504 1.1 mrg goto error; 505 1.1 mrg if (ok) { 506 1.1 mrg selection[level] = SELECTED; 507 1.1 mrg selected++; 508 1.1 mrg } else 509 1.1 mrg selection[level] = UNSELECTED; 510 1.1 mrg } else { 511 1.1 mrg selection[level] = DESELECTED; 512 1.1 mrg selected--; 513 1.1 mrg if (isl_tab_rollback(tab, snap[level]) < 0) 514 1.1 mrg goto error; 515 1.1 mrg } 516 1.1 mrg if (selected == nvar) { 517 1.1 mrg if (tab->n_dead == nvar) { 518 1.1 mrg isl_bool added = add_vertex(&list, copy, tab); 519 1.1 mrg if (added < 0) 520 1.1 mrg goto error; 521 1.1 mrg if (added) 522 1.1 mrg n_vertices++; 523 1.1 mrg } 524 1.1 mrg init = 0; 525 1.1 mrg continue; 526 1.1 mrg } 527 1.1 mrg ++level; 528 1.1 mrg init = 1; 529 1.1 mrg } 530 1.1 mrg 531 1.1 mrg isl_mat_free(facets); 532 1.1 mrg free(selection); 533 1.1 mrg free(snap); 534 1.1 mrg 535 1.1 mrg isl_tab_free(tab); 536 1.1 mrg 537 1.1 mrg vertices = vertices_from_list(copy, n_vertices, list); 538 1.1 mrg 539 1.1 mrg vertices = compute_chambers(copy, vertices); 540 1.1 mrg 541 1.1 mrg return vertices; 542 1.1 mrg error: 543 1.1 mrg free_vertex_list(list); 544 1.1 mrg isl_mat_free(facets); 545 1.1 mrg free(selection); 546 1.1 mrg free(snap); 547 1.1 mrg isl_tab_free(tab); 548 1.1 mrg isl_basic_set_free(copy); 549 1.1 mrg return NULL; 550 1.1 mrg } 551 1.1 mrg 552 1.1 mrg struct isl_chamber_list { 553 1.1 mrg struct isl_chamber c; 554 1.1 mrg struct isl_chamber_list *next; 555 1.1 mrg }; 556 1.1 mrg 557 1.1 mrg static void free_chamber_list(struct isl_chamber_list *list) 558 1.1 mrg { 559 1.1 mrg struct isl_chamber_list *next; 560 1.1 mrg 561 1.1 mrg for (; list; list = next) { 562 1.1 mrg next = list->next; 563 1.1 mrg isl_basic_set_free(list->c.dom); 564 1.1 mrg free(list->c.vertices); 565 1.1 mrg free(list); 566 1.1 mrg } 567 1.1 mrg } 568 1.1 mrg 569 1.1 mrg /* Check whether the basic set "bset" is a superset of the basic set described 570 1.1 mrg * by "tab", i.e., check whether all constraints of "bset" are redundant. 571 1.1 mrg */ 572 1.1 mrg static isl_bool bset_covers_tab(__isl_keep isl_basic_set *bset, 573 1.1 mrg struct isl_tab *tab) 574 1.1 mrg { 575 1.1 mrg int i; 576 1.1 mrg 577 1.1 mrg if (!bset || !tab) 578 1.1 mrg return isl_bool_error; 579 1.1 mrg 580 1.1 mrg for (i = 0; i < bset->n_ineq; ++i) { 581 1.1 mrg enum isl_ineq_type type = isl_tab_ineq_type(tab, bset->ineq[i]); 582 1.1 mrg switch (type) { 583 1.1 mrg case isl_ineq_error: return isl_bool_error; 584 1.1 mrg case isl_ineq_redundant: continue; 585 1.1 mrg default: return isl_bool_false; 586 1.1 mrg } 587 1.1 mrg } 588 1.1 mrg 589 1.1 mrg return isl_bool_true; 590 1.1 mrg } 591 1.1 mrg 592 1.1 mrg static __isl_give isl_vertices *vertices_add_chambers( 593 1.1 mrg __isl_take isl_vertices *vertices, int n_chambers, 594 1.1 mrg struct isl_chamber_list *list) 595 1.1 mrg { 596 1.1 mrg int i; 597 1.1 mrg isl_ctx *ctx; 598 1.1 mrg struct isl_chamber_list *next; 599 1.1 mrg 600 1.1 mrg ctx = isl_vertices_get_ctx(vertices); 601 1.1 mrg vertices->c = isl_alloc_array(ctx, struct isl_chamber, n_chambers); 602 1.1 mrg if (!vertices->c) 603 1.1 mrg goto error; 604 1.1 mrg vertices->n_chambers = n_chambers; 605 1.1 mrg 606 1.1 mrg for (i = 0; list; list = next, i++) { 607 1.1 mrg next = list->next; 608 1.1 mrg vertices->c[i] = list->c; 609 1.1 mrg free(list); 610 1.1 mrg } 611 1.1 mrg 612 1.1 mrg return vertices; 613 1.1 mrg error: 614 1.1 mrg isl_vertices_free(vertices); 615 1.1 mrg free_chamber_list(list); 616 1.1 mrg return NULL; 617 1.1 mrg } 618 1.1 mrg 619 1.1 mrg /* Can "tab" be intersected with "bset" without resulting in 620 1.1 mrg * a lower-dimensional set. 621 1.1 mrg * "bset" itself is assumed to be full-dimensional. 622 1.1 mrg */ 623 1.1 mrg static isl_bool can_intersect(struct isl_tab *tab, 624 1.1 mrg __isl_keep isl_basic_set *bset) 625 1.1 mrg { 626 1.1 mrg int i; 627 1.1 mrg struct isl_tab_undo *snap; 628 1.1 mrg 629 1.1 mrg if (bset->n_eq > 0) 630 1.1 mrg isl_die(isl_basic_set_get_ctx(bset), isl_error_internal, 631 1.1 mrg "expecting full-dimensional input", 632 1.1 mrg return isl_bool_error); 633 1.1 mrg 634 1.1 mrg if (isl_tab_extend_cons(tab, bset->n_ineq) < 0) 635 1.1 mrg return isl_bool_error; 636 1.1 mrg 637 1.1 mrg snap = isl_tab_snap(tab); 638 1.1 mrg 639 1.1 mrg for (i = 0; i < bset->n_ineq; ++i) { 640 1.1 mrg enum isl_ineq_type type; 641 1.1 mrg 642 1.1 mrg type = isl_tab_ineq_type(tab, bset->ineq[i]); 643 1.1 mrg if (type < 0) 644 1.1 mrg return isl_bool_error; 645 1.1 mrg if (type == isl_ineq_redundant) 646 1.1 mrg continue; 647 1.1 mrg if (isl_tab_add_ineq(tab, bset->ineq[i]) < 0) 648 1.1 mrg return isl_bool_error; 649 1.1 mrg } 650 1.1 mrg 651 1.1 mrg if (isl_tab_detect_implicit_equalities(tab) < 0) 652 1.1 mrg return isl_bool_error; 653 1.1 mrg if (tab->n_dead) { 654 1.1 mrg if (isl_tab_rollback(tab, snap) < 0) 655 1.1 mrg return isl_bool_error; 656 1.1 mrg return isl_bool_false; 657 1.1 mrg } 658 1.1 mrg 659 1.1 mrg return isl_bool_true; 660 1.1 mrg } 661 1.1 mrg 662 1.1 mrg static int add_chamber(struct isl_chamber_list **list, 663 1.1 mrg __isl_keep isl_vertices *vertices, struct isl_tab *tab, int *selection) 664 1.1 mrg { 665 1.1 mrg int n_frozen; 666 1.1 mrg int i, j; 667 1.1 mrg int n_vertices = 0; 668 1.1 mrg struct isl_tab_undo *snap; 669 1.1 mrg struct isl_chamber_list *c = NULL; 670 1.1 mrg 671 1.1 mrg for (i = 0; i < vertices->n_vertices; ++i) 672 1.1 mrg if (selection[i]) 673 1.1 mrg n_vertices++; 674 1.1 mrg 675 1.1 mrg snap = isl_tab_snap(tab); 676 1.1 mrg 677 1.1 mrg for (i = 0; i < tab->n_con && tab->con[i].frozen; ++i) 678 1.1 mrg tab->con[i].frozen = 0; 679 1.1 mrg n_frozen = i; 680 1.1 mrg 681 1.1 mrg if (isl_tab_detect_redundant(tab) < 0) 682 1.1 mrg return -1; 683 1.1 mrg 684 1.1 mrg c = isl_calloc_type(tab->mat->ctx, struct isl_chamber_list); 685 1.1 mrg if (!c) 686 1.1 mrg goto error; 687 1.1 mrg c->c.vertices = isl_alloc_array(tab->mat->ctx, int, n_vertices); 688 1.1 mrg if (n_vertices && !c->c.vertices) 689 1.1 mrg goto error; 690 1.1 mrg c->c.dom = isl_basic_set_copy(isl_tab_peek_bset(tab)); 691 1.1 mrg c->c.dom = isl_basic_set_set_rational(c->c.dom); 692 1.1 mrg c->c.dom = isl_basic_set_cow(c->c.dom); 693 1.1 mrg c->c.dom = isl_basic_set_update_from_tab(c->c.dom, tab); 694 1.1 mrg c->c.dom = isl_basic_set_simplify(c->c.dom); 695 1.1 mrg c->c.dom = isl_basic_set_finalize(c->c.dom); 696 1.1 mrg if (!c->c.dom) 697 1.1 mrg goto error; 698 1.1 mrg 699 1.1 mrg c->c.n_vertices = n_vertices; 700 1.1 mrg 701 1.1 mrg for (i = 0, j = 0; i < vertices->n_vertices; ++i) 702 1.1 mrg if (selection[i]) { 703 1.1 mrg c->c.vertices[j] = i; 704 1.1 mrg j++; 705 1.1 mrg } 706 1.1 mrg 707 1.1 mrg c->next = *list; 708 1.1 mrg *list = c; 709 1.1 mrg 710 1.1 mrg for (i = 0; i < n_frozen; ++i) 711 1.1 mrg tab->con[i].frozen = 1; 712 1.1 mrg 713 1.1 mrg if (isl_tab_rollback(tab, snap) < 0) 714 1.1 mrg return -1; 715 1.1 mrg 716 1.1 mrg return 0; 717 1.1 mrg error: 718 1.1 mrg free_chamber_list(c); 719 1.1 mrg return -1; 720 1.1 mrg } 721 1.1 mrg 722 1.1 mrg struct isl_facet_todo { 723 1.1 mrg struct isl_tab *tab; /* A tableau representation of the facet */ 724 1.1 mrg isl_basic_set *bset; /* A normalized basic set representation */ 725 1.1 mrg isl_vec *constraint; /* Constraint pointing to the other side */ 726 1.1 mrg struct isl_facet_todo *next; 727 1.1 mrg }; 728 1.1 mrg 729 1.1 mrg static void free_todo(struct isl_facet_todo *todo) 730 1.1 mrg { 731 1.1 mrg while (todo) { 732 1.1 mrg struct isl_facet_todo *next = todo->next; 733 1.1 mrg 734 1.1 mrg isl_tab_free(todo->tab); 735 1.1 mrg isl_basic_set_free(todo->bset); 736 1.1 mrg isl_vec_free(todo->constraint); 737 1.1 mrg free(todo); 738 1.1 mrg 739 1.1 mrg todo = next; 740 1.1 mrg } 741 1.1 mrg } 742 1.1 mrg 743 1.1 mrg static struct isl_facet_todo *create_todo(struct isl_tab *tab, int con) 744 1.1 mrg { 745 1.1 mrg int i; 746 1.1 mrg int n_frozen; 747 1.1 mrg struct isl_tab_undo *snap; 748 1.1 mrg struct isl_facet_todo *todo; 749 1.1 mrg 750 1.1 mrg snap = isl_tab_snap(tab); 751 1.1 mrg 752 1.1 mrg for (i = 0; i < tab->n_con && tab->con[i].frozen; ++i) 753 1.1 mrg tab->con[i].frozen = 0; 754 1.1 mrg n_frozen = i; 755 1.1 mrg 756 1.1 mrg if (isl_tab_detect_redundant(tab) < 0) 757 1.1 mrg return NULL; 758 1.1 mrg 759 1.1 mrg todo = isl_calloc_type(tab->mat->ctx, struct isl_facet_todo); 760 1.1 mrg if (!todo) 761 1.1 mrg return NULL; 762 1.1 mrg 763 1.1 mrg todo->constraint = isl_vec_alloc(tab->mat->ctx, 1 + tab->n_var); 764 1.1 mrg if (!todo->constraint) 765 1.1 mrg goto error; 766 1.1 mrg isl_seq_neg(todo->constraint->el, tab->bmap->ineq[con], 1 + tab->n_var); 767 1.1 mrg todo->bset = isl_basic_set_copy(isl_tab_peek_bset(tab)); 768 1.1 mrg todo->bset = isl_basic_set_set_rational(todo->bset); 769 1.1 mrg todo->bset = isl_basic_set_cow(todo->bset); 770 1.1 mrg todo->bset = isl_basic_set_update_from_tab(todo->bset, tab); 771 1.1 mrg todo->bset = isl_basic_set_simplify(todo->bset); 772 1.1 mrg todo->bset = isl_basic_set_sort_constraints(todo->bset); 773 1.1 mrg if (!todo->bset) 774 1.1 mrg goto error; 775 1.1 mrg ISL_F_SET(todo->bset, ISL_BASIC_SET_NO_REDUNDANT); 776 1.1 mrg todo->tab = isl_tab_dup(tab); 777 1.1 mrg if (!todo->tab) 778 1.1 mrg goto error; 779 1.1 mrg 780 1.1 mrg for (i = 0; i < n_frozen; ++i) 781 1.1 mrg tab->con[i].frozen = 1; 782 1.1 mrg 783 1.1 mrg if (isl_tab_rollback(tab, snap) < 0) 784 1.1 mrg goto error; 785 1.1 mrg 786 1.1 mrg return todo; 787 1.1 mrg error: 788 1.1 mrg free_todo(todo); 789 1.1 mrg return NULL; 790 1.1 mrg } 791 1.1 mrg 792 1.1 mrg /* Create todo items for all interior facets of the chamber represented 793 1.1 mrg * by "tab" and collect them in "next". 794 1.1 mrg */ 795 1.1 mrg static int init_todo(struct isl_facet_todo **next, struct isl_tab *tab) 796 1.1 mrg { 797 1.1 mrg int i; 798 1.1 mrg struct isl_tab_undo *snap; 799 1.1 mrg struct isl_facet_todo *todo; 800 1.1 mrg 801 1.1 mrg snap = isl_tab_snap(tab); 802 1.1 mrg 803 1.1 mrg for (i = 0; i < tab->n_con; ++i) { 804 1.1 mrg if (tab->con[i].frozen) 805 1.1 mrg continue; 806 1.1 mrg if (tab->con[i].is_redundant) 807 1.1 mrg continue; 808 1.1 mrg 809 1.1 mrg if (isl_tab_select_facet(tab, i) < 0) 810 1.1 mrg return -1; 811 1.1 mrg 812 1.1 mrg todo = create_todo(tab, i); 813 1.1 mrg if (!todo) 814 1.1 mrg return -1; 815 1.1 mrg 816 1.1 mrg todo->next = *next; 817 1.1 mrg *next = todo; 818 1.1 mrg 819 1.1 mrg if (isl_tab_rollback(tab, snap) < 0) 820 1.1 mrg return -1; 821 1.1 mrg } 822 1.1 mrg 823 1.1 mrg return 0; 824 1.1 mrg } 825 1.1 mrg 826 1.1 mrg /* Does the linked list contain a todo item that is the opposite of "todo". 827 1.1 mrg * If so, return 1 and remove the opposite todo item. 828 1.1 mrg */ 829 1.1 mrg static int has_opposite(struct isl_facet_todo *todo, 830 1.1 mrg struct isl_facet_todo **list) 831 1.1 mrg { 832 1.1 mrg for (; *list; list = &(*list)->next) { 833 1.1 mrg int eq; 834 1.1 mrg eq = isl_basic_set_plain_is_equal(todo->bset, (*list)->bset); 835 1.1 mrg if (eq < 0) 836 1.1 mrg return -1; 837 1.1 mrg if (!eq) 838 1.1 mrg continue; 839 1.1 mrg todo = *list; 840 1.1 mrg *list = todo->next; 841 1.1 mrg todo->next = NULL; 842 1.1 mrg free_todo(todo); 843 1.1 mrg return 1; 844 1.1 mrg } 845 1.1 mrg 846 1.1 mrg return 0; 847 1.1 mrg } 848 1.1 mrg 849 1.1 mrg /* Create todo items for all interior facets of the chamber represented 850 1.1 mrg * by "tab" and collect them in first->next, taking care to cancel 851 1.1 mrg * opposite todo items. 852 1.1 mrg */ 853 1.1 mrg static int update_todo(struct isl_facet_todo *first, struct isl_tab *tab) 854 1.1 mrg { 855 1.1 mrg int i; 856 1.1 mrg struct isl_tab_undo *snap; 857 1.1 mrg struct isl_facet_todo *todo; 858 1.1 mrg 859 1.1 mrg snap = isl_tab_snap(tab); 860 1.1 mrg 861 1.1 mrg for (i = 0; i < tab->n_con; ++i) { 862 1.1 mrg int drop; 863 1.1 mrg 864 1.1 mrg if (tab->con[i].frozen) 865 1.1 mrg continue; 866 1.1 mrg if (tab->con[i].is_redundant) 867 1.1 mrg continue; 868 1.1 mrg 869 1.1 mrg if (isl_tab_select_facet(tab, i) < 0) 870 1.1 mrg return -1; 871 1.1 mrg 872 1.1 mrg todo = create_todo(tab, i); 873 1.1 mrg if (!todo) 874 1.1 mrg return -1; 875 1.1 mrg 876 1.1 mrg drop = has_opposite(todo, &first->next); 877 1.1 mrg if (drop < 0) 878 1.1 mrg return -1; 879 1.1 mrg 880 1.1 mrg if (drop) 881 1.1 mrg free_todo(todo); 882 1.1 mrg else { 883 1.1 mrg todo->next = first->next; 884 1.1 mrg first->next = todo; 885 1.1 mrg } 886 1.1 mrg 887 1.1 mrg if (isl_tab_rollback(tab, snap) < 0) 888 1.1 mrg return -1; 889 1.1 mrg } 890 1.1 mrg 891 1.1 mrg return 0; 892 1.1 mrg } 893 1.1 mrg 894 1.1 mrg /* Compute the chamber decomposition of the parametric polytope respresented 895 1.1 mrg * by "bset" given the parametric vertices and their activity domains. 896 1.1 mrg * 897 1.1 mrg * We are only interested in full-dimensional chambers. 898 1.1 mrg * Each of these chambers is the intersection of the activity domains of 899 1.1 mrg * one or more vertices and the union of all chambers is equal to the 900 1.1 mrg * projection of the entire parametric polytope onto the parameter space. 901 1.1 mrg * 902 1.1 mrg * We first create an initial chamber by intersecting as many activity 903 1.1 mrg * domains as possible without ending up with an empty or lower-dimensional 904 1.1 mrg * set. As a minor optimization, we only consider those activity domains 905 1.1 mrg * that contain some arbitrary point. 906 1.1 mrg * 907 1.1 mrg * For each of the interior facets of the chamber, we construct a todo item, 908 1.1 mrg * containing the facet and a constraint containing the other side of the facet, 909 1.1 mrg * for constructing the chamber on the other side. 910 1.1 mrg * While their are any todo items left, we pick a todo item and 911 1.1 mrg * create the required chamber by intersecting all activity domains 912 1.1 mrg * that contain the facet and have a full-dimensional intersection with 913 1.1 mrg * the other side of the facet. For each of the interior facets, we 914 1.1 mrg * again create todo items, taking care to cancel opposite todo items. 915 1.1 mrg */ 916 1.1 mrg static __isl_give isl_vertices *compute_chambers(__isl_take isl_basic_set *bset, 917 1.1 mrg __isl_take isl_vertices *vertices) 918 1.1 mrg { 919 1.1 mrg int i; 920 1.1 mrg isl_ctx *ctx; 921 1.1 mrg isl_size n_eq; 922 1.1 mrg isl_vec *sample = NULL; 923 1.1 mrg struct isl_tab *tab = NULL; 924 1.1 mrg struct isl_tab_undo *snap; 925 1.1 mrg int *selection = NULL; 926 1.1 mrg int n_chambers = 0; 927 1.1 mrg struct isl_chamber_list *list = NULL; 928 1.1 mrg struct isl_facet_todo *todo = NULL; 929 1.1 mrg 930 1.1 mrg if (!bset || !vertices) 931 1.1 mrg goto error; 932 1.1 mrg 933 1.1 mrg ctx = isl_vertices_get_ctx(vertices); 934 1.1 mrg selection = isl_alloc_array(ctx, int, vertices->n_vertices); 935 1.1 mrg if (vertices->n_vertices && !selection) 936 1.1 mrg goto error; 937 1.1 mrg 938 1.1 mrg bset = isl_basic_set_params(bset); 939 1.1 mrg n_eq = isl_basic_set_n_equality(bset); 940 1.1 mrg if (n_eq < 0) 941 1.1 mrg goto error; 942 1.1 mrg if (n_eq > 0) 943 1.1 mrg isl_die(isl_basic_set_get_ctx(bset), isl_error_internal, 944 1.1 mrg "expecting full-dimensional input", goto error); 945 1.1 mrg 946 1.1 mrg tab = isl_tab_from_basic_set(bset, 1); 947 1.1 mrg if (!tab) 948 1.1 mrg goto error; 949 1.1 mrg for (i = 0; i < bset->n_ineq; ++i) 950 1.1 mrg if (isl_tab_freeze_constraint(tab, i) < 0) 951 1.1 mrg goto error; 952 1.1 mrg isl_basic_set_free(bset); 953 1.1 mrg 954 1.1 mrg snap = isl_tab_snap(tab); 955 1.1 mrg 956 1.1 mrg sample = isl_tab_get_sample_value(tab); 957 1.1 mrg 958 1.1 mrg for (i = 0; i < vertices->n_vertices; ++i) { 959 1.1 mrg selection[i] = isl_basic_set_contains(vertices->v[i].dom, sample); 960 1.1 mrg if (selection[i] < 0) 961 1.1 mrg goto error; 962 1.1 mrg if (!selection[i]) 963 1.1 mrg continue; 964 1.1 mrg selection[i] = can_intersect(tab, vertices->v[i].dom); 965 1.1 mrg if (selection[i] < 0) 966 1.1 mrg goto error; 967 1.1 mrg } 968 1.1 mrg 969 1.1 mrg if (isl_tab_detect_redundant(tab) < 0) 970 1.1 mrg goto error; 971 1.1 mrg 972 1.1 mrg if (add_chamber(&list, vertices, tab, selection) < 0) 973 1.1 mrg goto error; 974 1.1 mrg n_chambers++; 975 1.1 mrg 976 1.1 mrg if (init_todo(&todo, tab) < 0) 977 1.1 mrg goto error; 978 1.1 mrg 979 1.1 mrg while (todo) { 980 1.1 mrg struct isl_facet_todo *next; 981 1.1 mrg 982 1.1 mrg if (isl_tab_rollback(tab, snap) < 0) 983 1.1 mrg goto error; 984 1.1 mrg 985 1.1 mrg if (isl_tab_add_ineq(tab, todo->constraint->el) < 0) 986 1.1 mrg goto error; 987 1.1 mrg if (isl_tab_freeze_constraint(tab, tab->n_con - 1) < 0) 988 1.1 mrg goto error; 989 1.1 mrg 990 1.1 mrg for (i = 0; i < vertices->n_vertices; ++i) { 991 1.1 mrg selection[i] = bset_covers_tab(vertices->v[i].dom, 992 1.1 mrg todo->tab); 993 1.1 mrg if (selection[i] < 0) 994 1.1 mrg goto error; 995 1.1 mrg if (!selection[i]) 996 1.1 mrg continue; 997 1.1 mrg selection[i] = can_intersect(tab, vertices->v[i].dom); 998 1.1 mrg if (selection[i] < 0) 999 1.1 mrg goto error; 1000 1.1 mrg } 1001 1.1 mrg 1002 1.1 mrg if (isl_tab_detect_redundant(tab) < 0) 1003 1.1 mrg goto error; 1004 1.1 mrg 1005 1.1 mrg if (add_chamber(&list, vertices, tab, selection) < 0) 1006 1.1 mrg goto error; 1007 1.1 mrg n_chambers++; 1008 1.1 mrg 1009 1.1 mrg if (update_todo(todo, tab) < 0) 1010 1.1 mrg goto error; 1011 1.1 mrg 1012 1.1 mrg next = todo->next; 1013 1.1 mrg todo->next = NULL; 1014 1.1 mrg free_todo(todo); 1015 1.1 mrg todo = next; 1016 1.1 mrg } 1017 1.1 mrg 1018 1.1 mrg isl_vec_free(sample); 1019 1.1 mrg 1020 1.1 mrg isl_tab_free(tab); 1021 1.1 mrg free(selection); 1022 1.1 mrg 1023 1.1 mrg vertices = vertices_add_chambers(vertices, n_chambers, list); 1024 1.1 mrg 1025 1.1 mrg for (i = 0; vertices && i < vertices->n_vertices; ++i) { 1026 1.1 mrg isl_basic_set_free(vertices->v[i].dom); 1027 1.1 mrg vertices->v[i].dom = NULL; 1028 1.1 mrg } 1029 1.1 mrg 1030 1.1 mrg return vertices; 1031 1.1 mrg error: 1032 1.1 mrg free_chamber_list(list); 1033 1.1 mrg free_todo(todo); 1034 1.1 mrg isl_vec_free(sample); 1035 1.1 mrg isl_tab_free(tab); 1036 1.1 mrg free(selection); 1037 1.1 mrg if (!tab) 1038 1.1 mrg isl_basic_set_free(bset); 1039 1.1 mrg isl_vertices_free(vertices); 1040 1.1 mrg return NULL; 1041 1.1 mrg } 1042 1.1 mrg 1043 1.1 mrg isl_ctx *isl_vertex_get_ctx(__isl_keep isl_vertex *vertex) 1044 1.1 mrg { 1045 1.1 mrg return vertex ? isl_vertices_get_ctx(vertex->vertices) : NULL; 1046 1.1 mrg } 1047 1.1 mrg 1048 1.1 mrg isl_size isl_vertex_get_id(__isl_keep isl_vertex *vertex) 1049 1.1 mrg { 1050 1.1 mrg return vertex ? vertex->id : isl_size_error; 1051 1.1 mrg } 1052 1.1 mrg 1053 1.1 mrg /* Return the activity domain of the vertex "vertex". 1054 1.1 mrg */ 1055 1.1 mrg __isl_give isl_basic_set *isl_vertex_get_domain(__isl_keep isl_vertex *vertex) 1056 1.1 mrg { 1057 1.1 mrg struct isl_vertex *v; 1058 1.1 mrg 1059 1.1 mrg if (!vertex) 1060 1.1 mrg return NULL; 1061 1.1 mrg 1062 1.1 mrg v = &vertex->vertices->v[vertex->id]; 1063 1.1 mrg if (!v->dom) { 1064 1.1 mrg v->dom = isl_basic_set_copy(v->vertex); 1065 1.1 mrg v->dom = isl_basic_set_params(v->dom); 1066 1.1 mrg v->dom = isl_basic_set_set_integral(v->dom); 1067 1.1 mrg } 1068 1.1 mrg 1069 1.1 mrg return isl_basic_set_copy(v->dom); 1070 1.1 mrg } 1071 1.1 mrg 1072 1.1 mrg /* Return a multiple quasi-affine expression describing the vertex "vertex" 1073 1.1 mrg * in terms of the parameters, 1074 1.1 mrg */ 1075 1.1 mrg __isl_give isl_multi_aff *isl_vertex_get_expr(__isl_keep isl_vertex *vertex) 1076 1.1 mrg { 1077 1.1 mrg struct isl_vertex *v; 1078 1.1 mrg isl_basic_set *bset; 1079 1.1 mrg 1080 1.1 mrg if (!vertex) 1081 1.1 mrg return NULL; 1082 1.1 mrg 1083 1.1 mrg v = &vertex->vertices->v[vertex->id]; 1084 1.1 mrg 1085 1.1 mrg bset = isl_basic_set_copy(v->vertex); 1086 1.1 mrg return isl_multi_aff_from_basic_set_equalities(bset); 1087 1.1 mrg } 1088 1.1 mrg 1089 1.1 mrg static __isl_give isl_vertex *isl_vertex_alloc(__isl_take isl_vertices *vertices, 1090 1.1 mrg int id) 1091 1.1 mrg { 1092 1.1 mrg isl_ctx *ctx; 1093 1.1 mrg isl_vertex *vertex; 1094 1.1 mrg 1095 1.1 mrg if (!vertices) 1096 1.1 mrg return NULL; 1097 1.1 mrg 1098 1.1 mrg ctx = isl_vertices_get_ctx(vertices); 1099 1.1 mrg vertex = isl_alloc_type(ctx, isl_vertex); 1100 1.1 mrg if (!vertex) 1101 1.1 mrg goto error; 1102 1.1 mrg 1103 1.1 mrg vertex->vertices = vertices; 1104 1.1 mrg vertex->id = id; 1105 1.1 mrg 1106 1.1 mrg return vertex; 1107 1.1 mrg error: 1108 1.1 mrg isl_vertices_free(vertices); 1109 1.1 mrg return NULL; 1110 1.1 mrg } 1111 1.1 mrg 1112 1.1 mrg __isl_null isl_vertex *isl_vertex_free(__isl_take isl_vertex *vertex) 1113 1.1 mrg { 1114 1.1 mrg if (!vertex) 1115 1.1 mrg return NULL; 1116 1.1 mrg isl_vertices_free(vertex->vertices); 1117 1.1 mrg free(vertex); 1118 1.1 mrg 1119 1.1 mrg return NULL; 1120 1.1 mrg } 1121 1.1 mrg 1122 1.1 mrg isl_ctx *isl_cell_get_ctx(__isl_keep isl_cell *cell) 1123 1.1 mrg { 1124 1.1 mrg return cell ? cell->dom->ctx : NULL; 1125 1.1 mrg } 1126 1.1 mrg 1127 1.1 mrg __isl_give isl_basic_set *isl_cell_get_domain(__isl_keep isl_cell *cell) 1128 1.1 mrg { 1129 1.1 mrg return cell ? isl_basic_set_copy(cell->dom) : NULL; 1130 1.1 mrg } 1131 1.1 mrg 1132 1.1 mrg static __isl_give isl_cell *isl_cell_alloc(__isl_take isl_vertices *vertices, 1133 1.1 mrg __isl_take isl_basic_set *dom, int id) 1134 1.1 mrg { 1135 1.1 mrg int i; 1136 1.1 mrg isl_cell *cell = NULL; 1137 1.1 mrg 1138 1.1 mrg if (!vertices || !dom) 1139 1.1 mrg goto error; 1140 1.1 mrg 1141 1.1 mrg cell = isl_calloc_type(dom->ctx, isl_cell); 1142 1.1 mrg if (!cell) 1143 1.1 mrg goto error; 1144 1.1 mrg 1145 1.1 mrg cell->n_vertices = vertices->c[id].n_vertices; 1146 1.1 mrg cell->ids = isl_alloc_array(dom->ctx, int, cell->n_vertices); 1147 1.1 mrg if (cell->n_vertices && !cell->ids) 1148 1.1 mrg goto error; 1149 1.1 mrg for (i = 0; i < cell->n_vertices; ++i) 1150 1.1 mrg cell->ids[i] = vertices->c[id].vertices[i]; 1151 1.1 mrg cell->vertices = vertices; 1152 1.1 mrg cell->dom = dom; 1153 1.1 mrg 1154 1.1 mrg return cell; 1155 1.1 mrg error: 1156 1.1 mrg isl_cell_free(cell); 1157 1.1 mrg isl_vertices_free(vertices); 1158 1.1 mrg isl_basic_set_free(dom); 1159 1.1 mrg return NULL; 1160 1.1 mrg } 1161 1.1 mrg 1162 1.1 mrg __isl_null isl_cell *isl_cell_free(__isl_take isl_cell *cell) 1163 1.1 mrg { 1164 1.1 mrg if (!cell) 1165 1.1 mrg return NULL; 1166 1.1 mrg 1167 1.1 mrg isl_vertices_free(cell->vertices); 1168 1.1 mrg free(cell->ids); 1169 1.1 mrg isl_basic_set_free(cell->dom); 1170 1.1 mrg free(cell); 1171 1.1 mrg 1172 1.1 mrg return NULL; 1173 1.1 mrg } 1174 1.1 mrg 1175 1.1 mrg /* Create a tableau of the cone obtained by first homogenizing the given 1176 1.1 mrg * polytope and then making all inequalities strict by setting the 1177 1.1 mrg * constant term to -1. 1178 1.1 mrg */ 1179 1.1 mrg static struct isl_tab *tab_for_shifted_cone(__isl_keep isl_basic_set *bset) 1180 1.1 mrg { 1181 1.1 mrg int i; 1182 1.1 mrg isl_vec *c = NULL; 1183 1.1 mrg struct isl_tab *tab; 1184 1.1 mrg isl_size total; 1185 1.1 mrg 1186 1.1 mrg total = isl_basic_set_dim(bset, isl_dim_all); 1187 1.1 mrg if (total < 0) 1188 1.1 mrg return NULL; 1189 1.1 mrg tab = isl_tab_alloc(bset->ctx, bset->n_eq + bset->n_ineq + 1, 1190 1.1 mrg 1 + total, 0); 1191 1.1 mrg if (!tab) 1192 1.1 mrg return NULL; 1193 1.1 mrg tab->rational = ISL_F_ISSET(bset, ISL_BASIC_SET_RATIONAL); 1194 1.1 mrg if (ISL_F_ISSET(bset, ISL_BASIC_MAP_EMPTY)) { 1195 1.1 mrg if (isl_tab_mark_empty(tab) < 0) 1196 1.1 mrg goto error; 1197 1.1 mrg return tab; 1198 1.1 mrg } 1199 1.1 mrg 1200 1.1 mrg c = isl_vec_alloc(bset->ctx, 1 + 1 + total); 1201 1.1 mrg if (!c) 1202 1.1 mrg goto error; 1203 1.1 mrg 1204 1.1 mrg isl_int_set_si(c->el[0], 0); 1205 1.1 mrg for (i = 0; i < bset->n_eq; ++i) { 1206 1.1 mrg isl_seq_cpy(c->el + 1, bset->eq[i], c->size - 1); 1207 1.1 mrg if (isl_tab_add_eq(tab, c->el) < 0) 1208 1.1 mrg goto error; 1209 1.1 mrg } 1210 1.1 mrg 1211 1.1 mrg isl_int_set_si(c->el[0], -1); 1212 1.1 mrg for (i = 0; i < bset->n_ineq; ++i) { 1213 1.1 mrg isl_seq_cpy(c->el + 1, bset->ineq[i], c->size - 1); 1214 1.1 mrg if (isl_tab_add_ineq(tab, c->el) < 0) 1215 1.1 mrg goto error; 1216 1.1 mrg if (tab->empty) { 1217 1.1 mrg isl_vec_free(c); 1218 1.1 mrg return tab; 1219 1.1 mrg } 1220 1.1 mrg } 1221 1.1 mrg 1222 1.1 mrg isl_seq_clr(c->el + 1, c->size - 1); 1223 1.1 mrg isl_int_set_si(c->el[1], 1); 1224 1.1 mrg if (isl_tab_add_ineq(tab, c->el) < 0) 1225 1.1 mrg goto error; 1226 1.1 mrg 1227 1.1 mrg isl_vec_free(c); 1228 1.1 mrg return tab; 1229 1.1 mrg error: 1230 1.1 mrg isl_vec_free(c); 1231 1.1 mrg isl_tab_free(tab); 1232 1.1 mrg return NULL; 1233 1.1 mrg } 1234 1.1 mrg 1235 1.1 mrg /* Compute an interior point of "bset" by selecting an interior 1236 1.1 mrg * point in homogeneous space and projecting the point back down. 1237 1.1 mrg */ 1238 1.1 mrg static __isl_give isl_vec *isl_basic_set_interior_point( 1239 1.1 mrg __isl_keep isl_basic_set *bset) 1240 1.1 mrg { 1241 1.1 mrg isl_vec *vec; 1242 1.1 mrg struct isl_tab *tab; 1243 1.1 mrg 1244 1.1 mrg tab = tab_for_shifted_cone(bset); 1245 1.1 mrg vec = isl_tab_get_sample_value(tab); 1246 1.1 mrg isl_tab_free(tab); 1247 1.1 mrg if (!vec) 1248 1.1 mrg return NULL; 1249 1.1 mrg 1250 1.1 mrg isl_seq_cpy(vec->el, vec->el + 1, vec->size - 1); 1251 1.1 mrg vec->size--; 1252 1.1 mrg 1253 1.1 mrg return vec; 1254 1.1 mrg } 1255 1.1 mrg 1256 1.1 mrg /* Call "fn" on all chambers of the parametric polytope with the shared 1257 1.1 mrg * facets of neighboring chambers only appearing in one of the chambers. 1258 1.1 mrg * 1259 1.1 mrg * We pick an interior point from one of the chambers and then make 1260 1.1 mrg * all constraints that do not satisfy this point strict. 1261 1.1 mrg * For constraints that saturate the interior point, the sign 1262 1.1 mrg * of the first non-zero coefficient is used to determine which 1263 1.1 mrg * of the two (internal) constraints should be tightened. 1264 1.1 mrg */ 1265 1.1 mrg isl_stat isl_vertices_foreach_disjoint_cell(__isl_keep isl_vertices *vertices, 1266 1.1 mrg isl_stat (*fn)(__isl_take isl_cell *cell, void *user), void *user) 1267 1.1 mrg { 1268 1.1 mrg int i; 1269 1.1 mrg isl_vec *vec; 1270 1.1 mrg isl_cell *cell; 1271 1.1 mrg 1272 1.1 mrg if (!vertices) 1273 1.1 mrg return isl_stat_error; 1274 1.1 mrg 1275 1.1 mrg if (vertices->n_chambers == 0) 1276 1.1 mrg return isl_stat_ok; 1277 1.1 mrg 1278 1.1 mrg if (vertices->n_chambers == 1) { 1279 1.1 mrg isl_basic_set *dom = isl_basic_set_copy(vertices->c[0].dom); 1280 1.1 mrg dom = isl_basic_set_set_integral(dom); 1281 1.1 mrg cell = isl_cell_alloc(isl_vertices_copy(vertices), dom, 0); 1282 1.1 mrg if (!cell) 1283 1.1 mrg return isl_stat_error; 1284 1.1 mrg return fn(cell, user); 1285 1.1 mrg } 1286 1.1 mrg 1287 1.1 mrg vec = isl_basic_set_interior_point(vertices->c[0].dom); 1288 1.1 mrg if (!vec) 1289 1.1 mrg return isl_stat_error; 1290 1.1 mrg 1291 1.1 mrg for (i = 0; i < vertices->n_chambers; ++i) { 1292 1.1 mrg int r; 1293 1.1 mrg isl_basic_set *dom = isl_basic_set_copy(vertices->c[i].dom); 1294 1.1 mrg if (i) 1295 1.1 mrg dom = isl_basic_set_tighten_outward(dom, vec); 1296 1.1 mrg dom = isl_basic_set_set_integral(dom); 1297 1.1 mrg cell = isl_cell_alloc(isl_vertices_copy(vertices), dom, i); 1298 1.1 mrg if (!cell) 1299 1.1 mrg goto error; 1300 1.1 mrg r = fn(cell, user); 1301 1.1 mrg if (r < 0) 1302 1.1 mrg goto error; 1303 1.1 mrg } 1304 1.1 mrg 1305 1.1 mrg isl_vec_free(vec); 1306 1.1 mrg 1307 1.1 mrg return isl_stat_ok; 1308 1.1 mrg error: 1309 1.1 mrg isl_vec_free(vec); 1310 1.1 mrg return isl_stat_error; 1311 1.1 mrg } 1312 1.1 mrg 1313 1.1 mrg isl_stat isl_vertices_foreach_cell(__isl_keep isl_vertices *vertices, 1314 1.1 mrg isl_stat (*fn)(__isl_take isl_cell *cell, void *user), void *user) 1315 1.1 mrg { 1316 1.1 mrg int i; 1317 1.1 mrg isl_cell *cell; 1318 1.1 mrg 1319 1.1 mrg if (!vertices) 1320 1.1 mrg return isl_stat_error; 1321 1.1 mrg 1322 1.1 mrg if (vertices->n_chambers == 0) 1323 1.1 mrg return isl_stat_ok; 1324 1.1 mrg 1325 1.1 mrg for (i = 0; i < vertices->n_chambers; ++i) { 1326 1.1 mrg isl_stat r; 1327 1.1 mrg isl_basic_set *dom = isl_basic_set_copy(vertices->c[i].dom); 1328 1.1 mrg 1329 1.1 mrg cell = isl_cell_alloc(isl_vertices_copy(vertices), dom, i); 1330 1.1 mrg if (!cell) 1331 1.1 mrg return isl_stat_error; 1332 1.1 mrg 1333 1.1 mrg r = fn(cell, user); 1334 1.1 mrg if (r < 0) 1335 1.1 mrg return isl_stat_error; 1336 1.1 mrg } 1337 1.1 mrg 1338 1.1 mrg return isl_stat_ok; 1339 1.1 mrg } 1340 1.1 mrg 1341 1.1 mrg isl_stat isl_vertices_foreach_vertex(__isl_keep isl_vertices *vertices, 1342 1.1 mrg isl_stat (*fn)(__isl_take isl_vertex *vertex, void *user), void *user) 1343 1.1 mrg { 1344 1.1 mrg int i; 1345 1.1 mrg isl_vertex *vertex; 1346 1.1 mrg 1347 1.1 mrg if (!vertices) 1348 1.1 mrg return isl_stat_error; 1349 1.1 mrg 1350 1.1 mrg if (vertices->n_vertices == 0) 1351 1.1 mrg return isl_stat_ok; 1352 1.1 mrg 1353 1.1 mrg for (i = 0; i < vertices->n_vertices; ++i) { 1354 1.1 mrg isl_stat r; 1355 1.1 mrg 1356 1.1 mrg vertex = isl_vertex_alloc(isl_vertices_copy(vertices), i); 1357 1.1 mrg if (!vertex) 1358 1.1 mrg return isl_stat_error; 1359 1.1 mrg 1360 1.1 mrg r = fn(vertex, user); 1361 1.1 mrg if (r < 0) 1362 1.1 mrg return isl_stat_error; 1363 1.1 mrg } 1364 1.1 mrg 1365 1.1 mrg return isl_stat_ok; 1366 1.1 mrg } 1367 1.1 mrg 1368 1.1 mrg isl_stat isl_cell_foreach_vertex(__isl_keep isl_cell *cell, 1369 1.1 mrg isl_stat (*fn)(__isl_take isl_vertex *vertex, void *user), void *user) 1370 1.1 mrg { 1371 1.1 mrg int i; 1372 1.1 mrg isl_vertex *vertex; 1373 1.1 mrg 1374 1.1 mrg if (!cell) 1375 1.1 mrg return isl_stat_error; 1376 1.1 mrg 1377 1.1 mrg if (cell->n_vertices == 0) 1378 1.1 mrg return isl_stat_ok; 1379 1.1 mrg 1380 1.1 mrg for (i = 0; i < cell->n_vertices; ++i) { 1381 1.1 mrg isl_stat r; 1382 1.1 mrg 1383 1.1 mrg vertex = isl_vertex_alloc(isl_vertices_copy(cell->vertices), 1384 1.1 mrg cell->ids[i]); 1385 1.1 mrg if (!vertex) 1386 1.1 mrg return isl_stat_error; 1387 1.1 mrg 1388 1.1 mrg r = fn(vertex, user); 1389 1.1 mrg if (r < 0) 1390 1.1 mrg return isl_stat_error; 1391 1.1 mrg } 1392 1.1 mrg 1393 1.1 mrg return isl_stat_ok; 1394 1.1 mrg } 1395 1.1 mrg 1396 1.1 mrg isl_ctx *isl_vertices_get_ctx(__isl_keep isl_vertices *vertices) 1397 1.1 mrg { 1398 1.1 mrg return vertices ? vertices->bset->ctx : NULL; 1399 1.1 mrg } 1400 1.1 mrg 1401 1.1 mrg isl_size isl_vertices_get_n_vertices(__isl_keep isl_vertices *vertices) 1402 1.1 mrg { 1403 1.1 mrg return vertices ? vertices->n_vertices : isl_size_error; 1404 1.1 mrg } 1405 1.1 mrg 1406 1.1 mrg __isl_give isl_vertices *isl_morph_vertices(__isl_take isl_morph *morph, 1407 1.1 mrg __isl_take isl_vertices *vertices) 1408 1.1 mrg { 1409 1.1 mrg int i; 1410 1.1 mrg isl_morph *param_morph = NULL; 1411 1.1 mrg 1412 1.1 mrg if (!morph || !vertices) 1413 1.1 mrg goto error; 1414 1.1 mrg 1415 1.1 mrg isl_assert(vertices->bset->ctx, vertices->ref == 1, goto error); 1416 1.1 mrg 1417 1.1 mrg param_morph = isl_morph_copy(morph); 1418 1.1 mrg param_morph = isl_morph_dom_params(param_morph); 1419 1.1 mrg param_morph = isl_morph_ran_params(param_morph); 1420 1.1 mrg 1421 1.1 mrg for (i = 0; i < vertices->n_vertices; ++i) { 1422 1.1 mrg vertices->v[i].dom = isl_morph_basic_set( 1423 1.1 mrg isl_morph_copy(param_morph), vertices->v[i].dom); 1424 1.1 mrg vertices->v[i].vertex = isl_morph_basic_set( 1425 1.1 mrg isl_morph_copy(morph), vertices->v[i].vertex); 1426 1.1 mrg if (!vertices->v[i].vertex) 1427 1.1 mrg goto error; 1428 1.1 mrg } 1429 1.1 mrg 1430 1.1 mrg for (i = 0; i < vertices->n_chambers; ++i) { 1431 1.1 mrg vertices->c[i].dom = isl_morph_basic_set( 1432 1.1 mrg isl_morph_copy(param_morph), vertices->c[i].dom); 1433 1.1 mrg if (!vertices->c[i].dom) 1434 1.1 mrg goto error; 1435 1.1 mrg } 1436 1.1 mrg 1437 1.1 mrg isl_morph_free(param_morph); 1438 1.1 mrg isl_morph_free(morph); 1439 1.1 mrg return vertices; 1440 1.1 mrg error: 1441 1.1 mrg isl_morph_free(param_morph); 1442 1.1 mrg isl_morph_free(morph); 1443 1.1 mrg isl_vertices_free(vertices); 1444 1.1 mrg return NULL; 1445 1.1 mrg } 1446 1.1 mrg 1447 1.1 mrg /* Construct a simplex isl_cell spanned by the vertices with indices in 1448 1.1 mrg * "simplex_ids" and "other_ids" and call "fn" on this isl_cell. 1449 1.1 mrg */ 1450 1.1 mrg static isl_stat call_on_simplex(__isl_keep isl_cell *cell, 1451 1.1 mrg int *simplex_ids, int n_simplex, int *other_ids, int n_other, 1452 1.1 mrg isl_stat (*fn)(__isl_take isl_cell *simplex, void *user), void *user) 1453 1.1 mrg { 1454 1.1 mrg int i; 1455 1.1 mrg isl_ctx *ctx; 1456 1.1 mrg struct isl_cell *simplex; 1457 1.1 mrg 1458 1.1 mrg ctx = isl_cell_get_ctx(cell); 1459 1.1 mrg 1460 1.1 mrg simplex = isl_calloc_type(ctx, struct isl_cell); 1461 1.1 mrg if (!simplex) 1462 1.1 mrg return isl_stat_error; 1463 1.1 mrg simplex->vertices = isl_vertices_copy(cell->vertices); 1464 1.1 mrg if (!simplex->vertices) 1465 1.1 mrg goto error; 1466 1.1 mrg simplex->dom = isl_basic_set_copy(cell->dom); 1467 1.1 mrg if (!simplex->dom) 1468 1.1 mrg goto error; 1469 1.1 mrg simplex->n_vertices = n_simplex + n_other; 1470 1.1 mrg simplex->ids = isl_alloc_array(ctx, int, simplex->n_vertices); 1471 1.1 mrg if (!simplex->ids) 1472 1.1 mrg goto error; 1473 1.1 mrg 1474 1.1 mrg for (i = 0; i < n_simplex; ++i) 1475 1.1 mrg simplex->ids[i] = simplex_ids[i]; 1476 1.1 mrg for (i = 0; i < n_other; ++i) 1477 1.1 mrg simplex->ids[n_simplex + i] = other_ids[i]; 1478 1.1 mrg 1479 1.1 mrg return fn(simplex, user); 1480 1.1 mrg error: 1481 1.1 mrg isl_cell_free(simplex); 1482 1.1 mrg return isl_stat_error; 1483 1.1 mrg } 1484 1.1 mrg 1485 1.1 mrg /* Check whether the parametric vertex described by "vertex" 1486 1.1 mrg * lies on the facet corresponding to constraint "facet" of "bset". 1487 1.1 mrg * The isl_vec "v" is a temporary vector than can be used by this function. 1488 1.1 mrg * 1489 1.1 mrg * We eliminate the variables from the facet constraint using the 1490 1.1 mrg * equalities defining the vertex and check if the result is identical 1491 1.1 mrg * to zero. 1492 1.1 mrg * 1493 1.1 mrg * It would probably be better to keep track of the constraints defining 1494 1.1 mrg * a vertex during the vertex construction so that we could simply look 1495 1.1 mrg * it up here. 1496 1.1 mrg */ 1497 1.1 mrg static int vertex_on_facet(__isl_keep isl_basic_set *vertex, 1498 1.1 mrg __isl_keep isl_basic_set *bset, int facet, __isl_keep isl_vec *v) 1499 1.1 mrg { 1500 1.1 mrg int i; 1501 1.1 mrg isl_int m; 1502 1.1 mrg 1503 1.1 mrg isl_seq_cpy(v->el, bset->ineq[facet], v->size); 1504 1.1 mrg 1505 1.1 mrg isl_int_init(m); 1506 1.1 mrg for (i = 0; i < vertex->n_eq; ++i) { 1507 1.1 mrg int k = isl_seq_last_non_zero(vertex->eq[i], v->size); 1508 1.1 mrg isl_seq_elim(v->el, vertex->eq[i], k, v->size, &m); 1509 1.1 mrg } 1510 1.1 mrg isl_int_clear(m); 1511 1.1 mrg 1512 1.1 mrg return isl_seq_first_non_zero(v->el, v->size) == -1; 1513 1.1 mrg } 1514 1.1 mrg 1515 1.1 mrg /* Triangulate the polytope spanned by the vertices with ids 1516 1.1 mrg * in "simplex_ids" and "other_ids" and call "fn" on each of 1517 1.1 mrg * the resulting simplices. 1518 1.1 mrg * If the input polytope is already a simplex, we simply call "fn". 1519 1.1 mrg * Otherwise, we pick a point from "other_ids" and add it to "simplex_ids". 1520 1.1 mrg * Then we consider each facet of "bset" that does not contain the point 1521 1.1 mrg * we just picked, but does contain some of the other points in "other_ids" 1522 1.1 mrg * and call ourselves recursively on the polytope spanned by the new 1523 1.1 mrg * "simplex_ids" and those points in "other_ids" that lie on the facet. 1524 1.1 mrg */ 1525 1.1 mrg static isl_stat triangulate(__isl_keep isl_cell *cell, __isl_keep isl_vec *v, 1526 1.1 mrg int *simplex_ids, int n_simplex, int *other_ids, int n_other, 1527 1.1 mrg isl_stat (*fn)(__isl_take isl_cell *simplex, void *user), void *user) 1528 1.1 mrg { 1529 1.1 mrg int i, j, k; 1530 1.1 mrg isl_size d, nparam; 1531 1.1 mrg int *ids; 1532 1.1 mrg isl_ctx *ctx; 1533 1.1 mrg isl_basic_set *vertex; 1534 1.1 mrg isl_basic_set *bset; 1535 1.1 mrg 1536 1.1 mrg ctx = isl_cell_get_ctx(cell); 1537 1.1 mrg d = isl_basic_set_dim(cell->vertices->bset, isl_dim_set); 1538 1.1 mrg nparam = isl_basic_set_dim(cell->vertices->bset, isl_dim_param); 1539 1.1 mrg if (d < 0 || nparam < 0) 1540 1.1 mrg return isl_stat_error; 1541 1.1 mrg 1542 1.1 mrg if (n_simplex + n_other == d + 1) 1543 1.1 mrg return call_on_simplex(cell, simplex_ids, n_simplex, 1544 1.1 mrg other_ids, n_other, fn, user); 1545 1.1 mrg 1546 1.1 mrg simplex_ids[n_simplex] = other_ids[0]; 1547 1.1 mrg vertex = cell->vertices->v[other_ids[0]].vertex; 1548 1.1 mrg bset = cell->vertices->bset; 1549 1.1 mrg 1550 1.1 mrg ids = isl_alloc_array(ctx, int, n_other - 1); 1551 1.1 mrg if (!ids) 1552 1.1 mrg goto error; 1553 1.1 mrg for (i = 0; i < bset->n_ineq; ++i) { 1554 1.1 mrg if (isl_seq_first_non_zero(bset->ineq[i] + 1 + nparam, d) == -1) 1555 1.1 mrg continue; 1556 1.1 mrg if (vertex_on_facet(vertex, bset, i, v)) 1557 1.1 mrg continue; 1558 1.1 mrg 1559 1.1 mrg for (j = 1, k = 0; j < n_other; ++j) { 1560 1.1 mrg isl_basic_set *ov; 1561 1.1 mrg ov = cell->vertices->v[other_ids[j]].vertex; 1562 1.1 mrg if (vertex_on_facet(ov, bset, i, v)) 1563 1.1 mrg ids[k++] = other_ids[j]; 1564 1.1 mrg } 1565 1.1 mrg if (k == 0) 1566 1.1 mrg continue; 1567 1.1 mrg 1568 1.1 mrg if (triangulate(cell, v, simplex_ids, n_simplex + 1, 1569 1.1 mrg ids, k, fn, user) < 0) 1570 1.1 mrg goto error; 1571 1.1 mrg } 1572 1.1 mrg free(ids); 1573 1.1 mrg 1574 1.1 mrg return isl_stat_ok; 1575 1.1 mrg error: 1576 1.1 mrg free(ids); 1577 1.1 mrg return isl_stat_error; 1578 1.1 mrg } 1579 1.1 mrg 1580 1.1 mrg /* Triangulate the given cell and call "fn" on each of the resulting 1581 1.1 mrg * simplices. 1582 1.1 mrg */ 1583 1.1 mrg isl_stat isl_cell_foreach_simplex(__isl_take isl_cell *cell, 1584 1.1 mrg isl_stat (*fn)(__isl_take isl_cell *simplex, void *user), void *user) 1585 1.1 mrg { 1586 1.1 mrg isl_size d, total; 1587 1.1 mrg isl_stat r; 1588 1.1 mrg isl_ctx *ctx; 1589 1.1 mrg isl_vec *v = NULL; 1590 1.1 mrg int *simplex_ids = NULL; 1591 1.1 mrg 1592 1.1 mrg if (!cell) 1593 1.1 mrg return isl_stat_error; 1594 1.1 mrg 1595 1.1 mrg d = isl_basic_set_dim(cell->vertices->bset, isl_dim_set); 1596 1.1 mrg total = isl_basic_set_dim(cell->vertices->bset, isl_dim_all); 1597 1.1 mrg if (d < 0 || total < 0) 1598 1.1 mrg return isl_stat_error; 1599 1.1 mrg 1600 1.1 mrg if (cell->n_vertices == d + 1) 1601 1.1 mrg return fn(cell, user); 1602 1.1 mrg 1603 1.1 mrg ctx = isl_cell_get_ctx(cell); 1604 1.1 mrg simplex_ids = isl_alloc_array(ctx, int, d + 1); 1605 1.1 mrg if (!simplex_ids) 1606 1.1 mrg goto error; 1607 1.1 mrg 1608 1.1 mrg v = isl_vec_alloc(ctx, 1 + total); 1609 1.1 mrg if (!v) 1610 1.1 mrg goto error; 1611 1.1 mrg 1612 1.1 mrg r = triangulate(cell, v, simplex_ids, 0, 1613 1.1 mrg cell->ids, cell->n_vertices, fn, user); 1614 1.1 mrg 1615 1.1 mrg isl_vec_free(v); 1616 1.1 mrg free(simplex_ids); 1617 1.1 mrg 1618 1.1 mrg isl_cell_free(cell); 1619 1.1 mrg 1620 1.1 mrg return r; 1621 1.1 mrg error: 1622 1.1 mrg free(simplex_ids); 1623 1.1 mrg isl_vec_free(v); 1624 1.1 mrg isl_cell_free(cell); 1625 1.1 mrg return isl_stat_error; 1626 1.1 mrg } 1627