1 /* 2 * Copyright 2011 INRIA Saclay 3 * Copyright 2012-2013 Ecole Normale Superieure 4 * Copyright 2016 Sven Verdoolaege 5 * 6 * Use of this software is governed by the MIT license 7 * 8 * Written by Sven Verdoolaege, INRIA Saclay - Ile-de-France, 9 * Parc Club Orsay Universite, ZAC des vignes, 4 rue Jacques Monod, 10 * 91893 Orsay, France 11 * and Ecole Normale Superieure, 45 rue d'Ulm, 75230 Paris, France 12 */ 13 14 #include <isl/ctx.h> 15 #include <isl/space.h> 16 #include <isl/local_space.h> 17 #include <isl/union_map.h> 18 #include <isl_map_private.h> 19 #include <isl_aff_private.h> 20 #include <isl_vec_private.h> 21 #include <isl_seq.h> 22 23 #include <bset_from_bmap.c> 24 #include <set_from_map.c> 25 26 /* Check that the input living in "space" lives in a map space. 27 * That is, check that "space" is a map space. 28 */ 29 static isl_stat check_input_is_map(__isl_keep isl_space *space) 30 { 31 isl_bool is_set; 32 33 is_set = isl_space_is_set(space); 34 if (is_set < 0) 35 return isl_stat_error; 36 if (is_set) 37 isl_die(isl_space_get_ctx(space), isl_error_invalid, 38 "space of input is not a map", return isl_stat_error); 39 return isl_stat_ok; 40 } 41 42 /* Check that the input living in "space" lives in a set space. 43 * That is, check that "space" is a set space. 44 */ 45 static isl_stat check_input_is_set(__isl_keep isl_space *space) 46 { 47 isl_bool is_set; 48 49 is_set = isl_space_is_set(space); 50 if (is_set < 0) 51 return isl_stat_error; 52 if (!is_set) 53 isl_die(isl_space_get_ctx(space), isl_error_invalid, 54 "space of input is not a set", return isl_stat_error); 55 return isl_stat_ok; 56 } 57 58 /* Construct a basic map mapping the domain of the affine expression 59 * to a one-dimensional range prescribed by the affine expression. 60 * If "rational" is set, then construct a rational basic map. 61 * 62 * A NaN affine expression cannot be converted to a basic map. 63 */ 64 static __isl_give isl_basic_map *isl_basic_map_from_aff2( 65 __isl_take isl_aff *aff, int rational) 66 { 67 int k; 68 int pos; 69 isl_bool is_nan; 70 isl_local_space *ls; 71 isl_basic_map *bmap = NULL; 72 73 if (!aff) 74 return NULL; 75 is_nan = isl_aff_is_nan(aff); 76 if (is_nan < 0) 77 goto error; 78 if (is_nan) 79 isl_die(isl_aff_get_ctx(aff), isl_error_invalid, 80 "cannot convert NaN", goto error); 81 82 ls = isl_aff_get_local_space(aff); 83 bmap = isl_basic_map_from_local_space(ls); 84 bmap = isl_basic_map_extend_constraints(bmap, 1, 0); 85 k = isl_basic_map_alloc_equality(bmap); 86 if (k < 0) 87 goto error; 88 89 pos = isl_basic_map_offset(bmap, isl_dim_out); 90 isl_seq_cpy(bmap->eq[k], aff->v->el + 1, pos); 91 isl_int_neg(bmap->eq[k][pos], aff->v->el[0]); 92 isl_seq_cpy(bmap->eq[k] + pos + 1, aff->v->el + 1 + pos, 93 aff->v->size - (pos + 1)); 94 95 isl_aff_free(aff); 96 if (rational) 97 bmap = isl_basic_map_set_rational(bmap); 98 bmap = isl_basic_map_gauss(bmap, NULL); 99 bmap = isl_basic_map_finalize(bmap); 100 return bmap; 101 error: 102 isl_aff_free(aff); 103 isl_basic_map_free(bmap); 104 return NULL; 105 } 106 107 /* Construct a basic map mapping the domain of the affine expression 108 * to a one-dimensional range prescribed by the affine expression. 109 */ 110 __isl_give isl_basic_map *isl_basic_map_from_aff(__isl_take isl_aff *aff) 111 { 112 return isl_basic_map_from_aff2(aff, 0); 113 } 114 115 /* Construct a map mapping the domain of the affine expression 116 * to a one-dimensional range prescribed by the affine expression. 117 */ 118 __isl_give isl_map *isl_map_from_aff(__isl_take isl_aff *aff) 119 { 120 isl_basic_map *bmap; 121 122 bmap = isl_basic_map_from_aff(aff); 123 return isl_map_from_basic_map(bmap); 124 } 125 126 /* Construct a basic map mapping the domain of the multi-affine expression 127 * to its range, with each dimension in the range equated to the 128 * corresponding affine expression. 129 * If "rational" is set, then construct a rational basic map. 130 */ 131 __isl_give isl_basic_map *isl_basic_map_from_multi_aff2( 132 __isl_take isl_multi_aff *maff, int rational) 133 { 134 int i; 135 isl_size dim; 136 isl_space *space; 137 isl_basic_map *bmap; 138 139 dim = isl_multi_aff_dim(maff, isl_dim_out); 140 if (dim < 0) 141 goto error; 142 143 if (dim != maff->n) 144 isl_die(isl_multi_aff_get_ctx(maff), isl_error_internal, 145 "invalid space", goto error); 146 147 space = isl_space_domain(isl_multi_aff_get_space(maff)); 148 bmap = isl_basic_map_universe(isl_space_from_domain(space)); 149 if (rational) 150 bmap = isl_basic_map_set_rational(bmap); 151 152 for (i = 0; i < maff->n; ++i) { 153 isl_aff *aff; 154 isl_basic_map *bmap_i; 155 156 aff = isl_aff_copy(maff->u.p[i]); 157 bmap_i = isl_basic_map_from_aff2(aff, rational); 158 159 bmap = isl_basic_map_flat_range_product(bmap, bmap_i); 160 } 161 162 bmap = isl_basic_map_reset_space(bmap, isl_multi_aff_get_space(maff)); 163 164 isl_multi_aff_free(maff); 165 return bmap; 166 error: 167 isl_multi_aff_free(maff); 168 return NULL; 169 } 170 171 /* Construct a basic map mapping the domain of the multi-affine expression 172 * to its range, with each dimension in the range equated to the 173 * corresponding affine expression. 174 * If "ma" lives in a set space, then the result is actually a set. 175 */ 176 static __isl_give isl_basic_map *basic_map_from_multi_aff( 177 __isl_take isl_multi_aff *ma) 178 { 179 return isl_basic_map_from_multi_aff2(ma, 0); 180 } 181 182 /* Construct a basic map mapping the domain of the multi-affine expression 183 * to its range, with each dimension in the range equated to the 184 * corresponding affine expression. 185 */ 186 __isl_give isl_basic_map *isl_basic_map_from_multi_aff( 187 __isl_take isl_multi_aff *ma) 188 { 189 if (check_input_is_map(isl_multi_aff_peek_space(ma)) < 0) 190 ma = isl_multi_aff_free(ma); 191 return basic_map_from_multi_aff(ma); 192 } 193 194 /* Construct a basic set mapping the parameter domain 195 * of the multi-affine expression to its space, with each dimension 196 * in the space equated to the corresponding affine expression. 197 */ 198 __isl_give isl_basic_set *isl_basic_set_from_multi_aff( 199 __isl_take isl_multi_aff *ma) 200 { 201 if (check_input_is_set(isl_multi_aff_peek_space(ma)) < 0) 202 ma = isl_multi_aff_free(ma); 203 return bset_from_bmap(basic_map_from_multi_aff(ma)); 204 } 205 206 /* Construct a map mapping the domain of the multi-affine expression 207 * to its range, with each dimension in the range equated to the 208 * corresponding affine expression. 209 * If "maff" lives in a set space, then the result is actually a set. 210 */ 211 __isl_give isl_map *isl_map_from_multi_aff_internal( 212 __isl_take isl_multi_aff *maff) 213 { 214 isl_basic_map *bmap; 215 216 bmap = basic_map_from_multi_aff(maff); 217 return isl_map_from_basic_map(bmap); 218 } 219 220 /* Construct a map mapping the domain the multi-affine expression 221 * to its range, with each dimension in the range equated to the 222 * corresponding affine expression. 223 */ 224 __isl_give isl_map *isl_map_from_multi_aff(__isl_take isl_multi_aff *ma) 225 { 226 if (check_input_is_map(isl_multi_aff_peek_space(ma)) < 0) 227 ma = isl_multi_aff_free(ma); 228 return isl_map_from_multi_aff_internal(ma); 229 } 230 231 /* This function performs the same operation as isl_map_from_multi_aff, 232 * but is considered as a function on an isl_multi_aff when exported. 233 */ 234 __isl_give isl_map *isl_multi_aff_as_map(__isl_take isl_multi_aff *ma) 235 { 236 return isl_map_from_multi_aff(ma); 237 } 238 239 /* Construct a set mapping the parameter domain the multi-affine expression 240 * to its space, with each dimension in the space equated to the 241 * corresponding affine expression. 242 */ 243 __isl_give isl_set *isl_set_from_multi_aff(__isl_take isl_multi_aff *ma) 244 { 245 if (check_input_is_set(isl_multi_aff_peek_space(ma)) < 0) 246 ma = isl_multi_aff_free(ma); 247 return isl_map_from_multi_aff_internal(ma); 248 } 249 250 /* This function performs the same operation as isl_set_from_multi_aff, 251 * but is considered as a function on an isl_multi_aff when exported. 252 */ 253 __isl_give isl_set *isl_multi_aff_as_set(__isl_take isl_multi_aff *ma) 254 { 255 return isl_set_from_multi_aff(ma); 256 } 257 258 /* Construct a basic map mapping a domain in the given space to 259 * to an n-dimensional range, with n the number of elements in the list, 260 * where each coordinate in the range is prescribed by the 261 * corresponding affine expression. 262 * The domains of all affine expressions in the list are assumed to match 263 * domain_space. 264 */ 265 __isl_give isl_basic_map *isl_basic_map_from_aff_list( 266 __isl_take isl_space *domain_space, __isl_take isl_aff_list *list) 267 { 268 int i; 269 isl_space *space; 270 isl_basic_map *bmap; 271 272 if (!list) 273 return NULL; 274 275 space = isl_space_from_domain(domain_space); 276 bmap = isl_basic_map_universe(space); 277 278 for (i = 0; i < list->n; ++i) { 279 isl_aff *aff; 280 isl_basic_map *bmap_i; 281 282 aff = isl_aff_copy(list->p[i]); 283 bmap_i = isl_basic_map_from_aff(aff); 284 285 bmap = isl_basic_map_flat_range_product(bmap, bmap_i); 286 } 287 288 isl_aff_list_free(list); 289 return bmap; 290 } 291 292 /* Construct a map with as domain the domain of pwaff and 293 * one-dimensional range corresponding to the affine expressions. 294 * If "pwaff" lives in a set space, then the result is actually a set. 295 */ 296 __isl_give isl_map *isl_map_from_pw_aff_internal(__isl_take isl_pw_aff *pwaff) 297 { 298 int i; 299 isl_space *space; 300 isl_map *map; 301 302 if (!pwaff) 303 return NULL; 304 305 space = isl_pw_aff_get_space(pwaff); 306 map = isl_map_empty(space); 307 308 for (i = 0; i < pwaff->n; ++i) { 309 isl_basic_map *bmap; 310 isl_map *map_i; 311 312 bmap = isl_basic_map_from_aff(isl_aff_copy(pwaff->p[i].aff)); 313 map_i = isl_map_from_basic_map(bmap); 314 map_i = isl_map_intersect_domain(map_i, 315 isl_set_copy(pwaff->p[i].set)); 316 map = isl_map_union_disjoint(map, map_i); 317 } 318 319 isl_pw_aff_free(pwaff); 320 321 return map; 322 } 323 324 /* Construct a map with as domain the domain of pwaff and 325 * one-dimensional range corresponding to the affine expressions. 326 */ 327 __isl_give isl_map *isl_map_from_pw_aff(__isl_take isl_pw_aff *pwaff) 328 { 329 if (check_input_is_map(isl_pw_aff_peek_space(pwaff)) < 0) 330 pwaff = isl_pw_aff_free(pwaff); 331 return isl_map_from_pw_aff_internal(pwaff); 332 } 333 334 /* This function performs the same operation as isl_map_from_pw_aff, 335 * but is considered as a function on an isl_pw_aff when exported. 336 */ 337 __isl_give isl_map *isl_pw_aff_as_map(__isl_take isl_pw_aff *pa) 338 { 339 return isl_map_from_pw_aff(pa); 340 } 341 342 /* Construct a one-dimensional set with as parameter domain 343 * the domain of pwaff and the single set dimension 344 * corresponding to the affine expressions. 345 */ 346 __isl_give isl_set *isl_set_from_pw_aff(__isl_take isl_pw_aff *pwaff) 347 { 348 if (check_input_is_set(isl_pw_aff_peek_space(pwaff)) < 0) 349 pwaff = isl_pw_aff_free(pwaff); 350 return set_from_map(isl_map_from_pw_aff_internal(pwaff)); 351 } 352 353 /* Construct a map mapping the domain of the piecewise multi-affine expression 354 * to its range, with each dimension in the range equated to the 355 * corresponding affine expression on its cell. 356 * If "pma" lives in a set space, then the result is actually a set. 357 * 358 * If the domain of "pma" is rational, then so is the constructed "map". 359 */ 360 __isl_give isl_map *isl_map_from_pw_multi_aff_internal( 361 __isl_take isl_pw_multi_aff *pma) 362 { 363 int i; 364 isl_map *map; 365 366 if (!pma) 367 return NULL; 368 369 map = isl_map_empty(isl_pw_multi_aff_get_space(pma)); 370 371 for (i = 0; i < pma->n; ++i) { 372 isl_bool rational; 373 isl_multi_aff *maff; 374 isl_basic_map *bmap; 375 isl_map *map_i; 376 377 rational = isl_set_is_rational(pma->p[i].set); 378 if (rational < 0) 379 map = isl_map_free(map); 380 maff = isl_multi_aff_copy(pma->p[i].maff); 381 bmap = isl_basic_map_from_multi_aff2(maff, rational); 382 map_i = isl_map_from_basic_map(bmap); 383 map_i = isl_map_intersect_domain(map_i, 384 isl_set_copy(pma->p[i].set)); 385 map = isl_map_union_disjoint(map, map_i); 386 } 387 388 isl_pw_multi_aff_free(pma); 389 return map; 390 } 391 392 /* Construct a map mapping the domain of the piecewise multi-affine expression 393 * to its range, with each dimension in the range equated to the 394 * corresponding affine expression on its cell. 395 */ 396 __isl_give isl_map *isl_map_from_pw_multi_aff(__isl_take isl_pw_multi_aff *pma) 397 { 398 if (check_input_is_map(isl_pw_multi_aff_peek_space(pma)) < 0) 399 pma = isl_pw_multi_aff_free(pma); 400 return isl_map_from_pw_multi_aff_internal(pma); 401 } 402 403 /* This function performs the same operation as isl_map_from_pw_multi_aff, 404 * but is considered as a function on an isl_pw_multi_aff when exported. 405 */ 406 __isl_give isl_map *isl_pw_multi_aff_as_map(__isl_take isl_pw_multi_aff *pma) 407 { 408 return isl_map_from_pw_multi_aff(pma); 409 } 410 411 __isl_give isl_set *isl_set_from_pw_multi_aff(__isl_take isl_pw_multi_aff *pma) 412 { 413 if (check_input_is_set(isl_pw_multi_aff_peek_space(pma)) < 0) 414 pma = isl_pw_multi_aff_free(pma); 415 return set_from_map(isl_map_from_pw_multi_aff_internal(pma)); 416 } 417 418 /* This function performs the same operation as isl_set_from_pw_multi_aff, 419 * but is considered as a function on an isl_pw_multi_aff when exported. 420 */ 421 __isl_give isl_set *isl_pw_multi_aff_as_set(__isl_take isl_pw_multi_aff *pma) 422 { 423 return isl_set_from_pw_multi_aff(pma); 424 } 425 426 /* Construct a set or map mapping the shared (parameter) domain 427 * of the piecewise affine expressions to the range of "mpa" 428 * with each dimension in the range equated to the 429 * corresponding piecewise affine expression. 430 * 431 * If "mpa" has an explicit domain (i.e., it is zero-dimensional), 432 * then return a set or map with the same (parameter) domain. 433 */ 434 static __isl_give isl_map *map_from_multi_pw_aff( 435 __isl_take isl_multi_pw_aff *mpa) 436 { 437 int i; 438 isl_size dim; 439 isl_space *space; 440 isl_map *map; 441 442 dim = isl_multi_pw_aff_dim(mpa, isl_dim_out); 443 if (dim < 0) 444 goto error; 445 446 if (isl_space_dim(mpa->space, isl_dim_out) != mpa->n) 447 isl_die(isl_multi_pw_aff_get_ctx(mpa), isl_error_internal, 448 "invalid space", goto error); 449 450 space = isl_multi_pw_aff_get_domain_space(mpa); 451 map = isl_map_universe(isl_space_from_domain(space)); 452 453 for (i = 0; i < mpa->n; ++i) { 454 isl_pw_aff *pa; 455 isl_map *map_i; 456 457 pa = isl_pw_aff_copy(mpa->u.p[i]); 458 map_i = isl_map_from_pw_aff_internal(pa); 459 460 map = isl_map_flat_range_product(map, map_i); 461 } 462 463 map = isl_map_reset_space(map, isl_multi_pw_aff_get_space(mpa)); 464 465 map = isl_map_intersect_multi_pw_aff_explicit_domain(map, mpa); 466 467 isl_multi_pw_aff_free(mpa); 468 return map; 469 error: 470 isl_multi_pw_aff_free(mpa); 471 return NULL; 472 } 473 474 /* Construct a map mapping the shared domain 475 * of the piecewise affine expressions to the range of "mpa" 476 * with each dimension in the range equated to the 477 * corresponding piecewise affine expression. 478 */ 479 __isl_give isl_map *isl_map_from_multi_pw_aff(__isl_take isl_multi_pw_aff *mpa) 480 { 481 if (check_input_is_map(isl_multi_pw_aff_peek_space(mpa)) < 0) 482 mpa = isl_multi_pw_aff_free(mpa); 483 return map_from_multi_pw_aff(mpa); 484 } 485 486 /* This function performs the same operation as isl_map_from_multi_pw_aff, 487 * but is considered as a function on an isl_multi_pw_aff when exported. 488 */ 489 __isl_give isl_map *isl_multi_pw_aff_as_map(__isl_take isl_multi_pw_aff *mpa) 490 { 491 return isl_map_from_multi_pw_aff(mpa); 492 } 493 494 /* Construct a set mapping the shared parameter domain 495 * of the piecewise affine expressions to the space of "mpa" 496 * with each dimension in the range equated to the 497 * corresponding piecewise affine expression. 498 */ 499 __isl_give isl_set *isl_set_from_multi_pw_aff(__isl_take isl_multi_pw_aff *mpa) 500 { 501 if (check_input_is_set(isl_multi_pw_aff_peek_space(mpa)) < 0) 502 mpa = isl_multi_pw_aff_free(mpa); 503 return set_from_map(map_from_multi_pw_aff(mpa)); 504 } 505 506 /* This function performs the same operation as isl_set_from_multi_pw_aff, 507 * but is considered as a function on an isl_multi_pw_aff when exported. 508 */ 509 __isl_give isl_set *isl_multi_pw_aff_as_set(__isl_take isl_multi_pw_aff *mpa) 510 { 511 return isl_set_from_multi_pw_aff(mpa); 512 } 513 514 /* Convert "pa" to an isl_map and add it to *umap. 515 */ 516 static isl_stat map_from_pw_aff_entry(__isl_take isl_pw_aff *pa, void *user) 517 { 518 isl_union_map **umap = user; 519 isl_map *map; 520 521 map = isl_map_from_pw_aff(pa); 522 *umap = isl_union_map_add_map(*umap, map); 523 524 return *umap ? isl_stat_ok : isl_stat_error; 525 } 526 527 /* Construct a union map mapping the domain of the union 528 * piecewise affine expression to its range, with the single output dimension 529 * equated to the corresponding affine expressions on their cells. 530 */ 531 __isl_give isl_union_map *isl_union_map_from_union_pw_aff( 532 __isl_take isl_union_pw_aff *upa) 533 { 534 isl_space *space; 535 isl_union_map *umap; 536 537 if (!upa) 538 return NULL; 539 540 space = isl_union_pw_aff_get_space(upa); 541 umap = isl_union_map_empty(space); 542 543 if (isl_union_pw_aff_foreach_pw_aff(upa, &map_from_pw_aff_entry, 544 &umap) < 0) 545 umap = isl_union_map_free(umap); 546 547 isl_union_pw_aff_free(upa); 548 return umap; 549 } 550 551 /* Convert "pma" to an isl_map and add it to *umap. 552 */ 553 static isl_stat map_from_pw_multi_aff(__isl_take isl_pw_multi_aff *pma, 554 void *user) 555 { 556 isl_union_map **umap = user; 557 isl_map *map; 558 559 map = isl_map_from_pw_multi_aff(pma); 560 *umap = isl_union_map_add_map(*umap, map); 561 562 return isl_stat_ok; 563 } 564 565 /* Construct a union map mapping the domain of the union 566 * piecewise multi-affine expression to its range, with each dimension 567 * in the range equated to the corresponding affine expression on its cell. 568 */ 569 __isl_give isl_union_map *isl_union_map_from_union_pw_multi_aff( 570 __isl_take isl_union_pw_multi_aff *upma) 571 { 572 isl_space *space; 573 isl_union_map *umap; 574 575 if (!upma) 576 return NULL; 577 578 space = isl_union_pw_multi_aff_get_space(upma); 579 umap = isl_union_map_empty(space); 580 581 if (isl_union_pw_multi_aff_foreach_pw_multi_aff(upma, 582 &map_from_pw_multi_aff, &umap) < 0) 583 goto error; 584 585 isl_union_pw_multi_aff_free(upma); 586 return umap; 587 error: 588 isl_union_pw_multi_aff_free(upma); 589 isl_union_map_free(umap); 590 return NULL; 591 } 592 593 /* This function performs the same operation as 594 * isl_union_map_from_union_pw_multi_aff, 595 * but is considered as a function on an isl_union_pw_multi_aff when exported. 596 */ 597 __isl_give isl_union_map *isl_union_pw_multi_aff_as_union_map( 598 __isl_take isl_union_pw_multi_aff *upma) 599 { 600 return isl_union_map_from_union_pw_multi_aff(upma); 601 } 602