1 1.1 mrg /* 2 1.1 mrg * Copyright 2010-2011 INRIA Saclay 3 1.1 mrg * Copyright 2011 Sven Verdoolaege 4 1.1 mrg * Copyright 2012-2014 Ecole Normale Superieure 5 1.1 mrg * 6 1.1 mrg * Use of this software is governed by the MIT license 7 1.1 mrg * 8 1.1 mrg * Written by Sven Verdoolaege, INRIA Saclay - Ile-de-France, 9 1.1 mrg * Parc Club Orsay Universite, ZAC des vignes, 4 rue Jacques Monod, 10 1.1 mrg * 91893 Orsay, France 11 1.1 mrg * and Ecole Normale Superieure, 45 rue dUlm, 75230 Paris, France 12 1.1 mrg */ 13 1.1 mrg 14 1.1 mrg #include <isl/id.h> 15 1.1 mrg #include <isl/aff.h> 16 1.1 mrg #include <isl_sort.h> 17 1.1 mrg #include <isl_val_private.h> 18 1.1 mrg 19 1.1 mrg #include <isl_pw_macro.h> 20 1.1 mrg 21 1.1 mrg #include "opt_type.h" 22 1.1 mrg 23 1.1 mrg __isl_give PW *FN(PW,alloc_size)(__isl_take isl_space *space 24 1.1 mrg OPT_TYPE_PARAM, int n) 25 1.1 mrg { 26 1.1 mrg isl_ctx *ctx; 27 1.1 mrg struct PW *pw; 28 1.1 mrg 29 1.1 mrg if (!space) 30 1.1 mrg return NULL; 31 1.1 mrg ctx = isl_space_get_ctx(space); 32 1.1 mrg isl_assert(ctx, n >= 0, goto error); 33 1.1 mrg pw = isl_alloc(ctx, struct PW, 34 1.1 mrg sizeof(struct PW) + (n - 1) * sizeof(S(PW,piece))); 35 1.1 mrg if (!pw) 36 1.1 mrg goto error; 37 1.1 mrg 38 1.1 mrg pw->ref = 1; 39 1.1 mrg OPT_SET_TYPE(pw->, type); 40 1.1 mrg pw->size = n; 41 1.1 mrg pw->n = 0; 42 1.1 mrg pw->dim = space; 43 1.1 mrg return pw; 44 1.1 mrg error: 45 1.1 mrg isl_space_free(space); 46 1.1 mrg return NULL; 47 1.1 mrg } 48 1.1 mrg 49 1.1 mrg __isl_give PW *FN(PW,ZERO)(__isl_take isl_space *space OPT_TYPE_PARAM) 50 1.1 mrg { 51 1.1 mrg return FN(PW,alloc_size)(space OPT_TYPE_ARG(NO_LOC), 0); 52 1.1 mrg } 53 1.1 mrg 54 1.1 mrg /* Add a piece with domain "set" and base expression "el" 55 1.1 mrg * to the piecewise expression "pw". 56 1.1 mrg * 57 1.1 mrg * Do this independently of the values of "set" and "el", 58 1.1 mrg * such that this function can be used by isl_pw_*_dup. 59 1.1 mrg */ 60 1.1 mrg static __isl_give PW *FN(PW,add_dup_piece)(__isl_take PW *pw, 61 1.1 mrg __isl_take isl_set *set, __isl_take EL *el) 62 1.1 mrg { 63 1.1 mrg isl_ctx *ctx; 64 1.1 mrg isl_space *el_dim = NULL; 65 1.1 mrg 66 1.1 mrg if (!pw || !set || !el) 67 1.1 mrg goto error; 68 1.1 mrg 69 1.1 mrg ctx = isl_set_get_ctx(set); 70 1.1 mrg if (!OPT_EQUAL_TYPES(pw->, el->)) 71 1.1 mrg isl_die(ctx, isl_error_invalid, "fold types don't match", 72 1.1 mrg goto error); 73 1.1 mrg el_dim = FN(EL,get_space(el)); 74 1.1 mrg isl_assert(ctx, isl_space_is_equal(pw->dim, el_dim), goto error); 75 1.1 mrg isl_assert(ctx, pw->n < pw->size, goto error); 76 1.1 mrg 77 1.1 mrg pw->p[pw->n].set = set; 78 1.1 mrg pw->p[pw->n].FIELD = el; 79 1.1 mrg pw->n++; 80 1.1 mrg 81 1.1 mrg isl_space_free(el_dim); 82 1.1 mrg return pw; 83 1.1 mrg error: 84 1.1 mrg isl_space_free(el_dim); 85 1.1 mrg FN(PW,free)(pw); 86 1.1 mrg isl_set_free(set); 87 1.1 mrg FN(EL,free)(el); 88 1.1 mrg return NULL; 89 1.1 mrg } 90 1.1 mrg 91 1.1 mrg /* Add a piece with domain "set" and base expression "el" 92 1.1 mrg * to the piecewise expression "pw", provided the domain 93 1.1 mrg * is not obviously empty and the base expression 94 1.1 mrg * is not equal to the default value. 95 1.1 mrg */ 96 1.1 mrg __isl_give PW *FN(PW,add_piece)(__isl_take PW *pw, 97 1.1 mrg __isl_take isl_set *set, __isl_take EL *el) 98 1.1 mrg { 99 1.1 mrg isl_bool skip; 100 1.1 mrg 101 1.1 mrg skip = isl_set_plain_is_empty(set); 102 1.1 mrg if (skip >= 0 && !skip) 103 1.1 mrg skip = FN(EL,EL_IS_ZERO)(el); 104 1.1 mrg if (skip >= 0 && !skip) 105 1.1 mrg return FN(PW,add_dup_piece)(pw, set, el); 106 1.1 mrg 107 1.1 mrg isl_set_free(set); 108 1.1 mrg FN(EL,free)(el); 109 1.1 mrg if (skip < 0) 110 1.1 mrg return FN(PW,free)(pw); 111 1.1 mrg return pw; 112 1.1 mrg } 113 1.1 mrg 114 1.1 mrg /* Does the space of "set" correspond to that of the domain of "el". 115 1.1 mrg */ 116 1.1 mrg static isl_bool FN(PW,compatible_domain)(__isl_keep EL *el, 117 1.1 mrg __isl_keep isl_set *set) 118 1.1 mrg { 119 1.1 mrg isl_bool ok; 120 1.1 mrg isl_space *el_space, *set_space; 121 1.1 mrg 122 1.1 mrg if (!set || !el) 123 1.1 mrg return isl_bool_error; 124 1.1 mrg set_space = isl_set_get_space(set); 125 1.1 mrg el_space = FN(EL,get_space)(el); 126 1.1 mrg ok = isl_space_is_domain_internal(set_space, el_space); 127 1.1 mrg isl_space_free(el_space); 128 1.1 mrg isl_space_free(set_space); 129 1.1 mrg return ok; 130 1.1 mrg } 131 1.1 mrg 132 1.1 mrg /* Check that the space of "set" corresponds to that of the domain of "el". 133 1.1 mrg */ 134 1.1 mrg static isl_stat FN(PW,check_compatible_domain)(__isl_keep EL *el, 135 1.1 mrg __isl_keep isl_set *set) 136 1.1 mrg { 137 1.1 mrg isl_bool ok; 138 1.1 mrg 139 1.1 mrg ok = FN(PW,compatible_domain)(el, set); 140 1.1 mrg if (ok < 0) 141 1.1 mrg return isl_stat_error; 142 1.1 mrg if (!ok) 143 1.1 mrg isl_die(isl_set_get_ctx(set), isl_error_invalid, 144 1.1 mrg "incompatible spaces", return isl_stat_error); 145 1.1 mrg 146 1.1 mrg return isl_stat_ok; 147 1.1 mrg } 148 1.1 mrg 149 1.1 mrg __isl_give PW *FN(PW,alloc)(OPT_TYPE_PARAM_FIRST 150 1.1 mrg __isl_take isl_set *set, __isl_take EL *el) 151 1.1 mrg { 152 1.1 mrg PW *pw; 153 1.1 mrg 154 1.1 mrg if (FN(PW,check_compatible_domain)(el, set) < 0) 155 1.1 mrg goto error; 156 1.1 mrg 157 1.1 mrg pw = FN(PW,alloc_size)(FN(EL,get_space)(el) OPT_TYPE_ARG(NO_LOC), 1); 158 1.1 mrg 159 1.1 mrg return FN(PW,add_piece)(pw, set, el); 160 1.1 mrg error: 161 1.1 mrg isl_set_free(set); 162 1.1 mrg FN(EL,free)(el); 163 1.1 mrg return NULL; 164 1.1 mrg } 165 1.1 mrg 166 1.1 mrg __isl_give PW *FN(PW,dup)(__isl_keep PW *pw) 167 1.1 mrg { 168 1.1 mrg int i; 169 1.1 mrg PW *dup; 170 1.1 mrg 171 1.1 mrg if (!pw) 172 1.1 mrg return NULL; 173 1.1 mrg 174 1.1 mrg dup = FN(PW,alloc_size)(isl_space_copy(pw->dim) 175 1.1 mrg OPT_TYPE_ARG(pw->), pw->n); 176 1.1 mrg if (!dup) 177 1.1 mrg return NULL; 178 1.1 mrg 179 1.1 mrg for (i = 0; i < pw->n; ++i) 180 1.1 mrg dup = FN(PW,add_dup_piece)(dup, isl_set_copy(pw->p[i].set), 181 1.1 mrg FN(EL,copy)(pw->p[i].FIELD)); 182 1.1 mrg 183 1.1 mrg return dup; 184 1.1 mrg } 185 1.1 mrg 186 1.1 mrg __isl_give PW *FN(PW,cow)(__isl_take PW *pw) 187 1.1 mrg { 188 1.1 mrg if (!pw) 189 1.1 mrg return NULL; 190 1.1 mrg 191 1.1 mrg if (pw->ref == 1) 192 1.1 mrg return pw; 193 1.1 mrg pw->ref--; 194 1.1 mrg return FN(PW,dup)(pw); 195 1.1 mrg } 196 1.1 mrg 197 1.1 mrg __isl_give PW *FN(PW,copy)(__isl_keep PW *pw) 198 1.1 mrg { 199 1.1 mrg if (!pw) 200 1.1 mrg return NULL; 201 1.1 mrg 202 1.1 mrg pw->ref++; 203 1.1 mrg return pw; 204 1.1 mrg } 205 1.1 mrg 206 1.1 mrg __isl_null PW *FN(PW,free)(__isl_take PW *pw) 207 1.1 mrg { 208 1.1 mrg int i; 209 1.1 mrg 210 1.1 mrg if (!pw) 211 1.1 mrg return NULL; 212 1.1 mrg if (--pw->ref > 0) 213 1.1 mrg return NULL; 214 1.1 mrg 215 1.1 mrg for (i = 0; i < pw->n; ++i) { 216 1.1 mrg isl_set_free(pw->p[i].set); 217 1.1 mrg FN(EL,free)(pw->p[i].FIELD); 218 1.1 mrg } 219 1.1 mrg isl_space_free(pw->dim); 220 1.1 mrg free(pw); 221 1.1 mrg 222 1.1 mrg return NULL; 223 1.1 mrg } 224 1.1 mrg 225 1.1 mrg /* Return the space of "pw". 226 1.1 mrg */ 227 1.1 mrg __isl_keep isl_space *FN(PW,peek_space)(__isl_keep PW *pw) 228 1.1 mrg { 229 1.1 mrg return pw ? pw->dim : NULL; 230 1.1 mrg } 231 1.1 mrg 232 1.1 mrg __isl_give isl_space *FN(PW,get_space)(__isl_keep PW *pw) 233 1.1 mrg { 234 1.1 mrg return isl_space_copy(FN(PW,peek_space)(pw)); 235 1.1 mrg } 236 1.1 mrg 237 1.1 mrg /* Return the space of "pw". 238 1.1 mrg * This may be either a copy or the space itself 239 1.1 mrg * if there is only one reference to "pw". 240 1.1 mrg * This allows the space to be modified inplace 241 1.1 mrg * if both the piecewise expression and its space have only a single reference. 242 1.1 mrg * The caller is not allowed to modify "pw" between this call and 243 1.1 mrg * a subsequent call to isl_pw_*_restore_*. 244 1.1 mrg * The only exception is that isl_pw_*_free can be called instead. 245 1.1 mrg */ 246 1.1 mrg static __isl_give isl_space *FN(PW,take_space)(__isl_keep PW *pw) 247 1.1 mrg { 248 1.1 mrg isl_space *space; 249 1.1 mrg 250 1.1 mrg if (!pw) 251 1.1 mrg return NULL; 252 1.1 mrg if (pw->ref != 1) 253 1.1 mrg return FN(PW,get_space)(pw); 254 1.1 mrg space = pw->dim; 255 1.1 mrg pw->dim = NULL; 256 1.1 mrg return space; 257 1.1 mrg } 258 1.1 mrg 259 1.1 mrg /* Set the space of "pw" to "space", where the space of "pw" may be missing 260 1.1 mrg * due to a preceding call to isl_pw_*_take_space. 261 1.1 mrg * However, in this case, "pw" only has a single reference and 262 1.1 mrg * then the call to isl_pw_*_cow has no effect. 263 1.1 mrg */ 264 1.1 mrg static __isl_give PW *FN(PW,restore_space)(__isl_take PW *pw, 265 1.1 mrg __isl_take isl_space *space) 266 1.1 mrg { 267 1.1 mrg if (!pw || !space) 268 1.1 mrg goto error; 269 1.1 mrg 270 1.1 mrg if (pw->dim == space) { 271 1.1 mrg isl_space_free(space); 272 1.1 mrg return pw; 273 1.1 mrg } 274 1.1 mrg 275 1.1 mrg pw = FN(PW,cow)(pw); 276 1.1 mrg if (!pw) 277 1.1 mrg goto error; 278 1.1 mrg isl_space_free(pw->dim); 279 1.1 mrg pw->dim = space; 280 1.1 mrg 281 1.1 mrg return pw; 282 1.1 mrg error: 283 1.1 mrg FN(PW,free)(pw); 284 1.1 mrg isl_space_free(space); 285 1.1 mrg return NULL; 286 1.1 mrg } 287 1.1 mrg 288 1.1 mrg /* Check that "pos" is a valid position for a cell in "pw". 289 1.1 mrg */ 290 1.1 mrg static isl_stat FN(PW,check_pos)(__isl_keep PW *pw, int pos) 291 1.1 mrg { 292 1.1 mrg if (!pw) 293 1.1 mrg return isl_stat_error; 294 1.1 mrg if (pos < 0 || pos >= pw->n) 295 1.1 mrg isl_die(FN(PW,get_ctx)(pw), isl_error_internal, 296 1.1 mrg "position out of bounds", return isl_stat_error); 297 1.1 mrg return isl_stat_ok; 298 1.1 mrg } 299 1.1 mrg 300 1.1 mrg /* Return the cell at position "pos" in "pw". 301 1.1 mrg */ 302 1.1 mrg static __isl_keep isl_set *FN(PW,peek_domain_at)(__isl_keep PW *pw, int pos) 303 1.1 mrg { 304 1.1 mrg if (FN(PW,check_pos)(pw, pos) < 0) 305 1.1 mrg return NULL; 306 1.1 mrg return pw->p[pos].set; 307 1.1 mrg } 308 1.1 mrg 309 1.1 mrg /* Return a copy of the cell at position "pos" in "pw". 310 1.1 mrg */ 311 1.1 mrg static __isl_give isl_set *FN(PW,get_domain_at)(__isl_keep PW *pw, int pos) 312 1.1 mrg { 313 1.1 mrg return isl_set_copy(FN(PW,peek_domain_at)(pw, pos)); 314 1.1 mrg } 315 1.1 mrg 316 1.1 mrg /* Return the cell at position "pos" in "pw". 317 1.1 mrg * This may be either a copy or the cell itself 318 1.1 mrg * if there is only one reference to "pw". 319 1.1 mrg * This allows the cell to be modified inplace 320 1.1 mrg * if both the piecewise expression and this cell 321 1.1 mrg * have only a single reference. 322 1.1 mrg * The caller is not allowed to modify "pw" between this call and 323 1.1 mrg * the subsequent call to isl_pw_*_restore_domain_at. 324 1.1 mrg * The only exception is that isl_pw_*_free can be called instead. 325 1.1 mrg */ 326 1.1 mrg static __isl_give isl_set *FN(PW,take_domain_at)(__isl_keep PW *pw, int pos) 327 1.1 mrg { 328 1.1 mrg isl_set *domain; 329 1.1 mrg 330 1.1 mrg if (!pw) 331 1.1 mrg return NULL; 332 1.1 mrg if (pw->ref != 1) 333 1.1 mrg return FN(PW,get_domain_at)(pw, pos); 334 1.1 mrg if (FN(PW,check_pos)(pw, pos) < 0) 335 1.1 mrg return NULL; 336 1.1 mrg domain = pw->p[pos].set; 337 1.1 mrg pw->p[pos].set = NULL; 338 1.1 mrg return domain; 339 1.1 mrg } 340 1.1 mrg 341 1.1 mrg /* Set the cell at position "pos" in "pw" to "el", 342 1.1 mrg * where this cell may be missing 343 1.1 mrg * due to a preceding call to isl_pw_*_take_domain_at. 344 1.1 mrg * However, in this case, "pw" only has a single reference and 345 1.1 mrg * then the call to isl_pw_*_cow has no effect. 346 1.1 mrg */ 347 1.1 mrg static __isl_give PW *FN(PW,restore_domain_at)(__isl_take PW *pw, int pos, 348 1.1 mrg __isl_take isl_set *domain) 349 1.1 mrg { 350 1.1 mrg if (FN(PW,check_pos)(pw, pos) < 0 || !domain) 351 1.1 mrg goto error; 352 1.1 mrg 353 1.1 mrg if (pw->p[pos].set == domain) { 354 1.1 mrg isl_set_free(domain); 355 1.1 mrg return pw; 356 1.1 mrg } 357 1.1 mrg 358 1.1 mrg pw = FN(PW,cow)(pw); 359 1.1 mrg if (!pw) 360 1.1 mrg goto error; 361 1.1 mrg isl_set_free(pw->p[pos].set); 362 1.1 mrg pw->p[pos].set = domain; 363 1.1 mrg 364 1.1 mrg return pw; 365 1.1 mrg error: 366 1.1 mrg FN(PW,free)(pw); 367 1.1 mrg isl_set_free(domain); 368 1.1 mrg return NULL; 369 1.1 mrg } 370 1.1 mrg 371 1.1 mrg /* Return the base expression associated to 372 1.1 mrg * the cell at position "pos" in "pw". 373 1.1 mrg */ 374 1.1 mrg __isl_keep EL *FN(PW,peek_base_at)(__isl_keep PW *pw, int pos) 375 1.1 mrg { 376 1.1 mrg if (FN(PW,check_pos)(pw, pos) < 0) 377 1.1 mrg return NULL; 378 1.1 mrg return pw->p[pos].FIELD; 379 1.1 mrg } 380 1.1 mrg 381 1.1 mrg /* Return a copy of the base expression associated to 382 1.1 mrg * the cell at position "pos" in "pw". 383 1.1 mrg */ 384 1.1 mrg static __isl_give EL *FN(PW,get_base_at)(__isl_keep PW *pw, int pos) 385 1.1 mrg { 386 1.1 mrg return FN(EL,copy)(FN(PW,peek_base_at)(pw, pos)); 387 1.1 mrg } 388 1.1 mrg 389 1.1 mrg /* Return the base expression associated to 390 1.1 mrg * the cell at position "pos" in "pw". 391 1.1 mrg * This may be either a copy or the base expression itself 392 1.1 mrg * if there is only one reference to "pw". 393 1.1 mrg * This allows the base expression to be modified inplace 394 1.1 mrg * if both the piecewise expression and this base expression 395 1.1 mrg * have only a single reference. 396 1.1 mrg * The caller is not allowed to modify "pw" between this call and 397 1.1 mrg * a subsequent call to isl_pw_*_restore_*. 398 1.1 mrg * The only exception is that isl_pw_*_free can be called instead. 399 1.1 mrg */ 400 1.1 mrg static __isl_give EL *FN(PW,take_base_at)(__isl_keep PW *pw, int pos) 401 1.1 mrg { 402 1.1 mrg EL *el; 403 1.1 mrg 404 1.1 mrg if (!pw) 405 1.1 mrg return NULL; 406 1.1 mrg if (pw->ref != 1) 407 1.1 mrg return FN(PW,get_base_at)(pw, pos); 408 1.1 mrg if (FN(PW,check_pos)(pw, pos) < 0) 409 1.1 mrg return NULL; 410 1.1 mrg el = pw->p[pos].FIELD; 411 1.1 mrg pw->p[pos].FIELD = NULL; 412 1.1 mrg return el; 413 1.1 mrg } 414 1.1 mrg 415 1.1 mrg /* Set the base expression associated to 416 1.1 mrg * the cell at position "pos" in "pw" to "el", 417 1.1 mrg * where this base expression may be missing 418 1.1 mrg * due to a preceding call to isl_pw_*_take_base_at. 419 1.1 mrg * However, in this case, "pw" only has a single reference and 420 1.1 mrg * then the call to isl_pw_*_cow has no effect. 421 1.1 mrg * If "inplace" is set, then replacing the base expression by "el" 422 1.1 mrg * is known not to change the meaning of "pw". It can therefore be replaced 423 1.1 mrg * in all references to "pw". 424 1.1 mrg */ 425 1.1 mrg static __isl_give PW *FN(PW,restore_base_at_)(__isl_take PW *pw, int pos, 426 1.1 mrg __isl_take EL *el, int inplace) 427 1.1 mrg { 428 1.1 mrg if (FN(PW,check_pos)(pw, pos) < 0 || !el) 429 1.1 mrg goto error; 430 1.1 mrg 431 1.1 mrg if (pw->p[pos].FIELD == el) { 432 1.1 mrg FN(EL,free)(el); 433 1.1 mrg return pw; 434 1.1 mrg } 435 1.1 mrg 436 1.1 mrg if (!inplace) 437 1.1 mrg pw = FN(PW,cow)(pw); 438 1.1 mrg if (!pw) 439 1.1 mrg goto error; 440 1.1 mrg FN(EL,free)(pw->p[pos].FIELD); 441 1.1 mrg pw->p[pos].FIELD = el; 442 1.1 mrg 443 1.1 mrg return pw; 444 1.1 mrg error: 445 1.1 mrg FN(PW,free)(pw); 446 1.1 mrg FN(EL,free)(el); 447 1.1 mrg return NULL; 448 1.1 mrg } 449 1.1 mrg 450 1.1 mrg /* Set the base expression associated to 451 1.1 mrg * the cell at position "pos" in "pw" to "el", 452 1.1 mrg * where this base expression may be missing 453 1.1 mrg * due to a preceding call to isl_pw_*_take_base_at. 454 1.1 mrg */ 455 1.1 mrg static __isl_give PW *FN(PW,restore_base_at)(__isl_take PW *pw, int pos, 456 1.1 mrg __isl_take EL *el) 457 1.1 mrg { 458 1.1 mrg return FN(PW,restore_base_at_)(pw, pos, el, 0); 459 1.1 mrg } 460 1.1 mrg 461 1.1 mrg /* Set the base expression associated to 462 1.1 mrg * the cell at position "pos" in "pw" to "el", 463 1.1 mrg * where this base expression may be missing 464 1.1 mrg * due to a preceding call to isl_pw_*_take_base_at. 465 1.1 mrg * Furthermore, replacing the base expression by "el" 466 1.1 mrg * is known not to change the meaning of "pw". 467 1.1 mrg */ 468 1.1 mrg static __isl_give PW *FN(PW,restore_base_at_inplace)(__isl_take PW *pw, int pos, 469 1.1 mrg __isl_take EL *el) 470 1.1 mrg { 471 1.1 mrg return FN(PW,restore_base_at_)(pw, pos, el, 1); 472 1.1 mrg } 473 1.1 mrg 474 1.1 mrg /* Create a piecewise expression with the given base expression on a universe 475 1.1 mrg * domain. 476 1.1 mrg */ 477 1.1 mrg static __isl_give PW *FN(FN(FN(PW,from),BASE),type_base)(__isl_take EL *el 478 1.1 mrg OPT_TYPE_PARAM) 479 1.1 mrg { 480 1.1 mrg isl_set *dom = isl_set_universe(FN(EL,get_domain_space)(el)); 481 1.1 mrg return FN(PW,alloc)(OPT_TYPE_ARG_FIRST(NO_LOC) dom, el); 482 1.1 mrg } 483 1.1 mrg 484 1.1 mrg /* Create a piecewise expression with the given base expression on a universe 485 1.1 mrg * domain. 486 1.1 mrg * 487 1.1 mrg * If the default value of this piecewise type is zero and 488 1.1 mrg * if "el" is effectively zero, then create an empty piecewise expression 489 1.1 mrg * instead. 490 1.1 mrg */ 491 1.1 mrg static __isl_give PW *FN(FN(FN(PW,from),BASE),type)(__isl_take EL *el 492 1.1 mrg OPT_TYPE_PARAM) 493 1.1 mrg { 494 1.1 mrg isl_bool is_zero; 495 1.1 mrg isl_space *space; 496 1.1 mrg 497 1.1 mrg if (!DEFAULT_IS_ZERO) 498 1.1 mrg return FN(FN(FN(PW,from),BASE),type_base)(el 499 1.1 mrg OPT_TYPE_ARG(NO_LOC)); 500 1.1 mrg is_zero = FN(EL,EL_IS_ZERO)(el); 501 1.1 mrg if (is_zero < 0) 502 1.1 mrg goto error; 503 1.1 mrg if (!is_zero) 504 1.1 mrg return FN(FN(FN(PW,from),BASE),type_base)(el 505 1.1 mrg OPT_TYPE_ARG(NO_LOC)); 506 1.1 mrg space = FN(EL,get_space)(el); 507 1.1 mrg FN(EL,free)(el); 508 1.1 mrg return FN(PW,ZERO)(space OPT_TYPE_ARG(NO_LOC)); 509 1.1 mrg error: 510 1.1 mrg FN(EL,free)(el); 511 1.1 mrg return NULL; 512 1.1 mrg } 513 1.1 mrg 514 1.1 mrg #ifdef HAS_TYPE 515 1.1 mrg /* Create a piecewise expression with the given base expression on a universe 516 1.1 mrg * domain. 517 1.1 mrg * 518 1.1 mrg * Pass along the type as an extra argument for improved uniformity 519 1.1 mrg * with piecewise types that do not have a fold type. 520 1.1 mrg */ 521 1.1 mrg __isl_give PW *FN(FN(PW,from),BASE)(__isl_take EL *el) 522 1.1 mrg { 523 1.1 mrg enum isl_fold type = FN(EL,get_type)(el); 524 1.1 mrg return FN(FN(FN(PW,from),BASE),type)(el, type); 525 1.1 mrg } 526 1.1 mrg #else 527 1.1 mrg __isl_give PW *FN(FN(PW,from),BASE)(__isl_take EL *el) 528 1.1 mrg { 529 1.1 mrg return FN(FN(FN(PW,from),BASE),type)(el); 530 1.1 mrg } 531 1.1 mrg #endif 532 1.1 mrg 533 1.1 mrg const char *FN(PW,get_dim_name)(__isl_keep PW *pw, enum isl_dim_type type, 534 1.1 mrg unsigned pos) 535 1.1 mrg { 536 1.1 mrg return pw ? isl_space_get_dim_name(pw->dim, type, pos) : NULL; 537 1.1 mrg } 538 1.1 mrg 539 1.1 mrg isl_bool FN(PW,has_dim_id)(__isl_keep PW *pw, enum isl_dim_type type, 540 1.1 mrg unsigned pos) 541 1.1 mrg { 542 1.1 mrg return pw ? isl_space_has_dim_id(pw->dim, type, pos) : isl_bool_error; 543 1.1 mrg } 544 1.1 mrg 545 1.1 mrg __isl_give isl_id *FN(PW,get_dim_id)(__isl_keep PW *pw, enum isl_dim_type type, 546 1.1 mrg unsigned pos) 547 1.1 mrg { 548 1.1 mrg return pw ? isl_space_get_dim_id(pw->dim, type, pos) : NULL; 549 1.1 mrg } 550 1.1 mrg 551 1.1 mrg isl_bool FN(PW,has_tuple_name)(__isl_keep PW *pw, enum isl_dim_type type) 552 1.1 mrg { 553 1.1 mrg return pw ? isl_space_has_tuple_name(pw->dim, type) : isl_bool_error; 554 1.1 mrg } 555 1.1 mrg 556 1.1 mrg const char *FN(PW,get_tuple_name)(__isl_keep PW *pw, enum isl_dim_type type) 557 1.1 mrg { 558 1.1 mrg return pw ? isl_space_get_tuple_name(pw->dim, type) : NULL; 559 1.1 mrg } 560 1.1 mrg 561 1.1 mrg isl_bool FN(PW,has_tuple_id)(__isl_keep PW *pw, enum isl_dim_type type) 562 1.1 mrg { 563 1.1 mrg return pw ? isl_space_has_tuple_id(pw->dim, type) : isl_bool_error; 564 1.1 mrg } 565 1.1 mrg 566 1.1 mrg __isl_give isl_id *FN(PW,get_tuple_id)(__isl_keep PW *pw, enum isl_dim_type type) 567 1.1 mrg { 568 1.1 mrg return pw ? isl_space_get_tuple_id(pw->dim, type) : NULL; 569 1.1 mrg } 570 1.1 mrg 571 1.1 mrg isl_bool FN(PW,IS_ZERO)(__isl_keep PW *pw) 572 1.1 mrg { 573 1.1 mrg if (!pw) 574 1.1 mrg return isl_bool_error; 575 1.1 mrg 576 1.1 mrg return isl_bool_ok(pw->n == 0); 577 1.1 mrg } 578 1.1 mrg 579 1.1 mrg static __isl_give PW *FN(PW,realign_domain)(__isl_take PW *pw, 580 1.1 mrg __isl_take isl_reordering *exp) 581 1.1 mrg { 582 1.1 mrg int i; 583 1.1 mrg isl_size n; 584 1.1 mrg 585 1.1 mrg n = FN(PW,n_piece)(pw); 586 1.1 mrg if (n < 0 || !exp) 587 1.1 mrg goto error; 588 1.1 mrg 589 1.1 mrg for (i = 0; i < n; ++i) { 590 1.1 mrg isl_set *domain; 591 1.1 mrg EL *el; 592 1.1 mrg 593 1.1 mrg domain = FN(PW,take_domain_at)(pw, i); 594 1.1 mrg domain = isl_set_realign(domain, isl_reordering_copy(exp)); 595 1.1 mrg pw = FN(PW,restore_domain_at)(pw, i, domain); 596 1.1 mrg 597 1.1 mrg el = FN(PW,take_base_at)(pw, i); 598 1.1 mrg el = FN(EL,realign_domain)(el, isl_reordering_copy(exp)); 599 1.1 mrg pw = FN(PW,restore_base_at)(pw, i, el); 600 1.1 mrg } 601 1.1 mrg 602 1.1 mrg pw = FN(PW,reset_domain_space)(pw, isl_reordering_get_space(exp)); 603 1.1 mrg 604 1.1 mrg isl_reordering_free(exp); 605 1.1 mrg return pw; 606 1.1 mrg error: 607 1.1 mrg isl_reordering_free(exp); 608 1.1 mrg FN(PW,free)(pw); 609 1.1 mrg return NULL; 610 1.1 mrg } 611 1.1 mrg 612 1.1 mrg #undef TYPE 613 1.1 mrg #define TYPE PW 614 1.1 mrg 615 1.1 mrg #include "isl_check_named_params_templ.c" 616 1.1 mrg 617 1.1 mrg /* Align the parameters of "pw" to those of "model". 618 1.1 mrg */ 619 1.1 mrg __isl_give PW *FN(PW,align_params)(__isl_take PW *pw, __isl_take isl_space *model) 620 1.1 mrg { 621 1.1 mrg isl_ctx *ctx; 622 1.1 mrg isl_bool equal_params; 623 1.1 mrg 624 1.1 mrg if (!pw || !model) 625 1.1 mrg goto error; 626 1.1 mrg 627 1.1 mrg ctx = isl_space_get_ctx(model); 628 1.1 mrg if (!isl_space_has_named_params(model)) 629 1.1 mrg isl_die(ctx, isl_error_invalid, 630 1.1 mrg "model has unnamed parameters", goto error); 631 1.1 mrg if (FN(PW,check_named_params)(pw) < 0) 632 1.1 mrg goto error; 633 1.1 mrg equal_params = isl_space_has_equal_params(pw->dim, model); 634 1.1 mrg if (equal_params < 0) 635 1.1 mrg goto error; 636 1.1 mrg if (!equal_params) { 637 1.1 mrg isl_space *space; 638 1.1 mrg isl_reordering *exp; 639 1.1 mrg 640 1.1 mrg space = FN(PW,get_domain_space)(pw); 641 1.1 mrg exp = isl_parameter_alignment_reordering(space, model); 642 1.1 mrg isl_space_free(space); 643 1.1 mrg pw = FN(PW,realign_domain)(pw, exp); 644 1.1 mrg } 645 1.1 mrg 646 1.1 mrg isl_space_free(model); 647 1.1 mrg return pw; 648 1.1 mrg error: 649 1.1 mrg isl_space_free(model); 650 1.1 mrg FN(PW,free)(pw); 651 1.1 mrg return NULL; 652 1.1 mrg } 653 1.1 mrg 654 1.1 mrg #undef TYPE 655 1.1 mrg #define TYPE PW 656 1.1 mrg 657 1.1 mrg static 658 1.1 mrg #include "isl_align_params_bin_templ.c" 659 1.1 mrg 660 1.1 mrg #undef SUFFIX 661 1.1 mrg #define SUFFIX set 662 1.1 mrg #undef ARG1 663 1.1 mrg #define ARG1 PW 664 1.1 mrg #undef ARG2 665 1.1 mrg #define ARG2 isl_set 666 1.1 mrg 667 1.1 mrg static 668 1.1 mrg #include "isl_align_params_templ.c" 669 1.1 mrg 670 1.1 mrg #undef TYPE 671 1.1 mrg #define TYPE PW 672 1.1 mrg 673 1.1 mrg #include "isl_type_has_equal_space_bin_templ.c" 674 1.1 mrg #include "isl_type_check_equal_space_templ.c" 675 1.1 mrg 676 1.1 mrg /* Private version of "union_add". For isl_pw_qpolynomial and 677 1.1 mrg * isl_pw_qpolynomial_fold, we prefer to simply call it "add". 678 1.1 mrg */ 679 1.1 mrg static __isl_give PW *FN(PW,union_add_)(__isl_take PW *pw1, __isl_take PW *pw2) 680 1.1 mrg { 681 1.1 mrg int i, j, n; 682 1.1 mrg struct PW *res; 683 1.1 mrg isl_ctx *ctx; 684 1.1 mrg isl_set *set; 685 1.1 mrg 686 1.1 mrg if (FN(PW,align_params_bin)(&pw1, &pw2) < 0) 687 1.1 mrg goto error; 688 1.1 mrg 689 1.1 mrg ctx = isl_space_get_ctx(pw1->dim); 690 1.1 mrg if (!OPT_EQUAL_TYPES(pw1->, pw2->)) 691 1.1 mrg isl_die(ctx, isl_error_invalid, 692 1.1 mrg "fold types don't match", goto error); 693 1.1 mrg if (FN(PW,check_equal_space)(pw1, pw2) < 0) 694 1.1 mrg goto error; 695 1.1 mrg 696 1.1 mrg if (FN(PW,IS_ZERO)(pw1)) { 697 1.1 mrg FN(PW,free)(pw1); 698 1.1 mrg return pw2; 699 1.1 mrg } 700 1.1 mrg 701 1.1 mrg if (FN(PW,IS_ZERO)(pw2)) { 702 1.1 mrg FN(PW,free)(pw2); 703 1.1 mrg return pw1; 704 1.1 mrg } 705 1.1 mrg 706 1.1 mrg n = (pw1->n + 1) * (pw2->n + 1); 707 1.1 mrg res = FN(PW,alloc_size)(isl_space_copy(pw1->dim) 708 1.1 mrg OPT_TYPE_ARG(pw1->), n); 709 1.1 mrg 710 1.1 mrg for (i = 0; i < pw1->n; ++i) { 711 1.1 mrg set = isl_set_copy(pw1->p[i].set); 712 1.1 mrg for (j = 0; j < pw2->n; ++j) { 713 1.1 mrg struct isl_set *common; 714 1.1 mrg EL *sum; 715 1.1 mrg common = isl_set_intersect(isl_set_copy(pw1->p[i].set), 716 1.1 mrg isl_set_copy(pw2->p[j].set)); 717 1.1 mrg if (isl_set_plain_is_empty(common)) { 718 1.1 mrg isl_set_free(common); 719 1.1 mrg continue; 720 1.1 mrg } 721 1.1 mrg set = isl_set_subtract(set, 722 1.1 mrg isl_set_copy(pw2->p[j].set)); 723 1.1 mrg 724 1.1 mrg sum = FN(EL,add_on_domain)(common, 725 1.1 mrg FN(EL,copy)(pw1->p[i].FIELD), 726 1.1 mrg FN(EL,copy)(pw2->p[j].FIELD)); 727 1.1 mrg 728 1.1 mrg res = FN(PW,add_piece)(res, common, sum); 729 1.1 mrg } 730 1.1 mrg res = FN(PW,add_piece)(res, set, FN(EL,copy)(pw1->p[i].FIELD)); 731 1.1 mrg } 732 1.1 mrg 733 1.1 mrg for (j = 0; j < pw2->n; ++j) { 734 1.1 mrg set = isl_set_copy(pw2->p[j].set); 735 1.1 mrg for (i = 0; i < pw1->n; ++i) 736 1.1 mrg set = isl_set_subtract(set, 737 1.1 mrg isl_set_copy(pw1->p[i].set)); 738 1.1 mrg res = FN(PW,add_piece)(res, set, FN(EL,copy)(pw2->p[j].FIELD)); 739 1.1 mrg } 740 1.1 mrg 741 1.1 mrg FN(PW,free)(pw1); 742 1.1 mrg FN(PW,free)(pw2); 743 1.1 mrg 744 1.1 mrg return res; 745 1.1 mrg error: 746 1.1 mrg FN(PW,free)(pw1); 747 1.1 mrg FN(PW,free)(pw2); 748 1.1 mrg return NULL; 749 1.1 mrg } 750 1.1 mrg 751 1.1 mrg #if !DEFAULT_IS_ZERO 752 1.1 mrg 753 1.1 mrg /* Compute the sum of "pw1" and "pw2 on the union of their domains, 754 1.1 mrg * with the actual sum on the shared domain and 755 1.1 mrg * the defined expression on the symmetric difference of the domains. 756 1.1 mrg * 757 1.1 mrg * This function is only defined for object types that do not have 758 1.1 mrg * a default zero value. For other object types, this function 759 1.1 mrg * is simply called "add". 760 1.1 mrg */ 761 1.1 mrg __isl_give PW *FN(PW,union_add)(__isl_take PW *pw1, __isl_take PW *pw2) 762 1.1 mrg { 763 1.1 mrg return FN(PW,union_add_)(pw1, pw2); 764 1.1 mrg } 765 1.1 mrg 766 1.1 mrg #endif 767 1.1 mrg 768 1.1 mrg /* This function is currently only used from isl_aff.c 769 1.1 mrg */ 770 1.1 mrg static __isl_give PW *FN(PW,on_shared_domain_in)(__isl_take PW *pw1, 771 1.1 mrg __isl_take PW *pw2, __isl_take isl_space *space, 772 1.1 mrg __isl_give EL *(*fn)(__isl_take EL *el1, __isl_take EL *el2)) 773 1.1 mrg __attribute__ ((unused)); 774 1.1 mrg 775 1.1 mrg /* Apply "fn" to pairs of elements from pw1 and pw2 on shared domains. 776 1.1 mrg * The result of "fn" (and therefore also of this function) lives in "space". 777 1.1 mrg */ 778 1.1 mrg static __isl_give PW *FN(PW,on_shared_domain_in)(__isl_take PW *pw1, 779 1.1 mrg __isl_take PW *pw2, __isl_take isl_space *space, 780 1.1 mrg __isl_give EL *(*fn)(__isl_take EL *el1, __isl_take EL *el2)) 781 1.1 mrg { 782 1.1 mrg int i, j, n; 783 1.1 mrg PW *res = NULL; 784 1.1 mrg 785 1.1 mrg if (!pw1 || !pw2) 786 1.1 mrg goto error; 787 1.1 mrg 788 1.1 mrg n = pw1->n * pw2->n; 789 1.1 mrg res = FN(PW,alloc_size)(isl_space_copy(space) OPT_TYPE_ARG(pw1->), n); 790 1.1 mrg 791 1.1 mrg for (i = 0; i < pw1->n; ++i) { 792 1.1 mrg for (j = 0; j < pw2->n; ++j) { 793 1.1 mrg isl_set *common; 794 1.1 mrg EL *res_ij; 795 1.1 mrg int empty; 796 1.1 mrg 797 1.1 mrg common = isl_set_intersect( 798 1.1 mrg isl_set_copy(pw1->p[i].set), 799 1.1 mrg isl_set_copy(pw2->p[j].set)); 800 1.1 mrg empty = isl_set_plain_is_empty(common); 801 1.1 mrg if (empty < 0 || empty) { 802 1.1 mrg isl_set_free(common); 803 1.1 mrg if (empty < 0) 804 1.1 mrg goto error; 805 1.1 mrg continue; 806 1.1 mrg } 807 1.1 mrg 808 1.1 mrg res_ij = fn(FN(EL,copy)(pw1->p[i].FIELD), 809 1.1 mrg FN(EL,copy)(pw2->p[j].FIELD)); 810 1.1 mrg res_ij = FN(EL,gist)(res_ij, isl_set_copy(common)); 811 1.1 mrg 812 1.1 mrg res = FN(PW,add_piece)(res, common, res_ij); 813 1.1 mrg } 814 1.1 mrg } 815 1.1 mrg 816 1.1 mrg isl_space_free(space); 817 1.1 mrg FN(PW,free)(pw1); 818 1.1 mrg FN(PW,free)(pw2); 819 1.1 mrg return res; 820 1.1 mrg error: 821 1.1 mrg isl_space_free(space); 822 1.1 mrg FN(PW,free)(pw1); 823 1.1 mrg FN(PW,free)(pw2); 824 1.1 mrg FN(PW,free)(res); 825 1.1 mrg return NULL; 826 1.1 mrg } 827 1.1 mrg 828 1.1 mrg /* This function is currently only used from isl_aff.c 829 1.1 mrg */ 830 1.1 mrg static __isl_give PW *FN(PW,on_shared_domain)(__isl_take PW *pw1, 831 1.1 mrg __isl_take PW *pw2, 832 1.1 mrg __isl_give EL *(*fn)(__isl_take EL *el1, __isl_take EL *el2)) 833 1.1 mrg __attribute__ ((unused)); 834 1.1 mrg 835 1.1 mrg /* Apply "fn" to pairs of elements from pw1 and pw2 on shared domains. 836 1.1 mrg * The result of "fn" is assumed to live in the same space as "pw1" and "pw2". 837 1.1 mrg */ 838 1.1 mrg static __isl_give PW *FN(PW,on_shared_domain)(__isl_take PW *pw1, 839 1.1 mrg __isl_take PW *pw2, 840 1.1 mrg __isl_give EL *(*fn)(__isl_take EL *el1, __isl_take EL *el2)) 841 1.1 mrg { 842 1.1 mrg isl_space *space; 843 1.1 mrg 844 1.1 mrg if (FN(PW,check_equal_space)(pw1, pw2) < 0) 845 1.1 mrg goto error; 846 1.1 mrg 847 1.1 mrg space = isl_space_copy(pw1->dim); 848 1.1 mrg return FN(PW,on_shared_domain_in)(pw1, pw2, space, fn); 849 1.1 mrg error: 850 1.1 mrg FN(PW,free)(pw1); 851 1.1 mrg FN(PW,free)(pw2); 852 1.1 mrg return NULL; 853 1.1 mrg } 854 1.1 mrg 855 1.1 mrg /* Return the parameter domain of "pw". 856 1.1 mrg */ 857 1.1 mrg __isl_give isl_set *FN(PW,params)(__isl_take PW *pw) 858 1.1 mrg { 859 1.1 mrg return isl_set_params(FN(PW,domain)(pw)); 860 1.1 mrg } 861 1.1 mrg 862 1.1 mrg __isl_give isl_set *FN(PW,domain)(__isl_take PW *pw) 863 1.1 mrg { 864 1.1 mrg int i; 865 1.1 mrg isl_set *dom; 866 1.1 mrg 867 1.1 mrg if (!pw) 868 1.1 mrg return NULL; 869 1.1 mrg 870 1.1 mrg dom = isl_set_empty(FN(PW,get_domain_space)(pw)); 871 1.1 mrg for (i = 0; i < pw->n; ++i) 872 1.1 mrg dom = isl_set_union_disjoint(dom, isl_set_copy(pw->p[i].set)); 873 1.1 mrg 874 1.1 mrg FN(PW,free)(pw); 875 1.1 mrg 876 1.1 mrg return dom; 877 1.1 mrg } 878 1.1 mrg 879 1.1 mrg /* Exploit the equalities in the domain of piece "i" of "pw" 880 1.1 mrg * to simplify the associated function. 881 1.1 mrg * If the domain of piece "i" is empty, then remove it entirely, 882 1.1 mrg * replacing it with the final piece. 883 1.1 mrg */ 884 1.1 mrg static __isl_give PW *FN(PW,exploit_equalities_and_remove_if_empty)( 885 1.1 mrg __isl_take PW *pw, int i) 886 1.1 mrg { 887 1.1 mrg EL *el; 888 1.1 mrg isl_set *domain; 889 1.1 mrg isl_basic_set *aff; 890 1.1 mrg int empty; 891 1.1 mrg 892 1.1 mrg domain = FN(PW,peek_domain_at)(pw, i); 893 1.1 mrg empty = isl_set_plain_is_empty(domain); 894 1.1 mrg if (empty < 0) 895 1.1 mrg return FN(PW,free)(pw); 896 1.1 mrg if (empty) { 897 1.1 mrg isl_set_free(pw->p[i].set); 898 1.1 mrg FN(EL,free)(pw->p[i].FIELD); 899 1.1 mrg if (i != pw->n - 1) 900 1.1 mrg pw->p[i] = pw->p[pw->n - 1]; 901 1.1 mrg pw->n--; 902 1.1 mrg 903 1.1 mrg return pw; 904 1.1 mrg } 905 1.1 mrg 906 1.1 mrg aff = isl_set_affine_hull(FN(PW,get_domain_at)(pw, i)); 907 1.1 mrg el = FN(PW,take_base_at)(pw, i); 908 1.1 mrg el = FN(EL,substitute_equalities)(el, aff); 909 1.1 mrg pw = FN(PW,restore_base_at_inplace)(pw, i, el); 910 1.1 mrg 911 1.1 mrg return pw; 912 1.1 mrg } 913 1.1 mrg 914 1.1 mrg /* Restrict the domain of "pw" by combining each cell 915 1.1 mrg * with "set" through a call to "fn", where "fn" may be 916 1.1 mrg * isl_set_intersect, isl_set_intersect_params, isl_set_intersect_factor_domain, 917 1.1 mrg * isl_set_intersect_factor_range or isl_set_subtract. 918 1.1 mrg */ 919 1.1 mrg static __isl_give PW *FN(PW,restrict_domain)(__isl_take PW *pw, 920 1.1 mrg __isl_take isl_set *set, 921 1.1 mrg __isl_give isl_set *(*fn)(__isl_take isl_set *set1, 922 1.1 mrg __isl_take isl_set *set2)) 923 1.1 mrg { 924 1.1 mrg int i; 925 1.1 mrg isl_size n; 926 1.1 mrg 927 1.1 mrg FN(PW,align_params_set)(&pw, &set); 928 1.1 mrg n = FN(PW,n_piece)(pw); 929 1.1 mrg if (n < 0 || !set) 930 1.1 mrg goto error; 931 1.1 mrg 932 1.1 mrg for (i = n - 1; i >= 0; --i) { 933 1.1 mrg isl_set *domain; 934 1.1 mrg 935 1.1 mrg domain = FN(PW,take_domain_at)(pw, i); 936 1.1 mrg domain = fn(domain, isl_set_copy(set)); 937 1.1 mrg pw = FN(PW,restore_domain_at)(pw, i, domain); 938 1.1 mrg pw = FN(PW,exploit_equalities_and_remove_if_empty)(pw, i); 939 1.1 mrg } 940 1.1 mrg 941 1.1 mrg isl_set_free(set); 942 1.1 mrg return pw; 943 1.1 mrg error: 944 1.1 mrg isl_set_free(set); 945 1.1 mrg FN(PW,free)(pw); 946 1.1 mrg return NULL; 947 1.1 mrg } 948 1.1 mrg 949 1.1 mrg __isl_give PW *FN(PW,intersect_domain)(__isl_take PW *pw, 950 1.1 mrg __isl_take isl_set *context) 951 1.1 mrg { 952 1.1 mrg return FN(PW,restrict_domain)(pw, context, &isl_set_intersect); 953 1.1 mrg } 954 1.1 mrg 955 1.1 mrg /* Intersect the domain of "pw" with the parameter domain "context". 956 1.1 mrg */ 957 1.1 mrg __isl_give PW *FN(PW,intersect_params)(__isl_take PW *pw, 958 1.1 mrg __isl_take isl_set *context) 959 1.1 mrg { 960 1.1 mrg return FN(PW,restrict_domain)(pw, context, &isl_set_intersect_params); 961 1.1 mrg } 962 1.1 mrg 963 1.1 mrg /* Given a piecewise expression "pw" with domain in a space [A -> B] and 964 1.1 mrg * a set in the space A, intersect the domain with the set. 965 1.1 mrg */ 966 1.1 mrg __isl_give PW *FN(PW,intersect_domain_wrapped_domain)(__isl_take PW *pw, 967 1.1 mrg __isl_take isl_set *set) 968 1.1 mrg { 969 1.1 mrg return FN(PW,restrict_domain)(pw, set, 970 1.1 mrg &isl_set_intersect_factor_domain); 971 1.1 mrg } 972 1.1 mrg 973 1.1 mrg /* Given a piecewise expression "pw" with domain in a space [A -> B] and 974 1.1 mrg * a set in the space B, intersect the domain with the set. 975 1.1 mrg */ 976 1.1 mrg __isl_give PW *FN(PW,intersect_domain_wrapped_range)(__isl_take PW *pw, 977 1.1 mrg __isl_take isl_set *set) 978 1.1 mrg { 979 1.1 mrg return FN(PW,restrict_domain)(pw, set, &isl_set_intersect_factor_range); 980 1.1 mrg } 981 1.1 mrg 982 1.1 mrg /* Subtract "domain' from the domain of "pw". 983 1.1 mrg */ 984 1.1 mrg __isl_give PW *FN(PW,subtract_domain)(__isl_take PW *pw, 985 1.1 mrg __isl_take isl_set *domain) 986 1.1 mrg { 987 1.1 mrg return FN(PW,restrict_domain)(pw, domain, &isl_set_subtract); 988 1.1 mrg } 989 1.1 mrg 990 1.1 mrg /* Return -1 if the piece "p1" should be sorted before "p2" 991 1.1 mrg * and 1 if it should be sorted after "p2". 992 1.1 mrg * Return 0 if they do not need to be sorted in a specific order. 993 1.1 mrg * 994 1.1 mrg * The two pieces are compared on the basis of their function value expressions. 995 1.1 mrg */ 996 1.1 mrg static int FN(PW,sort_field_cmp)(const void *p1, const void *p2, void *arg) 997 1.1 mrg { 998 1.1 mrg struct FN(PW,piece) const *pc1 = p1; 999 1.1 mrg struct FN(PW,piece) const *pc2 = p2; 1000 1.1 mrg 1001 1.1 mrg return FN(EL,plain_cmp)(pc1->FIELD, pc2->FIELD); 1002 1.1 mrg } 1003 1.1 mrg 1004 1.1 mrg /* Sort the pieces of "pw" according to their function value 1005 1.1 mrg * expressions and then combine pairs of adjacent pieces with 1006 1.1 mrg * the same such expression. 1007 1.1 mrg * 1008 1.1 mrg * The sorting is performed in place because it does not 1009 1.1 mrg * change the meaning of "pw", but care needs to be 1010 1.1 mrg * taken not to change any possible other copies of "pw" 1011 1.1 mrg * in case anything goes wrong. 1012 1.1 mrg */ 1013 1.1 mrg static __isl_give PW *FN(PW,sort_unique)(__isl_take PW *pw) 1014 1.1 mrg { 1015 1.1 mrg int i, j; 1016 1.1 mrg isl_set *set; 1017 1.1 mrg 1018 1.1 mrg if (!pw) 1019 1.1 mrg return NULL; 1020 1.1 mrg if (pw->n <= 1) 1021 1.1 mrg return pw; 1022 1.1 mrg if (isl_sort(pw->p, pw->n, sizeof(pw->p[0]), 1023 1.1 mrg &FN(PW,sort_field_cmp), NULL) < 0) 1024 1.1 mrg return FN(PW,free)(pw); 1025 1.1 mrg for (i = pw->n - 1; i >= 1; --i) { 1026 1.1 mrg isl_bool equal; 1027 1.1 mrg EL *el, *el_prev; 1028 1.1 mrg isl_set *set_prev; 1029 1.1 mrg 1030 1.1 mrg el = FN(PW,peek_base_at)(pw, i); 1031 1.1 mrg el_prev = FN(PW,peek_base_at)(pw, i - 1); 1032 1.1 mrg equal = FN(EL,plain_is_equal)(el, el_prev); 1033 1.1 mrg if (equal < 0) 1034 1.1 mrg return FN(PW,free)(pw); 1035 1.1 mrg if (!equal) 1036 1.1 mrg continue; 1037 1.1 mrg set = FN(PW,get_domain_at)(pw, i); 1038 1.1 mrg set_prev = FN(PW,get_domain_at)(pw, i - 1); 1039 1.1 mrg set = isl_set_union(set_prev, set); 1040 1.1 mrg if (!set) 1041 1.1 mrg return FN(PW,free)(pw); 1042 1.1 mrg isl_set_free(pw->p[i].set); 1043 1.1 mrg FN(EL,free)(pw->p[i].FIELD); 1044 1.1 mrg isl_set_free(pw->p[i - 1].set); 1045 1.1 mrg pw->p[i - 1].set = set; 1046 1.1 mrg for (j = i + 1; j < pw->n; ++j) 1047 1.1 mrg pw->p[j - 1] = pw->p[j]; 1048 1.1 mrg pw->n--; 1049 1.1 mrg } 1050 1.1 mrg 1051 1.1 mrg return pw; 1052 1.1 mrg } 1053 1.1 mrg 1054 1.1 mrg /* Compute the gist of "pw" with respect to the domain constraints 1055 1.1 mrg * of "context" for the case where the domain of the last element 1056 1.1 mrg * of "pw" is equal to "context". 1057 1.1 mrg * Compute the gist of this element, replace 1058 1.1 mrg * its domain by the universe and drop all other elements 1059 1.1 mrg * as their domains are necessarily disjoint from "context". 1060 1.1 mrg */ 1061 1.1 mrg static __isl_give PW *FN(PW,gist_last)(__isl_take PW *pw, 1062 1.1 mrg __isl_take isl_set *context) 1063 1.1 mrg { 1064 1.1 mrg int i; 1065 1.1 mrg isl_space *space; 1066 1.1 mrg EL *el; 1067 1.1 mrg 1068 1.1 mrg for (i = 0; i < pw->n - 1; ++i) { 1069 1.1 mrg isl_set_free(pw->p[i].set); 1070 1.1 mrg FN(EL,free)(pw->p[i].FIELD); 1071 1.1 mrg } 1072 1.1 mrg pw->p[0].FIELD = pw->p[pw->n - 1].FIELD; 1073 1.1 mrg pw->p[0].set = pw->p[pw->n - 1].set; 1074 1.1 mrg pw->n = 1; 1075 1.1 mrg 1076 1.1 mrg space = isl_set_get_space(context); 1077 1.1 mrg el = FN(PW,take_base_at)(pw, 0); 1078 1.1 mrg el = FN(EL,gist)(el, context); 1079 1.1 mrg pw = FN(PW,restore_base_at)(pw, 0, el); 1080 1.1 mrg context = isl_set_universe(space); 1081 1.1 mrg pw = FN(PW,restore_domain_at)(pw, 0, context); 1082 1.1 mrg 1083 1.1 mrg return pw; 1084 1.1 mrg } 1085 1.1 mrg 1086 1.1 mrg /* Compute the gist of "pw" with respect to the domain constraints 1087 1.1 mrg * of "context". 1088 1.1 mrg * Call "fn_dom" to compute the gist of the domains and 1089 1.1 mrg * "intersect_context" to intersect the domain with the context. 1090 1.1 mrg * 1091 1.1 mrg * If the piecewise expression is empty or the context is the universe, 1092 1.1 mrg * then nothing can be simplified. 1093 1.1 mrg * If "pw" has a single domain and it is equal to "context", 1094 1.1 mrg * then simply replace the domain by the universe. 1095 1.1 mrg * Combine duplicate function value expressions first 1096 1.1 mrg * to increase the chance of "pw" having a single domain. 1097 1.1 mrg */ 1098 1.1 mrg static __isl_give PW *FN(PW,gist_fn)(__isl_take PW *pw, 1099 1.1 mrg __isl_take isl_set *context, 1100 1.1 mrg __isl_give isl_set *(*fn_dom)(__isl_take isl_set *set, 1101 1.1 mrg __isl_take isl_set *context), 1102 1.1 mrg __isl_give isl_set *intersect_context(__isl_take isl_set *set, 1103 1.1 mrg __isl_take isl_set *context)) 1104 1.1 mrg { 1105 1.1 mrg int i; 1106 1.1 mrg int is_universe; 1107 1.1 mrg 1108 1.1 mrg pw = FN(PW,sort_unique)(pw); 1109 1.1 mrg if (!pw || !context) 1110 1.1 mrg goto error; 1111 1.1 mrg 1112 1.1 mrg if (pw->n == 0) { 1113 1.1 mrg isl_set_free(context); 1114 1.1 mrg return pw; 1115 1.1 mrg } 1116 1.1 mrg 1117 1.1 mrg is_universe = isl_set_plain_is_universe(context); 1118 1.1 mrg if (is_universe < 0) 1119 1.1 mrg goto error; 1120 1.1 mrg if (is_universe) { 1121 1.1 mrg isl_set_free(context); 1122 1.1 mrg return pw; 1123 1.1 mrg } 1124 1.1 mrg 1125 1.1 mrg FN(PW,align_params_set)(&pw, &context); 1126 1.1 mrg 1127 1.1 mrg pw = FN(PW,cow)(pw); 1128 1.1 mrg if (!pw) 1129 1.1 mrg goto error; 1130 1.1 mrg 1131 1.1 mrg if (pw->n == 1) { 1132 1.1 mrg int equal; 1133 1.1 mrg 1134 1.1 mrg equal = isl_set_plain_is_equal(pw->p[0].set, context); 1135 1.1 mrg if (equal < 0) 1136 1.1 mrg goto error; 1137 1.1 mrg if (equal) 1138 1.1 mrg return FN(PW,gist_last)(pw, context); 1139 1.1 mrg } 1140 1.1 mrg 1141 1.1 mrg context = isl_set_compute_divs(context); 1142 1.1 mrg 1143 1.1 mrg for (i = pw->n - 1; i >= 0; --i) { 1144 1.1 mrg isl_set *set_i; 1145 1.1 mrg EL *el; 1146 1.1 mrg int empty; 1147 1.1 mrg 1148 1.1 mrg if (i == pw->n - 1) { 1149 1.1 mrg int equal; 1150 1.1 mrg equal = isl_set_plain_is_equal(pw->p[i].set, context); 1151 1.1 mrg if (equal < 0) 1152 1.1 mrg goto error; 1153 1.1 mrg if (equal) 1154 1.1 mrg return FN(PW,gist_last)(pw, context); 1155 1.1 mrg } 1156 1.1 mrg set_i = FN(PW,get_domain_at)(pw, i); 1157 1.1 mrg set_i = intersect_context(set_i, isl_set_copy(context)); 1158 1.1 mrg empty = isl_set_plain_is_empty(set_i); 1159 1.1 mrg el = FN(PW,take_base_at)(pw, i); 1160 1.1 mrg el = FN(EL,gist)(el, set_i); 1161 1.1 mrg pw = FN(PW,restore_base_at)(pw, i, el); 1162 1.1 mrg set_i = FN(PW,take_domain_at)(pw, i); 1163 1.1 mrg set_i = fn_dom(set_i, isl_set_copy(context)); 1164 1.1 mrg pw = FN(PW,restore_domain_at)(pw, i, set_i); 1165 1.1 mrg if (empty < 0 || !pw) 1166 1.1 mrg goto error; 1167 1.1 mrg if (empty) { 1168 1.1 mrg isl_set_free(pw->p[i].set); 1169 1.1 mrg FN(EL,free)(pw->p[i].FIELD); 1170 1.1 mrg if (i != pw->n - 1) 1171 1.1 mrg pw->p[i] = pw->p[pw->n - 1]; 1172 1.1 mrg pw->n--; 1173 1.1 mrg } 1174 1.1 mrg } 1175 1.1 mrg 1176 1.1 mrg isl_set_free(context); 1177 1.1 mrg 1178 1.1 mrg return pw; 1179 1.1 mrg error: 1180 1.1 mrg FN(PW,free)(pw); 1181 1.1 mrg isl_set_free(context); 1182 1.1 mrg return NULL; 1183 1.1 mrg } 1184 1.1 mrg 1185 1.1 mrg __isl_give PW *FN(PW,gist)(__isl_take PW *pw, __isl_take isl_set *context) 1186 1.1 mrg { 1187 1.1 mrg return FN(PW,gist_fn)(pw, context, &isl_set_gist, 1188 1.1 mrg &isl_set_intersect); 1189 1.1 mrg } 1190 1.1 mrg 1191 1.1 mrg __isl_give PW *FN(PW,gist_params)(__isl_take PW *pw, 1192 1.1 mrg __isl_take isl_set *context) 1193 1.1 mrg { 1194 1.1 mrg return FN(PW,gist_fn)(pw, context, &isl_set_gist_params, 1195 1.1 mrg &isl_set_intersect_params); 1196 1.1 mrg } 1197 1.1 mrg 1198 1.1 mrg /* Coalesce the domains of "pw". 1199 1.1 mrg * 1200 1.1 mrg * Prior to the actual coalescing, first sort the pieces such that 1201 1.1 mrg * pieces with the same function value expression are combined 1202 1.1 mrg * into a single piece, the combined domain of which can then 1203 1.1 mrg * be coalesced. 1204 1.1 mrg */ 1205 1.1 mrg __isl_give PW *FN(PW,coalesce)(__isl_take PW *pw) 1206 1.1 mrg { 1207 1.1 mrg int i; 1208 1.1 mrg isl_size n; 1209 1.1 mrg 1210 1.1 mrg pw = FN(PW,sort_unique)(pw); 1211 1.1 mrg n = FN(PW,n_piece)(pw); 1212 1.1 mrg if (n < 0) 1213 1.1 mrg return FN(PW,free)(pw); 1214 1.1 mrg 1215 1.1 mrg for (i = 0; i < n; ++i) { 1216 1.1 mrg pw->p[i].set = isl_set_coalesce(pw->p[i].set); 1217 1.1 mrg if (!pw->p[i].set) 1218 1.1 mrg goto error; 1219 1.1 mrg } 1220 1.1 mrg 1221 1.1 mrg return pw; 1222 1.1 mrg error: 1223 1.1 mrg FN(PW,free)(pw); 1224 1.1 mrg return NULL; 1225 1.1 mrg } 1226 1.1 mrg 1227 1.1 mrg isl_ctx *FN(PW,get_ctx)(__isl_keep PW *pw) 1228 1.1 mrg { 1229 1.1 mrg return pw ? isl_space_get_ctx(pw->dim) : NULL; 1230 1.1 mrg } 1231 1.1 mrg 1232 1.1 mrg isl_bool FN(PW,involves_dims)(__isl_keep PW *pw, enum isl_dim_type type, 1233 1.1 mrg unsigned first, unsigned n) 1234 1.1 mrg { 1235 1.1 mrg int i; 1236 1.1 mrg enum isl_dim_type set_type; 1237 1.1 mrg 1238 1.1 mrg if (!pw) 1239 1.1 mrg return isl_bool_error; 1240 1.1 mrg if (pw->n == 0 || n == 0) 1241 1.1 mrg return isl_bool_false; 1242 1.1 mrg 1243 1.1 mrg set_type = type == isl_dim_in ? isl_dim_set : type; 1244 1.1 mrg 1245 1.1 mrg for (i = 0; i < pw->n; ++i) { 1246 1.1 mrg isl_bool involves = FN(EL,involves_dims)(pw->p[i].FIELD, 1247 1.1 mrg type, first, n); 1248 1.1 mrg if (involves < 0 || involves) 1249 1.1 mrg return involves; 1250 1.1 mrg involves = isl_set_involves_dims(pw->p[i].set, 1251 1.1 mrg set_type, first, n); 1252 1.1 mrg if (involves < 0 || involves) 1253 1.1 mrg return involves; 1254 1.1 mrg } 1255 1.1 mrg return isl_bool_false; 1256 1.1 mrg } 1257 1.1 mrg 1258 1.1 mrg __isl_give PW *FN(PW,set_dim_name)(__isl_take PW *pw, 1259 1.1 mrg enum isl_dim_type type, unsigned pos, const char *s) 1260 1.1 mrg { 1261 1.1 mrg isl_space *space; 1262 1.1 mrg 1263 1.1 mrg space = FN(PW,get_space)(pw); 1264 1.1 mrg space = isl_space_set_dim_name(space, type, pos, s); 1265 1.1 mrg return FN(PW,reset_space)(pw, space); 1266 1.1 mrg } 1267 1.1 mrg 1268 1.1 mrg __isl_give PW *FN(PW,drop_dims)(__isl_take PW *pw, 1269 1.1 mrg enum isl_dim_type type, unsigned first, unsigned n) 1270 1.1 mrg { 1271 1.1 mrg int i; 1272 1.1 mrg isl_size n_piece; 1273 1.1 mrg enum isl_dim_type set_type; 1274 1.1 mrg isl_space *space; 1275 1.1 mrg 1276 1.1 mrg n_piece = FN(PW,n_piece)(pw); 1277 1.1 mrg if (n_piece < 0) 1278 1.1 mrg return FN(PW,free)(pw); 1279 1.1 mrg if (n == 0 && !isl_space_get_tuple_name(pw->dim, type)) 1280 1.1 mrg return pw; 1281 1.1 mrg 1282 1.1 mrg set_type = type == isl_dim_in ? isl_dim_set : type; 1283 1.1 mrg 1284 1.1 mrg space = FN(PW,take_space)(pw); 1285 1.1 mrg space = isl_space_drop_dims(space, type, first, n); 1286 1.1 mrg pw = FN(PW,restore_space)(pw, space); 1287 1.1 mrg for (i = 0; i < n_piece; ++i) { 1288 1.1 mrg isl_set *domain; 1289 1.1 mrg EL *el; 1290 1.1 mrg 1291 1.1 mrg el = FN(PW,take_base_at)(pw, i); 1292 1.1 mrg el = FN(EL,drop_dims)(el, type, first, n); 1293 1.1 mrg pw = FN(PW,restore_base_at)(pw, i, el); 1294 1.1 mrg if (type == isl_dim_out) 1295 1.1 mrg continue; 1296 1.1 mrg domain = FN(PW,take_domain_at)(pw, i); 1297 1.1 mrg domain = isl_set_drop(domain, set_type, first, n); 1298 1.1 mrg pw = FN(PW,restore_domain_at)(pw, i, domain); 1299 1.1 mrg } 1300 1.1 mrg 1301 1.1 mrg return pw; 1302 1.1 mrg } 1303 1.1 mrg 1304 1.1 mrg /* This function is very similar to drop_dims. 1305 1.1 mrg * The only difference is that the cells may still involve 1306 1.1 mrg * the specified dimensions. They are removed using 1307 1.1 mrg * isl_set_project_out instead of isl_set_drop. 1308 1.1 mrg */ 1309 1.1 mrg __isl_give PW *FN(PW,project_out)(__isl_take PW *pw, 1310 1.1 mrg enum isl_dim_type type, unsigned first, unsigned n) 1311 1.1 mrg { 1312 1.1 mrg int i; 1313 1.1 mrg isl_size n_piece; 1314 1.1 mrg enum isl_dim_type set_type; 1315 1.1 mrg isl_space *space; 1316 1.1 mrg 1317 1.1 mrg n_piece = FN(PW,n_piece)(pw); 1318 1.1 mrg if (n_piece < 0) 1319 1.1 mrg return FN(PW,free)(pw); 1320 1.1 mrg if (n == 0 && !isl_space_get_tuple_name(pw->dim, type)) 1321 1.1 mrg return pw; 1322 1.1 mrg 1323 1.1 mrg set_type = type == isl_dim_in ? isl_dim_set : type; 1324 1.1 mrg 1325 1.1 mrg space = FN(PW,take_space)(pw); 1326 1.1 mrg space = isl_space_drop_dims(space, type, first, n); 1327 1.1 mrg pw = FN(PW,restore_space)(pw, space); 1328 1.1 mrg for (i = 0; i < n_piece; ++i) { 1329 1.1 mrg isl_set *domain; 1330 1.1 mrg EL *el; 1331 1.1 mrg 1332 1.1 mrg domain = FN(PW,take_domain_at)(pw, i); 1333 1.1 mrg domain = isl_set_project_out(domain, set_type, first, n); 1334 1.1 mrg pw = FN(PW,restore_domain_at)(pw, i, domain); 1335 1.1 mrg el = FN(PW,take_base_at)(pw, i); 1336 1.1 mrg el = FN(EL,drop_dims)(el, type, first, n); 1337 1.1 mrg pw = FN(PW,restore_base_at)(pw, i, el); 1338 1.1 mrg } 1339 1.1 mrg 1340 1.1 mrg return pw; 1341 1.1 mrg } 1342 1.1 mrg 1343 1.1 mrg /* Project the domain of pw onto its parameter space. 1344 1.1 mrg */ 1345 1.1 mrg __isl_give PW *FN(PW,project_domain_on_params)(__isl_take PW *pw) 1346 1.1 mrg { 1347 1.1 mrg isl_space *space; 1348 1.1 mrg isl_size n; 1349 1.1 mrg 1350 1.1 mrg n = FN(PW,dim)(pw, isl_dim_in); 1351 1.1 mrg if (n < 0) 1352 1.1 mrg return FN(PW,free)(pw); 1353 1.1 mrg pw = FN(PW,project_out)(pw, isl_dim_in, 0, n); 1354 1.1 mrg space = FN(PW,get_domain_space)(pw); 1355 1.1 mrg space = isl_space_params(space); 1356 1.1 mrg pw = FN(PW,reset_domain_space)(pw, space); 1357 1.1 mrg return pw; 1358 1.1 mrg } 1359 1.1 mrg 1360 1.1 mrg #undef TYPE 1361 1.1 mrg #define TYPE PW 1362 1.1 mrg #include "isl_drop_unused_params_templ.c" 1363 1.1 mrg 1364 1.1 mrg isl_size FN(PW,dim)(__isl_keep PW *pw, enum isl_dim_type type) 1365 1.1 mrg { 1366 1.1 mrg return isl_space_dim(FN(PW,peek_space)(pw), type); 1367 1.1 mrg } 1368 1.1 mrg 1369 1.1 mrg __isl_give isl_space *FN(PW,get_domain_space)(__isl_keep PW *pw) 1370 1.1 mrg { 1371 1.1 mrg return pw ? isl_space_domain(isl_space_copy(pw->dim)) : NULL; 1372 1.1 mrg } 1373 1.1 mrg 1374 1.1 mrg /* Return the position of the dimension of the given type and name 1375 1.1 mrg * in "pw". 1376 1.1 mrg * Return -1 if no such dimension can be found. 1377 1.1 mrg */ 1378 1.1 mrg int FN(PW,find_dim_by_name)(__isl_keep PW *pw, 1379 1.1 mrg enum isl_dim_type type, const char *name) 1380 1.1 mrg { 1381 1.1 mrg if (!pw) 1382 1.1 mrg return -1; 1383 1.1 mrg return isl_space_find_dim_by_name(pw->dim, type, name); 1384 1.1 mrg } 1385 1.1 mrg 1386 1.1 mrg /* Return the position of the dimension of the given type and identifier 1387 1.1 mrg * in "pw". 1388 1.1 mrg * Return -1 if no such dimension can be found. 1389 1.1 mrg */ 1390 1.1 mrg static int FN(PW,find_dim_by_id)(__isl_keep PW *pw, 1391 1.1 mrg enum isl_dim_type type, __isl_keep isl_id *id) 1392 1.1 mrg { 1393 1.1 mrg isl_space *space; 1394 1.1 mrg 1395 1.1 mrg space = FN(PW,peek_space)(pw); 1396 1.1 mrg return isl_space_find_dim_by_id(space, type, id); 1397 1.1 mrg } 1398 1.1 mrg 1399 1.1 mrg /* Does the piecewise expression "pw" depend in any way 1400 1.1 mrg * on the parameter with identifier "id"? 1401 1.1 mrg */ 1402 1.1 mrg isl_bool FN(PW,involves_param_id)(__isl_keep PW *pw, __isl_keep isl_id *id) 1403 1.1 mrg { 1404 1.1 mrg int pos; 1405 1.1 mrg 1406 1.1 mrg if (!pw || !id) 1407 1.1 mrg return isl_bool_error; 1408 1.1 mrg if (pw->n == 0) 1409 1.1 mrg return isl_bool_false; 1410 1.1 mrg 1411 1.1 mrg pos = FN(PW,find_dim_by_id)(pw, isl_dim_param, id); 1412 1.1 mrg if (pos < 0) 1413 1.1 mrg return isl_bool_false; 1414 1.1 mrg return FN(PW,involves_dims)(pw, isl_dim_param, pos, 1); 1415 1.1 mrg } 1416 1.1 mrg 1417 1.1 mrg /* Reset the space of "pw". Since we don't know if the elements 1418 1.1 mrg * represent the spaces themselves or their domains, we pass along 1419 1.1 mrg * both when we call their reset_space_and_domain. 1420 1.1 mrg */ 1421 1.1 mrg static __isl_give PW *FN(PW,reset_space_and_domain)(__isl_take PW *pw, 1422 1.1 mrg __isl_take isl_space *space, __isl_take isl_space *domain) 1423 1.1 mrg { 1424 1.1 mrg int i; 1425 1.1 mrg isl_size n; 1426 1.1 mrg 1427 1.1 mrg n = FN(PW,n_piece)(pw); 1428 1.1 mrg if (n < 0 || !space || !domain) 1429 1.1 mrg goto error; 1430 1.1 mrg 1431 1.1 mrg for (i = 0; i < n; ++i) { 1432 1.1 mrg isl_set *set; 1433 1.1 mrg EL *el; 1434 1.1 mrg 1435 1.1 mrg set = FN(PW,take_domain_at)(pw, i); 1436 1.1 mrg set = isl_set_reset_space(set, isl_space_copy(domain)); 1437 1.1 mrg pw = FN(PW,restore_domain_at)(pw, i, set); 1438 1.1 mrg el = FN(PW,take_base_at)(pw, i); 1439 1.1 mrg el = FN(EL,reset_space_and_domain)(el, 1440 1.1 mrg isl_space_copy(space), isl_space_copy(domain)); 1441 1.1 mrg pw = FN(PW,restore_base_at)(pw, i, el); 1442 1.1 mrg } 1443 1.1 mrg 1444 1.1 mrg isl_space_free(domain); 1445 1.1 mrg 1446 1.1 mrg pw = FN(PW,restore_space)(pw, space); 1447 1.1 mrg 1448 1.1 mrg return pw; 1449 1.1 mrg error: 1450 1.1 mrg isl_space_free(domain); 1451 1.1 mrg isl_space_free(space); 1452 1.1 mrg FN(PW,free)(pw); 1453 1.1 mrg return NULL; 1454 1.1 mrg } 1455 1.1 mrg 1456 1.1 mrg __isl_give PW *FN(PW,reset_domain_space)(__isl_take PW *pw, 1457 1.1 mrg __isl_take isl_space *domain) 1458 1.1 mrg { 1459 1.1 mrg isl_space *space; 1460 1.1 mrg 1461 1.1 mrg space = isl_space_extend_domain_with_range(isl_space_copy(domain), 1462 1.1 mrg FN(PW,get_space)(pw)); 1463 1.1 mrg return FN(PW,reset_space_and_domain)(pw, space, domain); 1464 1.1 mrg } 1465 1.1 mrg 1466 1.1 mrg __isl_give PW *FN(PW,reset_space)(__isl_take PW *pw, 1467 1.1 mrg __isl_take isl_space *space) 1468 1.1 mrg { 1469 1.1 mrg isl_space *domain; 1470 1.1 mrg 1471 1.1 mrg domain = isl_space_domain(isl_space_copy(space)); 1472 1.1 mrg return FN(PW,reset_space_and_domain)(pw, space, domain); 1473 1.1 mrg } 1474 1.1 mrg 1475 1.1 mrg __isl_give PW *FN(PW,set_tuple_id)(__isl_take PW *pw, enum isl_dim_type type, 1476 1.1 mrg __isl_take isl_id *id) 1477 1.1 mrg { 1478 1.1 mrg isl_space *space; 1479 1.1 mrg 1480 1.1 mrg pw = FN(PW,cow)(pw); 1481 1.1 mrg if (!pw) 1482 1.1 mrg goto error; 1483 1.1 mrg 1484 1.1 mrg space = FN(PW,get_space)(pw); 1485 1.1 mrg space = isl_space_set_tuple_id(space, type, id); 1486 1.1 mrg 1487 1.1 mrg return FN(PW,reset_space)(pw, space); 1488 1.1 mrg error: 1489 1.1 mrg isl_id_free(id); 1490 1.1 mrg return FN(PW,free)(pw); 1491 1.1 mrg } 1492 1.1 mrg 1493 1.1 mrg /* Drop the id on the specified tuple. 1494 1.1 mrg */ 1495 1.1 mrg __isl_give PW *FN(PW,reset_tuple_id)(__isl_take PW *pw, enum isl_dim_type type) 1496 1.1 mrg { 1497 1.1 mrg isl_space *space; 1498 1.1 mrg 1499 1.1 mrg if (!pw) 1500 1.1 mrg return NULL; 1501 1.1 mrg if (!FN(PW,has_tuple_id)(pw, type)) 1502 1.1 mrg return pw; 1503 1.1 mrg 1504 1.1 mrg pw = FN(PW,cow)(pw); 1505 1.1 mrg if (!pw) 1506 1.1 mrg return NULL; 1507 1.1 mrg 1508 1.1 mrg space = FN(PW,get_space)(pw); 1509 1.1 mrg space = isl_space_reset_tuple_id(space, type); 1510 1.1 mrg 1511 1.1 mrg return FN(PW,reset_space)(pw, space); 1512 1.1 mrg } 1513 1.1 mrg 1514 1.1 mrg __isl_give PW *FN(PW,set_dim_id)(__isl_take PW *pw, 1515 1.1 mrg enum isl_dim_type type, unsigned pos, __isl_take isl_id *id) 1516 1.1 mrg { 1517 1.1 mrg isl_space *space; 1518 1.1 mrg 1519 1.1 mrg space = FN(PW,get_space)(pw); 1520 1.1 mrg space = isl_space_set_dim_id(space, type, pos, id); 1521 1.1 mrg return FN(PW,reset_space)(pw, space); 1522 1.1 mrg } 1523 1.1 mrg 1524 1.1 mrg /* Reset the user pointer on all identifiers of parameters and tuples 1525 1.1 mrg * of the space of "pw". 1526 1.1 mrg */ 1527 1.1 mrg __isl_give PW *FN(PW,reset_user)(__isl_take PW *pw) 1528 1.1 mrg { 1529 1.1 mrg isl_space *space; 1530 1.1 mrg 1531 1.1 mrg space = FN(PW,get_space)(pw); 1532 1.1 mrg space = isl_space_reset_user(space); 1533 1.1 mrg 1534 1.1 mrg return FN(PW,reset_space)(pw, space); 1535 1.1 mrg } 1536 1.1 mrg 1537 1.1 mrg isl_size FN(PW,n_piece)(__isl_keep PW *pw) 1538 1.1 mrg { 1539 1.1 mrg return pw ? pw->n : isl_size_error; 1540 1.1 mrg } 1541 1.1 mrg 1542 1.1 mrg isl_stat FN(PW,foreach_piece)(__isl_keep PW *pw, 1543 1.1 mrg isl_stat (*fn)(__isl_take isl_set *set, __isl_take EL *el, void *user), 1544 1.1 mrg void *user) 1545 1.1 mrg { 1546 1.1 mrg int i; 1547 1.1 mrg 1548 1.1 mrg if (!pw) 1549 1.1 mrg return isl_stat_error; 1550 1.1 mrg 1551 1.1 mrg for (i = 0; i < pw->n; ++i) 1552 1.1 mrg if (fn(isl_set_copy(pw->p[i].set), 1553 1.1 mrg FN(EL,copy)(pw->p[i].FIELD), user) < 0) 1554 1.1 mrg return isl_stat_error; 1555 1.1 mrg 1556 1.1 mrg return isl_stat_ok; 1557 1.1 mrg } 1558 1.1 mrg 1559 1.1 mrg /* Does "test" succeed on every cell of "pw"? 1560 1.1 mrg */ 1561 1.1 mrg isl_bool FN(PW,every_piece)(__isl_keep PW *pw, 1562 1.1 mrg isl_bool (*test)(__isl_keep isl_set *set, 1563 1.1 mrg __isl_keep EL *el, void *user), void *user) 1564 1.1 mrg { 1565 1.1 mrg int i; 1566 1.1 mrg 1567 1.1 mrg if (!pw) 1568 1.1 mrg return isl_bool_error; 1569 1.1 mrg 1570 1.1 mrg for (i = 0; i < pw->n; ++i) { 1571 1.1 mrg isl_bool r; 1572 1.1 mrg 1573 1.1 mrg r = test(pw->p[i].set, pw->p[i].FIELD, user); 1574 1.1 mrg if (r < 0 || !r) 1575 1.1 mrg return r; 1576 1.1 mrg } 1577 1.1 mrg 1578 1.1 mrg return isl_bool_true; 1579 1.1 mrg } 1580 1.1 mrg 1581 1.1 mrg /* Is "pw" defined over a single universe domain? 1582 1.1 mrg * 1583 1.1 mrg * If the default value of this piecewise type is zero, 1584 1.1 mrg * then a "pw" with a zero number of cells is also accepted 1585 1.1 mrg * as it represents the default zero value. 1586 1.1 mrg */ 1587 1.1 mrg isl_bool FN(FN(PW,isa),BASE)(__isl_keep PW *pw) 1588 1.1 mrg { 1589 1.1 mrg isl_size n; 1590 1.1 mrg 1591 1.1 mrg n = FN(PW,n_piece)(pw); 1592 1.1 mrg if (n < 0) 1593 1.1 mrg return isl_bool_error; 1594 1.1 mrg if (DEFAULT_IS_ZERO && n == 0) 1595 1.1 mrg return isl_bool_true; 1596 1.1 mrg if (n != 1) 1597 1.1 mrg return isl_bool_false; 1598 1.1 mrg return isl_set_plain_is_universe(FN(PW,peek_domain_at)(pw, 0)); 1599 1.1 mrg } 1600 1.1 mrg 1601 1.1 mrg /* Return a zero base expression in the same space (and of the same type) 1602 1.1 mrg * as "pw". 1603 1.1 mrg */ 1604 1.1 mrg static __isl_give EL *FN(EL,zero_like_type)(__isl_take PW *pw OPT_TYPE_PARAM) 1605 1.1 mrg { 1606 1.1 mrg isl_space *space; 1607 1.1 mrg 1608 1.1 mrg space = FN(PW,get_space)(pw); 1609 1.1 mrg FN(PW,free)(pw); 1610 1.1 mrg return FN(EL,zero_in_space)(space OPT_TYPE_ARG(NO_LOC)); 1611 1.1 mrg } 1612 1.1 mrg 1613 1.1 mrg #ifndef HAS_TYPE 1614 1.1 mrg /* Return a zero base expression in the same space as "pw". 1615 1.1 mrg */ 1616 1.1 mrg static __isl_give EL *FN(EL,zero_like)(__isl_take PW *pw) 1617 1.1 mrg { 1618 1.1 mrg return FN(EL,zero_like_type)(pw); 1619 1.1 mrg } 1620 1.1 mrg #else 1621 1.1 mrg /* Return a zero base expression in the same space and of the same type 1622 1.1 mrg * as "pw". 1623 1.1 mrg * 1624 1.1 mrg * Pass along the type as an explicit argument for uniform handling 1625 1.1 mrg * in isl_*_zero_like_type. 1626 1.1 mrg */ 1627 1.1 mrg static __isl_give EL *FN(EL,zero_like)(__isl_take PW *pw) 1628 1.1 mrg { 1629 1.1 mrg enum isl_fold type; 1630 1.1 mrg 1631 1.1 mrg type = FN(PW,get_type)(pw); 1632 1.1 mrg if (type < 0) 1633 1.1 mrg goto error; 1634 1.1 mrg return FN(EL,zero_like_type)(pw, type); 1635 1.1 mrg error: 1636 1.1 mrg FN(PW,free)(pw); 1637 1.1 mrg return NULL; 1638 1.1 mrg } 1639 1.1 mrg #endif 1640 1.1 mrg 1641 1.1 mrg /* Given that "pw" is defined over a single universe domain, 1642 1.1 mrg * return the base expression associated to this domain. 1643 1.1 mrg * 1644 1.1 mrg * If the number of cells is zero, then "pw" is of a piecewise type 1645 1.1 mrg * with a default zero value and effectively represents zero. 1646 1.1 mrg * In this case, create a zero base expression in the same space 1647 1.1 mrg * (and with the same type). 1648 1.1 mrg * Otherwise, simply extract the associated base expression. 1649 1.1 mrg */ 1650 1.1 mrg __isl_give EL *FN(FN(PW,as),BASE)(__isl_take PW *pw) 1651 1.1 mrg { 1652 1.1 mrg isl_bool is_total; 1653 1.1 mrg isl_size n; 1654 1.1 mrg EL *el; 1655 1.1 mrg 1656 1.1 mrg is_total = FN(FN(PW,isa),BASE)(pw); 1657 1.1 mrg if (is_total < 0) 1658 1.1 mrg goto error; 1659 1.1 mrg if (!is_total) 1660 1.1 mrg isl_die(FN(PW,get_ctx)(pw), isl_error_invalid, 1661 1.1 mrg "expecting single total function", goto error); 1662 1.1 mrg n = FN(PW,n_piece)(pw); 1663 1.1 mrg if (n < 0) 1664 1.1 mrg goto error; 1665 1.1 mrg if (n == 0) 1666 1.1 mrg return FN(EL,zero_like)(pw); 1667 1.1 mrg el = FN(PW,take_base_at)(pw, 0); 1668 1.1 mrg FN(PW,free)(pw); 1669 1.1 mrg return el; 1670 1.1 mrg error: 1671 1.1 mrg FN(PW,free)(pw); 1672 1.1 mrg return NULL; 1673 1.1 mrg } 1674 1.1 mrg 1675 1.1 mrg #ifdef HAS_TYPE 1676 1.1 mrg /* Negate the type of "pw". 1677 1.1 mrg */ 1678 1.1 mrg static __isl_give PW *FN(PW,negate_type)(__isl_take PW *pw) 1679 1.1 mrg { 1680 1.1 mrg pw = FN(PW,cow)(pw); 1681 1.1 mrg if (!pw) 1682 1.1 mrg return NULL; 1683 1.1 mrg pw->type = isl_fold_type_negate(pw->type); 1684 1.1 mrg return pw; 1685 1.1 mrg } 1686 1.1 mrg #else 1687 1.1 mrg /* Negate the type of "pw". 1688 1.1 mrg * Since "pw" does not have a type, do nothing. 1689 1.1 mrg */ 1690 1.1 mrg static __isl_give PW *FN(PW,negate_type)(__isl_take PW *pw) 1691 1.1 mrg { 1692 1.1 mrg return pw; 1693 1.1 mrg } 1694 1.1 mrg #endif 1695 1.1 mrg 1696 1.1 mrg /* Multiply the pieces of "pw" by "v" and return the result. 1697 1.1 mrg */ 1698 1.1 mrg __isl_give PW *FN(PW,scale_val)(__isl_take PW *pw, __isl_take isl_val *v) 1699 1.1 mrg { 1700 1.1 mrg int i; 1701 1.1 mrg isl_size n; 1702 1.1 mrg 1703 1.1 mrg if (!pw || !v) 1704 1.1 mrg goto error; 1705 1.1 mrg 1706 1.1 mrg if (isl_val_is_one(v)) { 1707 1.1 mrg isl_val_free(v); 1708 1.1 mrg return pw; 1709 1.1 mrg } 1710 1.1 mrg if (pw && DEFAULT_IS_ZERO && isl_val_is_zero(v)) { 1711 1.1 mrg PW *zero; 1712 1.1 mrg isl_space *space = FN(PW,get_space)(pw); 1713 1.1 mrg zero = FN(PW,ZERO)(space OPT_TYPE_ARG(pw->)); 1714 1.1 mrg FN(PW,free)(pw); 1715 1.1 mrg isl_val_free(v); 1716 1.1 mrg return zero; 1717 1.1 mrg } 1718 1.1 mrg if (isl_val_is_neg(v)) 1719 1.1 mrg pw = FN(PW,negate_type)(pw); 1720 1.1 mrg n = FN(PW,n_piece)(pw); 1721 1.1 mrg if (n < 0) 1722 1.1 mrg goto error; 1723 1.1 mrg 1724 1.1 mrg for (i = 0; i < n; ++i) { 1725 1.1 mrg EL *el; 1726 1.1 mrg 1727 1.1 mrg el = FN(PW,take_base_at)(pw, i); 1728 1.1 mrg el = FN(EL,scale_val)(el, isl_val_copy(v)); 1729 1.1 mrg pw = FN(PW,restore_base_at)(pw, i, el); 1730 1.1 mrg } 1731 1.1 mrg 1732 1.1 mrg isl_val_free(v); 1733 1.1 mrg return pw; 1734 1.1 mrg error: 1735 1.1 mrg isl_val_free(v); 1736 1.1 mrg FN(PW,free)(pw); 1737 1.1 mrg return NULL; 1738 1.1 mrg } 1739 1.1 mrg 1740 1.1 mrg /* Divide the pieces of "pw" by "v" and return the result. 1741 1.1 mrg */ 1742 1.1 mrg __isl_give PW *FN(PW,scale_down_val)(__isl_take PW *pw, __isl_take isl_val *v) 1743 1.1 mrg { 1744 1.1 mrg int i; 1745 1.1 mrg isl_size n; 1746 1.1 mrg 1747 1.1 mrg if (!pw || !v) 1748 1.1 mrg goto error; 1749 1.1 mrg 1750 1.1 mrg if (isl_val_is_one(v)) { 1751 1.1 mrg isl_val_free(v); 1752 1.1 mrg return pw; 1753 1.1 mrg } 1754 1.1 mrg 1755 1.1 mrg if (!isl_val_is_rat(v)) 1756 1.1 mrg isl_die(isl_val_get_ctx(v), isl_error_invalid, 1757 1.1 mrg "expecting rational factor", goto error); 1758 1.1 mrg if (isl_val_is_zero(v)) 1759 1.1 mrg isl_die(isl_val_get_ctx(v), isl_error_invalid, 1760 1.1 mrg "cannot scale down by zero", goto error); 1761 1.1 mrg 1762 1.1 mrg if (isl_val_is_neg(v)) 1763 1.1 mrg pw = FN(PW,negate_type)(pw); 1764 1.1 mrg n = FN(PW,n_piece)(pw); 1765 1.1 mrg if (n < 0) 1766 1.1 mrg goto error; 1767 1.1 mrg 1768 1.1 mrg for (i = 0; i < n; ++i) { 1769 1.1 mrg EL *el; 1770 1.1 mrg 1771 1.1 mrg el = FN(PW,take_base_at)(pw, i); 1772 1.1 mrg el = FN(EL,scale_down_val)(el, isl_val_copy(v)); 1773 1.1 mrg pw = FN(PW,restore_base_at)(pw, i, el); 1774 1.1 mrg } 1775 1.1 mrg 1776 1.1 mrg isl_val_free(v); 1777 1.1 mrg return pw; 1778 1.1 mrg error: 1779 1.1 mrg isl_val_free(v); 1780 1.1 mrg FN(PW,free)(pw); 1781 1.1 mrg return NULL; 1782 1.1 mrg } 1783 1.1 mrg 1784 1.1 mrg /* Apply some normalization to "pw". 1785 1.1 mrg * In particular, sort the pieces according to their function value 1786 1.1 mrg * expressions, combining pairs of adjacent pieces with 1787 1.1 mrg * the same such expression, and then normalize the domains of the pieces. 1788 1.1 mrg * 1789 1.1 mrg * We normalize in place, but if anything goes wrong we need 1790 1.1 mrg * to return NULL, so we need to make sure we don't change the 1791 1.1 mrg * meaning of any possible other copies of "pw". 1792 1.1 mrg */ 1793 1.1 mrg static __isl_give PW *FN(PW,normalize)(__isl_take PW *pw) 1794 1.1 mrg { 1795 1.1 mrg int i; 1796 1.1 mrg isl_set *set; 1797 1.1 mrg 1798 1.1 mrg pw = FN(PW,sort_unique)(pw); 1799 1.1 mrg if (!pw) 1800 1.1 mrg return NULL; 1801 1.1 mrg for (i = 0; i < pw->n; ++i) { 1802 1.1 mrg set = isl_set_normalize(isl_set_copy(pw->p[i].set)); 1803 1.1 mrg if (!set) 1804 1.1 mrg return FN(PW,free)(pw); 1805 1.1 mrg isl_set_free(pw->p[i].set); 1806 1.1 mrg pw->p[i].set = set; 1807 1.1 mrg } 1808 1.1 mrg 1809 1.1 mrg return pw; 1810 1.1 mrg } 1811 1.1 mrg 1812 1.1 mrg /* Is pw1 obviously equal to pw2? 1813 1.1 mrg * That is, do they have obviously identical cells and obviously identical 1814 1.1 mrg * elements on each cell? 1815 1.1 mrg * 1816 1.1 mrg * If "pw1" or "pw2" contain any NaNs, then they are considered 1817 1.1 mrg * not to be the same. A NaN is not equal to anything, not even 1818 1.1 mrg * to another NaN. 1819 1.1 mrg */ 1820 1.1 mrg isl_bool FN(PW,plain_is_equal)(__isl_keep PW *pw1, __isl_keep PW *pw2) 1821 1.1 mrg { 1822 1.1 mrg int i; 1823 1.1 mrg isl_bool equal, has_nan; 1824 1.1 mrg 1825 1.1 mrg if (!pw1 || !pw2) 1826 1.1 mrg return isl_bool_error; 1827 1.1 mrg 1828 1.1 mrg has_nan = FN(PW,involves_nan)(pw1); 1829 1.1 mrg if (has_nan >= 0 && !has_nan) 1830 1.1 mrg has_nan = FN(PW,involves_nan)(pw2); 1831 1.1 mrg if (has_nan < 0 || has_nan) 1832 1.1 mrg return isl_bool_not(has_nan); 1833 1.1 mrg 1834 1.1 mrg if (pw1 == pw2) 1835 1.1 mrg return isl_bool_true; 1836 1.1 mrg equal = FN(PW,has_equal_space)(pw1, pw2); 1837 1.1 mrg if (equal < 0 || !equal) 1838 1.1 mrg return equal; 1839 1.1 mrg 1840 1.1 mrg pw1 = FN(PW,copy)(pw1); 1841 1.1 mrg pw2 = FN(PW,copy)(pw2); 1842 1.1 mrg pw1 = FN(PW,normalize)(pw1); 1843 1.1 mrg pw2 = FN(PW,normalize)(pw2); 1844 1.1 mrg if (!pw1 || !pw2) 1845 1.1 mrg goto error; 1846 1.1 mrg 1847 1.1 mrg equal = isl_bool_ok(pw1->n == pw2->n); 1848 1.1 mrg for (i = 0; equal && i < pw1->n; ++i) { 1849 1.1 mrg equal = isl_set_plain_is_equal(pw1->p[i].set, pw2->p[i].set); 1850 1.1 mrg if (equal < 0) 1851 1.1 mrg goto error; 1852 1.1 mrg if (!equal) 1853 1.1 mrg break; 1854 1.1 mrg equal = FN(EL,plain_is_equal)(pw1->p[i].FIELD, pw2->p[i].FIELD); 1855 1.1 mrg if (equal < 0) 1856 1.1 mrg goto error; 1857 1.1 mrg } 1858 1.1 mrg 1859 1.1 mrg FN(PW,free)(pw1); 1860 1.1 mrg FN(PW,free)(pw2); 1861 1.1 mrg return equal; 1862 1.1 mrg error: 1863 1.1 mrg FN(PW,free)(pw1); 1864 1.1 mrg FN(PW,free)(pw2); 1865 1.1 mrg return isl_bool_error; 1866 1.1 mrg } 1867 1.1 mrg 1868 1.1 mrg /* Does "pw" involve any NaNs? 1869 1.1 mrg */ 1870 1.1 mrg isl_bool FN(PW,involves_nan)(__isl_keep PW *pw) 1871 1.1 mrg { 1872 1.1 mrg int i; 1873 1.1 mrg 1874 1.1 mrg if (!pw) 1875 1.1 mrg return isl_bool_error; 1876 1.1 mrg if (pw->n == 0) 1877 1.1 mrg return isl_bool_false; 1878 1.1 mrg 1879 1.1 mrg for (i = 0; i < pw->n; ++i) { 1880 1.1 mrg isl_bool has_nan = FN(EL,involves_nan)(pw->p[i].FIELD); 1881 1.1 mrg if (has_nan < 0 || has_nan) 1882 1.1 mrg return has_nan; 1883 1.1 mrg } 1884 1.1 mrg 1885 1.1 mrg return isl_bool_false; 1886 1.1 mrg } 1887