1 1.1 mrg /* 2 1.1 mrg * Copyright 2008-2009 Katholieke Universiteit Leuven 3 1.1 mrg * Copyright 2010 INRIA Saclay 4 1.1 mrg * 5 1.1 mrg * Use of this software is governed by the MIT license 6 1.1 mrg * 7 1.1 mrg * Written by Sven Verdoolaege, K.U.Leuven, Departement 8 1.1 mrg * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium 9 1.1 mrg * and INRIA Saclay - Ile-de-France, Parc Club Orsay Universite, 10 1.1 mrg * ZAC des vignes, 4 rue Jacques Monod, 91893 Orsay, France 11 1.1 mrg */ 12 1.1 mrg 13 1.1 mrg #include <isl_map_private.h> 14 1.1 mrg #include <isl_constraint_private.h> 15 1.1 mrg #include <isl_space_private.h> 16 1.1 mrg #include <isl_seq.h> 17 1.1 mrg #include <isl_aff_private.h> 18 1.1 mrg #include <isl_local_space_private.h> 19 1.1 mrg #include <isl_val_private.h> 20 1.1 mrg #include <isl_vec_private.h> 21 1.1 mrg 22 1.1 mrg #include <bset_to_bmap.c> 23 1.1 mrg #include <bset_from_bmap.c> 24 1.1 mrg 25 1.1 mrg #undef EL_BASE 26 1.1 mrg #define EL_BASE constraint 27 1.1 mrg 28 1.1 mrg #include <isl_list_templ.c> 29 1.1 mrg 30 1.1 mrg isl_ctx *isl_constraint_get_ctx(__isl_keep isl_constraint *c) 31 1.1 mrg { 32 1.1 mrg return c ? isl_local_space_get_ctx(c->ls) : NULL; 33 1.1 mrg } 34 1.1 mrg 35 1.1 mrg static isl_size n(__isl_keep isl_constraint *c, enum isl_dim_type type) 36 1.1 mrg { 37 1.1 mrg return isl_local_space_dim(c->ls, type); 38 1.1 mrg } 39 1.1 mrg 40 1.1 mrg static unsigned offset(__isl_keep isl_constraint *c, enum isl_dim_type type) 41 1.1 mrg { 42 1.1 mrg return isl_local_space_offset(c->ls, type); 43 1.1 mrg } 44 1.1 mrg 45 1.1 mrg __isl_give isl_constraint *isl_constraint_alloc_vec(int eq, 46 1.1 mrg __isl_take isl_local_space *ls, __isl_take isl_vec *v) 47 1.1 mrg { 48 1.1 mrg isl_constraint *constraint; 49 1.1 mrg 50 1.1 mrg if (!ls || !v) 51 1.1 mrg goto error; 52 1.1 mrg 53 1.1 mrg constraint = isl_alloc_type(isl_vec_get_ctx(v), isl_constraint); 54 1.1 mrg if (!constraint) 55 1.1 mrg goto error; 56 1.1 mrg 57 1.1 mrg constraint->ref = 1; 58 1.1 mrg constraint->eq = eq; 59 1.1 mrg constraint->ls = ls; 60 1.1 mrg constraint->v = v; 61 1.1 mrg 62 1.1 mrg return constraint; 63 1.1 mrg error: 64 1.1 mrg isl_local_space_free(ls); 65 1.1 mrg isl_vec_free(v); 66 1.1 mrg return NULL; 67 1.1 mrg } 68 1.1 mrg 69 1.1 mrg __isl_give isl_constraint *isl_constraint_alloc(int eq, 70 1.1 mrg __isl_take isl_local_space *ls) 71 1.1 mrg { 72 1.1 mrg isl_size dim; 73 1.1 mrg isl_ctx *ctx; 74 1.1 mrg isl_vec *v; 75 1.1 mrg 76 1.1 mrg dim = isl_local_space_dim(ls, isl_dim_all); 77 1.1 mrg if (dim < 0) 78 1.1 mrg ls = isl_local_space_free(ls); 79 1.1 mrg if (!ls) 80 1.1 mrg return NULL; 81 1.1 mrg 82 1.1 mrg ctx = isl_local_space_get_ctx(ls); 83 1.1 mrg v = isl_vec_alloc(ctx, 1 + dim); 84 1.1 mrg v = isl_vec_clr(v); 85 1.1 mrg return isl_constraint_alloc_vec(eq, ls, v); 86 1.1 mrg } 87 1.1 mrg 88 1.1 mrg __isl_give isl_constraint *isl_basic_map_constraint( 89 1.1 mrg __isl_take isl_basic_map *bmap, isl_int **line) 90 1.1 mrg { 91 1.1 mrg int eq; 92 1.1 mrg isl_size dim; 93 1.1 mrg isl_ctx *ctx; 94 1.1 mrg isl_vec *v; 95 1.1 mrg isl_local_space *ls = NULL; 96 1.1 mrg isl_constraint *constraint; 97 1.1 mrg 98 1.1 mrg if (!bmap || !line) 99 1.1 mrg goto error; 100 1.1 mrg 101 1.1 mrg eq = line >= bmap->eq; 102 1.1 mrg 103 1.1 mrg ctx = isl_basic_map_get_ctx(bmap); 104 1.1 mrg ls = isl_basic_map_get_local_space(bmap); 105 1.1 mrg dim = isl_local_space_dim(ls, isl_dim_all); 106 1.1 mrg if (dim < 0) 107 1.1 mrg goto error; 108 1.1 mrg v = isl_vec_alloc(ctx, 1 + dim); 109 1.1 mrg if (!v) 110 1.1 mrg goto error; 111 1.1 mrg isl_seq_cpy(v->el, line[0], v->size); 112 1.1 mrg constraint = isl_constraint_alloc_vec(eq, ls, v); 113 1.1 mrg 114 1.1 mrg isl_basic_map_free(bmap); 115 1.1 mrg return constraint; 116 1.1 mrg error: 117 1.1 mrg isl_local_space_free(ls); 118 1.1 mrg isl_basic_map_free(bmap); 119 1.1 mrg return NULL; 120 1.1 mrg } 121 1.1 mrg 122 1.1 mrg __isl_give isl_constraint *isl_basic_set_constraint( 123 1.1 mrg __isl_take isl_basic_set *bset, isl_int **line) 124 1.1 mrg { 125 1.1 mrg return isl_basic_map_constraint(bset_to_bmap(bset), line); 126 1.1 mrg } 127 1.1 mrg 128 1.1 mrg __isl_give isl_constraint *isl_constraint_alloc_equality( 129 1.1 mrg __isl_take isl_local_space *ls) 130 1.1 mrg { 131 1.1 mrg return isl_constraint_alloc(1, ls); 132 1.1 mrg } 133 1.1 mrg 134 1.1 mrg __isl_give isl_constraint *isl_constraint_alloc_inequality( 135 1.1 mrg __isl_take isl_local_space *ls) 136 1.1 mrg { 137 1.1 mrg return isl_constraint_alloc(0, ls); 138 1.1 mrg } 139 1.1 mrg 140 1.1 mrg __isl_give isl_constraint *isl_constraint_dup(__isl_keep isl_constraint *c) 141 1.1 mrg { 142 1.1 mrg if (!c) 143 1.1 mrg return NULL; 144 1.1 mrg 145 1.1 mrg return isl_constraint_alloc_vec(c->eq, isl_local_space_copy(c->ls), 146 1.1 mrg isl_vec_copy(c->v)); 147 1.1 mrg } 148 1.1 mrg 149 1.1 mrg __isl_give isl_constraint *isl_constraint_cow(__isl_take isl_constraint *c) 150 1.1 mrg { 151 1.1 mrg if (!c) 152 1.1 mrg return NULL; 153 1.1 mrg 154 1.1 mrg if (c->ref == 1) 155 1.1 mrg return c; 156 1.1 mrg c->ref--; 157 1.1 mrg return isl_constraint_dup(c); 158 1.1 mrg } 159 1.1 mrg 160 1.1 mrg __isl_give isl_constraint *isl_constraint_copy( 161 1.1 mrg __isl_keep isl_constraint *constraint) 162 1.1 mrg { 163 1.1 mrg if (!constraint) 164 1.1 mrg return NULL; 165 1.1 mrg 166 1.1 mrg constraint->ref++; 167 1.1 mrg return constraint; 168 1.1 mrg } 169 1.1 mrg 170 1.1 mrg __isl_null isl_constraint *isl_constraint_free(__isl_take isl_constraint *c) 171 1.1 mrg { 172 1.1 mrg if (!c) 173 1.1 mrg return NULL; 174 1.1 mrg 175 1.1 mrg if (--c->ref > 0) 176 1.1 mrg return NULL; 177 1.1 mrg 178 1.1 mrg isl_local_space_free(c->ls); 179 1.1 mrg isl_vec_free(c->v); 180 1.1 mrg free(c); 181 1.1 mrg 182 1.1 mrg return NULL; 183 1.1 mrg } 184 1.1 mrg 185 1.1 mrg /* Return the number of constraints in "bmap", i.e., the 186 1.1 mrg * number of times isl_basic_map_foreach_constraint will 187 1.1 mrg * call the callback. 188 1.1 mrg */ 189 1.1 mrg isl_size isl_basic_map_n_constraint(__isl_keep isl_basic_map *bmap) 190 1.1 mrg { 191 1.1 mrg if (!bmap) 192 1.1 mrg return isl_size_error; 193 1.1 mrg 194 1.1 mrg return bmap->n_eq + bmap->n_ineq; 195 1.1 mrg } 196 1.1 mrg 197 1.1 mrg /* Return the number of constraints in "bset", i.e., the 198 1.1 mrg * number of times isl_basic_set_foreach_constraint will 199 1.1 mrg * call the callback. 200 1.1 mrg */ 201 1.1 mrg isl_size isl_basic_set_n_constraint(__isl_keep isl_basic_set *bset) 202 1.1 mrg { 203 1.1 mrg return isl_basic_map_n_constraint(bset); 204 1.1 mrg } 205 1.1 mrg 206 1.1 mrg isl_stat isl_basic_map_foreach_constraint(__isl_keep isl_basic_map *bmap, 207 1.1 mrg isl_stat (*fn)(__isl_take isl_constraint *c, void *user), void *user) 208 1.1 mrg { 209 1.1 mrg int i; 210 1.1 mrg struct isl_constraint *c; 211 1.1 mrg 212 1.1 mrg if (!bmap) 213 1.1 mrg return isl_stat_error; 214 1.1 mrg 215 1.1 mrg isl_assert(bmap->ctx, ISL_F_ISSET(bmap, ISL_BASIC_MAP_FINAL), 216 1.1 mrg return isl_stat_error); 217 1.1 mrg 218 1.1 mrg for (i = 0; i < bmap->n_eq; ++i) { 219 1.1 mrg c = isl_basic_map_constraint(isl_basic_map_copy(bmap), 220 1.1 mrg &bmap->eq[i]); 221 1.1 mrg if (!c) 222 1.1 mrg return isl_stat_error; 223 1.1 mrg if (fn(c, user) < 0) 224 1.1 mrg return isl_stat_error; 225 1.1 mrg } 226 1.1 mrg 227 1.1 mrg for (i = 0; i < bmap->n_ineq; ++i) { 228 1.1 mrg c = isl_basic_map_constraint(isl_basic_map_copy(bmap), 229 1.1 mrg &bmap->ineq[i]); 230 1.1 mrg if (!c) 231 1.1 mrg return isl_stat_error; 232 1.1 mrg if (fn(c, user) < 0) 233 1.1 mrg return isl_stat_error; 234 1.1 mrg } 235 1.1 mrg 236 1.1 mrg return isl_stat_ok; 237 1.1 mrg } 238 1.1 mrg 239 1.1 mrg isl_stat isl_basic_set_foreach_constraint(__isl_keep isl_basic_set *bset, 240 1.1 mrg isl_stat (*fn)(__isl_take isl_constraint *c, void *user), void *user) 241 1.1 mrg { 242 1.1 mrg return isl_basic_map_foreach_constraint(bset_to_bmap(bset), fn, user); 243 1.1 mrg } 244 1.1 mrg 245 1.1 mrg /* Add the constraint to the list that "user" points to, if it is not 246 1.1 mrg * a div constraint. 247 1.1 mrg */ 248 1.1 mrg static isl_stat collect_constraint(__isl_take isl_constraint *constraint, 249 1.1 mrg void *user) 250 1.1 mrg { 251 1.1 mrg isl_constraint_list **list = user; 252 1.1 mrg isl_bool is_div; 253 1.1 mrg 254 1.1 mrg is_div = isl_constraint_is_div_constraint(constraint); 255 1.1 mrg if (is_div < 0 || is_div) 256 1.1 mrg isl_constraint_free(constraint); 257 1.1 mrg else 258 1.1 mrg *list = isl_constraint_list_add(*list, constraint); 259 1.1 mrg 260 1.1 mrg return is_div < 0 ? isl_stat_error : isl_stat_ok; 261 1.1 mrg } 262 1.1 mrg 263 1.1 mrg /* Return a list of constraints that, when combined, are equivalent 264 1.1 mrg * to "bmap". The input is required to have only known divs. 265 1.1 mrg * 266 1.1 mrg * There is no need to include the div constraints as they are 267 1.1 mrg * implied by the div expressions. 268 1.1 mrg */ 269 1.1 mrg __isl_give isl_constraint_list *isl_basic_map_get_constraint_list( 270 1.1 mrg __isl_keep isl_basic_map *bmap) 271 1.1 mrg { 272 1.1 mrg isl_size n; 273 1.1 mrg isl_bool known; 274 1.1 mrg isl_ctx *ctx; 275 1.1 mrg isl_constraint_list *list; 276 1.1 mrg 277 1.1 mrg known = isl_basic_map_divs_known(bmap); 278 1.1 mrg if (known < 0) 279 1.1 mrg return NULL; 280 1.1 mrg ctx = isl_basic_map_get_ctx(bmap); 281 1.1 mrg if (!known) 282 1.1 mrg isl_die(ctx, isl_error_invalid, 283 1.1 mrg "input involves unknown divs", return NULL); 284 1.1 mrg 285 1.1 mrg n = isl_basic_map_n_constraint(bmap); 286 1.1 mrg if (n < 0) 287 1.1 mrg return NULL; 288 1.1 mrg list = isl_constraint_list_alloc(ctx, n); 289 1.1 mrg if (isl_basic_map_foreach_constraint(bmap, 290 1.1 mrg &collect_constraint, &list) < 0) 291 1.1 mrg list = isl_constraint_list_free(list); 292 1.1 mrg 293 1.1 mrg return list; 294 1.1 mrg } 295 1.1 mrg 296 1.1 mrg /* Return a list of constraints that, when combined, are equivalent 297 1.1 mrg * to "bset". The input is required to have only known divs. 298 1.1 mrg */ 299 1.1 mrg __isl_give isl_constraint_list *isl_basic_set_get_constraint_list( 300 1.1 mrg __isl_keep isl_basic_set *bset) 301 1.1 mrg { 302 1.1 mrg return isl_basic_map_get_constraint_list(bset); 303 1.1 mrg } 304 1.1 mrg 305 1.1 mrg int isl_constraint_is_equal(__isl_keep isl_constraint *constraint1, 306 1.1 mrg __isl_keep isl_constraint *constraint2) 307 1.1 mrg { 308 1.1 mrg int equal; 309 1.1 mrg 310 1.1 mrg if (!constraint1 || !constraint2) 311 1.1 mrg return 0; 312 1.1 mrg if (constraint1->eq != constraint2->eq) 313 1.1 mrg return 0; 314 1.1 mrg equal = isl_local_space_is_equal(constraint1->ls, constraint2->ls); 315 1.1 mrg if (equal < 0 || !equal) 316 1.1 mrg return equal; 317 1.1 mrg return isl_vec_is_equal(constraint1->v, constraint2->v); 318 1.1 mrg } 319 1.1 mrg 320 1.1 mrg __isl_give isl_basic_map *isl_basic_map_add_constraint( 321 1.1 mrg __isl_take isl_basic_map *bmap, __isl_take isl_constraint *constraint) 322 1.1 mrg { 323 1.1 mrg isl_ctx *ctx; 324 1.1 mrg isl_space *space; 325 1.1 mrg int equal_space; 326 1.1 mrg 327 1.1 mrg if (!bmap || !constraint) 328 1.1 mrg goto error; 329 1.1 mrg 330 1.1 mrg ctx = isl_constraint_get_ctx(constraint); 331 1.1 mrg space = isl_constraint_get_space(constraint); 332 1.1 mrg equal_space = isl_space_is_equal(bmap->dim, space); 333 1.1 mrg isl_space_free(space); 334 1.1 mrg isl_assert(ctx, equal_space, goto error); 335 1.1 mrg 336 1.1 mrg bmap = isl_basic_map_intersect(bmap, 337 1.1 mrg isl_basic_map_from_constraint(constraint)); 338 1.1 mrg return bmap; 339 1.1 mrg error: 340 1.1 mrg isl_basic_map_free(bmap); 341 1.1 mrg isl_constraint_free(constraint); 342 1.1 mrg return NULL; 343 1.1 mrg } 344 1.1 mrg 345 1.1 mrg __isl_give isl_basic_set *isl_basic_set_add_constraint( 346 1.1 mrg __isl_take isl_basic_set *bset, __isl_take isl_constraint *constraint) 347 1.1 mrg { 348 1.1 mrg return bset_from_bmap(isl_basic_map_add_constraint(bset_to_bmap(bset), 349 1.1 mrg constraint)); 350 1.1 mrg } 351 1.1 mrg 352 1.1 mrg __isl_give isl_map *isl_map_add_constraint(__isl_take isl_map *map, 353 1.1 mrg __isl_take isl_constraint *constraint) 354 1.1 mrg { 355 1.1 mrg isl_basic_map *bmap; 356 1.1 mrg 357 1.1 mrg bmap = isl_basic_map_from_constraint(constraint); 358 1.1 mrg map = isl_map_intersect(map, isl_map_from_basic_map(bmap)); 359 1.1 mrg 360 1.1 mrg return map; 361 1.1 mrg } 362 1.1 mrg 363 1.1 mrg __isl_give isl_set *isl_set_add_constraint(__isl_take isl_set *set, 364 1.1 mrg __isl_take isl_constraint *constraint) 365 1.1 mrg { 366 1.1 mrg return isl_map_add_constraint(set, constraint); 367 1.1 mrg } 368 1.1 mrg 369 1.1 mrg /* Return the space of "constraint". 370 1.1 mrg */ 371 1.1 mrg static __isl_keep isl_space *isl_constraint_peek_space( 372 1.1 mrg __isl_keep isl_constraint *constraint) 373 1.1 mrg { 374 1.1 mrg return constraint ? isl_local_space_peek_space(constraint->ls) : NULL; 375 1.1 mrg } 376 1.1 mrg 377 1.1 mrg __isl_give isl_space *isl_constraint_get_space( 378 1.1 mrg __isl_keep isl_constraint *constraint) 379 1.1 mrg { 380 1.1 mrg return constraint ? isl_local_space_get_space(constraint->ls) : NULL; 381 1.1 mrg } 382 1.1 mrg 383 1.1 mrg __isl_give isl_local_space *isl_constraint_get_local_space( 384 1.1 mrg __isl_keep isl_constraint *constraint) 385 1.1 mrg { 386 1.1 mrg return constraint ? isl_local_space_copy(constraint->ls) : NULL; 387 1.1 mrg } 388 1.1 mrg 389 1.1 mrg isl_size isl_constraint_dim(__isl_keep isl_constraint *constraint, 390 1.1 mrg enum isl_dim_type type) 391 1.1 mrg { 392 1.1 mrg if (!constraint) 393 1.1 mrg return isl_size_error; 394 1.1 mrg return n(constraint, type); 395 1.1 mrg } 396 1.1 mrg 397 1.1 mrg #undef TYPE 398 1.1 mrg #define TYPE isl_constraint 399 1.1 mrg static 400 1.1 mrg #include "check_type_range_templ.c" 401 1.1 mrg 402 1.1 mrg isl_bool isl_constraint_involves_dims(__isl_keep isl_constraint *constraint, 403 1.1 mrg enum isl_dim_type type, unsigned first, unsigned n) 404 1.1 mrg { 405 1.1 mrg int i; 406 1.1 mrg int *active = NULL; 407 1.1 mrg isl_bool involves = isl_bool_false; 408 1.1 mrg 409 1.1 mrg if (!constraint) 410 1.1 mrg return isl_bool_error; 411 1.1 mrg if (n == 0) 412 1.1 mrg return isl_bool_false; 413 1.1 mrg 414 1.1 mrg if (isl_constraint_check_range(constraint, type, first, n) < 0) 415 1.1 mrg return isl_bool_error; 416 1.1 mrg 417 1.1 mrg active = isl_local_space_get_active(constraint->ls, 418 1.1 mrg constraint->v->el + 1); 419 1.1 mrg if (!active) 420 1.1 mrg goto error; 421 1.1 mrg 422 1.1 mrg first += isl_local_space_offset(constraint->ls, type) - 1; 423 1.1 mrg for (i = 0; i < n; ++i) 424 1.1 mrg if (active[first + i]) { 425 1.1 mrg involves = isl_bool_true; 426 1.1 mrg break; 427 1.1 mrg } 428 1.1 mrg 429 1.1 mrg free(active); 430 1.1 mrg 431 1.1 mrg return involves; 432 1.1 mrg error: 433 1.1 mrg free(active); 434 1.1 mrg return isl_bool_error; 435 1.1 mrg } 436 1.1 mrg 437 1.1 mrg /* Does the given constraint represent a lower bound on the given 438 1.1 mrg * dimension? 439 1.1 mrg */ 440 1.1 mrg isl_bool isl_constraint_is_lower_bound(__isl_keep isl_constraint *constraint, 441 1.1 mrg enum isl_dim_type type, unsigned pos) 442 1.1 mrg { 443 1.1 mrg if (isl_constraint_check_range(constraint, type, pos, 1) < 0) 444 1.1 mrg return isl_bool_error; 445 1.1 mrg 446 1.1 mrg pos += isl_local_space_offset(constraint->ls, type); 447 1.1 mrg return isl_bool_ok(isl_int_is_pos(constraint->v->el[pos])); 448 1.1 mrg } 449 1.1 mrg 450 1.1 mrg /* Does the given constraint represent an upper bound on the given 451 1.1 mrg * dimension? 452 1.1 mrg */ 453 1.1 mrg isl_bool isl_constraint_is_upper_bound(__isl_keep isl_constraint *constraint, 454 1.1 mrg enum isl_dim_type type, unsigned pos) 455 1.1 mrg { 456 1.1 mrg if (isl_constraint_check_range(constraint, type, pos, 1) < 0) 457 1.1 mrg return isl_bool_error; 458 1.1 mrg 459 1.1 mrg pos += isl_local_space_offset(constraint->ls, type); 460 1.1 mrg return isl_bool_ok(isl_int_is_neg(constraint->v->el[pos])); 461 1.1 mrg } 462 1.1 mrg 463 1.1 mrg const char *isl_constraint_get_dim_name(__isl_keep isl_constraint *constraint, 464 1.1 mrg enum isl_dim_type type, unsigned pos) 465 1.1 mrg { 466 1.1 mrg return constraint ? 467 1.1 mrg isl_local_space_get_dim_name(constraint->ls, type, pos) : NULL; 468 1.1 mrg } 469 1.1 mrg 470 1.1 mrg void isl_constraint_get_constant(__isl_keep isl_constraint *constraint, 471 1.1 mrg isl_int *v) 472 1.1 mrg { 473 1.1 mrg if (!constraint) 474 1.1 mrg return; 475 1.1 mrg isl_int_set(*v, constraint->v->el[0]); 476 1.1 mrg } 477 1.1 mrg 478 1.1 mrg /* Return the constant term of "constraint". 479 1.1 mrg */ 480 1.1 mrg __isl_give isl_val *isl_constraint_get_constant_val( 481 1.1 mrg __isl_keep isl_constraint *constraint) 482 1.1 mrg { 483 1.1 mrg isl_ctx *ctx; 484 1.1 mrg 485 1.1 mrg if (!constraint) 486 1.1 mrg return NULL; 487 1.1 mrg 488 1.1 mrg ctx = isl_constraint_get_ctx(constraint); 489 1.1 mrg return isl_val_int_from_isl_int(ctx, constraint->v->el[0]); 490 1.1 mrg } 491 1.1 mrg 492 1.1 mrg void isl_constraint_get_coefficient(__isl_keep isl_constraint *constraint, 493 1.1 mrg enum isl_dim_type type, int pos, isl_int *v) 494 1.1 mrg { 495 1.1 mrg if (isl_constraint_check_range(constraint, type, pos, 1) < 0) 496 1.1 mrg return; 497 1.1 mrg 498 1.1 mrg pos += isl_local_space_offset(constraint->ls, type); 499 1.1 mrg isl_int_set(*v, constraint->v->el[pos]); 500 1.1 mrg } 501 1.1 mrg 502 1.1 mrg /* Return the coefficient of the variable of type "type" at position "pos" 503 1.1 mrg * of "constraint". 504 1.1 mrg */ 505 1.1 mrg __isl_give isl_val *isl_constraint_get_coefficient_val( 506 1.1 mrg __isl_keep isl_constraint *constraint, enum isl_dim_type type, int pos) 507 1.1 mrg { 508 1.1 mrg isl_ctx *ctx; 509 1.1 mrg 510 1.1 mrg if (isl_constraint_check_range(constraint, type, pos, 1) < 0) 511 1.1 mrg return NULL; 512 1.1 mrg 513 1.1 mrg ctx = isl_constraint_get_ctx(constraint); 514 1.1 mrg pos += isl_local_space_offset(constraint->ls, type); 515 1.1 mrg return isl_val_int_from_isl_int(ctx, constraint->v->el[pos]); 516 1.1 mrg } 517 1.1 mrg 518 1.1 mrg __isl_give isl_aff *isl_constraint_get_div(__isl_keep isl_constraint *constraint, 519 1.1 mrg int pos) 520 1.1 mrg { 521 1.1 mrg if (!constraint) 522 1.1 mrg return NULL; 523 1.1 mrg 524 1.1 mrg return isl_local_space_get_div(constraint->ls, pos); 525 1.1 mrg } 526 1.1 mrg 527 1.1 mrg __isl_give isl_constraint *isl_constraint_set_constant( 528 1.1 mrg __isl_take isl_constraint *constraint, isl_int v) 529 1.1 mrg { 530 1.1 mrg constraint = isl_constraint_cow(constraint); 531 1.1 mrg if (!constraint) 532 1.1 mrg return NULL; 533 1.1 mrg 534 1.1 mrg constraint->v = isl_vec_cow(constraint->v); 535 1.1 mrg if (!constraint->v) 536 1.1 mrg return isl_constraint_free(constraint); 537 1.1 mrg 538 1.1 mrg isl_int_set(constraint->v->el[0], v); 539 1.1 mrg return constraint; 540 1.1 mrg } 541 1.1 mrg 542 1.1 mrg /* Replace the constant term of "constraint" by "v". 543 1.1 mrg */ 544 1.1 mrg __isl_give isl_constraint *isl_constraint_set_constant_val( 545 1.1 mrg __isl_take isl_constraint *constraint, __isl_take isl_val *v) 546 1.1 mrg { 547 1.1 mrg constraint = isl_constraint_cow(constraint); 548 1.1 mrg if (!constraint || !v) 549 1.1 mrg goto error; 550 1.1 mrg if (!isl_val_is_int(v)) 551 1.1 mrg isl_die(isl_constraint_get_ctx(constraint), isl_error_invalid, 552 1.1 mrg "expecting integer value", goto error); 553 1.1 mrg constraint->v = isl_vec_set_element_val(constraint->v, 0, v); 554 1.1 mrg if (!constraint->v) 555 1.1 mrg constraint = isl_constraint_free(constraint); 556 1.1 mrg return constraint; 557 1.1 mrg error: 558 1.1 mrg isl_val_free(v); 559 1.1 mrg return isl_constraint_free(constraint); 560 1.1 mrg } 561 1.1 mrg 562 1.1 mrg __isl_give isl_constraint *isl_constraint_set_constant_si( 563 1.1 mrg __isl_take isl_constraint *constraint, int v) 564 1.1 mrg { 565 1.1 mrg constraint = isl_constraint_cow(constraint); 566 1.1 mrg if (!constraint) 567 1.1 mrg return NULL; 568 1.1 mrg 569 1.1 mrg constraint->v = isl_vec_cow(constraint->v); 570 1.1 mrg if (!constraint->v) 571 1.1 mrg return isl_constraint_free(constraint); 572 1.1 mrg 573 1.1 mrg isl_int_set_si(constraint->v->el[0], v); 574 1.1 mrg return constraint; 575 1.1 mrg } 576 1.1 mrg 577 1.1 mrg /* Replace the coefficient of the variable of type "type" at position "pos" 578 1.1 mrg * of "constraint" by "v". 579 1.1 mrg */ 580 1.1 mrg __isl_give isl_constraint *isl_constraint_set_coefficient_val( 581 1.1 mrg __isl_take isl_constraint *constraint, 582 1.1 mrg enum isl_dim_type type, int pos, __isl_take isl_val *v) 583 1.1 mrg { 584 1.1 mrg constraint = isl_constraint_cow(constraint); 585 1.1 mrg if (!constraint || !v) 586 1.1 mrg goto error; 587 1.1 mrg if (!isl_val_is_int(v)) 588 1.1 mrg isl_die(isl_constraint_get_ctx(constraint), isl_error_invalid, 589 1.1 mrg "expecting integer value", goto error); 590 1.1 mrg if (isl_constraint_check_range(constraint, type, pos, 1) < 0) 591 1.1 mrg goto error; 592 1.1 mrg 593 1.1 mrg pos += isl_local_space_offset(constraint->ls, type); 594 1.1 mrg constraint->v = isl_vec_set_element_val(constraint->v, pos, v); 595 1.1 mrg if (!constraint->v) 596 1.1 mrg constraint = isl_constraint_free(constraint); 597 1.1 mrg return constraint; 598 1.1 mrg error: 599 1.1 mrg isl_val_free(v); 600 1.1 mrg return isl_constraint_free(constraint); 601 1.1 mrg } 602 1.1 mrg 603 1.1 mrg __isl_give isl_constraint *isl_constraint_set_coefficient_si( 604 1.1 mrg __isl_take isl_constraint *constraint, 605 1.1 mrg enum isl_dim_type type, int pos, int v) 606 1.1 mrg { 607 1.1 mrg constraint = isl_constraint_cow(constraint); 608 1.1 mrg if (isl_constraint_check_range(constraint, type, pos, 1) < 0) 609 1.1 mrg return isl_constraint_free(constraint); 610 1.1 mrg 611 1.1 mrg constraint->v = isl_vec_cow(constraint->v); 612 1.1 mrg if (!constraint->v) 613 1.1 mrg return isl_constraint_free(constraint); 614 1.1 mrg 615 1.1 mrg pos += isl_local_space_offset(constraint->ls, type); 616 1.1 mrg isl_int_set_si(constraint->v->el[pos], v); 617 1.1 mrg 618 1.1 mrg return constraint; 619 1.1 mrg } 620 1.1 mrg 621 1.1 mrg __isl_give isl_constraint *isl_constraint_negate( 622 1.1 mrg __isl_take isl_constraint *constraint) 623 1.1 mrg { 624 1.1 mrg isl_ctx *ctx; 625 1.1 mrg 626 1.1 mrg constraint = isl_constraint_cow(constraint); 627 1.1 mrg if (!constraint) 628 1.1 mrg return NULL; 629 1.1 mrg 630 1.1 mrg ctx = isl_constraint_get_ctx(constraint); 631 1.1 mrg if (isl_constraint_is_equality(constraint)) 632 1.1 mrg isl_die(ctx, isl_error_invalid, "cannot negate equality", 633 1.1 mrg return isl_constraint_free(constraint)); 634 1.1 mrg constraint->v = isl_vec_neg(constraint->v); 635 1.1 mrg constraint->v = isl_vec_cow(constraint->v); 636 1.1 mrg if (!constraint->v) 637 1.1 mrg return isl_constraint_free(constraint); 638 1.1 mrg isl_int_sub_ui(constraint->v->el[0], constraint->v->el[0], 1); 639 1.1 mrg return constraint; 640 1.1 mrg } 641 1.1 mrg 642 1.1 mrg isl_bool isl_constraint_is_equality(struct isl_constraint *constraint) 643 1.1 mrg { 644 1.1 mrg if (!constraint) 645 1.1 mrg return isl_bool_error; 646 1.1 mrg return isl_bool_ok(constraint->eq); 647 1.1 mrg } 648 1.1 mrg 649 1.1 mrg isl_bool isl_constraint_is_div_constraint(__isl_keep isl_constraint *constraint) 650 1.1 mrg { 651 1.1 mrg int i; 652 1.1 mrg isl_size n_div; 653 1.1 mrg 654 1.1 mrg if (!constraint) 655 1.1 mrg return isl_bool_error; 656 1.1 mrg if (isl_constraint_is_equality(constraint)) 657 1.1 mrg return isl_bool_false; 658 1.1 mrg n_div = isl_constraint_dim(constraint, isl_dim_div); 659 1.1 mrg if (n_div < 0) 660 1.1 mrg return isl_bool_error; 661 1.1 mrg for (i = 0; i < n_div; ++i) { 662 1.1 mrg isl_bool is_div; 663 1.1 mrg is_div = isl_local_space_is_div_constraint(constraint->ls, 664 1.1 mrg constraint->v->el, i); 665 1.1 mrg if (is_div < 0 || is_div) 666 1.1 mrg return is_div; 667 1.1 mrg } 668 1.1 mrg 669 1.1 mrg return isl_bool_false; 670 1.1 mrg } 671 1.1 mrg 672 1.1 mrg /* Is "constraint" an equality that corresponds to integer division "div"? 673 1.1 mrg * 674 1.1 mrg * That is, given an integer division of the form 675 1.1 mrg * 676 1.1 mrg * a = floor((f + c)/m) 677 1.1 mrg * 678 1.1 mrg * is the equality of the form 679 1.1 mrg * 680 1.1 mrg * -f + m d + c' = 0 681 1.1 mrg * ? 682 1.1 mrg * Note that the constant term is not checked explicitly, but given 683 1.1 mrg * that this is a valid equality constraint, the constant c' necessarily 684 1.1 mrg * has a value close to -c. 685 1.1 mrg */ 686 1.1 mrg isl_bool isl_constraint_is_div_equality(__isl_keep isl_constraint *constraint, 687 1.1 mrg unsigned div) 688 1.1 mrg { 689 1.1 mrg isl_bool equality; 690 1.1 mrg 691 1.1 mrg equality = isl_constraint_is_equality(constraint); 692 1.1 mrg if (equality < 0 || !equality) 693 1.1 mrg return equality; 694 1.1 mrg return isl_local_space_is_div_equality(constraint->ls, 695 1.1 mrg constraint->v->el, div); 696 1.1 mrg } 697 1.1 mrg 698 1.1 mrg /* We manually set ISL_BASIC_SET_FINAL instead of calling 699 1.1 mrg * isl_basic_map_finalize because we want to keep the position 700 1.1 mrg * of the divs and we therefore do not want to throw away redundant divs. 701 1.1 mrg * This is arguably a bit fragile. 702 1.1 mrg */ 703 1.1 mrg __isl_give isl_basic_map *isl_basic_map_from_constraint( 704 1.1 mrg __isl_take isl_constraint *constraint) 705 1.1 mrg { 706 1.1 mrg int k; 707 1.1 mrg isl_local_space *ls; 708 1.1 mrg struct isl_basic_map *bmap; 709 1.1 mrg isl_int *c; 710 1.1 mrg isl_size total; 711 1.1 mrg 712 1.1 mrg if (!constraint) 713 1.1 mrg return NULL; 714 1.1 mrg 715 1.1 mrg ls = isl_local_space_copy(constraint->ls); 716 1.1 mrg bmap = isl_basic_map_from_local_space(ls); 717 1.1 mrg bmap = isl_basic_map_extend_constraints(bmap, 1, 1); 718 1.1 mrg if (isl_constraint_is_equality(constraint)) { 719 1.1 mrg k = isl_basic_map_alloc_equality(bmap); 720 1.1 mrg if (k < 0) 721 1.1 mrg goto error; 722 1.1 mrg c = bmap->eq[k]; 723 1.1 mrg } 724 1.1 mrg else { 725 1.1 mrg k = isl_basic_map_alloc_inequality(bmap); 726 1.1 mrg if (k < 0) 727 1.1 mrg goto error; 728 1.1 mrg c = bmap->ineq[k]; 729 1.1 mrg } 730 1.1 mrg total = isl_basic_map_dim(bmap, isl_dim_all); 731 1.1 mrg if (total < 0) 732 1.1 mrg goto error; 733 1.1 mrg isl_seq_cpy(c, constraint->v->el, 1 + total); 734 1.1 mrg isl_constraint_free(constraint); 735 1.1 mrg if (bmap) 736 1.1 mrg ISL_F_SET(bmap, ISL_BASIC_SET_FINAL); 737 1.1 mrg return bmap; 738 1.1 mrg error: 739 1.1 mrg isl_constraint_free(constraint); 740 1.1 mrg isl_basic_map_free(bmap); 741 1.1 mrg return NULL; 742 1.1 mrg } 743 1.1 mrg 744 1.1 mrg __isl_give isl_basic_set *isl_basic_set_from_constraint( 745 1.1 mrg __isl_take isl_constraint *constraint) 746 1.1 mrg { 747 1.1 mrg isl_space *space; 748 1.1 mrg 749 1.1 mrg space = isl_constraint_peek_space(constraint); 750 1.1 mrg if (isl_space_check_is_set(space) < 0) 751 1.1 mrg goto error; 752 1.1 mrg return bset_from_bmap(isl_basic_map_from_constraint(constraint)); 753 1.1 mrg error: 754 1.1 mrg isl_constraint_free(constraint); 755 1.1 mrg return NULL; 756 1.1 mrg } 757 1.1 mrg 758 1.1 mrg /* Is the variable of "type" at position "pos" of "bmap" defined 759 1.1 mrg * in terms of earlier dimensions through an equality? 760 1.1 mrg * 761 1.1 mrg * If so, and if c is not NULL, then return a copy of this equality in *c. 762 1.1 mrg */ 763 1.1 mrg isl_bool isl_basic_map_has_defining_equality( 764 1.1 mrg __isl_keep isl_basic_map *bmap, enum isl_dim_type type, int pos, 765 1.1 mrg __isl_give isl_constraint **c) 766 1.1 mrg { 767 1.1 mrg int i; 768 1.1 mrg unsigned offset; 769 1.1 mrg isl_size total; 770 1.1 mrg 771 1.1 mrg if (isl_basic_map_check_range(bmap, type, pos, 1) < 0) 772 1.1 mrg return isl_bool_error; 773 1.1 mrg offset = isl_basic_map_offset(bmap, type); 774 1.1 mrg total = isl_basic_map_dim(bmap, isl_dim_all); 775 1.1 mrg if (total < 0) 776 1.1 mrg return isl_bool_error; 777 1.1 mrg for (i = 0; i < bmap->n_eq; ++i) { 778 1.1 mrg if (isl_int_is_zero(bmap->eq[i][offset + pos]) || 779 1.1 mrg isl_seq_first_non_zero(bmap->eq[i]+offset+pos+1, 780 1.1 mrg 1+total-offset-pos-1) != -1) 781 1.1 mrg continue; 782 1.1 mrg if (c) 783 1.1 mrg *c = isl_basic_map_constraint(isl_basic_map_copy(bmap), 784 1.1 mrg &bmap->eq[i]); 785 1.1 mrg return isl_bool_true; 786 1.1 mrg } 787 1.1 mrg return isl_bool_false; 788 1.1 mrg } 789 1.1 mrg 790 1.1 mrg /* Is the variable of "type" at position "pos" of "bset" defined 791 1.1 mrg * in terms of earlier dimensions through an equality? 792 1.1 mrg * 793 1.1 mrg * If so, and if c is not NULL, then return a copy of this equality in *c. 794 1.1 mrg */ 795 1.1 mrg isl_bool isl_basic_set_has_defining_equality( 796 1.1 mrg __isl_keep isl_basic_set *bset, enum isl_dim_type type, int pos, 797 1.1 mrg __isl_give isl_constraint **c) 798 1.1 mrg { 799 1.1 mrg return isl_basic_map_has_defining_equality(bset_to_bmap(bset), 800 1.1 mrg type, pos, c); 801 1.1 mrg } 802 1.1 mrg 803 1.1 mrg isl_bool isl_basic_set_has_defining_inequalities( 804 1.1 mrg struct isl_basic_set *bset, enum isl_dim_type type, int pos, 805 1.1 mrg struct isl_constraint **lower, 806 1.1 mrg struct isl_constraint **upper) 807 1.1 mrg { 808 1.1 mrg int i, j; 809 1.1 mrg unsigned offset; 810 1.1 mrg isl_size total; 811 1.1 mrg isl_int m; 812 1.1 mrg isl_int **lower_line, **upper_line; 813 1.1 mrg 814 1.1 mrg if (isl_basic_set_check_range(bset, type, pos, 1) < 0) 815 1.1 mrg return isl_bool_error; 816 1.1 mrg offset = isl_basic_set_offset(bset, type); 817 1.1 mrg total = isl_basic_set_dim(bset, isl_dim_all); 818 1.1 mrg if (total < 0) 819 1.1 mrg return isl_bool_error; 820 1.1 mrg isl_int_init(m); 821 1.1 mrg for (i = 0; i < bset->n_ineq; ++i) { 822 1.1 mrg if (isl_int_is_zero(bset->ineq[i][offset + pos])) 823 1.1 mrg continue; 824 1.1 mrg if (isl_int_is_one(bset->ineq[i][offset + pos])) 825 1.1 mrg continue; 826 1.1 mrg if (isl_int_is_negone(bset->ineq[i][offset + pos])) 827 1.1 mrg continue; 828 1.1 mrg if (isl_seq_first_non_zero(bset->ineq[i]+offset+pos+1, 829 1.1 mrg 1+total-offset-pos-1) != -1) 830 1.1 mrg continue; 831 1.1 mrg for (j = i + 1; j < bset->n_ineq; ++j) { 832 1.1 mrg if (!isl_seq_is_neg(bset->ineq[i]+1, bset->ineq[j]+1, 833 1.1 mrg total)) 834 1.1 mrg continue; 835 1.1 mrg isl_int_add(m, bset->ineq[i][0], bset->ineq[j][0]); 836 1.1 mrg if (isl_int_abs_ge(m, bset->ineq[i][offset+pos])) 837 1.1 mrg continue; 838 1.1 mrg 839 1.1 mrg if (isl_int_is_pos(bset->ineq[i][offset+pos])) { 840 1.1 mrg lower_line = &bset->ineq[i]; 841 1.1 mrg upper_line = &bset->ineq[j]; 842 1.1 mrg } else { 843 1.1 mrg lower_line = &bset->ineq[j]; 844 1.1 mrg upper_line = &bset->ineq[i]; 845 1.1 mrg } 846 1.1 mrg *lower = isl_basic_set_constraint( 847 1.1 mrg isl_basic_set_copy(bset), lower_line); 848 1.1 mrg *upper = isl_basic_set_constraint( 849 1.1 mrg isl_basic_set_copy(bset), upper_line); 850 1.1 mrg isl_int_clear(m); 851 1.1 mrg return isl_bool_true; 852 1.1 mrg } 853 1.1 mrg } 854 1.1 mrg *lower = NULL; 855 1.1 mrg *upper = NULL; 856 1.1 mrg isl_int_clear(m); 857 1.1 mrg return isl_bool_false; 858 1.1 mrg } 859 1.1 mrg 860 1.1 mrg /* Given two constraints "a" and "b" on the variable at position "abs_pos" 861 1.1 mrg * (in "a" and "b"), add a constraint to "bset" that ensures that the 862 1.1 mrg * bound implied by "a" is (strictly) larger than the bound implied by "b". 863 1.1 mrg * 864 1.1 mrg * If both constraints imply lower bounds, then this means that "a" is 865 1.1 mrg * active in the result. 866 1.1 mrg * If both constraints imply upper bounds, then this means that "b" is 867 1.1 mrg * active in the result. 868 1.1 mrg */ 869 1.1 mrg static __isl_give isl_basic_set *add_larger_bound_constraint( 870 1.1 mrg __isl_take isl_basic_set *bset, isl_int *a, isl_int *b, 871 1.1 mrg unsigned abs_pos, int strict) 872 1.1 mrg { 873 1.1 mrg int k; 874 1.1 mrg isl_int t; 875 1.1 mrg isl_size total; 876 1.1 mrg 877 1.1 mrg total = isl_basic_set_dim(bset, isl_dim_all); 878 1.1 mrg if (total < 0) 879 1.1 mrg return isl_basic_set_free(bset); 880 1.1 mrg k = isl_basic_set_alloc_inequality(bset); 881 1.1 mrg if (k < 0) 882 1.1 mrg goto error; 883 1.1 mrg 884 1.1 mrg isl_int_init(t); 885 1.1 mrg isl_int_neg(t, b[1 + abs_pos]); 886 1.1 mrg 887 1.1 mrg isl_seq_combine(bset->ineq[k], t, a, a[1 + abs_pos], b, 1 + abs_pos); 888 1.1 mrg isl_seq_combine(bset->ineq[k] + 1 + abs_pos, 889 1.1 mrg t, a + 1 + abs_pos + 1, a[1 + abs_pos], b + 1 + abs_pos + 1, 890 1.1 mrg total - abs_pos); 891 1.1 mrg 892 1.1 mrg if (strict) 893 1.1 mrg isl_int_sub_ui(bset->ineq[k][0], bset->ineq[k][0], 1); 894 1.1 mrg 895 1.1 mrg isl_int_clear(t); 896 1.1 mrg 897 1.1 mrg return bset; 898 1.1 mrg error: 899 1.1 mrg isl_basic_set_free(bset); 900 1.1 mrg return NULL; 901 1.1 mrg } 902 1.1 mrg 903 1.1 mrg /* Add constraints to "context" that ensure that "u" is the smallest 904 1.1 mrg * (and therefore active) upper bound on "abs_pos" in "bset" and return 905 1.1 mrg * the resulting basic set. 906 1.1 mrg */ 907 1.1 mrg static __isl_give isl_basic_set *set_smallest_upper_bound( 908 1.1 mrg __isl_keep isl_basic_set *context, 909 1.1 mrg __isl_keep isl_basic_set *bset, unsigned abs_pos, int n_upper, int u) 910 1.1 mrg { 911 1.1 mrg int j; 912 1.1 mrg 913 1.1 mrg context = isl_basic_set_copy(context); 914 1.1 mrg context = isl_basic_set_cow(context); 915 1.1 mrg 916 1.1 mrg context = isl_basic_set_extend_constraints(context, 0, n_upper - 1); 917 1.1 mrg 918 1.1 mrg for (j = 0; j < bset->n_ineq; ++j) { 919 1.1 mrg if (j == u) 920 1.1 mrg continue; 921 1.1 mrg if (!isl_int_is_neg(bset->ineq[j][1 + abs_pos])) 922 1.1 mrg continue; 923 1.1 mrg context = add_larger_bound_constraint(context, 924 1.1 mrg bset->ineq[j], bset->ineq[u], abs_pos, j > u); 925 1.1 mrg } 926 1.1 mrg 927 1.1 mrg context = isl_basic_set_simplify(context); 928 1.1 mrg context = isl_basic_set_finalize(context); 929 1.1 mrg 930 1.1 mrg return context; 931 1.1 mrg } 932 1.1 mrg 933 1.1 mrg /* Add constraints to "context" that ensure that "u" is the largest 934 1.1 mrg * (and therefore active) upper bound on "abs_pos" in "bset" and return 935 1.1 mrg * the resulting basic set. 936 1.1 mrg */ 937 1.1 mrg static __isl_give isl_basic_set *set_largest_lower_bound( 938 1.1 mrg __isl_keep isl_basic_set *context, 939 1.1 mrg __isl_keep isl_basic_set *bset, unsigned abs_pos, int n_lower, int l) 940 1.1 mrg { 941 1.1 mrg int j; 942 1.1 mrg 943 1.1 mrg context = isl_basic_set_copy(context); 944 1.1 mrg context = isl_basic_set_cow(context); 945 1.1 mrg 946 1.1 mrg context = isl_basic_set_extend_constraints(context, 0, n_lower - 1); 947 1.1 mrg 948 1.1 mrg for (j = 0; j < bset->n_ineq; ++j) { 949 1.1 mrg if (j == l) 950 1.1 mrg continue; 951 1.1 mrg if (!isl_int_is_pos(bset->ineq[j][1 + abs_pos])) 952 1.1 mrg continue; 953 1.1 mrg context = add_larger_bound_constraint(context, 954 1.1 mrg bset->ineq[l], bset->ineq[j], abs_pos, j > l); 955 1.1 mrg } 956 1.1 mrg 957 1.1 mrg context = isl_basic_set_simplify(context); 958 1.1 mrg context = isl_basic_set_finalize(context); 959 1.1 mrg 960 1.1 mrg return context; 961 1.1 mrg } 962 1.1 mrg 963 1.1 mrg static isl_stat foreach_upper_bound(__isl_keep isl_basic_set *bset, 964 1.1 mrg enum isl_dim_type type, unsigned abs_pos, 965 1.1 mrg __isl_take isl_basic_set *context, int n_upper, 966 1.1 mrg isl_stat (*fn)(__isl_take isl_constraint *lower, 967 1.1 mrg __isl_take isl_constraint *upper, 968 1.1 mrg __isl_take isl_basic_set *bset, void *user), void *user) 969 1.1 mrg { 970 1.1 mrg isl_basic_set *context_i; 971 1.1 mrg isl_constraint *upper = NULL; 972 1.1 mrg int i; 973 1.1 mrg 974 1.1 mrg for (i = 0; i < bset->n_ineq; ++i) { 975 1.1 mrg if (isl_int_is_zero(bset->ineq[i][1 + abs_pos])) 976 1.1 mrg continue; 977 1.1 mrg 978 1.1 mrg context_i = set_smallest_upper_bound(context, bset, 979 1.1 mrg abs_pos, n_upper, i); 980 1.1 mrg if (isl_basic_set_is_empty(context_i)) { 981 1.1 mrg isl_basic_set_free(context_i); 982 1.1 mrg continue; 983 1.1 mrg } 984 1.1 mrg upper = isl_basic_set_constraint(isl_basic_set_copy(bset), 985 1.1 mrg &bset->ineq[i]); 986 1.1 mrg if (!upper || !context_i) 987 1.1 mrg goto error; 988 1.1 mrg if (fn(NULL, upper, context_i, user) < 0) 989 1.1 mrg break; 990 1.1 mrg } 991 1.1 mrg 992 1.1 mrg isl_basic_set_free(context); 993 1.1 mrg 994 1.1 mrg if (i < bset->n_ineq) 995 1.1 mrg return isl_stat_error; 996 1.1 mrg 997 1.1 mrg return isl_stat_ok; 998 1.1 mrg error: 999 1.1 mrg isl_constraint_free(upper); 1000 1.1 mrg isl_basic_set_free(context_i); 1001 1.1 mrg isl_basic_set_free(context); 1002 1.1 mrg return isl_stat_error; 1003 1.1 mrg } 1004 1.1 mrg 1005 1.1 mrg static isl_stat foreach_lower_bound(__isl_keep isl_basic_set *bset, 1006 1.1 mrg enum isl_dim_type type, unsigned abs_pos, 1007 1.1 mrg __isl_take isl_basic_set *context, int n_lower, 1008 1.1 mrg isl_stat (*fn)(__isl_take isl_constraint *lower, 1009 1.1 mrg __isl_take isl_constraint *upper, 1010 1.1 mrg __isl_take isl_basic_set *bset, void *user), void *user) 1011 1.1 mrg { 1012 1.1 mrg isl_basic_set *context_i; 1013 1.1 mrg isl_constraint *lower = NULL; 1014 1.1 mrg int i; 1015 1.1 mrg 1016 1.1 mrg for (i = 0; i < bset->n_ineq; ++i) { 1017 1.1 mrg if (isl_int_is_zero(bset->ineq[i][1 + abs_pos])) 1018 1.1 mrg continue; 1019 1.1 mrg 1020 1.1 mrg context_i = set_largest_lower_bound(context, bset, 1021 1.1 mrg abs_pos, n_lower, i); 1022 1.1 mrg if (isl_basic_set_is_empty(context_i)) { 1023 1.1 mrg isl_basic_set_free(context_i); 1024 1.1 mrg continue; 1025 1.1 mrg } 1026 1.1 mrg lower = isl_basic_set_constraint(isl_basic_set_copy(bset), 1027 1.1 mrg &bset->ineq[i]); 1028 1.1 mrg if (!lower || !context_i) 1029 1.1 mrg goto error; 1030 1.1 mrg if (fn(lower, NULL, context_i, user) < 0) 1031 1.1 mrg break; 1032 1.1 mrg } 1033 1.1 mrg 1034 1.1 mrg isl_basic_set_free(context); 1035 1.1 mrg 1036 1.1 mrg if (i < bset->n_ineq) 1037 1.1 mrg return isl_stat_error; 1038 1.1 mrg 1039 1.1 mrg return isl_stat_ok; 1040 1.1 mrg error: 1041 1.1 mrg isl_constraint_free(lower); 1042 1.1 mrg isl_basic_set_free(context_i); 1043 1.1 mrg isl_basic_set_free(context); 1044 1.1 mrg return isl_stat_error; 1045 1.1 mrg } 1046 1.1 mrg 1047 1.1 mrg static isl_stat foreach_bound_pair(__isl_keep isl_basic_set *bset, 1048 1.1 mrg enum isl_dim_type type, unsigned abs_pos, 1049 1.1 mrg __isl_take isl_basic_set *context, int n_lower, int n_upper, 1050 1.1 mrg isl_stat (*fn)(__isl_take isl_constraint *lower, 1051 1.1 mrg __isl_take isl_constraint *upper, 1052 1.1 mrg __isl_take isl_basic_set *bset, void *user), void *user) 1053 1.1 mrg { 1054 1.1 mrg isl_basic_set *context_i, *context_j; 1055 1.1 mrg isl_constraint *lower = NULL; 1056 1.1 mrg isl_constraint *upper = NULL; 1057 1.1 mrg int i, j; 1058 1.1 mrg 1059 1.1 mrg for (i = 0; i < bset->n_ineq; ++i) { 1060 1.1 mrg if (!isl_int_is_pos(bset->ineq[i][1 + abs_pos])) 1061 1.1 mrg continue; 1062 1.1 mrg 1063 1.1 mrg context_i = set_largest_lower_bound(context, bset, 1064 1.1 mrg abs_pos, n_lower, i); 1065 1.1 mrg if (isl_basic_set_is_empty(context_i)) { 1066 1.1 mrg isl_basic_set_free(context_i); 1067 1.1 mrg continue; 1068 1.1 mrg } 1069 1.1 mrg 1070 1.1 mrg for (j = 0; j < bset->n_ineq; ++j) { 1071 1.1 mrg if (!isl_int_is_neg(bset->ineq[j][1 + abs_pos])) 1072 1.1 mrg continue; 1073 1.1 mrg 1074 1.1 mrg context_j = set_smallest_upper_bound(context_i, bset, 1075 1.1 mrg abs_pos, n_upper, j); 1076 1.1 mrg context_j = isl_basic_set_extend_constraints(context_j, 1077 1.1 mrg 0, 1); 1078 1.1 mrg context_j = add_larger_bound_constraint(context_j, 1079 1.1 mrg bset->ineq[i], bset->ineq[j], abs_pos, 0); 1080 1.1 mrg context_j = isl_basic_set_simplify(context_j); 1081 1.1 mrg context_j = isl_basic_set_finalize(context_j); 1082 1.1 mrg if (isl_basic_set_is_empty(context_j)) { 1083 1.1 mrg isl_basic_set_free(context_j); 1084 1.1 mrg continue; 1085 1.1 mrg } 1086 1.1 mrg lower = isl_basic_set_constraint(isl_basic_set_copy(bset), 1087 1.1 mrg &bset->ineq[i]); 1088 1.1 mrg upper = isl_basic_set_constraint(isl_basic_set_copy(bset), 1089 1.1 mrg &bset->ineq[j]); 1090 1.1 mrg if (!lower || !upper || !context_j) 1091 1.1 mrg goto error; 1092 1.1 mrg if (fn(lower, upper, context_j, user) < 0) 1093 1.1 mrg break; 1094 1.1 mrg } 1095 1.1 mrg 1096 1.1 mrg isl_basic_set_free(context_i); 1097 1.1 mrg 1098 1.1 mrg if (j < bset->n_ineq) 1099 1.1 mrg break; 1100 1.1 mrg } 1101 1.1 mrg 1102 1.1 mrg isl_basic_set_free(context); 1103 1.1 mrg 1104 1.1 mrg if (i < bset->n_ineq) 1105 1.1 mrg return isl_stat_error; 1106 1.1 mrg 1107 1.1 mrg return isl_stat_ok; 1108 1.1 mrg error: 1109 1.1 mrg isl_constraint_free(lower); 1110 1.1 mrg isl_constraint_free(upper); 1111 1.1 mrg isl_basic_set_free(context_i); 1112 1.1 mrg isl_basic_set_free(context_j); 1113 1.1 mrg isl_basic_set_free(context); 1114 1.1 mrg return isl_stat_error; 1115 1.1 mrg } 1116 1.1 mrg 1117 1.1 mrg /* For each pair of lower and upper bounds on the variable "pos" 1118 1.1 mrg * of type "type", call "fn" with these lower and upper bounds and the 1119 1.1 mrg * set of constraints on the remaining variables where these bounds 1120 1.1 mrg * are active, i.e., (stricly) larger/smaller than the other lower/upper bounds. 1121 1.1 mrg * 1122 1.1 mrg * If the designated variable is equal to an affine combination of the 1123 1.1 mrg * other variables then fn is called with both lower and upper 1124 1.1 mrg * set to the corresponding equality. 1125 1.1 mrg * 1126 1.1 mrg * If there is no lower (or upper) bound, then NULL is passed 1127 1.1 mrg * as the corresponding bound. 1128 1.1 mrg * 1129 1.1 mrg * We first check if the variable is involved in any equality. 1130 1.1 mrg * If not, we count the number of lower and upper bounds and 1131 1.1 mrg * act accordingly. 1132 1.1 mrg */ 1133 1.1 mrg isl_stat isl_basic_set_foreach_bound_pair(__isl_keep isl_basic_set *bset, 1134 1.1 mrg enum isl_dim_type type, unsigned pos, 1135 1.1 mrg isl_stat (*fn)(__isl_take isl_constraint *lower, 1136 1.1 mrg __isl_take isl_constraint *upper, 1137 1.1 mrg __isl_take isl_basic_set *bset, void *user), void *user) 1138 1.1 mrg { 1139 1.1 mrg int i; 1140 1.1 mrg isl_constraint *lower = NULL; 1141 1.1 mrg isl_constraint *upper = NULL; 1142 1.1 mrg isl_basic_set *context = NULL; 1143 1.1 mrg unsigned abs_pos; 1144 1.1 mrg int n_lower, n_upper; 1145 1.1 mrg isl_size off; 1146 1.1 mrg 1147 1.1 mrg if (isl_basic_set_check_range(bset, type, pos, 1) < 0) 1148 1.1 mrg return isl_stat_error; 1149 1.1 mrg isl_assert(bset->ctx, type == isl_dim_param || type == isl_dim_set, 1150 1.1 mrg return isl_stat_error); 1151 1.1 mrg 1152 1.1 mrg off = isl_basic_set_var_offset(bset, type); 1153 1.1 mrg if (off < 0) 1154 1.1 mrg return isl_stat_error; 1155 1.1 mrg abs_pos = off + pos; 1156 1.1 mrg 1157 1.1 mrg for (i = 0; i < bset->n_eq; ++i) { 1158 1.1 mrg if (isl_int_is_zero(bset->eq[i][1 + abs_pos])) 1159 1.1 mrg continue; 1160 1.1 mrg 1161 1.1 mrg lower = isl_basic_set_constraint(isl_basic_set_copy(bset), 1162 1.1 mrg &bset->eq[i]); 1163 1.1 mrg upper = isl_constraint_copy(lower); 1164 1.1 mrg context = isl_basic_set_remove_dims(isl_basic_set_copy(bset), 1165 1.1 mrg type, pos, 1); 1166 1.1 mrg if (!lower || !upper || !context) 1167 1.1 mrg goto error; 1168 1.1 mrg return fn(lower, upper, context, user); 1169 1.1 mrg } 1170 1.1 mrg 1171 1.1 mrg n_lower = 0; 1172 1.1 mrg n_upper = 0; 1173 1.1 mrg for (i = 0; i < bset->n_ineq; ++i) { 1174 1.1 mrg if (isl_int_is_pos(bset->ineq[i][1 + abs_pos])) 1175 1.1 mrg n_lower++; 1176 1.1 mrg else if (isl_int_is_neg(bset->ineq[i][1 + abs_pos])) 1177 1.1 mrg n_upper++; 1178 1.1 mrg } 1179 1.1 mrg 1180 1.1 mrg context = isl_basic_set_copy(bset); 1181 1.1 mrg context = isl_basic_set_cow(context); 1182 1.1 mrg if (!context) 1183 1.1 mrg goto error; 1184 1.1 mrg for (i = context->n_ineq - 1; i >= 0; --i) 1185 1.1 mrg if (!isl_int_is_zero(context->ineq[i][1 + abs_pos])) 1186 1.1 mrg isl_basic_set_drop_inequality(context, i); 1187 1.1 mrg 1188 1.1 mrg context = isl_basic_set_drop(context, type, pos, 1); 1189 1.1 mrg if (!n_lower && !n_upper) 1190 1.1 mrg return fn(NULL, NULL, context, user); 1191 1.1 mrg if (!n_lower) 1192 1.1 mrg return foreach_upper_bound(bset, type, abs_pos, context, n_upper, 1193 1.1 mrg fn, user); 1194 1.1 mrg if (!n_upper) 1195 1.1 mrg return foreach_lower_bound(bset, type, abs_pos, context, n_lower, 1196 1.1 mrg fn, user); 1197 1.1 mrg return foreach_bound_pair(bset, type, abs_pos, context, n_lower, n_upper, 1198 1.1 mrg fn, user); 1199 1.1 mrg error: 1200 1.1 mrg isl_constraint_free(lower); 1201 1.1 mrg isl_constraint_free(upper); 1202 1.1 mrg isl_basic_set_free(context); 1203 1.1 mrg return isl_stat_error; 1204 1.1 mrg } 1205 1.1 mrg 1206 1.1 mrg __isl_give isl_aff *isl_constraint_get_bound( 1207 1.1 mrg __isl_keep isl_constraint *constraint, enum isl_dim_type type, int pos) 1208 1.1 mrg { 1209 1.1 mrg isl_space *space; 1210 1.1 mrg isl_aff *aff; 1211 1.1 mrg isl_ctx *ctx; 1212 1.1 mrg 1213 1.1 mrg if (isl_constraint_check_range(constraint, type, pos, 1) < 0) 1214 1.1 mrg return NULL; 1215 1.1 mrg space = isl_constraint_peek_space(constraint); 1216 1.1 mrg if (isl_space_check_is_set(space) < 0) 1217 1.1 mrg return NULL; 1218 1.1 mrg 1219 1.1 mrg ctx = isl_constraint_get_ctx(constraint); 1220 1.1 mrg pos += offset(constraint, type); 1221 1.1 mrg if (isl_int_is_zero(constraint->v->el[pos])) 1222 1.1 mrg isl_die(ctx, isl_error_invalid, 1223 1.1 mrg "constraint does not define a bound on given dimension", 1224 1.1 mrg return NULL); 1225 1.1 mrg 1226 1.1 mrg aff = isl_aff_alloc(isl_local_space_copy(constraint->ls)); 1227 1.1 mrg if (!aff) 1228 1.1 mrg return NULL; 1229 1.1 mrg 1230 1.1 mrg if (isl_int_is_neg(constraint->v->el[pos])) 1231 1.1 mrg isl_seq_cpy(aff->v->el + 1, constraint->v->el, aff->v->size - 1); 1232 1.1 mrg else 1233 1.1 mrg isl_seq_neg(aff->v->el + 1, constraint->v->el, aff->v->size - 1); 1234 1.1 mrg isl_int_set_si(aff->v->el[1 + pos], 0); 1235 1.1 mrg isl_int_abs(aff->v->el[0], constraint->v->el[pos]); 1236 1.1 mrg aff = isl_aff_normalize(aff); 1237 1.1 mrg 1238 1.1 mrg return aff; 1239 1.1 mrg } 1240 1.1 mrg 1241 1.1 mrg /* For an inequality constraint 1242 1.1 mrg * 1243 1.1 mrg * f >= 0 1244 1.1 mrg * 1245 1.1 mrg * or an equality constraint 1246 1.1 mrg * 1247 1.1 mrg * f = 0 1248 1.1 mrg * 1249 1.1 mrg * return the affine expression f. 1250 1.1 mrg */ 1251 1.1 mrg __isl_give isl_aff *isl_constraint_get_aff( 1252 1.1 mrg __isl_keep isl_constraint *constraint) 1253 1.1 mrg { 1254 1.1 mrg isl_aff *aff; 1255 1.1 mrg 1256 1.1 mrg if (!constraint) 1257 1.1 mrg return NULL; 1258 1.1 mrg 1259 1.1 mrg aff = isl_aff_alloc(isl_local_space_copy(constraint->ls)); 1260 1.1 mrg if (!aff) 1261 1.1 mrg return NULL; 1262 1.1 mrg 1263 1.1 mrg isl_seq_cpy(aff->v->el + 1, constraint->v->el, aff->v->size - 1); 1264 1.1 mrg isl_int_set_si(aff->v->el[0], 1); 1265 1.1 mrg 1266 1.1 mrg return aff; 1267 1.1 mrg } 1268 1.1 mrg 1269 1.1 mrg /* Construct an inequality (eq = 0) or equality (eq = 1) constraint from "aff". 1270 1.1 mrg * In particular, construct aff >= 0 or aff = 0. 1271 1.1 mrg * 1272 1.1 mrg * The denominator of "aff" can be ignored. 1273 1.1 mrg */ 1274 1.1 mrg static __isl_give isl_constraint *isl_constraint_alloc_aff(int eq, 1275 1.1 mrg __isl_take isl_aff *aff) 1276 1.1 mrg { 1277 1.1 mrg isl_local_space *ls; 1278 1.1 mrg isl_vec *v; 1279 1.1 mrg 1280 1.1 mrg if (!aff) 1281 1.1 mrg return NULL; 1282 1.1 mrg ls = isl_aff_get_domain_local_space(aff); 1283 1.1 mrg v = isl_vec_drop_els(isl_vec_copy(aff->v), 0, 1); 1284 1.1 mrg isl_aff_free(aff); 1285 1.1 mrg 1286 1.1 mrg return isl_constraint_alloc_vec(eq, ls, v); 1287 1.1 mrg } 1288 1.1 mrg 1289 1.1 mrg /* Construct an equality constraint equating the given affine expression 1290 1.1 mrg * to zero. 1291 1.1 mrg */ 1292 1.1 mrg __isl_give isl_constraint *isl_equality_from_aff(__isl_take isl_aff *aff) 1293 1.1 mrg { 1294 1.1 mrg return isl_constraint_alloc_aff(1, aff); 1295 1.1 mrg } 1296 1.1 mrg 1297 1.1 mrg /* Construct an inequality constraint enforcing the given affine expression 1298 1.1 mrg * to be non-negative. 1299 1.1 mrg */ 1300 1.1 mrg __isl_give isl_constraint *isl_inequality_from_aff(__isl_take isl_aff *aff) 1301 1.1 mrg { 1302 1.1 mrg return isl_constraint_alloc_aff(0, aff); 1303 1.1 mrg } 1304 1.1 mrg 1305 1.1 mrg /* Compare two isl_constraints. 1306 1.1 mrg * 1307 1.1 mrg * Return -1 if "c1" is "smaller" than "c2", 1 if "c1" is "greater" 1308 1.1 mrg * than "c2" and 0 if they are equal. 1309 1.1 mrg * 1310 1.1 mrg * The order is fairly arbitrary. We do consider constraints that only involve 1311 1.1 mrg * earlier dimensions as "smaller". 1312 1.1 mrg */ 1313 1.1 mrg int isl_constraint_plain_cmp(__isl_keep isl_constraint *c1, 1314 1.1 mrg __isl_keep isl_constraint *c2) 1315 1.1 mrg { 1316 1.1 mrg int cmp; 1317 1.1 mrg int last1, last2; 1318 1.1 mrg 1319 1.1 mrg if (c1 == c2) 1320 1.1 mrg return 0; 1321 1.1 mrg if (!c1) 1322 1.1 mrg return -1; 1323 1.1 mrg if (!c2) 1324 1.1 mrg return 1; 1325 1.1 mrg cmp = isl_local_space_cmp(c1->ls, c2->ls); 1326 1.1 mrg if (cmp != 0) 1327 1.1 mrg return cmp; 1328 1.1 mrg 1329 1.1 mrg last1 = isl_seq_last_non_zero(c1->v->el + 1, c1->v->size - 1); 1330 1.1 mrg last2 = isl_seq_last_non_zero(c2->v->el + 1, c1->v->size - 1); 1331 1.1 mrg if (last1 != last2) 1332 1.1 mrg return last1 - last2; 1333 1.1 mrg 1334 1.1 mrg return isl_seq_cmp(c1->v->el, c2->v->el, c1->v->size); 1335 1.1 mrg } 1336 1.1 mrg 1337 1.1 mrg /* Compare two constraints based on their final (non-zero) coefficients. 1338 1.1 mrg * In particular, the constraint that involves later variables or 1339 1.1 mrg * that has a larger coefficient for a shared latest variable 1340 1.1 mrg * is considered "greater" than the other constraint. 1341 1.1 mrg * 1342 1.1 mrg * Return -1 if "c1" is "smaller" than "c2", 1 if "c1" is "greater" 1343 1.1 mrg * than "c2" and 0 if they are equal. 1344 1.1 mrg * 1345 1.1 mrg * If the constraints live in different local spaces, then we cannot 1346 1.1 mrg * really compare the constraints so we compare the local spaces instead. 1347 1.1 mrg */ 1348 1.1 mrg int isl_constraint_cmp_last_non_zero(__isl_keep isl_constraint *c1, 1349 1.1 mrg __isl_keep isl_constraint *c2) 1350 1.1 mrg { 1351 1.1 mrg int cmp; 1352 1.1 mrg int last1, last2; 1353 1.1 mrg 1354 1.1 mrg if (c1 == c2) 1355 1.1 mrg return 0; 1356 1.1 mrg if (!c1) 1357 1.1 mrg return -1; 1358 1.1 mrg if (!c2) 1359 1.1 mrg return 1; 1360 1.1 mrg cmp = isl_local_space_cmp(c1->ls, c2->ls); 1361 1.1 mrg if (cmp != 0) 1362 1.1 mrg return cmp; 1363 1.1 mrg 1364 1.1 mrg last1 = isl_seq_last_non_zero(c1->v->el + 1, c1->v->size - 1); 1365 1.1 mrg last2 = isl_seq_last_non_zero(c2->v->el + 1, c1->v->size - 1); 1366 1.1 mrg if (last1 != last2) 1367 1.1 mrg return last1 - last2; 1368 1.1 mrg if (last1 == -1) 1369 1.1 mrg return 0; 1370 1.1 mrg return isl_int_abs_cmp(c1->v->el[1 + last1], c2->v->el[1 + last2]); 1371 1.1 mrg } 1372