1/* 2 * Copyright 2008-2009 Katholieke Universiteit Leuven 3 * Copyright 2010 INRIA Saclay 4 * Copyright 2012-2013 Ecole Normale Superieure 5 * 6 * Use of this software is governed by the MIT license 7 * 8 * Written by Sven Verdoolaege, K.U.Leuven, Departement 9 * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium 10 * and INRIA Saclay - Ile-de-France, Parc Club Orsay Universite, 11 * ZAC des vignes, 4 rue Jacques Monod, 91893 Orsay, France 12 * and Ecole Normale Superieure, 45 rue d���Ulm, 75230 Paris, France 13 */ 14 15#include <string.h> 16#include <isl_ctx_private.h> 17#include <isl_map_private.h> 18#include <isl/blk.h> 19#include "isl_space_private.h" 20#include "isl_equalities.h" 21#include <isl/lp.h> 22#include <isl/seq.h> 23#include <isl/set.h> 24#include <isl/map.h> 25#include "isl_map_piplib.h" 26#include <isl_reordering.h> 27#include "isl_sample.h" 28#include "isl_tab.h" 29#include <isl/vec.h> 30#include <isl_mat_private.h> 31#include <isl_dim_map.h> 32#include <isl_local_space_private.h> 33#include <isl_aff_private.h> 34#include <isl_options_private.h> 35#include <isl_morph.h> 36#include <isl_val_private.h> 37 38static unsigned n(__isl_keep isl_space *dim, enum isl_dim_type type) 39{ 40 switch (type) { 41 case isl_dim_param: return dim->nparam; 42 case isl_dim_in: return dim->n_in; 43 case isl_dim_out: return dim->n_out; 44 case isl_dim_all: return dim->nparam + dim->n_in + dim->n_out; 45 default: return 0; 46 } 47} 48 49static unsigned pos(__isl_keep isl_space *dim, enum isl_dim_type type) 50{ 51 switch (type) { 52 case isl_dim_param: return 1; 53 case isl_dim_in: return 1 + dim->nparam; 54 case isl_dim_out: return 1 + dim->nparam + dim->n_in; 55 default: return 0; 56 } 57} 58 59unsigned isl_basic_map_dim(__isl_keep isl_basic_map *bmap, 60 enum isl_dim_type type) 61{ 62 if (!bmap) 63 return 0; 64 switch (type) { 65 case isl_dim_cst: return 1; 66 case isl_dim_param: 67 case isl_dim_in: 68 case isl_dim_out: return isl_space_dim(bmap->dim, type); 69 case isl_dim_div: return bmap->n_div; 70 case isl_dim_all: return isl_basic_map_total_dim(bmap); 71 default: return 0; 72 } 73} 74 75unsigned isl_map_dim(__isl_keep isl_map *map, enum isl_dim_type type) 76{ 77 return map ? n(map->dim, type) : 0; 78} 79 80unsigned isl_set_dim(__isl_keep isl_set *set, enum isl_dim_type type) 81{ 82 return set ? n(set->dim, type) : 0; 83} 84 85unsigned isl_basic_map_offset(struct isl_basic_map *bmap, 86 enum isl_dim_type type) 87{ 88 isl_space *dim = bmap->dim; 89 switch (type) { 90 case isl_dim_cst: return 0; 91 case isl_dim_param: return 1; 92 case isl_dim_in: return 1 + dim->nparam; 93 case isl_dim_out: return 1 + dim->nparam + dim->n_in; 94 case isl_dim_div: return 1 + dim->nparam + dim->n_in + dim->n_out; 95 default: return 0; 96 } 97} 98 99unsigned isl_basic_set_offset(struct isl_basic_set *bset, 100 enum isl_dim_type type) 101{ 102 return isl_basic_map_offset(bset, type); 103} 104 105static unsigned map_offset(struct isl_map *map, enum isl_dim_type type) 106{ 107 return pos(map->dim, type); 108} 109 110unsigned isl_basic_set_dim(__isl_keep isl_basic_set *bset, 111 enum isl_dim_type type) 112{ 113 return isl_basic_map_dim(bset, type); 114} 115 116unsigned isl_basic_set_n_dim(__isl_keep isl_basic_set *bset) 117{ 118 return isl_basic_set_dim(bset, isl_dim_set); 119} 120 121unsigned isl_basic_set_n_param(__isl_keep isl_basic_set *bset) 122{ 123 return isl_basic_set_dim(bset, isl_dim_param); 124} 125 126unsigned isl_basic_set_total_dim(const struct isl_basic_set *bset) 127{ 128 if (!bset) 129 return 0; 130 return isl_space_dim(bset->dim, isl_dim_all) + bset->n_div; 131} 132 133unsigned isl_set_n_dim(__isl_keep isl_set *set) 134{ 135 return isl_set_dim(set, isl_dim_set); 136} 137 138unsigned isl_set_n_param(__isl_keep isl_set *set) 139{ 140 return isl_set_dim(set, isl_dim_param); 141} 142 143unsigned isl_basic_map_n_in(const struct isl_basic_map *bmap) 144{ 145 return bmap ? bmap->dim->n_in : 0; 146} 147 148unsigned isl_basic_map_n_out(const struct isl_basic_map *bmap) 149{ 150 return bmap ? bmap->dim->n_out : 0; 151} 152 153unsigned isl_basic_map_n_param(const struct isl_basic_map *bmap) 154{ 155 return bmap ? bmap->dim->nparam : 0; 156} 157 158unsigned isl_basic_map_n_div(const struct isl_basic_map *bmap) 159{ 160 return bmap ? bmap->n_div : 0; 161} 162 163unsigned isl_basic_map_total_dim(const struct isl_basic_map *bmap) 164{ 165 return bmap ? isl_space_dim(bmap->dim, isl_dim_all) + bmap->n_div : 0; 166} 167 168unsigned isl_map_n_in(const struct isl_map *map) 169{ 170 return map ? map->dim->n_in : 0; 171} 172 173unsigned isl_map_n_out(const struct isl_map *map) 174{ 175 return map ? map->dim->n_out : 0; 176} 177 178unsigned isl_map_n_param(const struct isl_map *map) 179{ 180 return map ? map->dim->nparam : 0; 181} 182 183int isl_map_compatible_domain(struct isl_map *map, struct isl_set *set) 184{ 185 int m; 186 if (!map || !set) 187 return -1; 188 m = isl_space_match(map->dim, isl_dim_param, set->dim, isl_dim_param); 189 if (m < 0 || !m) 190 return m; 191 return isl_space_tuple_match(map->dim, isl_dim_in, set->dim, isl_dim_set); 192} 193 194int isl_basic_map_compatible_domain(struct isl_basic_map *bmap, 195 struct isl_basic_set *bset) 196{ 197 int m; 198 if (!bmap || !bset) 199 return -1; 200 m = isl_space_match(bmap->dim, isl_dim_param, bset->dim, isl_dim_param); 201 if (m < 0 || !m) 202 return m; 203 return isl_space_tuple_match(bmap->dim, isl_dim_in, bset->dim, isl_dim_set); 204} 205 206int isl_map_compatible_range(__isl_keep isl_map *map, __isl_keep isl_set *set) 207{ 208 int m; 209 if (!map || !set) 210 return -1; 211 m = isl_space_match(map->dim, isl_dim_param, set->dim, isl_dim_param); 212 if (m < 0 || !m) 213 return m; 214 return isl_space_tuple_match(map->dim, isl_dim_out, set->dim, isl_dim_set); 215} 216 217int isl_basic_map_compatible_range(struct isl_basic_map *bmap, 218 struct isl_basic_set *bset) 219{ 220 int m; 221 if (!bmap || !bset) 222 return -1; 223 m = isl_space_match(bmap->dim, isl_dim_param, bset->dim, isl_dim_param); 224 if (m < 0 || !m) 225 return m; 226 return isl_space_tuple_match(bmap->dim, isl_dim_out, bset->dim, isl_dim_set); 227} 228 229isl_ctx *isl_basic_map_get_ctx(__isl_keep isl_basic_map *bmap) 230{ 231 return bmap ? bmap->ctx : NULL; 232} 233 234isl_ctx *isl_basic_set_get_ctx(__isl_keep isl_basic_set *bset) 235{ 236 return bset ? bset->ctx : NULL; 237} 238 239isl_ctx *isl_map_get_ctx(__isl_keep isl_map *map) 240{ 241 return map ? map->ctx : NULL; 242} 243 244isl_ctx *isl_set_get_ctx(__isl_keep isl_set *set) 245{ 246 return set ? set->ctx : NULL; 247} 248 249__isl_give isl_space *isl_basic_map_get_space(__isl_keep isl_basic_map *bmap) 250{ 251 if (!bmap) 252 return NULL; 253 return isl_space_copy(bmap->dim); 254} 255 256__isl_give isl_space *isl_basic_set_get_space(__isl_keep isl_basic_set *bset) 257{ 258 if (!bset) 259 return NULL; 260 return isl_space_copy(bset->dim); 261} 262 263/* Extract the divs in "bmap" as a matrix. 264 */ 265__isl_give isl_mat *isl_basic_map_get_divs(__isl_keep isl_basic_map *bmap) 266{ 267 int i; 268 isl_ctx *ctx; 269 isl_mat *div; 270 unsigned total; 271 unsigned cols; 272 273 if (!bmap) 274 return NULL; 275 276 ctx = isl_basic_map_get_ctx(bmap); 277 total = isl_space_dim(bmap->dim, isl_dim_all); 278 cols = 1 + 1 + total + bmap->n_div; 279 div = isl_mat_alloc(ctx, bmap->n_div, cols); 280 if (!div) 281 return NULL; 282 283 for (i = 0; i < bmap->n_div; ++i) 284 isl_seq_cpy(div->row[i], bmap->div[i], cols); 285 286 return div; 287} 288 289/* Extract the divs in "bset" as a matrix. 290 */ 291__isl_give isl_mat *isl_basic_set_get_divs(__isl_keep isl_basic_set *bset) 292{ 293 return isl_basic_map_get_divs(bset); 294} 295 296__isl_give isl_local_space *isl_basic_map_get_local_space( 297 __isl_keep isl_basic_map *bmap) 298{ 299 isl_mat *div; 300 301 if (!bmap) 302 return NULL; 303 304 div = isl_basic_map_get_divs(bmap); 305 return isl_local_space_alloc_div(isl_space_copy(bmap->dim), div); 306} 307 308__isl_give isl_local_space *isl_basic_set_get_local_space( 309 __isl_keep isl_basic_set *bset) 310{ 311 return isl_basic_map_get_local_space(bset); 312} 313 314__isl_give isl_basic_map *isl_basic_map_from_local_space( 315 __isl_take isl_local_space *ls) 316{ 317 int i; 318 int n_div; 319 isl_basic_map *bmap; 320 321 if (!ls) 322 return NULL; 323 324 n_div = isl_local_space_dim(ls, isl_dim_div); 325 bmap = isl_basic_map_alloc_space(isl_local_space_get_space(ls), 326 n_div, 0, 2 * n_div); 327 328 for (i = 0; i < n_div; ++i) 329 if (isl_basic_map_alloc_div(bmap) < 0) 330 goto error; 331 332 for (i = 0; i < n_div; ++i) { 333 isl_seq_cpy(bmap->div[i], ls->div->row[i], ls->div->n_col); 334 if (isl_basic_map_add_div_constraints(bmap, i) < 0) 335 goto error; 336 } 337 338 isl_local_space_free(ls); 339 return bmap; 340error: 341 isl_local_space_free(ls); 342 isl_basic_map_free(bmap); 343 return NULL; 344} 345 346__isl_give isl_basic_set *isl_basic_set_from_local_space( 347 __isl_take isl_local_space *ls) 348{ 349 return isl_basic_map_from_local_space(ls); 350} 351 352__isl_give isl_space *isl_map_get_space(__isl_keep isl_map *map) 353{ 354 if (!map) 355 return NULL; 356 return isl_space_copy(map->dim); 357} 358 359__isl_give isl_space *isl_set_get_space(__isl_keep isl_set *set) 360{ 361 if (!set) 362 return NULL; 363 return isl_space_copy(set->dim); 364} 365 366__isl_give isl_basic_map *isl_basic_map_set_tuple_name( 367 __isl_take isl_basic_map *bmap, enum isl_dim_type type, const char *s) 368{ 369 bmap = isl_basic_map_cow(bmap); 370 if (!bmap) 371 return NULL; 372 bmap->dim = isl_space_set_tuple_name(bmap->dim, type, s); 373 if (!bmap->dim) 374 goto error; 375 bmap = isl_basic_map_finalize(bmap); 376 return bmap; 377error: 378 isl_basic_map_free(bmap); 379 return NULL; 380} 381 382__isl_give isl_basic_set *isl_basic_set_set_tuple_name( 383 __isl_take isl_basic_set *bset, const char *s) 384{ 385 return isl_basic_map_set_tuple_name(bset, isl_dim_set, s); 386} 387 388const char *isl_basic_map_get_tuple_name(__isl_keep isl_basic_map *bmap, 389 enum isl_dim_type type) 390{ 391 return bmap ? isl_space_get_tuple_name(bmap->dim, type) : NULL; 392} 393 394__isl_give isl_map *isl_map_set_tuple_name(__isl_take isl_map *map, 395 enum isl_dim_type type, const char *s) 396{ 397 int i; 398 399 map = isl_map_cow(map); 400 if (!map) 401 return NULL; 402 403 map->dim = isl_space_set_tuple_name(map->dim, type, s); 404 if (!map->dim) 405 goto error; 406 407 for (i = 0; i < map->n; ++i) { 408 map->p[i] = isl_basic_map_set_tuple_name(map->p[i], type, s); 409 if (!map->p[i]) 410 goto error; 411 } 412 413 return map; 414error: 415 isl_map_free(map); 416 return NULL; 417} 418 419/* Does the input or output tuple have a name? 420 */ 421int isl_map_has_tuple_name(__isl_keep isl_map *map, enum isl_dim_type type) 422{ 423 return map ? isl_space_has_tuple_name(map->dim, type) : -1; 424} 425 426const char *isl_map_get_tuple_name(__isl_keep isl_map *map, 427 enum isl_dim_type type) 428{ 429 return map ? isl_space_get_tuple_name(map->dim, type) : NULL; 430} 431 432__isl_give isl_set *isl_set_set_tuple_name(__isl_take isl_set *set, 433 const char *s) 434{ 435 return (isl_set *)isl_map_set_tuple_name((isl_map *)set, isl_dim_set, s); 436} 437 438__isl_give isl_map *isl_map_set_tuple_id(__isl_take isl_map *map, 439 enum isl_dim_type type, __isl_take isl_id *id) 440{ 441 map = isl_map_cow(map); 442 if (!map) 443 return isl_id_free(id); 444 445 map->dim = isl_space_set_tuple_id(map->dim, type, id); 446 447 return isl_map_reset_space(map, isl_space_copy(map->dim)); 448} 449 450__isl_give isl_set *isl_set_set_tuple_id(__isl_take isl_set *set, 451 __isl_take isl_id *id) 452{ 453 return isl_map_set_tuple_id(set, isl_dim_set, id); 454} 455 456__isl_give isl_map *isl_map_reset_tuple_id(__isl_take isl_map *map, 457 enum isl_dim_type type) 458{ 459 map = isl_map_cow(map); 460 if (!map) 461 return NULL; 462 463 map->dim = isl_space_reset_tuple_id(map->dim, type); 464 465 return isl_map_reset_space(map, isl_space_copy(map->dim)); 466} 467 468__isl_give isl_set *isl_set_reset_tuple_id(__isl_take isl_set *set) 469{ 470 return isl_map_reset_tuple_id(set, isl_dim_set); 471} 472 473int isl_map_has_tuple_id(__isl_keep isl_map *map, enum isl_dim_type type) 474{ 475 return map ? isl_space_has_tuple_id(map->dim, type) : -1; 476} 477 478__isl_give isl_id *isl_map_get_tuple_id(__isl_keep isl_map *map, 479 enum isl_dim_type type) 480{ 481 return map ? isl_space_get_tuple_id(map->dim, type) : NULL; 482} 483 484int isl_set_has_tuple_id(__isl_keep isl_set *set) 485{ 486 return isl_map_has_tuple_id(set, isl_dim_set); 487} 488 489__isl_give isl_id *isl_set_get_tuple_id(__isl_keep isl_set *set) 490{ 491 return isl_map_get_tuple_id(set, isl_dim_set); 492} 493 494/* Does the set tuple have a name? 495 */ 496int isl_set_has_tuple_name(__isl_keep isl_set *set) 497{ 498 return set ? isl_space_has_tuple_name(set->dim, isl_dim_set) : -1; 499} 500 501 502const char *isl_basic_set_get_tuple_name(__isl_keep isl_basic_set *bset) 503{ 504 return bset ? isl_space_get_tuple_name(bset->dim, isl_dim_set) : NULL; 505} 506 507const char *isl_set_get_tuple_name(__isl_keep isl_set *set) 508{ 509 return set ? isl_space_get_tuple_name(set->dim, isl_dim_set) : NULL; 510} 511 512const char *isl_basic_map_get_dim_name(__isl_keep isl_basic_map *bmap, 513 enum isl_dim_type type, unsigned pos) 514{ 515 return bmap ? isl_space_get_dim_name(bmap->dim, type, pos) : NULL; 516} 517 518const char *isl_basic_set_get_dim_name(__isl_keep isl_basic_set *bset, 519 enum isl_dim_type type, unsigned pos) 520{ 521 return bset ? isl_space_get_dim_name(bset->dim, type, pos) : NULL; 522} 523 524/* Does the given dimension have a name? 525 */ 526int isl_map_has_dim_name(__isl_keep isl_map *map, 527 enum isl_dim_type type, unsigned pos) 528{ 529 return map ? isl_space_has_dim_name(map->dim, type, pos) : -1; 530} 531 532const char *isl_map_get_dim_name(__isl_keep isl_map *map, 533 enum isl_dim_type type, unsigned pos) 534{ 535 return map ? isl_space_get_dim_name(map->dim, type, pos) : NULL; 536} 537 538const char *isl_set_get_dim_name(__isl_keep isl_set *set, 539 enum isl_dim_type type, unsigned pos) 540{ 541 return set ? isl_space_get_dim_name(set->dim, type, pos) : NULL; 542} 543 544/* Does the given dimension have a name? 545 */ 546int isl_set_has_dim_name(__isl_keep isl_set *set, 547 enum isl_dim_type type, unsigned pos) 548{ 549 return set ? isl_space_has_dim_name(set->dim, type, pos) : -1; 550} 551 552__isl_give isl_basic_map *isl_basic_map_set_dim_name( 553 __isl_take isl_basic_map *bmap, 554 enum isl_dim_type type, unsigned pos, const char *s) 555{ 556 bmap = isl_basic_map_cow(bmap); 557 if (!bmap) 558 return NULL; 559 bmap->dim = isl_space_set_dim_name(bmap->dim, type, pos, s); 560 if (!bmap->dim) 561 goto error; 562 return isl_basic_map_finalize(bmap); 563error: 564 isl_basic_map_free(bmap); 565 return NULL; 566} 567 568__isl_give isl_map *isl_map_set_dim_name(__isl_take isl_map *map, 569 enum isl_dim_type type, unsigned pos, const char *s) 570{ 571 int i; 572 573 map = isl_map_cow(map); 574 if (!map) 575 return NULL; 576 577 map->dim = isl_space_set_dim_name(map->dim, type, pos, s); 578 if (!map->dim) 579 goto error; 580 581 for (i = 0; i < map->n; ++i) { 582 map->p[i] = isl_basic_map_set_dim_name(map->p[i], type, pos, s); 583 if (!map->p[i]) 584 goto error; 585 } 586 587 return map; 588error: 589 isl_map_free(map); 590 return NULL; 591} 592 593__isl_give isl_basic_set *isl_basic_set_set_dim_name( 594 __isl_take isl_basic_set *bset, 595 enum isl_dim_type type, unsigned pos, const char *s) 596{ 597 return (isl_basic_set *)isl_basic_map_set_dim_name( 598 (isl_basic_map *)bset, type, pos, s); 599} 600 601__isl_give isl_set *isl_set_set_dim_name(__isl_take isl_set *set, 602 enum isl_dim_type type, unsigned pos, const char *s) 603{ 604 return (isl_set *)isl_map_set_dim_name((isl_map *)set, type, pos, s); 605} 606 607int isl_basic_map_has_dim_id(__isl_keep isl_basic_map *bmap, 608 enum isl_dim_type type, unsigned pos) 609{ 610 return bmap ? isl_space_has_dim_id(bmap->dim, type, pos) : -1; 611} 612 613__isl_give isl_id *isl_basic_set_get_dim_id(__isl_keep isl_basic_set *bset, 614 enum isl_dim_type type, unsigned pos) 615{ 616 return bset ? isl_space_get_dim_id(bset->dim, type, pos) : NULL; 617} 618 619int isl_map_has_dim_id(__isl_keep isl_map *map, 620 enum isl_dim_type type, unsigned pos) 621{ 622 return map ? isl_space_has_dim_id(map->dim, type, pos) : -1; 623} 624 625__isl_give isl_id *isl_map_get_dim_id(__isl_keep isl_map *map, 626 enum isl_dim_type type, unsigned pos) 627{ 628 return map ? isl_space_get_dim_id(map->dim, type, pos) : NULL; 629} 630 631int isl_set_has_dim_id(__isl_keep isl_set *set, 632 enum isl_dim_type type, unsigned pos) 633{ 634 return isl_map_has_dim_id(set, type, pos); 635} 636 637__isl_give isl_id *isl_set_get_dim_id(__isl_keep isl_set *set, 638 enum isl_dim_type type, unsigned pos) 639{ 640 return isl_map_get_dim_id(set, type, pos); 641} 642 643__isl_give isl_map *isl_map_set_dim_id(__isl_take isl_map *map, 644 enum isl_dim_type type, unsigned pos, __isl_take isl_id *id) 645{ 646 map = isl_map_cow(map); 647 if (!map) 648 return isl_id_free(id); 649 650 map->dim = isl_space_set_dim_id(map->dim, type, pos, id); 651 652 return isl_map_reset_space(map, isl_space_copy(map->dim)); 653} 654 655__isl_give isl_set *isl_set_set_dim_id(__isl_take isl_set *set, 656 enum isl_dim_type type, unsigned pos, __isl_take isl_id *id) 657{ 658 return isl_map_set_dim_id(set, type, pos, id); 659} 660 661int isl_map_find_dim_by_id(__isl_keep isl_map *map, enum isl_dim_type type, 662 __isl_keep isl_id *id) 663{ 664 if (!map) 665 return -1; 666 return isl_space_find_dim_by_id(map->dim, type, id); 667} 668 669int isl_set_find_dim_by_id(__isl_keep isl_set *set, enum isl_dim_type type, 670 __isl_keep isl_id *id) 671{ 672 return isl_map_find_dim_by_id(set, type, id); 673} 674 675int isl_map_find_dim_by_name(__isl_keep isl_map *map, enum isl_dim_type type, 676 const char *name) 677{ 678 if (!map) 679 return -1; 680 return isl_space_find_dim_by_name(map->dim, type, name); 681} 682 683int isl_set_find_dim_by_name(__isl_keep isl_set *set, enum isl_dim_type type, 684 const char *name) 685{ 686 return isl_map_find_dim_by_name(set, type, name); 687} 688 689int isl_basic_map_is_rational(__isl_keep isl_basic_map *bmap) 690{ 691 if (!bmap) 692 return -1; 693 return ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL); 694} 695 696int isl_basic_set_is_rational(__isl_keep isl_basic_set *bset) 697{ 698 return isl_basic_map_is_rational(bset); 699} 700 701/* Does "bmap" contain any rational points? 702 * 703 * If "bmap" has an equality for each dimension, equating the dimension 704 * to an integer constant, then it has no rational points, even if it 705 * is marked as rational. 706 */ 707int isl_basic_map_has_rational(__isl_keep isl_basic_map *bmap) 708{ 709 int has_rational = 1; 710 unsigned total; 711 712 if (!bmap) 713 return -1; 714 if (isl_basic_map_plain_is_empty(bmap)) 715 return 0; 716 if (!isl_basic_map_is_rational(bmap)) 717 return 0; 718 bmap = isl_basic_map_copy(bmap); 719 bmap = isl_basic_map_implicit_equalities(bmap); 720 if (!bmap) 721 return -1; 722 total = isl_basic_map_total_dim(bmap); 723 if (bmap->n_eq == total) { 724 int i, j; 725 for (i = 0; i < bmap->n_eq; ++i) { 726 j = isl_seq_first_non_zero(bmap->eq[i] + 1, total); 727 if (j < 0) 728 break; 729 if (!isl_int_is_one(bmap->eq[i][1 + j]) && 730 !isl_int_is_negone(bmap->eq[i][1 + j])) 731 break; 732 j = isl_seq_first_non_zero(bmap->eq[i] + 1 + j + 1, 733 total - j - 1); 734 if (j >= 0) 735 break; 736 } 737 if (i == bmap->n_eq) 738 has_rational = 0; 739 } 740 isl_basic_map_free(bmap); 741 742 return has_rational; 743} 744 745/* Does "map" contain any rational points? 746 */ 747int isl_map_has_rational(__isl_keep isl_map *map) 748{ 749 int i; 750 int has_rational; 751 752 if (!map) 753 return -1; 754 for (i = 0; i < map->n; ++i) { 755 has_rational = isl_basic_map_has_rational(map->p[i]); 756 if (has_rational < 0) 757 return -1; 758 if (has_rational) 759 return 1; 760 } 761 return 0; 762} 763 764/* Does "set" contain any rational points? 765 */ 766int isl_set_has_rational(__isl_keep isl_set *set) 767{ 768 return isl_map_has_rational(set); 769} 770 771/* Is this basic set a parameter domain? 772 */ 773int isl_basic_set_is_params(__isl_keep isl_basic_set *bset) 774{ 775 if (!bset) 776 return -1; 777 return isl_space_is_params(bset->dim); 778} 779 780/* Is this set a parameter domain? 781 */ 782int isl_set_is_params(__isl_keep isl_set *set) 783{ 784 if (!set) 785 return -1; 786 return isl_space_is_params(set->dim); 787} 788 789/* Is this map actually a parameter domain? 790 * Users should never call this function. Outside of isl, 791 * a map can never be a parameter domain. 792 */ 793int isl_map_is_params(__isl_keep isl_map *map) 794{ 795 if (!map) 796 return -1; 797 return isl_space_is_params(map->dim); 798} 799 800static struct isl_basic_map *basic_map_init(struct isl_ctx *ctx, 801 struct isl_basic_map *bmap, unsigned extra, 802 unsigned n_eq, unsigned n_ineq) 803{ 804 int i; 805 size_t row_size = 1 + isl_space_dim(bmap->dim, isl_dim_all) + extra; 806 807 bmap->ctx = ctx; 808 isl_ctx_ref(ctx); 809 810 bmap->block = isl_blk_alloc(ctx, (n_ineq + n_eq) * row_size); 811 if (isl_blk_is_error(bmap->block)) 812 goto error; 813 814 bmap->ineq = isl_alloc_array(ctx, isl_int *, n_ineq + n_eq); 815 if ((n_ineq + n_eq) && !bmap->ineq) 816 goto error; 817 818 if (extra == 0) { 819 bmap->block2 = isl_blk_empty(); 820 bmap->div = NULL; 821 } else { 822 bmap->block2 = isl_blk_alloc(ctx, extra * (1 + row_size)); 823 if (isl_blk_is_error(bmap->block2)) 824 goto error; 825 826 bmap->div = isl_alloc_array(ctx, isl_int *, extra); 827 if (!bmap->div) 828 goto error; 829 } 830 831 for (i = 0; i < n_ineq + n_eq; ++i) 832 bmap->ineq[i] = bmap->block.data + i * row_size; 833 834 for (i = 0; i < extra; ++i) 835 bmap->div[i] = bmap->block2.data + i * (1 + row_size); 836 837 bmap->ref = 1; 838 bmap->flags = 0; 839 bmap->c_size = n_eq + n_ineq; 840 bmap->eq = bmap->ineq + n_ineq; 841 bmap->extra = extra; 842 bmap->n_eq = 0; 843 bmap->n_ineq = 0; 844 bmap->n_div = 0; 845 bmap->sample = NULL; 846 847 return bmap; 848error: 849 isl_basic_map_free(bmap); 850 return NULL; 851} 852 853struct isl_basic_set *isl_basic_set_alloc(struct isl_ctx *ctx, 854 unsigned nparam, unsigned dim, unsigned extra, 855 unsigned n_eq, unsigned n_ineq) 856{ 857 struct isl_basic_map *bmap; 858 isl_space *space; 859 860 space = isl_space_set_alloc(ctx, nparam, dim); 861 if (!space) 862 return NULL; 863 864 bmap = isl_basic_map_alloc_space(space, extra, n_eq, n_ineq); 865 return (struct isl_basic_set *)bmap; 866} 867 868struct isl_basic_set *isl_basic_set_alloc_space(__isl_take isl_space *dim, 869 unsigned extra, unsigned n_eq, unsigned n_ineq) 870{ 871 struct isl_basic_map *bmap; 872 if (!dim) 873 return NULL; 874 isl_assert(dim->ctx, dim->n_in == 0, goto error); 875 bmap = isl_basic_map_alloc_space(dim, extra, n_eq, n_ineq); 876 return (struct isl_basic_set *)bmap; 877error: 878 isl_space_free(dim); 879 return NULL; 880} 881 882struct isl_basic_map *isl_basic_map_alloc_space(__isl_take isl_space *dim, 883 unsigned extra, unsigned n_eq, unsigned n_ineq) 884{ 885 struct isl_basic_map *bmap; 886 887 if (!dim) 888 return NULL; 889 bmap = isl_calloc_type(dim->ctx, struct isl_basic_map); 890 if (!bmap) 891 goto error; 892 bmap->dim = dim; 893 894 return basic_map_init(dim->ctx, bmap, extra, n_eq, n_ineq); 895error: 896 isl_space_free(dim); 897 return NULL; 898} 899 900struct isl_basic_map *isl_basic_map_alloc(struct isl_ctx *ctx, 901 unsigned nparam, unsigned in, unsigned out, unsigned extra, 902 unsigned n_eq, unsigned n_ineq) 903{ 904 struct isl_basic_map *bmap; 905 isl_space *dim; 906 907 dim = isl_space_alloc(ctx, nparam, in, out); 908 if (!dim) 909 return NULL; 910 911 bmap = isl_basic_map_alloc_space(dim, extra, n_eq, n_ineq); 912 return bmap; 913} 914 915static void dup_constraints( 916 struct isl_basic_map *dst, struct isl_basic_map *src) 917{ 918 int i; 919 unsigned total = isl_basic_map_total_dim(src); 920 921 for (i = 0; i < src->n_eq; ++i) { 922 int j = isl_basic_map_alloc_equality(dst); 923 isl_seq_cpy(dst->eq[j], src->eq[i], 1+total); 924 } 925 926 for (i = 0; i < src->n_ineq; ++i) { 927 int j = isl_basic_map_alloc_inequality(dst); 928 isl_seq_cpy(dst->ineq[j], src->ineq[i], 1+total); 929 } 930 931 for (i = 0; i < src->n_div; ++i) { 932 int j = isl_basic_map_alloc_div(dst); 933 isl_seq_cpy(dst->div[j], src->div[i], 1+1+total); 934 } 935 ISL_F_SET(dst, ISL_BASIC_SET_FINAL); 936} 937 938struct isl_basic_map *isl_basic_map_dup(struct isl_basic_map *bmap) 939{ 940 struct isl_basic_map *dup; 941 942 if (!bmap) 943 return NULL; 944 dup = isl_basic_map_alloc_space(isl_space_copy(bmap->dim), 945 bmap->n_div, bmap->n_eq, bmap->n_ineq); 946 if (!dup) 947 return NULL; 948 dup_constraints(dup, bmap); 949 dup->flags = bmap->flags; 950 dup->sample = isl_vec_copy(bmap->sample); 951 return dup; 952} 953 954struct isl_basic_set *isl_basic_set_dup(struct isl_basic_set *bset) 955{ 956 struct isl_basic_map *dup; 957 958 dup = isl_basic_map_dup((struct isl_basic_map *)bset); 959 return (struct isl_basic_set *)dup; 960} 961 962struct isl_basic_set *isl_basic_set_copy(struct isl_basic_set *bset) 963{ 964 if (!bset) 965 return NULL; 966 967 if (ISL_F_ISSET(bset, ISL_BASIC_SET_FINAL)) { 968 bset->ref++; 969 return bset; 970 } 971 return isl_basic_set_dup(bset); 972} 973 974struct isl_set *isl_set_copy(struct isl_set *set) 975{ 976 if (!set) 977 return NULL; 978 979 set->ref++; 980 return set; 981} 982 983struct isl_basic_map *isl_basic_map_copy(struct isl_basic_map *bmap) 984{ 985 if (!bmap) 986 return NULL; 987 988 if (ISL_F_ISSET(bmap, ISL_BASIC_SET_FINAL)) { 989 bmap->ref++; 990 return bmap; 991 } 992 bmap = isl_basic_map_dup(bmap); 993 if (bmap) 994 ISL_F_SET(bmap, ISL_BASIC_SET_FINAL); 995 return bmap; 996} 997 998struct isl_map *isl_map_copy(struct isl_map *map) 999{ 1000 if (!map) 1001 return NULL; 1002 1003 map->ref++; 1004 return map; 1005} 1006 1007void *isl_basic_map_free(__isl_take isl_basic_map *bmap) 1008{ 1009 if (!bmap) 1010 return NULL; 1011 1012 if (--bmap->ref > 0) 1013 return NULL; 1014 1015 isl_ctx_deref(bmap->ctx); 1016 free(bmap->div); 1017 isl_blk_free(bmap->ctx, bmap->block2); 1018 free(bmap->ineq); 1019 isl_blk_free(bmap->ctx, bmap->block); 1020 isl_vec_free(bmap->sample); 1021 isl_space_free(bmap->dim); 1022 free(bmap); 1023 1024 return NULL; 1025} 1026 1027void *isl_basic_set_free(struct isl_basic_set *bset) 1028{ 1029 return isl_basic_map_free((struct isl_basic_map *)bset); 1030} 1031 1032static int room_for_con(struct isl_basic_map *bmap, unsigned n) 1033{ 1034 return bmap->n_eq + bmap->n_ineq + n <= bmap->c_size; 1035} 1036 1037__isl_give isl_map *isl_map_align_params_map_map_and( 1038 __isl_take isl_map *map1, __isl_take isl_map *map2, 1039 __isl_give isl_map *(*fn)(__isl_take isl_map *map1, 1040 __isl_take isl_map *map2)) 1041{ 1042 if (!map1 || !map2) 1043 goto error; 1044 if (isl_space_match(map1->dim, isl_dim_param, map2->dim, isl_dim_param)) 1045 return fn(map1, map2); 1046 if (!isl_space_has_named_params(map1->dim) || 1047 !isl_space_has_named_params(map2->dim)) 1048 isl_die(map1->ctx, isl_error_invalid, 1049 "unaligned unnamed parameters", goto error); 1050 map1 = isl_map_align_params(map1, isl_map_get_space(map2)); 1051 map2 = isl_map_align_params(map2, isl_map_get_space(map1)); 1052 return fn(map1, map2); 1053error: 1054 isl_map_free(map1); 1055 isl_map_free(map2); 1056 return NULL; 1057} 1058 1059int isl_map_align_params_map_map_and_test(__isl_keep isl_map *map1, 1060 __isl_keep isl_map *map2, 1061 int (*fn)(__isl_keep isl_map *map1, __isl_keep isl_map *map2)) 1062{ 1063 int r; 1064 1065 if (!map1 || !map2) 1066 return -1; 1067 if (isl_space_match(map1->dim, isl_dim_param, map2->dim, isl_dim_param)) 1068 return fn(map1, map2); 1069 if (!isl_space_has_named_params(map1->dim) || 1070 !isl_space_has_named_params(map2->dim)) 1071 isl_die(map1->ctx, isl_error_invalid, 1072 "unaligned unnamed parameters", return -1); 1073 map1 = isl_map_copy(map1); 1074 map2 = isl_map_copy(map2); 1075 map1 = isl_map_align_params(map1, isl_map_get_space(map2)); 1076 map2 = isl_map_align_params(map2, isl_map_get_space(map1)); 1077 r = fn(map1, map2); 1078 isl_map_free(map1); 1079 isl_map_free(map2); 1080 return r; 1081} 1082 1083int isl_basic_map_alloc_equality(struct isl_basic_map *bmap) 1084{ 1085 struct isl_ctx *ctx; 1086 if (!bmap) 1087 return -1; 1088 ctx = bmap->ctx; 1089 isl_assert(ctx, room_for_con(bmap, 1), return -1); 1090 isl_assert(ctx, (bmap->eq - bmap->ineq) + bmap->n_eq <= bmap->c_size, 1091 return -1); 1092 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED); 1093 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT); 1094 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_IMPLICIT); 1095 ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES); 1096 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS); 1097 if ((bmap->eq - bmap->ineq) + bmap->n_eq == bmap->c_size) { 1098 isl_int *t; 1099 int j = isl_basic_map_alloc_inequality(bmap); 1100 if (j < 0) 1101 return -1; 1102 t = bmap->ineq[j]; 1103 bmap->ineq[j] = bmap->ineq[bmap->n_ineq - 1]; 1104 bmap->ineq[bmap->n_ineq - 1] = bmap->eq[-1]; 1105 bmap->eq[-1] = t; 1106 bmap->n_eq++; 1107 bmap->n_ineq--; 1108 bmap->eq--; 1109 return 0; 1110 } 1111 isl_seq_clr(bmap->eq[bmap->n_eq] + 1 + isl_basic_map_total_dim(bmap), 1112 bmap->extra - bmap->n_div); 1113 return bmap->n_eq++; 1114} 1115 1116int isl_basic_set_alloc_equality(struct isl_basic_set *bset) 1117{ 1118 return isl_basic_map_alloc_equality((struct isl_basic_map *)bset); 1119} 1120 1121int isl_basic_map_free_equality(struct isl_basic_map *bmap, unsigned n) 1122{ 1123 if (!bmap) 1124 return -1; 1125 isl_assert(bmap->ctx, n <= bmap->n_eq, return -1); 1126 bmap->n_eq -= n; 1127 return 0; 1128} 1129 1130int isl_basic_set_free_equality(struct isl_basic_set *bset, unsigned n) 1131{ 1132 return isl_basic_map_free_equality((struct isl_basic_map *)bset, n); 1133} 1134 1135int isl_basic_map_drop_equality(struct isl_basic_map *bmap, unsigned pos) 1136{ 1137 isl_int *t; 1138 if (!bmap) 1139 return -1; 1140 isl_assert(bmap->ctx, pos < bmap->n_eq, return -1); 1141 1142 if (pos != bmap->n_eq - 1) { 1143 t = bmap->eq[pos]; 1144 bmap->eq[pos] = bmap->eq[bmap->n_eq - 1]; 1145 bmap->eq[bmap->n_eq - 1] = t; 1146 } 1147 bmap->n_eq--; 1148 return 0; 1149} 1150 1151int isl_basic_set_drop_equality(struct isl_basic_set *bset, unsigned pos) 1152{ 1153 return isl_basic_map_drop_equality((struct isl_basic_map *)bset, pos); 1154} 1155 1156/* Turn inequality "pos" of "bmap" into an equality. 1157 * 1158 * In particular, we move the inequality in front of the equalities 1159 * and move the last inequality in the position of the moved inequality. 1160 * Note that isl_tab_make_equalities_explicit depends on this particular 1161 * change in the ordering of the constraints. 1162 */ 1163void isl_basic_map_inequality_to_equality( 1164 struct isl_basic_map *bmap, unsigned pos) 1165{ 1166 isl_int *t; 1167 1168 t = bmap->ineq[pos]; 1169 bmap->ineq[pos] = bmap->ineq[bmap->n_ineq - 1]; 1170 bmap->ineq[bmap->n_ineq - 1] = bmap->eq[-1]; 1171 bmap->eq[-1] = t; 1172 bmap->n_eq++; 1173 bmap->n_ineq--; 1174 bmap->eq--; 1175 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT); 1176 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED); 1177 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS); 1178 ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES); 1179} 1180 1181static int room_for_ineq(struct isl_basic_map *bmap, unsigned n) 1182{ 1183 return bmap->n_ineq + n <= bmap->eq - bmap->ineq; 1184} 1185 1186int isl_basic_map_alloc_inequality(struct isl_basic_map *bmap) 1187{ 1188 struct isl_ctx *ctx; 1189 if (!bmap) 1190 return -1; 1191 ctx = bmap->ctx; 1192 isl_assert(ctx, room_for_ineq(bmap, 1), return -1); 1193 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_IMPLICIT); 1194 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT); 1195 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED); 1196 ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES); 1197 isl_seq_clr(bmap->ineq[bmap->n_ineq] + 1198 1 + isl_basic_map_total_dim(bmap), 1199 bmap->extra - bmap->n_div); 1200 return bmap->n_ineq++; 1201} 1202 1203int isl_basic_set_alloc_inequality(struct isl_basic_set *bset) 1204{ 1205 return isl_basic_map_alloc_inequality((struct isl_basic_map *)bset); 1206} 1207 1208int isl_basic_map_free_inequality(struct isl_basic_map *bmap, unsigned n) 1209{ 1210 if (!bmap) 1211 return -1; 1212 isl_assert(bmap->ctx, n <= bmap->n_ineq, return -1); 1213 bmap->n_ineq -= n; 1214 return 0; 1215} 1216 1217int isl_basic_set_free_inequality(struct isl_basic_set *bset, unsigned n) 1218{ 1219 return isl_basic_map_free_inequality((struct isl_basic_map *)bset, n); 1220} 1221 1222int isl_basic_map_drop_inequality(struct isl_basic_map *bmap, unsigned pos) 1223{ 1224 isl_int *t; 1225 if (!bmap) 1226 return -1; 1227 isl_assert(bmap->ctx, pos < bmap->n_ineq, return -1); 1228 1229 if (pos != bmap->n_ineq - 1) { 1230 t = bmap->ineq[pos]; 1231 bmap->ineq[pos] = bmap->ineq[bmap->n_ineq - 1]; 1232 bmap->ineq[bmap->n_ineq - 1] = t; 1233 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED); 1234 } 1235 bmap->n_ineq--; 1236 return 0; 1237} 1238 1239int isl_basic_set_drop_inequality(struct isl_basic_set *bset, unsigned pos) 1240{ 1241 return isl_basic_map_drop_inequality((struct isl_basic_map *)bset, pos); 1242} 1243 1244__isl_give isl_basic_map *isl_basic_map_add_eq(__isl_take isl_basic_map *bmap, 1245 isl_int *eq) 1246{ 1247 int k; 1248 1249 bmap = isl_basic_map_extend_constraints(bmap, 1, 0); 1250 if (!bmap) 1251 return NULL; 1252 k = isl_basic_map_alloc_equality(bmap); 1253 if (k < 0) 1254 goto error; 1255 isl_seq_cpy(bmap->eq[k], eq, 1 + isl_basic_map_total_dim(bmap)); 1256 return bmap; 1257error: 1258 isl_basic_map_free(bmap); 1259 return NULL; 1260} 1261 1262__isl_give isl_basic_set *isl_basic_set_add_eq(__isl_take isl_basic_set *bset, 1263 isl_int *eq) 1264{ 1265 return (isl_basic_set *) 1266 isl_basic_map_add_eq((isl_basic_map *)bset, eq); 1267} 1268 1269__isl_give isl_basic_map *isl_basic_map_add_ineq(__isl_take isl_basic_map *bmap, 1270 isl_int *ineq) 1271{ 1272 int k; 1273 1274 bmap = isl_basic_map_extend_constraints(bmap, 0, 1); 1275 if (!bmap) 1276 return NULL; 1277 k = isl_basic_map_alloc_inequality(bmap); 1278 if (k < 0) 1279 goto error; 1280 isl_seq_cpy(bmap->ineq[k], ineq, 1 + isl_basic_map_total_dim(bmap)); 1281 return bmap; 1282error: 1283 isl_basic_map_free(bmap); 1284 return NULL; 1285} 1286 1287__isl_give isl_basic_set *isl_basic_set_add_ineq(__isl_take isl_basic_set *bset, 1288 isl_int *ineq) 1289{ 1290 return (isl_basic_set *) 1291 isl_basic_map_add_ineq((isl_basic_map *)bset, ineq); 1292} 1293 1294int isl_basic_map_alloc_div(struct isl_basic_map *bmap) 1295{ 1296 if (!bmap) 1297 return -1; 1298 isl_assert(bmap->ctx, bmap->n_div < bmap->extra, return -1); 1299 isl_seq_clr(bmap->div[bmap->n_div] + 1300 1 + 1 + isl_basic_map_total_dim(bmap), 1301 bmap->extra - bmap->n_div); 1302 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS); 1303 return bmap->n_div++; 1304} 1305 1306int isl_basic_set_alloc_div(struct isl_basic_set *bset) 1307{ 1308 return isl_basic_map_alloc_div((struct isl_basic_map *)bset); 1309} 1310 1311int isl_basic_map_free_div(struct isl_basic_map *bmap, unsigned n) 1312{ 1313 if (!bmap) 1314 return -1; 1315 isl_assert(bmap->ctx, n <= bmap->n_div, return -1); 1316 bmap->n_div -= n; 1317 return 0; 1318} 1319 1320int isl_basic_set_free_div(struct isl_basic_set *bset, unsigned n) 1321{ 1322 return isl_basic_map_free_div((struct isl_basic_map *)bset, n); 1323} 1324 1325/* Copy constraint from src to dst, putting the vars of src at offset 1326 * dim_off in dst and the divs of src at offset div_off in dst. 1327 * If both sets are actually map, then dim_off applies to the input 1328 * variables. 1329 */ 1330static void copy_constraint(struct isl_basic_map *dst_map, isl_int *dst, 1331 struct isl_basic_map *src_map, isl_int *src, 1332 unsigned in_off, unsigned out_off, unsigned div_off) 1333{ 1334 unsigned src_nparam = isl_basic_map_n_param(src_map); 1335 unsigned dst_nparam = isl_basic_map_n_param(dst_map); 1336 unsigned src_in = isl_basic_map_n_in(src_map); 1337 unsigned dst_in = isl_basic_map_n_in(dst_map); 1338 unsigned src_out = isl_basic_map_n_out(src_map); 1339 unsigned dst_out = isl_basic_map_n_out(dst_map); 1340 isl_int_set(dst[0], src[0]); 1341 isl_seq_cpy(dst+1, src+1, isl_min(dst_nparam, src_nparam)); 1342 if (dst_nparam > src_nparam) 1343 isl_seq_clr(dst+1+src_nparam, 1344 dst_nparam - src_nparam); 1345 isl_seq_clr(dst+1+dst_nparam, in_off); 1346 isl_seq_cpy(dst+1+dst_nparam+in_off, 1347 src+1+src_nparam, 1348 isl_min(dst_in-in_off, src_in)); 1349 if (dst_in-in_off > src_in) 1350 isl_seq_clr(dst+1+dst_nparam+in_off+src_in, 1351 dst_in - in_off - src_in); 1352 isl_seq_clr(dst+1+dst_nparam+dst_in, out_off); 1353 isl_seq_cpy(dst+1+dst_nparam+dst_in+out_off, 1354 src+1+src_nparam+src_in, 1355 isl_min(dst_out-out_off, src_out)); 1356 if (dst_out-out_off > src_out) 1357 isl_seq_clr(dst+1+dst_nparam+dst_in+out_off+src_out, 1358 dst_out - out_off - src_out); 1359 isl_seq_clr(dst+1+dst_nparam+dst_in+dst_out, div_off); 1360 isl_seq_cpy(dst+1+dst_nparam+dst_in+dst_out+div_off, 1361 src+1+src_nparam+src_in+src_out, 1362 isl_min(dst_map->extra-div_off, src_map->n_div)); 1363 if (dst_map->n_div-div_off > src_map->n_div) 1364 isl_seq_clr(dst+1+dst_nparam+dst_in+dst_out+ 1365 div_off+src_map->n_div, 1366 dst_map->n_div - div_off - src_map->n_div); 1367} 1368 1369static void copy_div(struct isl_basic_map *dst_map, isl_int *dst, 1370 struct isl_basic_map *src_map, isl_int *src, 1371 unsigned in_off, unsigned out_off, unsigned div_off) 1372{ 1373 isl_int_set(dst[0], src[0]); 1374 copy_constraint(dst_map, dst+1, src_map, src+1, in_off, out_off, div_off); 1375} 1376 1377static struct isl_basic_map *add_constraints(struct isl_basic_map *bmap1, 1378 struct isl_basic_map *bmap2, unsigned i_pos, unsigned o_pos) 1379{ 1380 int i; 1381 unsigned div_off; 1382 1383 if (!bmap1 || !bmap2) 1384 goto error; 1385 1386 div_off = bmap1->n_div; 1387 1388 for (i = 0; i < bmap2->n_eq; ++i) { 1389 int i1 = isl_basic_map_alloc_equality(bmap1); 1390 if (i1 < 0) 1391 goto error; 1392 copy_constraint(bmap1, bmap1->eq[i1], bmap2, bmap2->eq[i], 1393 i_pos, o_pos, div_off); 1394 } 1395 1396 for (i = 0; i < bmap2->n_ineq; ++i) { 1397 int i1 = isl_basic_map_alloc_inequality(bmap1); 1398 if (i1 < 0) 1399 goto error; 1400 copy_constraint(bmap1, bmap1->ineq[i1], bmap2, bmap2->ineq[i], 1401 i_pos, o_pos, div_off); 1402 } 1403 1404 for (i = 0; i < bmap2->n_div; ++i) { 1405 int i1 = isl_basic_map_alloc_div(bmap1); 1406 if (i1 < 0) 1407 goto error; 1408 copy_div(bmap1, bmap1->div[i1], bmap2, bmap2->div[i], 1409 i_pos, o_pos, div_off); 1410 } 1411 1412 isl_basic_map_free(bmap2); 1413 1414 return bmap1; 1415 1416error: 1417 isl_basic_map_free(bmap1); 1418 isl_basic_map_free(bmap2); 1419 return NULL; 1420} 1421 1422struct isl_basic_set *isl_basic_set_add_constraints(struct isl_basic_set *bset1, 1423 struct isl_basic_set *bset2, unsigned pos) 1424{ 1425 return (struct isl_basic_set *) 1426 add_constraints((struct isl_basic_map *)bset1, 1427 (struct isl_basic_map *)bset2, 0, pos); 1428} 1429 1430struct isl_basic_map *isl_basic_map_extend_space(struct isl_basic_map *base, 1431 __isl_take isl_space *dim, unsigned extra, 1432 unsigned n_eq, unsigned n_ineq) 1433{ 1434 struct isl_basic_map *ext; 1435 unsigned flags; 1436 int dims_ok; 1437 1438 if (!dim) 1439 goto error; 1440 1441 if (!base) 1442 goto error; 1443 1444 dims_ok = isl_space_is_equal(base->dim, dim) && 1445 base->extra >= base->n_div + extra; 1446 1447 if (dims_ok && room_for_con(base, n_eq + n_ineq) && 1448 room_for_ineq(base, n_ineq)) { 1449 isl_space_free(dim); 1450 return base; 1451 } 1452 1453 isl_assert(base->ctx, base->dim->nparam <= dim->nparam, goto error); 1454 isl_assert(base->ctx, base->dim->n_in <= dim->n_in, goto error); 1455 isl_assert(base->ctx, base->dim->n_out <= dim->n_out, goto error); 1456 extra += base->extra; 1457 n_eq += base->n_eq; 1458 n_ineq += base->n_ineq; 1459 1460 ext = isl_basic_map_alloc_space(dim, extra, n_eq, n_ineq); 1461 dim = NULL; 1462 if (!ext) 1463 goto error; 1464 1465 if (dims_ok) 1466 ext->sample = isl_vec_copy(base->sample); 1467 flags = base->flags; 1468 ext = add_constraints(ext, base, 0, 0); 1469 if (ext) { 1470 ext->flags = flags; 1471 ISL_F_CLR(ext, ISL_BASIC_SET_FINAL); 1472 } 1473 1474 return ext; 1475 1476error: 1477 isl_space_free(dim); 1478 isl_basic_map_free(base); 1479 return NULL; 1480} 1481 1482struct isl_basic_set *isl_basic_set_extend_space(struct isl_basic_set *base, 1483 __isl_take isl_space *dim, unsigned extra, 1484 unsigned n_eq, unsigned n_ineq) 1485{ 1486 return (struct isl_basic_set *) 1487 isl_basic_map_extend_space((struct isl_basic_map *)base, dim, 1488 extra, n_eq, n_ineq); 1489} 1490 1491struct isl_basic_map *isl_basic_map_extend_constraints( 1492 struct isl_basic_map *base, unsigned n_eq, unsigned n_ineq) 1493{ 1494 if (!base) 1495 return NULL; 1496 return isl_basic_map_extend_space(base, isl_space_copy(base->dim), 1497 0, n_eq, n_ineq); 1498} 1499 1500struct isl_basic_map *isl_basic_map_extend(struct isl_basic_map *base, 1501 unsigned nparam, unsigned n_in, unsigned n_out, unsigned extra, 1502 unsigned n_eq, unsigned n_ineq) 1503{ 1504 struct isl_basic_map *bmap; 1505 isl_space *dim; 1506 1507 if (!base) 1508 return NULL; 1509 dim = isl_space_alloc(base->ctx, nparam, n_in, n_out); 1510 if (!dim) 1511 goto error; 1512 1513 bmap = isl_basic_map_extend_space(base, dim, extra, n_eq, n_ineq); 1514 return bmap; 1515error: 1516 isl_basic_map_free(base); 1517 return NULL; 1518} 1519 1520struct isl_basic_set *isl_basic_set_extend(struct isl_basic_set *base, 1521 unsigned nparam, unsigned dim, unsigned extra, 1522 unsigned n_eq, unsigned n_ineq) 1523{ 1524 return (struct isl_basic_set *) 1525 isl_basic_map_extend((struct isl_basic_map *)base, 1526 nparam, 0, dim, extra, n_eq, n_ineq); 1527} 1528 1529struct isl_basic_set *isl_basic_set_extend_constraints( 1530 struct isl_basic_set *base, unsigned n_eq, unsigned n_ineq) 1531{ 1532 return (struct isl_basic_set *) 1533 isl_basic_map_extend_constraints((struct isl_basic_map *)base, 1534 n_eq, n_ineq); 1535} 1536 1537struct isl_basic_set *isl_basic_set_cow(struct isl_basic_set *bset) 1538{ 1539 return (struct isl_basic_set *) 1540 isl_basic_map_cow((struct isl_basic_map *)bset); 1541} 1542 1543struct isl_basic_map *isl_basic_map_cow(struct isl_basic_map *bmap) 1544{ 1545 if (!bmap) 1546 return NULL; 1547 1548 if (bmap->ref > 1) { 1549 bmap->ref--; 1550 bmap = isl_basic_map_dup(bmap); 1551 } 1552 if (bmap) 1553 ISL_F_CLR(bmap, ISL_BASIC_SET_FINAL); 1554 return bmap; 1555} 1556 1557struct isl_set *isl_set_cow(struct isl_set *set) 1558{ 1559 if (!set) 1560 return NULL; 1561 1562 if (set->ref == 1) 1563 return set; 1564 set->ref--; 1565 return isl_set_dup(set); 1566} 1567 1568struct isl_map *isl_map_cow(struct isl_map *map) 1569{ 1570 if (!map) 1571 return NULL; 1572 1573 if (map->ref == 1) 1574 return map; 1575 map->ref--; 1576 return isl_map_dup(map); 1577} 1578 1579static void swap_vars(struct isl_blk blk, isl_int *a, 1580 unsigned a_len, unsigned b_len) 1581{ 1582 isl_seq_cpy(blk.data, a+a_len, b_len); 1583 isl_seq_cpy(blk.data+b_len, a, a_len); 1584 isl_seq_cpy(a, blk.data, b_len+a_len); 1585} 1586 1587static __isl_give isl_basic_map *isl_basic_map_swap_vars( 1588 __isl_take isl_basic_map *bmap, unsigned pos, unsigned n1, unsigned n2) 1589{ 1590 int i; 1591 struct isl_blk blk; 1592 1593 if (!bmap) 1594 goto error; 1595 1596 isl_assert(bmap->ctx, 1597 pos + n1 + n2 <= 1 + isl_basic_map_total_dim(bmap), goto error); 1598 1599 if (n1 == 0 || n2 == 0) 1600 return bmap; 1601 1602 bmap = isl_basic_map_cow(bmap); 1603 if (!bmap) 1604 return NULL; 1605 1606 blk = isl_blk_alloc(bmap->ctx, n1 + n2); 1607 if (isl_blk_is_error(blk)) 1608 goto error; 1609 1610 for (i = 0; i < bmap->n_eq; ++i) 1611 swap_vars(blk, 1612 bmap->eq[i] + pos, n1, n2); 1613 1614 for (i = 0; i < bmap->n_ineq; ++i) 1615 swap_vars(blk, 1616 bmap->ineq[i] + pos, n1, n2); 1617 1618 for (i = 0; i < bmap->n_div; ++i) 1619 swap_vars(blk, 1620 bmap->div[i]+1 + pos, n1, n2); 1621 1622 isl_blk_free(bmap->ctx, blk); 1623 1624 ISL_F_CLR(bmap, ISL_BASIC_SET_NORMALIZED); 1625 bmap = isl_basic_map_gauss(bmap, NULL); 1626 return isl_basic_map_finalize(bmap); 1627error: 1628 isl_basic_map_free(bmap); 1629 return NULL; 1630} 1631 1632static __isl_give isl_basic_set *isl_basic_set_swap_vars( 1633 __isl_take isl_basic_set *bset, unsigned n) 1634{ 1635 unsigned dim; 1636 unsigned nparam; 1637 1638 if (!bset) 1639 return NULL; 1640 1641 nparam = isl_basic_set_n_param(bset); 1642 dim = isl_basic_set_n_dim(bset); 1643 isl_assert(bset->ctx, n <= dim, goto error); 1644 1645 return isl_basic_map_swap_vars(bset, 1 + nparam, n, dim - n); 1646error: 1647 isl_basic_set_free(bset); 1648 return NULL; 1649} 1650 1651struct isl_basic_map *isl_basic_map_set_to_empty(struct isl_basic_map *bmap) 1652{ 1653 int i = 0; 1654 unsigned total; 1655 if (!bmap) 1656 goto error; 1657 total = isl_basic_map_total_dim(bmap); 1658 isl_basic_map_free_div(bmap, bmap->n_div); 1659 isl_basic_map_free_inequality(bmap, bmap->n_ineq); 1660 if (bmap->n_eq > 0) 1661 isl_basic_map_free_equality(bmap, bmap->n_eq-1); 1662 else { 1663 i = isl_basic_map_alloc_equality(bmap); 1664 if (i < 0) 1665 goto error; 1666 } 1667 isl_int_set_si(bmap->eq[i][0], 1); 1668 isl_seq_clr(bmap->eq[i]+1, total); 1669 ISL_F_SET(bmap, ISL_BASIC_MAP_EMPTY); 1670 isl_vec_free(bmap->sample); 1671 bmap->sample = NULL; 1672 return isl_basic_map_finalize(bmap); 1673error: 1674 isl_basic_map_free(bmap); 1675 return NULL; 1676} 1677 1678struct isl_basic_set *isl_basic_set_set_to_empty(struct isl_basic_set *bset) 1679{ 1680 return (struct isl_basic_set *) 1681 isl_basic_map_set_to_empty((struct isl_basic_map *)bset); 1682} 1683 1684/* Swap divs "a" and "b" in "bmap" (without modifying any of the constraints 1685 * of "bmap"). 1686 */ 1687static void swap_div(__isl_keep isl_basic_map *bmap, int a, int b) 1688{ 1689 isl_int *t = bmap->div[a]; 1690 bmap->div[a] = bmap->div[b]; 1691 bmap->div[b] = t; 1692} 1693 1694/* Swap divs "a" and "b" in "bmap" and adjust the constraints and 1695 * div definitions accordingly. 1696 */ 1697void isl_basic_map_swap_div(struct isl_basic_map *bmap, int a, int b) 1698{ 1699 int i; 1700 unsigned off = isl_space_dim(bmap->dim, isl_dim_all); 1701 1702 swap_div(bmap, a, b); 1703 1704 for (i = 0; i < bmap->n_eq; ++i) 1705 isl_int_swap(bmap->eq[i][1+off+a], bmap->eq[i][1+off+b]); 1706 1707 for (i = 0; i < bmap->n_ineq; ++i) 1708 isl_int_swap(bmap->ineq[i][1+off+a], bmap->ineq[i][1+off+b]); 1709 1710 for (i = 0; i < bmap->n_div; ++i) 1711 isl_int_swap(bmap->div[i][1+1+off+a], bmap->div[i][1+1+off+b]); 1712 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED); 1713} 1714 1715/* Eliminate the specified n dimensions starting at first from the 1716 * constraints, without removing the dimensions from the space. 1717 * If the set is rational, the dimensions are eliminated using Fourier-Motzkin. 1718 */ 1719__isl_give isl_map *isl_map_eliminate(__isl_take isl_map *map, 1720 enum isl_dim_type type, unsigned first, unsigned n) 1721{ 1722 int i; 1723 1724 if (!map) 1725 return NULL; 1726 if (n == 0) 1727 return map; 1728 1729 if (first + n > isl_map_dim(map, type) || first + n < first) 1730 isl_die(map->ctx, isl_error_invalid, 1731 "index out of bounds", goto error); 1732 1733 map = isl_map_cow(map); 1734 if (!map) 1735 return NULL; 1736 1737 for (i = 0; i < map->n; ++i) { 1738 map->p[i] = isl_basic_map_eliminate(map->p[i], type, first, n); 1739 if (!map->p[i]) 1740 goto error; 1741 } 1742 return map; 1743error: 1744 isl_map_free(map); 1745 return NULL; 1746} 1747 1748/* Eliminate the specified n dimensions starting at first from the 1749 * constraints, without removing the dimensions from the space. 1750 * If the set is rational, the dimensions are eliminated using Fourier-Motzkin. 1751 */ 1752__isl_give isl_set *isl_set_eliminate(__isl_take isl_set *set, 1753 enum isl_dim_type type, unsigned first, unsigned n) 1754{ 1755 return (isl_set *)isl_map_eliminate((isl_map *)set, type, first, n); 1756} 1757 1758/* Eliminate the specified n dimensions starting at first from the 1759 * constraints, without removing the dimensions from the space. 1760 * If the set is rational, the dimensions are eliminated using Fourier-Motzkin. 1761 */ 1762__isl_give isl_set *isl_set_eliminate_dims(__isl_take isl_set *set, 1763 unsigned first, unsigned n) 1764{ 1765 return isl_set_eliminate(set, isl_dim_set, first, n); 1766} 1767 1768__isl_give isl_basic_map *isl_basic_map_remove_divs( 1769 __isl_take isl_basic_map *bmap) 1770{ 1771 if (!bmap) 1772 return NULL; 1773 bmap = isl_basic_map_eliminate_vars(bmap, 1774 isl_space_dim(bmap->dim, isl_dim_all), bmap->n_div); 1775 if (!bmap) 1776 return NULL; 1777 bmap->n_div = 0; 1778 return isl_basic_map_finalize(bmap); 1779} 1780 1781__isl_give isl_basic_set *isl_basic_set_remove_divs( 1782 __isl_take isl_basic_set *bset) 1783{ 1784 return (struct isl_basic_set *)isl_basic_map_remove_divs( 1785 (struct isl_basic_map *)bset); 1786} 1787 1788__isl_give isl_map *isl_map_remove_divs(__isl_take isl_map *map) 1789{ 1790 int i; 1791 1792 if (!map) 1793 return NULL; 1794 if (map->n == 0) 1795 return map; 1796 1797 map = isl_map_cow(map); 1798 if (!map) 1799 return NULL; 1800 1801 for (i = 0; i < map->n; ++i) { 1802 map->p[i] = isl_basic_map_remove_divs(map->p[i]); 1803 if (!map->p[i]) 1804 goto error; 1805 } 1806 return map; 1807error: 1808 isl_map_free(map); 1809 return NULL; 1810} 1811 1812__isl_give isl_set *isl_set_remove_divs(__isl_take isl_set *set) 1813{ 1814 return isl_map_remove_divs(set); 1815} 1816 1817struct isl_basic_map *isl_basic_map_remove_dims(struct isl_basic_map *bmap, 1818 enum isl_dim_type type, unsigned first, unsigned n) 1819{ 1820 if (!bmap) 1821 return NULL; 1822 isl_assert(bmap->ctx, first + n <= isl_basic_map_dim(bmap, type), 1823 goto error); 1824 if (n == 0 && !isl_space_is_named_or_nested(bmap->dim, type)) 1825 return bmap; 1826 bmap = isl_basic_map_eliminate_vars(bmap, 1827 isl_basic_map_offset(bmap, type) - 1 + first, n); 1828 if (!bmap) 1829 return bmap; 1830 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY) && type == isl_dim_div) 1831 return bmap; 1832 bmap = isl_basic_map_drop(bmap, type, first, n); 1833 return bmap; 1834error: 1835 isl_basic_map_free(bmap); 1836 return NULL; 1837} 1838 1839/* Return true if the definition of the given div (recursively) involves 1840 * any of the given variables. 1841 */ 1842static int div_involves_vars(__isl_keep isl_basic_map *bmap, int div, 1843 unsigned first, unsigned n) 1844{ 1845 int i; 1846 unsigned div_offset = isl_basic_map_offset(bmap, isl_dim_div); 1847 1848 if (isl_int_is_zero(bmap->div[div][0])) 1849 return 0; 1850 if (isl_seq_first_non_zero(bmap->div[div] + 1 + first, n) >= 0) 1851 return 1; 1852 1853 for (i = bmap->n_div - 1; i >= 0; --i) { 1854 if (isl_int_is_zero(bmap->div[div][1 + div_offset + i])) 1855 continue; 1856 if (div_involves_vars(bmap, i, first, n)) 1857 return 1; 1858 } 1859 1860 return 0; 1861} 1862 1863/* Try and add a lower and/or upper bound on "div" to "bmap" 1864 * based on inequality "i". 1865 * "total" is the total number of variables (excluding the divs). 1866 * "v" is a temporary object that can be used during the calculations. 1867 * If "lb" is set, then a lower bound should be constructed. 1868 * If "ub" is set, then an upper bound should be constructed. 1869 * 1870 * The calling function has already checked that the inequality does not 1871 * reference "div", but we still need to check that the inequality is 1872 * of the right form. We'll consider the case where we want to construct 1873 * a lower bound. The construction of upper bounds is similar. 1874 * 1875 * Let "div" be of the form 1876 * 1877 * q = floor((a + f(x))/d) 1878 * 1879 * We essentially check if constraint "i" is of the form 1880 * 1881 * b + f(x) >= 0 1882 * 1883 * so that we can use it to derive a lower bound on "div". 1884 * However, we allow a slightly more general form 1885 * 1886 * b + g(x) >= 0 1887 * 1888 * with the condition that the coefficients of g(x) - f(x) are all 1889 * divisible by d. 1890 * Rewriting this constraint as 1891 * 1892 * 0 >= -b - g(x) 1893 * 1894 * adding a + f(x) to both sides and dividing by d, we obtain 1895 * 1896 * (a + f(x))/d >= (a-b)/d + (f(x)-g(x))/d 1897 * 1898 * Taking the floor on both sides, we obtain 1899 * 1900 * q >= floor((a-b)/d) + (f(x)-g(x))/d 1901 * 1902 * or 1903 * 1904 * (g(x)-f(x))/d + ceil((b-a)/d) + q >= 0 1905 * 1906 * In the case of an upper bound, we construct the constraint 1907 * 1908 * (g(x)+f(x))/d + floor((b+a)/d) - q >= 0 1909 * 1910 */ 1911static __isl_give isl_basic_map *insert_bounds_on_div_from_ineq( 1912 __isl_take isl_basic_map *bmap, int div, int i, 1913 unsigned total, isl_int v, int lb, int ub) 1914{ 1915 int j; 1916 1917 for (j = 0; (lb || ub) && j < total + bmap->n_div; ++j) { 1918 if (lb) { 1919 isl_int_sub(v, bmap->ineq[i][1 + j], 1920 bmap->div[div][1 + 1 + j]); 1921 lb = isl_int_is_divisible_by(v, bmap->div[div][0]); 1922 } 1923 if (ub) { 1924 isl_int_add(v, bmap->ineq[i][1 + j], 1925 bmap->div[div][1 + 1 + j]); 1926 ub = isl_int_is_divisible_by(v, bmap->div[div][0]); 1927 } 1928 } 1929 if (!lb && !ub) 1930 return bmap; 1931 1932 bmap = isl_basic_map_extend_constraints(bmap, 0, lb + ub); 1933 if (lb) { 1934 int k = isl_basic_map_alloc_inequality(bmap); 1935 if (k < 0) 1936 goto error; 1937 for (j = 0; j < 1 + total + bmap->n_div; ++j) { 1938 isl_int_sub(bmap->ineq[k][j], bmap->ineq[i][j], 1939 bmap->div[div][1 + j]); 1940 isl_int_cdiv_q(bmap->ineq[k][j], 1941 bmap->ineq[k][j], bmap->div[div][0]); 1942 } 1943 isl_int_set_si(bmap->ineq[k][1 + total + div], 1); 1944 } 1945 if (ub) { 1946 int k = isl_basic_map_alloc_inequality(bmap); 1947 if (k < 0) 1948 goto error; 1949 for (j = 0; j < 1 + total + bmap->n_div; ++j) { 1950 isl_int_add(bmap->ineq[k][j], bmap->ineq[i][j], 1951 bmap->div[div][1 + j]); 1952 isl_int_fdiv_q(bmap->ineq[k][j], 1953 bmap->ineq[k][j], bmap->div[div][0]); 1954 } 1955 isl_int_set_si(bmap->ineq[k][1 + total + div], -1); 1956 } 1957 1958 return bmap; 1959error: 1960 isl_basic_map_free(bmap); 1961 return NULL; 1962} 1963 1964/* This function is called right before "div" is eliminated from "bmap" 1965 * using Fourier-Motzkin. 1966 * Look through the constraints of "bmap" for constraints on the argument 1967 * of the integer division and use them to construct constraints on the 1968 * integer division itself. These constraints can then be combined 1969 * during the Fourier-Motzkin elimination. 1970 * Note that it is only useful to introduce lower bounds on "div" 1971 * if "bmap" already contains upper bounds on "div" as the newly 1972 * introduce lower bounds can then be combined with the pre-existing 1973 * upper bounds. Similarly for upper bounds. 1974 * We therefore first check if "bmap" contains any lower and/or upper bounds 1975 * on "div". 1976 * 1977 * It is interesting to note that the introduction of these constraints 1978 * can indeed lead to more accurate results, even when compared to 1979 * deriving constraints on the argument of "div" from constraints on "div". 1980 * Consider, for example, the set 1981 * 1982 * { [i,j,k] : 3 + i + 2j >= 0 and 2 * [(i+2j)/4] <= k } 1983 * 1984 * The second constraint can be rewritten as 1985 * 1986 * 2 * [(-i-2j+3)/4] + k >= 0 1987 * 1988 * from which we can derive 1989 * 1990 * -i - 2j + 3 >= -2k 1991 * 1992 * or 1993 * 1994 * i + 2j <= 3 + 2k 1995 * 1996 * Combined with the first constraint, we obtain 1997 * 1998 * -3 <= 3 + 2k or k >= -3 1999 * 2000 * If, on the other hand we derive a constraint on [(i+2j)/4] from 2001 * the first constraint, we obtain 2002 * 2003 * [(i + 2j)/4] >= [-3/4] = -1 2004 * 2005 * Combining this constraint with the second constraint, we obtain 2006 * 2007 * k >= -2 2008 */ 2009static __isl_give isl_basic_map *insert_bounds_on_div( 2010 __isl_take isl_basic_map *bmap, int div) 2011{ 2012 int i; 2013 int check_lb, check_ub; 2014 isl_int v; 2015 unsigned total; 2016 2017 if (!bmap) 2018 return NULL; 2019 2020 if (isl_int_is_zero(bmap->div[div][0])) 2021 return bmap; 2022 2023 total = isl_space_dim(bmap->dim, isl_dim_all); 2024 2025 check_lb = 0; 2026 check_ub = 0; 2027 for (i = 0; (!check_lb || !check_ub) && i < bmap->n_ineq; ++i) { 2028 int s = isl_int_sgn(bmap->ineq[i][1 + total + div]); 2029 if (s > 0) 2030 check_ub = 1; 2031 if (s < 0) 2032 check_lb = 1; 2033 } 2034 2035 if (!check_lb && !check_ub) 2036 return bmap; 2037 2038 isl_int_init(v); 2039 2040 for (i = 0; bmap && i < bmap->n_ineq; ++i) { 2041 if (!isl_int_is_zero(bmap->ineq[i][1 + total + div])) 2042 continue; 2043 2044 bmap = insert_bounds_on_div_from_ineq(bmap, div, i, total, v, 2045 check_lb, check_ub); 2046 } 2047 2048 isl_int_clear(v); 2049 2050 return bmap; 2051} 2052 2053/* Remove all divs (recursively) involving any of the given dimensions 2054 * in their definitions. 2055 */ 2056__isl_give isl_basic_map *isl_basic_map_remove_divs_involving_dims( 2057 __isl_take isl_basic_map *bmap, 2058 enum isl_dim_type type, unsigned first, unsigned n) 2059{ 2060 int i; 2061 2062 if (!bmap) 2063 return NULL; 2064 isl_assert(bmap->ctx, first + n <= isl_basic_map_dim(bmap, type), 2065 goto error); 2066 first += isl_basic_map_offset(bmap, type); 2067 2068 for (i = bmap->n_div - 1; i >= 0; --i) { 2069 if (!div_involves_vars(bmap, i, first, n)) 2070 continue; 2071 bmap = insert_bounds_on_div(bmap, i); 2072 bmap = isl_basic_map_remove_dims(bmap, isl_dim_div, i, 1); 2073 if (!bmap) 2074 return NULL; 2075 i = bmap->n_div; 2076 } 2077 2078 return bmap; 2079error: 2080 isl_basic_map_free(bmap); 2081 return NULL; 2082} 2083 2084__isl_give isl_basic_set *isl_basic_set_remove_divs_involving_dims( 2085 __isl_take isl_basic_set *bset, 2086 enum isl_dim_type type, unsigned first, unsigned n) 2087{ 2088 return isl_basic_map_remove_divs_involving_dims(bset, type, first, n); 2089} 2090 2091__isl_give isl_map *isl_map_remove_divs_involving_dims(__isl_take isl_map *map, 2092 enum isl_dim_type type, unsigned first, unsigned n) 2093{ 2094 int i; 2095 2096 if (!map) 2097 return NULL; 2098 if (map->n == 0) 2099 return map; 2100 2101 map = isl_map_cow(map); 2102 if (!map) 2103 return NULL; 2104 2105 for (i = 0; i < map->n; ++i) { 2106 map->p[i] = isl_basic_map_remove_divs_involving_dims(map->p[i], 2107 type, first, n); 2108 if (!map->p[i]) 2109 goto error; 2110 } 2111 return map; 2112error: 2113 isl_map_free(map); 2114 return NULL; 2115} 2116 2117__isl_give isl_set *isl_set_remove_divs_involving_dims(__isl_take isl_set *set, 2118 enum isl_dim_type type, unsigned first, unsigned n) 2119{ 2120 return (isl_set *)isl_map_remove_divs_involving_dims((isl_map *)set, 2121 type, first, n); 2122} 2123 2124/* Does the desciption of "bmap" depend on the specified dimensions? 2125 * We also check whether the dimensions appear in any of the div definitions. 2126 * In principle there is no need for this check. If the dimensions appear 2127 * in a div definition, they also appear in the defining constraints of that 2128 * div. 2129 */ 2130int isl_basic_map_involves_dims(__isl_keep isl_basic_map *bmap, 2131 enum isl_dim_type type, unsigned first, unsigned n) 2132{ 2133 int i; 2134 2135 if (!bmap) 2136 return -1; 2137 2138 if (first + n > isl_basic_map_dim(bmap, type)) 2139 isl_die(bmap->ctx, isl_error_invalid, 2140 "index out of bounds", return -1); 2141 2142 first += isl_basic_map_offset(bmap, type); 2143 for (i = 0; i < bmap->n_eq; ++i) 2144 if (isl_seq_first_non_zero(bmap->eq[i] + first, n) >= 0) 2145 return 1; 2146 for (i = 0; i < bmap->n_ineq; ++i) 2147 if (isl_seq_first_non_zero(bmap->ineq[i] + first, n) >= 0) 2148 return 1; 2149 for (i = 0; i < bmap->n_div; ++i) { 2150 if (isl_int_is_zero(bmap->div[i][0])) 2151 continue; 2152 if (isl_seq_first_non_zero(bmap->div[i] + 1 + first, n) >= 0) 2153 return 1; 2154 } 2155 2156 return 0; 2157} 2158 2159int isl_map_involves_dims(__isl_keep isl_map *map, 2160 enum isl_dim_type type, unsigned first, unsigned n) 2161{ 2162 int i; 2163 2164 if (!map) 2165 return -1; 2166 2167 if (first + n > isl_map_dim(map, type)) 2168 isl_die(map->ctx, isl_error_invalid, 2169 "index out of bounds", return -1); 2170 2171 for (i = 0; i < map->n; ++i) { 2172 int involves = isl_basic_map_involves_dims(map->p[i], 2173 type, first, n); 2174 if (involves < 0 || involves) 2175 return involves; 2176 } 2177 2178 return 0; 2179} 2180 2181int isl_basic_set_involves_dims(__isl_keep isl_basic_set *bset, 2182 enum isl_dim_type type, unsigned first, unsigned n) 2183{ 2184 return isl_basic_map_involves_dims(bset, type, first, n); 2185} 2186 2187int isl_set_involves_dims(__isl_keep isl_set *set, 2188 enum isl_dim_type type, unsigned first, unsigned n) 2189{ 2190 return isl_map_involves_dims(set, type, first, n); 2191} 2192 2193/* Return true if the definition of the given div is unknown or depends 2194 * on unknown divs. 2195 */ 2196static int div_is_unknown(__isl_keep isl_basic_map *bmap, int div) 2197{ 2198 int i; 2199 unsigned div_offset = isl_basic_map_offset(bmap, isl_dim_div); 2200 2201 if (isl_int_is_zero(bmap->div[div][0])) 2202 return 1; 2203 2204 for (i = bmap->n_div - 1; i >= 0; --i) { 2205 if (isl_int_is_zero(bmap->div[div][1 + div_offset + i])) 2206 continue; 2207 if (div_is_unknown(bmap, i)) 2208 return 1; 2209 } 2210 2211 return 0; 2212} 2213 2214/* Remove all divs that are unknown or defined in terms of unknown divs. 2215 */ 2216__isl_give isl_basic_map *isl_basic_map_remove_unknown_divs( 2217 __isl_take isl_basic_map *bmap) 2218{ 2219 int i; 2220 2221 if (!bmap) 2222 return NULL; 2223 2224 for (i = bmap->n_div - 1; i >= 0; --i) { 2225 if (!div_is_unknown(bmap, i)) 2226 continue; 2227 bmap = isl_basic_map_remove_dims(bmap, isl_dim_div, i, 1); 2228 if (!bmap) 2229 return NULL; 2230 i = bmap->n_div; 2231 } 2232 2233 return bmap; 2234} 2235 2236/* Remove all divs that are unknown or defined in terms of unknown divs. 2237 */ 2238__isl_give isl_basic_set *isl_basic_set_remove_unknown_divs( 2239 __isl_take isl_basic_set *bset) 2240{ 2241 return isl_basic_map_remove_unknown_divs(bset); 2242} 2243 2244__isl_give isl_map *isl_map_remove_unknown_divs(__isl_take isl_map *map) 2245{ 2246 int i; 2247 2248 if (!map) 2249 return NULL; 2250 if (map->n == 0) 2251 return map; 2252 2253 map = isl_map_cow(map); 2254 if (!map) 2255 return NULL; 2256 2257 for (i = 0; i < map->n; ++i) { 2258 map->p[i] = isl_basic_map_remove_unknown_divs(map->p[i]); 2259 if (!map->p[i]) 2260 goto error; 2261 } 2262 return map; 2263error: 2264 isl_map_free(map); 2265 return NULL; 2266} 2267 2268__isl_give isl_set *isl_set_remove_unknown_divs(__isl_take isl_set *set) 2269{ 2270 return (isl_set *)isl_map_remove_unknown_divs((isl_map *)set); 2271} 2272 2273__isl_give isl_basic_set *isl_basic_set_remove_dims( 2274 __isl_take isl_basic_set *bset, 2275 enum isl_dim_type type, unsigned first, unsigned n) 2276{ 2277 return (isl_basic_set *) 2278 isl_basic_map_remove_dims((isl_basic_map *)bset, type, first, n); 2279} 2280 2281struct isl_map *isl_map_remove_dims(struct isl_map *map, 2282 enum isl_dim_type type, unsigned first, unsigned n) 2283{ 2284 int i; 2285 2286 if (n == 0) 2287 return map; 2288 2289 map = isl_map_cow(map); 2290 if (!map) 2291 return NULL; 2292 isl_assert(map->ctx, first + n <= isl_map_dim(map, type), goto error); 2293 2294 for (i = 0; i < map->n; ++i) { 2295 map->p[i] = isl_basic_map_eliminate_vars(map->p[i], 2296 isl_basic_map_offset(map->p[i], type) - 1 + first, n); 2297 if (!map->p[i]) 2298 goto error; 2299 } 2300 map = isl_map_drop(map, type, first, n); 2301 return map; 2302error: 2303 isl_map_free(map); 2304 return NULL; 2305} 2306 2307__isl_give isl_set *isl_set_remove_dims(__isl_take isl_set *bset, 2308 enum isl_dim_type type, unsigned first, unsigned n) 2309{ 2310 return (isl_set *)isl_map_remove_dims((isl_map *)bset, type, first, n); 2311} 2312 2313/* Project out n inputs starting at first using Fourier-Motzkin */ 2314struct isl_map *isl_map_remove_inputs(struct isl_map *map, 2315 unsigned first, unsigned n) 2316{ 2317 return isl_map_remove_dims(map, isl_dim_in, first, n); 2318} 2319 2320static void dump_term(struct isl_basic_map *bmap, 2321 isl_int c, int pos, FILE *out) 2322{ 2323 const char *name; 2324 unsigned in = isl_basic_map_n_in(bmap); 2325 unsigned dim = in + isl_basic_map_n_out(bmap); 2326 unsigned nparam = isl_basic_map_n_param(bmap); 2327 if (!pos) 2328 isl_int_print(out, c, 0); 2329 else { 2330 if (!isl_int_is_one(c)) 2331 isl_int_print(out, c, 0); 2332 if (pos < 1 + nparam) { 2333 name = isl_space_get_dim_name(bmap->dim, 2334 isl_dim_param, pos - 1); 2335 if (name) 2336 fprintf(out, "%s", name); 2337 else 2338 fprintf(out, "p%d", pos - 1); 2339 } else if (pos < 1 + nparam + in) 2340 fprintf(out, "i%d", pos - 1 - nparam); 2341 else if (pos < 1 + nparam + dim) 2342 fprintf(out, "o%d", pos - 1 - nparam - in); 2343 else 2344 fprintf(out, "e%d", pos - 1 - nparam - dim); 2345 } 2346} 2347 2348static void dump_constraint_sign(struct isl_basic_map *bmap, isl_int *c, 2349 int sign, FILE *out) 2350{ 2351 int i; 2352 int first; 2353 unsigned len = 1 + isl_basic_map_total_dim(bmap); 2354 isl_int v; 2355 2356 isl_int_init(v); 2357 for (i = 0, first = 1; i < len; ++i) { 2358 if (isl_int_sgn(c[i]) * sign <= 0) 2359 continue; 2360 if (!first) 2361 fprintf(out, " + "); 2362 first = 0; 2363 isl_int_abs(v, c[i]); 2364 dump_term(bmap, v, i, out); 2365 } 2366 isl_int_clear(v); 2367 if (first) 2368 fprintf(out, "0"); 2369} 2370 2371static void dump_constraint(struct isl_basic_map *bmap, isl_int *c, 2372 const char *op, FILE *out, int indent) 2373{ 2374 int i; 2375 2376 fprintf(out, "%*s", indent, ""); 2377 2378 dump_constraint_sign(bmap, c, 1, out); 2379 fprintf(out, " %s ", op); 2380 dump_constraint_sign(bmap, c, -1, out); 2381 2382 fprintf(out, "\n"); 2383 2384 for (i = bmap->n_div; i < bmap->extra; ++i) { 2385 if (isl_int_is_zero(c[1+isl_space_dim(bmap->dim, isl_dim_all)+i])) 2386 continue; 2387 fprintf(out, "%*s", indent, ""); 2388 fprintf(out, "ERROR: unused div coefficient not zero\n"); 2389 abort(); 2390 } 2391} 2392 2393static void dump_constraints(struct isl_basic_map *bmap, 2394 isl_int **c, unsigned n, 2395 const char *op, FILE *out, int indent) 2396{ 2397 int i; 2398 2399 for (i = 0; i < n; ++i) 2400 dump_constraint(bmap, c[i], op, out, indent); 2401} 2402 2403static void dump_affine(struct isl_basic_map *bmap, isl_int *exp, FILE *out) 2404{ 2405 int j; 2406 int first = 1; 2407 unsigned total = isl_basic_map_total_dim(bmap); 2408 2409 for (j = 0; j < 1 + total; ++j) { 2410 if (isl_int_is_zero(exp[j])) 2411 continue; 2412 if (!first && isl_int_is_pos(exp[j])) 2413 fprintf(out, "+"); 2414 dump_term(bmap, exp[j], j, out); 2415 first = 0; 2416 } 2417} 2418 2419static void dump(struct isl_basic_map *bmap, FILE *out, int indent) 2420{ 2421 int i; 2422 2423 dump_constraints(bmap, bmap->eq, bmap->n_eq, "=", out, indent); 2424 dump_constraints(bmap, bmap->ineq, bmap->n_ineq, ">=", out, indent); 2425 2426 for (i = 0; i < bmap->n_div; ++i) { 2427 fprintf(out, "%*s", indent, ""); 2428 fprintf(out, "e%d = [(", i); 2429 dump_affine(bmap, bmap->div[i]+1, out); 2430 fprintf(out, ")/"); 2431 isl_int_print(out, bmap->div[i][0], 0); 2432 fprintf(out, "]\n"); 2433 } 2434} 2435 2436void isl_basic_set_print_internal(struct isl_basic_set *bset, 2437 FILE *out, int indent) 2438{ 2439 if (!bset) { 2440 fprintf(out, "null basic set\n"); 2441 return; 2442 } 2443 2444 fprintf(out, "%*s", indent, ""); 2445 fprintf(out, "ref: %d, nparam: %d, dim: %d, extra: %d, flags: %x\n", 2446 bset->ref, bset->dim->nparam, bset->dim->n_out, 2447 bset->extra, bset->flags); 2448 dump((struct isl_basic_map *)bset, out, indent); 2449} 2450 2451void isl_basic_map_print_internal(struct isl_basic_map *bmap, 2452 FILE *out, int indent) 2453{ 2454 if (!bmap) { 2455 fprintf(out, "null basic map\n"); 2456 return; 2457 } 2458 2459 fprintf(out, "%*s", indent, ""); 2460 fprintf(out, "ref: %d, nparam: %d, in: %d, out: %d, extra: %d, " 2461 "flags: %x, n_name: %d\n", 2462 bmap->ref, 2463 bmap->dim->nparam, bmap->dim->n_in, bmap->dim->n_out, 2464 bmap->extra, bmap->flags, bmap->dim->n_id); 2465 dump(bmap, out, indent); 2466} 2467 2468int isl_inequality_negate(struct isl_basic_map *bmap, unsigned pos) 2469{ 2470 unsigned total; 2471 if (!bmap) 2472 return -1; 2473 total = isl_basic_map_total_dim(bmap); 2474 isl_assert(bmap->ctx, pos < bmap->n_ineq, return -1); 2475 isl_seq_neg(bmap->ineq[pos], bmap->ineq[pos], 1 + total); 2476 isl_int_sub_ui(bmap->ineq[pos][0], bmap->ineq[pos][0], 1); 2477 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED); 2478 return 0; 2479} 2480 2481__isl_give isl_set *isl_set_alloc_space(__isl_take isl_space *dim, int n, 2482 unsigned flags) 2483{ 2484 struct isl_set *set; 2485 2486 if (!dim) 2487 return NULL; 2488 isl_assert(dim->ctx, dim->n_in == 0, goto error); 2489 isl_assert(dim->ctx, n >= 0, goto error); 2490 set = isl_alloc(dim->ctx, struct isl_set, 2491 sizeof(struct isl_set) + 2492 (n - 1) * sizeof(struct isl_basic_set *)); 2493 if (!set) 2494 goto error; 2495 2496 set->ctx = dim->ctx; 2497 isl_ctx_ref(set->ctx); 2498 set->ref = 1; 2499 set->size = n; 2500 set->n = 0; 2501 set->dim = dim; 2502 set->flags = flags; 2503 return set; 2504error: 2505 isl_space_free(dim); 2506 return NULL; 2507} 2508 2509struct isl_set *isl_set_alloc(struct isl_ctx *ctx, 2510 unsigned nparam, unsigned dim, int n, unsigned flags) 2511{ 2512 struct isl_set *set; 2513 isl_space *dims; 2514 2515 dims = isl_space_alloc(ctx, nparam, 0, dim); 2516 if (!dims) 2517 return NULL; 2518 2519 set = isl_set_alloc_space(dims, n, flags); 2520 return set; 2521} 2522 2523/* Make sure "map" has room for at least "n" more basic maps. 2524 */ 2525struct isl_map *isl_map_grow(struct isl_map *map, int n) 2526{ 2527 int i; 2528 struct isl_map *grown = NULL; 2529 2530 if (!map) 2531 return NULL; 2532 isl_assert(map->ctx, n >= 0, goto error); 2533 if (map->n + n <= map->size) 2534 return map; 2535 grown = isl_map_alloc_space(isl_map_get_space(map), map->n + n, map->flags); 2536 if (!grown) 2537 goto error; 2538 for (i = 0; i < map->n; ++i) { 2539 grown->p[i] = isl_basic_map_copy(map->p[i]); 2540 if (!grown->p[i]) 2541 goto error; 2542 grown->n++; 2543 } 2544 isl_map_free(map); 2545 return grown; 2546error: 2547 isl_map_free(grown); 2548 isl_map_free(map); 2549 return NULL; 2550} 2551 2552/* Make sure "set" has room for at least "n" more basic sets. 2553 */ 2554struct isl_set *isl_set_grow(struct isl_set *set, int n) 2555{ 2556 return (struct isl_set *)isl_map_grow((struct isl_map *)set, n); 2557} 2558 2559struct isl_set *isl_set_dup(struct isl_set *set) 2560{ 2561 int i; 2562 struct isl_set *dup; 2563 2564 if (!set) 2565 return NULL; 2566 2567 dup = isl_set_alloc_space(isl_space_copy(set->dim), set->n, set->flags); 2568 if (!dup) 2569 return NULL; 2570 for (i = 0; i < set->n; ++i) 2571 dup = isl_set_add_basic_set(dup, isl_basic_set_copy(set->p[i])); 2572 return dup; 2573} 2574 2575struct isl_set *isl_set_from_basic_set(struct isl_basic_set *bset) 2576{ 2577 return isl_map_from_basic_map(bset); 2578} 2579 2580struct isl_map *isl_map_from_basic_map(struct isl_basic_map *bmap) 2581{ 2582 struct isl_map *map; 2583 2584 if (!bmap) 2585 return NULL; 2586 2587 map = isl_map_alloc_space(isl_space_copy(bmap->dim), 1, ISL_MAP_DISJOINT); 2588 return isl_map_add_basic_map(map, bmap); 2589} 2590 2591__isl_give isl_set *isl_set_add_basic_set(__isl_take isl_set *set, 2592 __isl_take isl_basic_set *bset) 2593{ 2594 return (struct isl_set *)isl_map_add_basic_map((struct isl_map *)set, 2595 (struct isl_basic_map *)bset); 2596} 2597 2598void *isl_set_free(__isl_take isl_set *set) 2599{ 2600 int i; 2601 2602 if (!set) 2603 return NULL; 2604 2605 if (--set->ref > 0) 2606 return NULL; 2607 2608 isl_ctx_deref(set->ctx); 2609 for (i = 0; i < set->n; ++i) 2610 isl_basic_set_free(set->p[i]); 2611 isl_space_free(set->dim); 2612 free(set); 2613 2614 return NULL; 2615} 2616 2617void isl_set_print_internal(struct isl_set *set, FILE *out, int indent) 2618{ 2619 int i; 2620 2621 if (!set) { 2622 fprintf(out, "null set\n"); 2623 return; 2624 } 2625 2626 fprintf(out, "%*s", indent, ""); 2627 fprintf(out, "ref: %d, n: %d, nparam: %d, dim: %d, flags: %x\n", 2628 set->ref, set->n, set->dim->nparam, set->dim->n_out, 2629 set->flags); 2630 for (i = 0; i < set->n; ++i) { 2631 fprintf(out, "%*s", indent, ""); 2632 fprintf(out, "basic set %d:\n", i); 2633 isl_basic_set_print_internal(set->p[i], out, indent+4); 2634 } 2635} 2636 2637void isl_map_print_internal(struct isl_map *map, FILE *out, int indent) 2638{ 2639 int i; 2640 2641 if (!map) { 2642 fprintf(out, "null map\n"); 2643 return; 2644 } 2645 2646 fprintf(out, "%*s", indent, ""); 2647 fprintf(out, "ref: %d, n: %d, nparam: %d, in: %d, out: %d, " 2648 "flags: %x, n_name: %d\n", 2649 map->ref, map->n, map->dim->nparam, map->dim->n_in, 2650 map->dim->n_out, map->flags, map->dim->n_id); 2651 for (i = 0; i < map->n; ++i) { 2652 fprintf(out, "%*s", indent, ""); 2653 fprintf(out, "basic map %d:\n", i); 2654 isl_basic_map_print_internal(map->p[i], out, indent+4); 2655 } 2656} 2657 2658struct isl_basic_map *isl_basic_map_intersect_domain( 2659 struct isl_basic_map *bmap, struct isl_basic_set *bset) 2660{ 2661 struct isl_basic_map *bmap_domain; 2662 2663 if (!bmap || !bset) 2664 goto error; 2665 2666 isl_assert(bset->ctx, isl_space_match(bmap->dim, isl_dim_param, 2667 bset->dim, isl_dim_param), goto error); 2668 2669 if (isl_space_dim(bset->dim, isl_dim_set) != 0) 2670 isl_assert(bset->ctx, 2671 isl_basic_map_compatible_domain(bmap, bset), goto error); 2672 2673 bmap = isl_basic_map_cow(bmap); 2674 if (!bmap) 2675 goto error; 2676 bmap = isl_basic_map_extend_space(bmap, isl_space_copy(bmap->dim), 2677 bset->n_div, bset->n_eq, bset->n_ineq); 2678 bmap_domain = isl_basic_map_from_domain(bset); 2679 bmap = add_constraints(bmap, bmap_domain, 0, 0); 2680 2681 bmap = isl_basic_map_simplify(bmap); 2682 return isl_basic_map_finalize(bmap); 2683error: 2684 isl_basic_map_free(bmap); 2685 isl_basic_set_free(bset); 2686 return NULL; 2687} 2688 2689struct isl_basic_map *isl_basic_map_intersect_range( 2690 struct isl_basic_map *bmap, struct isl_basic_set *bset) 2691{ 2692 struct isl_basic_map *bmap_range; 2693 2694 if (!bmap || !bset) 2695 goto error; 2696 2697 isl_assert(bset->ctx, isl_space_match(bmap->dim, isl_dim_param, 2698 bset->dim, isl_dim_param), goto error); 2699 2700 if (isl_space_dim(bset->dim, isl_dim_set) != 0) 2701 isl_assert(bset->ctx, 2702 isl_basic_map_compatible_range(bmap, bset), goto error); 2703 2704 if (isl_basic_set_is_universe(bset)) { 2705 isl_basic_set_free(bset); 2706 return bmap; 2707 } 2708 2709 bmap = isl_basic_map_cow(bmap); 2710 if (!bmap) 2711 goto error; 2712 bmap = isl_basic_map_extend_space(bmap, isl_space_copy(bmap->dim), 2713 bset->n_div, bset->n_eq, bset->n_ineq); 2714 bmap_range = isl_basic_map_from_basic_set(bset, isl_space_copy(bset->dim)); 2715 bmap = add_constraints(bmap, bmap_range, 0, 0); 2716 2717 bmap = isl_basic_map_simplify(bmap); 2718 return isl_basic_map_finalize(bmap); 2719error: 2720 isl_basic_map_free(bmap); 2721 isl_basic_set_free(bset); 2722 return NULL; 2723} 2724 2725int isl_basic_map_contains(struct isl_basic_map *bmap, struct isl_vec *vec) 2726{ 2727 int i; 2728 unsigned total; 2729 isl_int s; 2730 2731 if (!bmap || !vec) 2732 return -1; 2733 2734 total = 1 + isl_basic_map_total_dim(bmap); 2735 if (total != vec->size) 2736 return -1; 2737 2738 isl_int_init(s); 2739 2740 for (i = 0; i < bmap->n_eq; ++i) { 2741 isl_seq_inner_product(vec->el, bmap->eq[i], total, &s); 2742 if (!isl_int_is_zero(s)) { 2743 isl_int_clear(s); 2744 return 0; 2745 } 2746 } 2747 2748 for (i = 0; i < bmap->n_ineq; ++i) { 2749 isl_seq_inner_product(vec->el, bmap->ineq[i], total, &s); 2750 if (isl_int_is_neg(s)) { 2751 isl_int_clear(s); 2752 return 0; 2753 } 2754 } 2755 2756 isl_int_clear(s); 2757 2758 return 1; 2759} 2760 2761int isl_basic_set_contains(struct isl_basic_set *bset, struct isl_vec *vec) 2762{ 2763 return isl_basic_map_contains((struct isl_basic_map *)bset, vec); 2764} 2765 2766struct isl_basic_map *isl_basic_map_intersect( 2767 struct isl_basic_map *bmap1, struct isl_basic_map *bmap2) 2768{ 2769 struct isl_vec *sample = NULL; 2770 2771 if (!bmap1 || !bmap2) 2772 goto error; 2773 2774 isl_assert(bmap1->ctx, isl_space_match(bmap1->dim, isl_dim_param, 2775 bmap2->dim, isl_dim_param), goto error); 2776 if (isl_space_dim(bmap1->dim, isl_dim_all) == 2777 isl_space_dim(bmap1->dim, isl_dim_param) && 2778 isl_space_dim(bmap2->dim, isl_dim_all) != 2779 isl_space_dim(bmap2->dim, isl_dim_param)) 2780 return isl_basic_map_intersect(bmap2, bmap1); 2781 2782 if (isl_space_dim(bmap2->dim, isl_dim_all) != 2783 isl_space_dim(bmap2->dim, isl_dim_param)) 2784 isl_assert(bmap1->ctx, 2785 isl_space_is_equal(bmap1->dim, bmap2->dim), goto error); 2786 2787 if (bmap1->sample && 2788 isl_basic_map_contains(bmap1, bmap1->sample) > 0 && 2789 isl_basic_map_contains(bmap2, bmap1->sample) > 0) 2790 sample = isl_vec_copy(bmap1->sample); 2791 else if (bmap2->sample && 2792 isl_basic_map_contains(bmap1, bmap2->sample) > 0 && 2793 isl_basic_map_contains(bmap2, bmap2->sample) > 0) 2794 sample = isl_vec_copy(bmap2->sample); 2795 2796 bmap1 = isl_basic_map_cow(bmap1); 2797 if (!bmap1) 2798 goto error; 2799 bmap1 = isl_basic_map_extend_space(bmap1, isl_space_copy(bmap1->dim), 2800 bmap2->n_div, bmap2->n_eq, bmap2->n_ineq); 2801 bmap1 = add_constraints(bmap1, bmap2, 0, 0); 2802 2803 if (!bmap1) 2804 isl_vec_free(sample); 2805 else if (sample) { 2806 isl_vec_free(bmap1->sample); 2807 bmap1->sample = sample; 2808 } 2809 2810 bmap1 = isl_basic_map_simplify(bmap1); 2811 return isl_basic_map_finalize(bmap1); 2812error: 2813 if (sample) 2814 isl_vec_free(sample); 2815 isl_basic_map_free(bmap1); 2816 isl_basic_map_free(bmap2); 2817 return NULL; 2818} 2819 2820struct isl_basic_set *isl_basic_set_intersect( 2821 struct isl_basic_set *bset1, struct isl_basic_set *bset2) 2822{ 2823 return (struct isl_basic_set *) 2824 isl_basic_map_intersect( 2825 (struct isl_basic_map *)bset1, 2826 (struct isl_basic_map *)bset2); 2827} 2828 2829__isl_give isl_basic_set *isl_basic_set_intersect_params( 2830 __isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2) 2831{ 2832 return isl_basic_set_intersect(bset1, bset2); 2833} 2834 2835/* Special case of isl_map_intersect, where both map1 and map2 2836 * are convex, without any divs and such that either map1 or map2 2837 * contains a single constraint. This constraint is then simply 2838 * added to the other map. 2839 */ 2840static __isl_give isl_map *map_intersect_add_constraint( 2841 __isl_take isl_map *map1, __isl_take isl_map *map2) 2842{ 2843 isl_assert(map1->ctx, map1->n == 1, goto error); 2844 isl_assert(map2->ctx, map1->n == 1, goto error); 2845 isl_assert(map1->ctx, map1->p[0]->n_div == 0, goto error); 2846 isl_assert(map2->ctx, map1->p[0]->n_div == 0, goto error); 2847 2848 if (map2->p[0]->n_eq + map2->p[0]->n_ineq != 1) 2849 return isl_map_intersect(map2, map1); 2850 2851 isl_assert(map2->ctx, 2852 map2->p[0]->n_eq + map2->p[0]->n_ineq == 1, goto error); 2853 2854 map1 = isl_map_cow(map1); 2855 if (!map1) 2856 goto error; 2857 if (isl_map_plain_is_empty(map1)) { 2858 isl_map_free(map2); 2859 return map1; 2860 } 2861 map1->p[0] = isl_basic_map_cow(map1->p[0]); 2862 if (map2->p[0]->n_eq == 1) 2863 map1->p[0] = isl_basic_map_add_eq(map1->p[0], map2->p[0]->eq[0]); 2864 else 2865 map1->p[0] = isl_basic_map_add_ineq(map1->p[0], 2866 map2->p[0]->ineq[0]); 2867 2868 map1->p[0] = isl_basic_map_simplify(map1->p[0]); 2869 map1->p[0] = isl_basic_map_finalize(map1->p[0]); 2870 if (!map1->p[0]) 2871 goto error; 2872 2873 if (isl_basic_map_plain_is_empty(map1->p[0])) { 2874 isl_basic_map_free(map1->p[0]); 2875 map1->n = 0; 2876 } 2877 2878 isl_map_free(map2); 2879 2880 return map1; 2881error: 2882 isl_map_free(map1); 2883 isl_map_free(map2); 2884 return NULL; 2885} 2886 2887/* map2 may be either a parameter domain or a map living in the same 2888 * space as map1. 2889 */ 2890static __isl_give isl_map *map_intersect_internal(__isl_take isl_map *map1, 2891 __isl_take isl_map *map2) 2892{ 2893 unsigned flags = 0; 2894 isl_map *result; 2895 int i, j; 2896 2897 if (!map1 || !map2) 2898 goto error; 2899 2900 if ((isl_map_plain_is_empty(map1) || 2901 isl_map_plain_is_universe(map2)) && 2902 isl_space_is_equal(map1->dim, map2->dim)) { 2903 isl_map_free(map2); 2904 return map1; 2905 } 2906 if ((isl_map_plain_is_empty(map2) || 2907 isl_map_plain_is_universe(map1)) && 2908 isl_space_is_equal(map1->dim, map2->dim)) { 2909 isl_map_free(map1); 2910 return map2; 2911 } 2912 2913 if (map1->n == 1 && map2->n == 1 && 2914 map1->p[0]->n_div == 0 && map2->p[0]->n_div == 0 && 2915 isl_space_is_equal(map1->dim, map2->dim) && 2916 (map1->p[0]->n_eq + map1->p[0]->n_ineq == 1 || 2917 map2->p[0]->n_eq + map2->p[0]->n_ineq == 1)) 2918 return map_intersect_add_constraint(map1, map2); 2919 2920 if (isl_space_dim(map2->dim, isl_dim_all) != 2921 isl_space_dim(map2->dim, isl_dim_param)) 2922 isl_assert(map1->ctx, 2923 isl_space_is_equal(map1->dim, map2->dim), goto error); 2924 2925 if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) && 2926 ISL_F_ISSET(map2, ISL_MAP_DISJOINT)) 2927 ISL_FL_SET(flags, ISL_MAP_DISJOINT); 2928 2929 result = isl_map_alloc_space(isl_space_copy(map1->dim), 2930 map1->n * map2->n, flags); 2931 if (!result) 2932 goto error; 2933 for (i = 0; i < map1->n; ++i) 2934 for (j = 0; j < map2->n; ++j) { 2935 struct isl_basic_map *part; 2936 part = isl_basic_map_intersect( 2937 isl_basic_map_copy(map1->p[i]), 2938 isl_basic_map_copy(map2->p[j])); 2939 if (isl_basic_map_is_empty(part) < 0) 2940 part = isl_basic_map_free(part); 2941 result = isl_map_add_basic_map(result, part); 2942 if (!result) 2943 goto error; 2944 } 2945 isl_map_free(map1); 2946 isl_map_free(map2); 2947 return result; 2948error: 2949 isl_map_free(map1); 2950 isl_map_free(map2); 2951 return NULL; 2952} 2953 2954static __isl_give isl_map *map_intersect(__isl_take isl_map *map1, 2955 __isl_take isl_map *map2) 2956{ 2957 if (!map1 || !map2) 2958 goto error; 2959 if (!isl_space_is_equal(map1->dim, map2->dim)) 2960 isl_die(isl_map_get_ctx(map1), isl_error_invalid, 2961 "spaces don't match", goto error); 2962 return map_intersect_internal(map1, map2); 2963error: 2964 isl_map_free(map1); 2965 isl_map_free(map2); 2966 return NULL; 2967} 2968 2969__isl_give isl_map *isl_map_intersect(__isl_take isl_map *map1, 2970 __isl_take isl_map *map2) 2971{ 2972 return isl_map_align_params_map_map_and(map1, map2, &map_intersect); 2973} 2974 2975struct isl_set *isl_set_intersect(struct isl_set *set1, struct isl_set *set2) 2976{ 2977 return (struct isl_set *) 2978 isl_map_intersect((struct isl_map *)set1, 2979 (struct isl_map *)set2); 2980} 2981 2982/* map_intersect_internal accepts intersections 2983 * with parameter domains, so we can just call that function. 2984 */ 2985static __isl_give isl_map *map_intersect_params(__isl_take isl_map *map, 2986 __isl_take isl_set *params) 2987{ 2988 return map_intersect_internal(map, params); 2989} 2990 2991__isl_give isl_map *isl_map_intersect_params(__isl_take isl_map *map1, 2992 __isl_take isl_map *map2) 2993{ 2994 return isl_map_align_params_map_map_and(map1, map2, &map_intersect_params); 2995} 2996 2997__isl_give isl_set *isl_set_intersect_params(__isl_take isl_set *set, 2998 __isl_take isl_set *params) 2999{ 3000 return isl_map_intersect_params(set, params); 3001} 3002 3003struct isl_basic_map *isl_basic_map_reverse(struct isl_basic_map *bmap) 3004{ 3005 isl_space *dim; 3006 struct isl_basic_set *bset; 3007 unsigned in; 3008 3009 if (!bmap) 3010 return NULL; 3011 bmap = isl_basic_map_cow(bmap); 3012 if (!bmap) 3013 return NULL; 3014 dim = isl_space_reverse(isl_space_copy(bmap->dim)); 3015 in = isl_basic_map_n_in(bmap); 3016 bset = isl_basic_set_from_basic_map(bmap); 3017 bset = isl_basic_set_swap_vars(bset, in); 3018 return isl_basic_map_from_basic_set(bset, dim); 3019} 3020 3021static __isl_give isl_basic_map *basic_map_space_reset( 3022 __isl_take isl_basic_map *bmap, enum isl_dim_type type) 3023{ 3024 isl_space *space; 3025 3026 if (!bmap) 3027 return NULL; 3028 if (!isl_space_is_named_or_nested(bmap->dim, type)) 3029 return bmap; 3030 3031 space = isl_basic_map_get_space(bmap); 3032 space = isl_space_reset(space, type); 3033 bmap = isl_basic_map_reset_space(bmap, space); 3034 return bmap; 3035} 3036 3037__isl_give isl_basic_map *isl_basic_map_insert_dims( 3038 __isl_take isl_basic_map *bmap, enum isl_dim_type type, 3039 unsigned pos, unsigned n) 3040{ 3041 isl_space *res_dim; 3042 struct isl_basic_map *res; 3043 struct isl_dim_map *dim_map; 3044 unsigned total, off; 3045 enum isl_dim_type t; 3046 3047 if (n == 0) 3048 return basic_map_space_reset(bmap, type); 3049 3050 if (!bmap) 3051 return NULL; 3052 3053 res_dim = isl_space_insert_dims(isl_basic_map_get_space(bmap), type, pos, n); 3054 3055 total = isl_basic_map_total_dim(bmap) + n; 3056 dim_map = isl_dim_map_alloc(bmap->ctx, total); 3057 off = 0; 3058 for (t = isl_dim_param; t <= isl_dim_out; ++t) { 3059 if (t != type) { 3060 isl_dim_map_dim(dim_map, bmap->dim, t, off); 3061 } else { 3062 unsigned size = isl_basic_map_dim(bmap, t); 3063 isl_dim_map_dim_range(dim_map, bmap->dim, t, 3064 0, pos, off); 3065 isl_dim_map_dim_range(dim_map, bmap->dim, t, 3066 pos, size - pos, off + pos + n); 3067 } 3068 off += isl_space_dim(res_dim, t); 3069 } 3070 isl_dim_map_div(dim_map, bmap, off); 3071 3072 res = isl_basic_map_alloc_space(res_dim, 3073 bmap->n_div, bmap->n_eq, bmap->n_ineq); 3074 if (isl_basic_map_is_rational(bmap)) 3075 res = isl_basic_map_set_rational(res); 3076 if (isl_basic_map_plain_is_empty(bmap)) { 3077 isl_basic_map_free(bmap); 3078 free(dim_map); 3079 return isl_basic_map_set_to_empty(res); 3080 } 3081 res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map); 3082 return isl_basic_map_finalize(res); 3083} 3084 3085__isl_give isl_basic_set *isl_basic_set_insert_dims( 3086 __isl_take isl_basic_set *bset, 3087 enum isl_dim_type type, unsigned pos, unsigned n) 3088{ 3089 return isl_basic_map_insert_dims(bset, type, pos, n); 3090} 3091 3092__isl_give isl_basic_map *isl_basic_map_add(__isl_take isl_basic_map *bmap, 3093 enum isl_dim_type type, unsigned n) 3094{ 3095 if (!bmap) 3096 return NULL; 3097 return isl_basic_map_insert_dims(bmap, type, 3098 isl_basic_map_dim(bmap, type), n); 3099} 3100 3101__isl_give isl_basic_set *isl_basic_set_add_dims(__isl_take isl_basic_set *bset, 3102 enum isl_dim_type type, unsigned n) 3103{ 3104 if (!bset) 3105 return NULL; 3106 isl_assert(bset->ctx, type != isl_dim_in, goto error); 3107 return (isl_basic_set *)isl_basic_map_add((isl_basic_map *)bset, type, n); 3108error: 3109 isl_basic_set_free(bset); 3110 return NULL; 3111} 3112 3113static __isl_give isl_map *map_space_reset(__isl_take isl_map *map, 3114 enum isl_dim_type type) 3115{ 3116 isl_space *space; 3117 3118 if (!map || !isl_space_is_named_or_nested(map->dim, type)) 3119 return map; 3120 3121 space = isl_map_get_space(map); 3122 space = isl_space_reset(space, type); 3123 map = isl_map_reset_space(map, space); 3124 return map; 3125} 3126 3127__isl_give isl_map *isl_map_insert_dims(__isl_take isl_map *map, 3128 enum isl_dim_type type, unsigned pos, unsigned n) 3129{ 3130 int i; 3131 3132 if (n == 0) 3133 return map_space_reset(map, type); 3134 3135 map = isl_map_cow(map); 3136 if (!map) 3137 return NULL; 3138 3139 map->dim = isl_space_insert_dims(map->dim, type, pos, n); 3140 if (!map->dim) 3141 goto error; 3142 3143 for (i = 0; i < map->n; ++i) { 3144 map->p[i] = isl_basic_map_insert_dims(map->p[i], type, pos, n); 3145 if (!map->p[i]) 3146 goto error; 3147 } 3148 3149 return map; 3150error: 3151 isl_map_free(map); 3152 return NULL; 3153} 3154 3155__isl_give isl_set *isl_set_insert_dims(__isl_take isl_set *set, 3156 enum isl_dim_type type, unsigned pos, unsigned n) 3157{ 3158 return isl_map_insert_dims(set, type, pos, n); 3159} 3160 3161__isl_give isl_map *isl_map_add_dims(__isl_take isl_map *map, 3162 enum isl_dim_type type, unsigned n) 3163{ 3164 if (!map) 3165 return NULL; 3166 return isl_map_insert_dims(map, type, isl_map_dim(map, type), n); 3167} 3168 3169__isl_give isl_set *isl_set_add_dims(__isl_take isl_set *set, 3170 enum isl_dim_type type, unsigned n) 3171{ 3172 if (!set) 3173 return NULL; 3174 isl_assert(set->ctx, type != isl_dim_in, goto error); 3175 return (isl_set *)isl_map_add_dims((isl_map *)set, type, n); 3176error: 3177 isl_set_free(set); 3178 return NULL; 3179} 3180 3181__isl_give isl_basic_map *isl_basic_map_move_dims( 3182 __isl_take isl_basic_map *bmap, 3183 enum isl_dim_type dst_type, unsigned dst_pos, 3184 enum isl_dim_type src_type, unsigned src_pos, unsigned n) 3185{ 3186 struct isl_dim_map *dim_map; 3187 struct isl_basic_map *res; 3188 enum isl_dim_type t; 3189 unsigned total, off; 3190 3191 if (!bmap) 3192 return NULL; 3193 if (n == 0) 3194 return bmap; 3195 3196 isl_assert(bmap->ctx, src_pos + n <= isl_basic_map_dim(bmap, src_type), 3197 goto error); 3198 3199 if (dst_type == src_type && dst_pos == src_pos) 3200 return bmap; 3201 3202 isl_assert(bmap->ctx, dst_type != src_type, goto error); 3203 3204 if (pos(bmap->dim, dst_type) + dst_pos == 3205 pos(bmap->dim, src_type) + src_pos + 3206 ((src_type < dst_type) ? n : 0)) { 3207 bmap = isl_basic_map_cow(bmap); 3208 if (!bmap) 3209 return NULL; 3210 3211 bmap->dim = isl_space_move_dims(bmap->dim, dst_type, dst_pos, 3212 src_type, src_pos, n); 3213 if (!bmap->dim) 3214 goto error; 3215 3216 bmap = isl_basic_map_finalize(bmap); 3217 3218 return bmap; 3219 } 3220 3221 total = isl_basic_map_total_dim(bmap); 3222 dim_map = isl_dim_map_alloc(bmap->ctx, total); 3223 3224 off = 0; 3225 for (t = isl_dim_param; t <= isl_dim_out; ++t) { 3226 unsigned size = isl_space_dim(bmap->dim, t); 3227 if (t == dst_type) { 3228 isl_dim_map_dim_range(dim_map, bmap->dim, t, 3229 0, dst_pos, off); 3230 off += dst_pos; 3231 isl_dim_map_dim_range(dim_map, bmap->dim, src_type, 3232 src_pos, n, off); 3233 off += n; 3234 isl_dim_map_dim_range(dim_map, bmap->dim, t, 3235 dst_pos, size - dst_pos, off); 3236 off += size - dst_pos; 3237 } else if (t == src_type) { 3238 isl_dim_map_dim_range(dim_map, bmap->dim, t, 3239 0, src_pos, off); 3240 off += src_pos; 3241 isl_dim_map_dim_range(dim_map, bmap->dim, t, 3242 src_pos + n, size - src_pos - n, off); 3243 off += size - src_pos - n; 3244 } else { 3245 isl_dim_map_dim(dim_map, bmap->dim, t, off); 3246 off += size; 3247 } 3248 } 3249 isl_dim_map_div(dim_map, bmap, off); 3250 3251 res = isl_basic_map_alloc_space(isl_basic_map_get_space(bmap), 3252 bmap->n_div, bmap->n_eq, bmap->n_ineq); 3253 bmap = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map); 3254 if (!bmap) 3255 goto error; 3256 3257 bmap->dim = isl_space_move_dims(bmap->dim, dst_type, dst_pos, 3258 src_type, src_pos, n); 3259 if (!bmap->dim) 3260 goto error; 3261 3262 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED); 3263 bmap = isl_basic_map_gauss(bmap, NULL); 3264 bmap = isl_basic_map_finalize(bmap); 3265 3266 return bmap; 3267error: 3268 isl_basic_map_free(bmap); 3269 return NULL; 3270} 3271 3272__isl_give isl_basic_set *isl_basic_set_move_dims(__isl_take isl_basic_set *bset, 3273 enum isl_dim_type dst_type, unsigned dst_pos, 3274 enum isl_dim_type src_type, unsigned src_pos, unsigned n) 3275{ 3276 return (isl_basic_set *)isl_basic_map_move_dims( 3277 (isl_basic_map *)bset, dst_type, dst_pos, src_type, src_pos, n); 3278} 3279 3280__isl_give isl_set *isl_set_move_dims(__isl_take isl_set *set, 3281 enum isl_dim_type dst_type, unsigned dst_pos, 3282 enum isl_dim_type src_type, unsigned src_pos, unsigned n) 3283{ 3284 if (!set) 3285 return NULL; 3286 isl_assert(set->ctx, dst_type != isl_dim_in, goto error); 3287 return (isl_set *)isl_map_move_dims((isl_map *)set, dst_type, dst_pos, 3288 src_type, src_pos, n); 3289error: 3290 isl_set_free(set); 3291 return NULL; 3292} 3293 3294__isl_give isl_map *isl_map_move_dims(__isl_take isl_map *map, 3295 enum isl_dim_type dst_type, unsigned dst_pos, 3296 enum isl_dim_type src_type, unsigned src_pos, unsigned n) 3297{ 3298 int i; 3299 3300 if (!map) 3301 return NULL; 3302 if (n == 0) 3303 return map; 3304 3305 isl_assert(map->ctx, src_pos + n <= isl_map_dim(map, src_type), 3306 goto error); 3307 3308 if (dst_type == src_type && dst_pos == src_pos) 3309 return map; 3310 3311 isl_assert(map->ctx, dst_type != src_type, goto error); 3312 3313 map = isl_map_cow(map); 3314 if (!map) 3315 return NULL; 3316 3317 map->dim = isl_space_move_dims(map->dim, dst_type, dst_pos, src_type, src_pos, n); 3318 if (!map->dim) 3319 goto error; 3320 3321 for (i = 0; i < map->n; ++i) { 3322 map->p[i] = isl_basic_map_move_dims(map->p[i], 3323 dst_type, dst_pos, 3324 src_type, src_pos, n); 3325 if (!map->p[i]) 3326 goto error; 3327 } 3328 3329 return map; 3330error: 3331 isl_map_free(map); 3332 return NULL; 3333} 3334 3335/* Move the specified dimensions to the last columns right before 3336 * the divs. Don't change the dimension specification of bmap. 3337 * That's the responsibility of the caller. 3338 */ 3339static __isl_give isl_basic_map *move_last(__isl_take isl_basic_map *bmap, 3340 enum isl_dim_type type, unsigned first, unsigned n) 3341{ 3342 struct isl_dim_map *dim_map; 3343 struct isl_basic_map *res; 3344 enum isl_dim_type t; 3345 unsigned total, off; 3346 3347 if (!bmap) 3348 return NULL; 3349 if (pos(bmap->dim, type) + first + n == 3350 1 + isl_space_dim(bmap->dim, isl_dim_all)) 3351 return bmap; 3352 3353 total = isl_basic_map_total_dim(bmap); 3354 dim_map = isl_dim_map_alloc(bmap->ctx, total); 3355 3356 off = 0; 3357 for (t = isl_dim_param; t <= isl_dim_out; ++t) { 3358 unsigned size = isl_space_dim(bmap->dim, t); 3359 if (t == type) { 3360 isl_dim_map_dim_range(dim_map, bmap->dim, t, 3361 0, first, off); 3362 off += first; 3363 isl_dim_map_dim_range(dim_map, bmap->dim, t, 3364 first, n, total - bmap->n_div - n); 3365 isl_dim_map_dim_range(dim_map, bmap->dim, t, 3366 first + n, size - (first + n), off); 3367 off += size - (first + n); 3368 } else { 3369 isl_dim_map_dim(dim_map, bmap->dim, t, off); 3370 off += size; 3371 } 3372 } 3373 isl_dim_map_div(dim_map, bmap, off + n); 3374 3375 res = isl_basic_map_alloc_space(isl_basic_map_get_space(bmap), 3376 bmap->n_div, bmap->n_eq, bmap->n_ineq); 3377 res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map); 3378 return res; 3379} 3380 3381/* Insert "n" rows in the divs of "bmap". 3382 * 3383 * The number of columns is not changed, which means that the last 3384 * dimensions of "bmap" are being reintepreted as the new divs. 3385 * The space of "bmap" is not adjusted, however, which means 3386 * that "bmap" is left in an inconsistent state. Removing "n" dimensions 3387 * from the space of "bmap" is the responsibility of the caller. 3388 */ 3389static __isl_give isl_basic_map *insert_div_rows(__isl_take isl_basic_map *bmap, 3390 int n) 3391{ 3392 int i; 3393 size_t row_size; 3394 isl_int **new_div; 3395 isl_int *old; 3396 3397 bmap = isl_basic_map_cow(bmap); 3398 if (!bmap) 3399 return NULL; 3400 3401 row_size = 1 + isl_space_dim(bmap->dim, isl_dim_all) + bmap->extra; 3402 old = bmap->block2.data; 3403 bmap->block2 = isl_blk_extend(bmap->ctx, bmap->block2, 3404 (bmap->extra + n) * (1 + row_size)); 3405 if (!bmap->block2.data) 3406 return isl_basic_map_free(bmap); 3407 new_div = isl_alloc_array(bmap->ctx, isl_int *, bmap->extra + n); 3408 if (!new_div) 3409 return isl_basic_map_free(bmap); 3410 for (i = 0; i < n; ++i) { 3411 new_div[i] = bmap->block2.data + 3412 (bmap->extra + i) * (1 + row_size); 3413 isl_seq_clr(new_div[i], 1 + row_size); 3414 } 3415 for (i = 0; i < bmap->extra; ++i) 3416 new_div[n + i] = bmap->block2.data + (bmap->div[i] - old); 3417 free(bmap->div); 3418 bmap->div = new_div; 3419 bmap->n_div += n; 3420 bmap->extra += n; 3421 3422 return bmap; 3423} 3424 3425/* Turn the n dimensions of type type, starting at first 3426 * into existentially quantified variables. 3427 */ 3428__isl_give isl_basic_map *isl_basic_map_project_out( 3429 __isl_take isl_basic_map *bmap, 3430 enum isl_dim_type type, unsigned first, unsigned n) 3431{ 3432 if (n == 0) 3433 return basic_map_space_reset(bmap, type); 3434 3435 if (!bmap) 3436 return NULL; 3437 3438 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL)) 3439 return isl_basic_map_remove_dims(bmap, type, first, n); 3440 3441 isl_assert(bmap->ctx, first + n <= isl_basic_map_dim(bmap, type), 3442 goto error); 3443 3444 bmap = move_last(bmap, type, first, n); 3445 bmap = isl_basic_map_cow(bmap); 3446 bmap = insert_div_rows(bmap, n); 3447 if (!bmap) 3448 return NULL; 3449 3450 bmap->dim = isl_space_drop_dims(bmap->dim, type, first, n); 3451 if (!bmap->dim) 3452 goto error; 3453 bmap = isl_basic_map_simplify(bmap); 3454 bmap = isl_basic_map_drop_redundant_divs(bmap); 3455 return isl_basic_map_finalize(bmap); 3456error: 3457 isl_basic_map_free(bmap); 3458 return NULL; 3459} 3460 3461/* Turn the n dimensions of type type, starting at first 3462 * into existentially quantified variables. 3463 */ 3464struct isl_basic_set *isl_basic_set_project_out(struct isl_basic_set *bset, 3465 enum isl_dim_type type, unsigned first, unsigned n) 3466{ 3467 return (isl_basic_set *)isl_basic_map_project_out( 3468 (isl_basic_map *)bset, type, first, n); 3469} 3470 3471/* Turn the n dimensions of type type, starting at first 3472 * into existentially quantified variables. 3473 */ 3474__isl_give isl_map *isl_map_project_out(__isl_take isl_map *map, 3475 enum isl_dim_type type, unsigned first, unsigned n) 3476{ 3477 int i; 3478 3479 if (!map) 3480 return NULL; 3481 3482 if (n == 0) 3483 return map_space_reset(map, type); 3484 3485 isl_assert(map->ctx, first + n <= isl_map_dim(map, type), goto error); 3486 3487 map = isl_map_cow(map); 3488 if (!map) 3489 return NULL; 3490 3491 map->dim = isl_space_drop_dims(map->dim, type, first, n); 3492 if (!map->dim) 3493 goto error; 3494 3495 for (i = 0; i < map->n; ++i) { 3496 map->p[i] = isl_basic_map_project_out(map->p[i], type, first, n); 3497 if (!map->p[i]) 3498 goto error; 3499 } 3500 3501 return map; 3502error: 3503 isl_map_free(map); 3504 return NULL; 3505} 3506 3507/* Turn the n dimensions of type type, starting at first 3508 * into existentially quantified variables. 3509 */ 3510__isl_give isl_set *isl_set_project_out(__isl_take isl_set *set, 3511 enum isl_dim_type type, unsigned first, unsigned n) 3512{ 3513 return (isl_set *)isl_map_project_out((isl_map *)set, type, first, n); 3514} 3515 3516static struct isl_basic_map *add_divs(struct isl_basic_map *bmap, unsigned n) 3517{ 3518 int i, j; 3519 3520 for (i = 0; i < n; ++i) { 3521 j = isl_basic_map_alloc_div(bmap); 3522 if (j < 0) 3523 goto error; 3524 isl_seq_clr(bmap->div[j], 1+1+isl_basic_map_total_dim(bmap)); 3525 } 3526 return bmap; 3527error: 3528 isl_basic_map_free(bmap); 3529 return NULL; 3530} 3531 3532struct isl_basic_map *isl_basic_map_apply_range( 3533 struct isl_basic_map *bmap1, struct isl_basic_map *bmap2) 3534{ 3535 isl_space *dim_result = NULL; 3536 struct isl_basic_map *bmap; 3537 unsigned n_in, n_out, n, nparam, total, pos; 3538 struct isl_dim_map *dim_map1, *dim_map2; 3539 3540 if (!bmap1 || !bmap2) 3541 goto error; 3542 if (!isl_space_match(bmap1->dim, isl_dim_param, 3543 bmap2->dim, isl_dim_param)) 3544 isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid, 3545 "parameters don't match", goto error); 3546 if (!isl_space_tuple_match(bmap1->dim, isl_dim_out, 3547 bmap2->dim, isl_dim_in)) 3548 isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid, 3549 "spaces don't match", goto error); 3550 3551 dim_result = isl_space_join(isl_space_copy(bmap1->dim), 3552 isl_space_copy(bmap2->dim)); 3553 3554 n_in = isl_basic_map_n_in(bmap1); 3555 n_out = isl_basic_map_n_out(bmap2); 3556 n = isl_basic_map_n_out(bmap1); 3557 nparam = isl_basic_map_n_param(bmap1); 3558 3559 total = nparam + n_in + n_out + bmap1->n_div + bmap2->n_div + n; 3560 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total); 3561 dim_map2 = isl_dim_map_alloc(bmap1->ctx, total); 3562 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0); 3563 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0); 3564 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam); 3565 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += n_in); 3566 isl_dim_map_div(dim_map1, bmap1, pos += n_out); 3567 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div); 3568 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += bmap2->n_div); 3569 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos); 3570 3571 bmap = isl_basic_map_alloc_space(dim_result, 3572 bmap1->n_div + bmap2->n_div + n, 3573 bmap1->n_eq + bmap2->n_eq, 3574 bmap1->n_ineq + bmap2->n_ineq); 3575 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1); 3576 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2); 3577 bmap = add_divs(bmap, n); 3578 bmap = isl_basic_map_simplify(bmap); 3579 bmap = isl_basic_map_drop_redundant_divs(bmap); 3580 return isl_basic_map_finalize(bmap); 3581error: 3582 isl_basic_map_free(bmap1); 3583 isl_basic_map_free(bmap2); 3584 return NULL; 3585} 3586 3587struct isl_basic_set *isl_basic_set_apply( 3588 struct isl_basic_set *bset, struct isl_basic_map *bmap) 3589{ 3590 if (!bset || !bmap) 3591 goto error; 3592 3593 isl_assert(bset->ctx, isl_basic_map_compatible_domain(bmap, bset), 3594 goto error); 3595 3596 return (struct isl_basic_set *) 3597 isl_basic_map_apply_range((struct isl_basic_map *)bset, bmap); 3598error: 3599 isl_basic_set_free(bset); 3600 isl_basic_map_free(bmap); 3601 return NULL; 3602} 3603 3604struct isl_basic_map *isl_basic_map_apply_domain( 3605 struct isl_basic_map *bmap1, struct isl_basic_map *bmap2) 3606{ 3607 if (!bmap1 || !bmap2) 3608 goto error; 3609 3610 isl_assert(bmap1->ctx, 3611 isl_basic_map_n_in(bmap1) == isl_basic_map_n_in(bmap2), goto error); 3612 isl_assert(bmap1->ctx, 3613 isl_basic_map_n_param(bmap1) == isl_basic_map_n_param(bmap2), 3614 goto error); 3615 3616 bmap1 = isl_basic_map_reverse(bmap1); 3617 bmap1 = isl_basic_map_apply_range(bmap1, bmap2); 3618 return isl_basic_map_reverse(bmap1); 3619error: 3620 isl_basic_map_free(bmap1); 3621 isl_basic_map_free(bmap2); 3622 return NULL; 3623} 3624 3625/* Given two basic maps A -> f(A) and B -> g(B), construct a basic map 3626 * A \cap B -> f(A) + f(B) 3627 */ 3628struct isl_basic_map *isl_basic_map_sum( 3629 struct isl_basic_map *bmap1, struct isl_basic_map *bmap2) 3630{ 3631 unsigned n_in, n_out, nparam, total, pos; 3632 struct isl_basic_map *bmap = NULL; 3633 struct isl_dim_map *dim_map1, *dim_map2; 3634 int i; 3635 3636 if (!bmap1 || !bmap2) 3637 goto error; 3638 3639 isl_assert(bmap1->ctx, isl_space_is_equal(bmap1->dim, bmap2->dim), 3640 goto error); 3641 3642 nparam = isl_basic_map_n_param(bmap1); 3643 n_in = isl_basic_map_n_in(bmap1); 3644 n_out = isl_basic_map_n_out(bmap1); 3645 3646 total = nparam + n_in + n_out + bmap1->n_div + bmap2->n_div + 2 * n_out; 3647 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total); 3648 dim_map2 = isl_dim_map_alloc(bmap2->ctx, total); 3649 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0); 3650 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos); 3651 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam); 3652 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos); 3653 isl_dim_map_div(dim_map1, bmap1, pos += n_in + n_out); 3654 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div); 3655 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += bmap2->n_div); 3656 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += n_out); 3657 3658 bmap = isl_basic_map_alloc_space(isl_space_copy(bmap1->dim), 3659 bmap1->n_div + bmap2->n_div + 2 * n_out, 3660 bmap1->n_eq + bmap2->n_eq + n_out, 3661 bmap1->n_ineq + bmap2->n_ineq); 3662 for (i = 0; i < n_out; ++i) { 3663 int j = isl_basic_map_alloc_equality(bmap); 3664 if (j < 0) 3665 goto error; 3666 isl_seq_clr(bmap->eq[j], 1+total); 3667 isl_int_set_si(bmap->eq[j][1+nparam+n_in+i], -1); 3668 isl_int_set_si(bmap->eq[j][1+pos+i], 1); 3669 isl_int_set_si(bmap->eq[j][1+pos-n_out+i], 1); 3670 } 3671 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1); 3672 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2); 3673 bmap = add_divs(bmap, 2 * n_out); 3674 3675 bmap = isl_basic_map_simplify(bmap); 3676 return isl_basic_map_finalize(bmap); 3677error: 3678 isl_basic_map_free(bmap); 3679 isl_basic_map_free(bmap1); 3680 isl_basic_map_free(bmap2); 3681 return NULL; 3682} 3683 3684/* Given two maps A -> f(A) and B -> g(B), construct a map 3685 * A \cap B -> f(A) + f(B) 3686 */ 3687struct isl_map *isl_map_sum(struct isl_map *map1, struct isl_map *map2) 3688{ 3689 struct isl_map *result; 3690 int i, j; 3691 3692 if (!map1 || !map2) 3693 goto error; 3694 3695 isl_assert(map1->ctx, isl_space_is_equal(map1->dim, map2->dim), goto error); 3696 3697 result = isl_map_alloc_space(isl_space_copy(map1->dim), 3698 map1->n * map2->n, 0); 3699 if (!result) 3700 goto error; 3701 for (i = 0; i < map1->n; ++i) 3702 for (j = 0; j < map2->n; ++j) { 3703 struct isl_basic_map *part; 3704 part = isl_basic_map_sum( 3705 isl_basic_map_copy(map1->p[i]), 3706 isl_basic_map_copy(map2->p[j])); 3707 if (isl_basic_map_is_empty(part)) 3708 isl_basic_map_free(part); 3709 else 3710 result = isl_map_add_basic_map(result, part); 3711 if (!result) 3712 goto error; 3713 } 3714 isl_map_free(map1); 3715 isl_map_free(map2); 3716 return result; 3717error: 3718 isl_map_free(map1); 3719 isl_map_free(map2); 3720 return NULL; 3721} 3722 3723__isl_give isl_set *isl_set_sum(__isl_take isl_set *set1, 3724 __isl_take isl_set *set2) 3725{ 3726 return (isl_set *)isl_map_sum((isl_map *)set1, (isl_map *)set2); 3727} 3728 3729/* Given a basic map A -> f(A), construct A -> -f(A). 3730 */ 3731struct isl_basic_map *isl_basic_map_neg(struct isl_basic_map *bmap) 3732{ 3733 int i, j; 3734 unsigned off, n; 3735 3736 bmap = isl_basic_map_cow(bmap); 3737 if (!bmap) 3738 return NULL; 3739 3740 n = isl_basic_map_dim(bmap, isl_dim_out); 3741 off = isl_basic_map_offset(bmap, isl_dim_out); 3742 for (i = 0; i < bmap->n_eq; ++i) 3743 for (j = 0; j < n; ++j) 3744 isl_int_neg(bmap->eq[i][off+j], bmap->eq[i][off+j]); 3745 for (i = 0; i < bmap->n_ineq; ++i) 3746 for (j = 0; j < n; ++j) 3747 isl_int_neg(bmap->ineq[i][off+j], bmap->ineq[i][off+j]); 3748 for (i = 0; i < bmap->n_div; ++i) 3749 for (j = 0; j < n; ++j) 3750 isl_int_neg(bmap->div[i][1+off+j], bmap->div[i][1+off+j]); 3751 bmap = isl_basic_map_gauss(bmap, NULL); 3752 return isl_basic_map_finalize(bmap); 3753} 3754 3755__isl_give isl_basic_set *isl_basic_set_neg(__isl_take isl_basic_set *bset) 3756{ 3757 return isl_basic_map_neg(bset); 3758} 3759 3760/* Given a map A -> f(A), construct A -> -f(A). 3761 */ 3762struct isl_map *isl_map_neg(struct isl_map *map) 3763{ 3764 int i; 3765 3766 map = isl_map_cow(map); 3767 if (!map) 3768 return NULL; 3769 3770 for (i = 0; i < map->n; ++i) { 3771 map->p[i] = isl_basic_map_neg(map->p[i]); 3772 if (!map->p[i]) 3773 goto error; 3774 } 3775 3776 return map; 3777error: 3778 isl_map_free(map); 3779 return NULL; 3780} 3781 3782__isl_give isl_set *isl_set_neg(__isl_take isl_set *set) 3783{ 3784 return (isl_set *)isl_map_neg((isl_map *)set); 3785} 3786 3787/* Given a basic map A -> f(A) and an integer d, construct a basic map 3788 * A -> floor(f(A)/d). 3789 */ 3790struct isl_basic_map *isl_basic_map_floordiv(struct isl_basic_map *bmap, 3791 isl_int d) 3792{ 3793 unsigned n_in, n_out, nparam, total, pos; 3794 struct isl_basic_map *result = NULL; 3795 struct isl_dim_map *dim_map; 3796 int i; 3797 3798 if (!bmap) 3799 return NULL; 3800 3801 nparam = isl_basic_map_n_param(bmap); 3802 n_in = isl_basic_map_n_in(bmap); 3803 n_out = isl_basic_map_n_out(bmap); 3804 3805 total = nparam + n_in + n_out + bmap->n_div + n_out; 3806 dim_map = isl_dim_map_alloc(bmap->ctx, total); 3807 isl_dim_map_dim(dim_map, bmap->dim, isl_dim_param, pos = 0); 3808 isl_dim_map_dim(dim_map, bmap->dim, isl_dim_in, pos += nparam); 3809 isl_dim_map_div(dim_map, bmap, pos += n_in + n_out); 3810 isl_dim_map_dim(dim_map, bmap->dim, isl_dim_out, pos += bmap->n_div); 3811 3812 result = isl_basic_map_alloc_space(isl_space_copy(bmap->dim), 3813 bmap->n_div + n_out, 3814 bmap->n_eq, bmap->n_ineq + 2 * n_out); 3815 result = isl_basic_map_add_constraints_dim_map(result, bmap, dim_map); 3816 result = add_divs(result, n_out); 3817 for (i = 0; i < n_out; ++i) { 3818 int j; 3819 j = isl_basic_map_alloc_inequality(result); 3820 if (j < 0) 3821 goto error; 3822 isl_seq_clr(result->ineq[j], 1+total); 3823 isl_int_neg(result->ineq[j][1+nparam+n_in+i], d); 3824 isl_int_set_si(result->ineq[j][1+pos+i], 1); 3825 j = isl_basic_map_alloc_inequality(result); 3826 if (j < 0) 3827 goto error; 3828 isl_seq_clr(result->ineq[j], 1+total); 3829 isl_int_set(result->ineq[j][1+nparam+n_in+i], d); 3830 isl_int_set_si(result->ineq[j][1+pos+i], -1); 3831 isl_int_sub_ui(result->ineq[j][0], d, 1); 3832 } 3833 3834 result = isl_basic_map_simplify(result); 3835 return isl_basic_map_finalize(result); 3836error: 3837 isl_basic_map_free(result); 3838 return NULL; 3839} 3840 3841/* Given a map A -> f(A) and an integer d, construct a map 3842 * A -> floor(f(A)/d). 3843 */ 3844struct isl_map *isl_map_floordiv(struct isl_map *map, isl_int d) 3845{ 3846 int i; 3847 3848 map = isl_map_cow(map); 3849 if (!map) 3850 return NULL; 3851 3852 ISL_F_CLR(map, ISL_MAP_DISJOINT); 3853 ISL_F_CLR(map, ISL_MAP_NORMALIZED); 3854 for (i = 0; i < map->n; ++i) { 3855 map->p[i] = isl_basic_map_floordiv(map->p[i], d); 3856 if (!map->p[i]) 3857 goto error; 3858 } 3859 3860 return map; 3861error: 3862 isl_map_free(map); 3863 return NULL; 3864} 3865 3866/* Given a map A -> f(A) and an integer d, construct a map 3867 * A -> floor(f(A)/d). 3868 */ 3869__isl_give isl_map *isl_map_floordiv_val(__isl_take isl_map *map, 3870 __isl_take isl_val *d) 3871{ 3872 if (!map || !d) 3873 goto error; 3874 if (!isl_val_is_int(d)) 3875 isl_die(isl_val_get_ctx(d), isl_error_invalid, 3876 "expecting integer denominator", goto error); 3877 map = isl_map_floordiv(map, d->n); 3878 isl_val_free(d); 3879 return map; 3880error: 3881 isl_map_free(map); 3882 isl_val_free(d); 3883 return NULL; 3884} 3885 3886static struct isl_basic_map *var_equal(struct isl_basic_map *bmap, unsigned pos) 3887{ 3888 int i; 3889 unsigned nparam; 3890 unsigned n_in; 3891 3892 i = isl_basic_map_alloc_equality(bmap); 3893 if (i < 0) 3894 goto error; 3895 nparam = isl_basic_map_n_param(bmap); 3896 n_in = isl_basic_map_n_in(bmap); 3897 isl_seq_clr(bmap->eq[i], 1 + isl_basic_map_total_dim(bmap)); 3898 isl_int_set_si(bmap->eq[i][1+nparam+pos], -1); 3899 isl_int_set_si(bmap->eq[i][1+nparam+n_in+pos], 1); 3900 return isl_basic_map_finalize(bmap); 3901error: 3902 isl_basic_map_free(bmap); 3903 return NULL; 3904} 3905 3906/* Add a constraints to "bmap" expressing i_pos < o_pos 3907 */ 3908static struct isl_basic_map *var_less(struct isl_basic_map *bmap, unsigned pos) 3909{ 3910 int i; 3911 unsigned nparam; 3912 unsigned n_in; 3913 3914 i = isl_basic_map_alloc_inequality(bmap); 3915 if (i < 0) 3916 goto error; 3917 nparam = isl_basic_map_n_param(bmap); 3918 n_in = isl_basic_map_n_in(bmap); 3919 isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap)); 3920 isl_int_set_si(bmap->ineq[i][0], -1); 3921 isl_int_set_si(bmap->ineq[i][1+nparam+pos], -1); 3922 isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], 1); 3923 return isl_basic_map_finalize(bmap); 3924error: 3925 isl_basic_map_free(bmap); 3926 return NULL; 3927} 3928 3929/* Add a constraint to "bmap" expressing i_pos <= o_pos 3930 */ 3931static __isl_give isl_basic_map *var_less_or_equal( 3932 __isl_take isl_basic_map *bmap, unsigned pos) 3933{ 3934 int i; 3935 unsigned nparam; 3936 unsigned n_in; 3937 3938 i = isl_basic_map_alloc_inequality(bmap); 3939 if (i < 0) 3940 goto error; 3941 nparam = isl_basic_map_n_param(bmap); 3942 n_in = isl_basic_map_n_in(bmap); 3943 isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap)); 3944 isl_int_set_si(bmap->ineq[i][1+nparam+pos], -1); 3945 isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], 1); 3946 return isl_basic_map_finalize(bmap); 3947error: 3948 isl_basic_map_free(bmap); 3949 return NULL; 3950} 3951 3952/* Add a constraints to "bmap" expressing i_pos > o_pos 3953 */ 3954static struct isl_basic_map *var_more(struct isl_basic_map *bmap, unsigned pos) 3955{ 3956 int i; 3957 unsigned nparam; 3958 unsigned n_in; 3959 3960 i = isl_basic_map_alloc_inequality(bmap); 3961 if (i < 0) 3962 goto error; 3963 nparam = isl_basic_map_n_param(bmap); 3964 n_in = isl_basic_map_n_in(bmap); 3965 isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap)); 3966 isl_int_set_si(bmap->ineq[i][0], -1); 3967 isl_int_set_si(bmap->ineq[i][1+nparam+pos], 1); 3968 isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], -1); 3969 return isl_basic_map_finalize(bmap); 3970error: 3971 isl_basic_map_free(bmap); 3972 return NULL; 3973} 3974 3975/* Add a constraint to "bmap" expressing i_pos >= o_pos 3976 */ 3977static __isl_give isl_basic_map *var_more_or_equal( 3978 __isl_take isl_basic_map *bmap, unsigned pos) 3979{ 3980 int i; 3981 unsigned nparam; 3982 unsigned n_in; 3983 3984 i = isl_basic_map_alloc_inequality(bmap); 3985 if (i < 0) 3986 goto error; 3987 nparam = isl_basic_map_n_param(bmap); 3988 n_in = isl_basic_map_n_in(bmap); 3989 isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap)); 3990 isl_int_set_si(bmap->ineq[i][1+nparam+pos], 1); 3991 isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], -1); 3992 return isl_basic_map_finalize(bmap); 3993error: 3994 isl_basic_map_free(bmap); 3995 return NULL; 3996} 3997 3998__isl_give isl_basic_map *isl_basic_map_equal( 3999 __isl_take isl_space *dim, unsigned n_equal) 4000{ 4001 int i; 4002 struct isl_basic_map *bmap; 4003 bmap = isl_basic_map_alloc_space(dim, 0, n_equal, 0); 4004 if (!bmap) 4005 return NULL; 4006 for (i = 0; i < n_equal && bmap; ++i) 4007 bmap = var_equal(bmap, i); 4008 return isl_basic_map_finalize(bmap); 4009} 4010 4011/* Return a relation on of dimension "dim" expressing i_[0..pos] << o_[0..pos] 4012 */ 4013__isl_give isl_basic_map *isl_basic_map_less_at(__isl_take isl_space *dim, 4014 unsigned pos) 4015{ 4016 int i; 4017 struct isl_basic_map *bmap; 4018 bmap = isl_basic_map_alloc_space(dim, 0, pos, 1); 4019 if (!bmap) 4020 return NULL; 4021 for (i = 0; i < pos && bmap; ++i) 4022 bmap = var_equal(bmap, i); 4023 if (bmap) 4024 bmap = var_less(bmap, pos); 4025 return isl_basic_map_finalize(bmap); 4026} 4027 4028/* Return a relation on of dimension "dim" expressing i_[0..pos] <<= o_[0..pos] 4029 */ 4030__isl_give isl_basic_map *isl_basic_map_less_or_equal_at( 4031 __isl_take isl_space *dim, unsigned pos) 4032{ 4033 int i; 4034 isl_basic_map *bmap; 4035 4036 bmap = isl_basic_map_alloc_space(dim, 0, pos, 1); 4037 for (i = 0; i < pos; ++i) 4038 bmap = var_equal(bmap, i); 4039 bmap = var_less_or_equal(bmap, pos); 4040 return isl_basic_map_finalize(bmap); 4041} 4042 4043/* Return a relation on pairs of sets of dimension "dim" expressing i_pos > o_pos 4044 */ 4045__isl_give isl_basic_map *isl_basic_map_more_at(__isl_take isl_space *dim, 4046 unsigned pos) 4047{ 4048 int i; 4049 struct isl_basic_map *bmap; 4050 bmap = isl_basic_map_alloc_space(dim, 0, pos, 1); 4051 if (!bmap) 4052 return NULL; 4053 for (i = 0; i < pos && bmap; ++i) 4054 bmap = var_equal(bmap, i); 4055 if (bmap) 4056 bmap = var_more(bmap, pos); 4057 return isl_basic_map_finalize(bmap); 4058} 4059 4060/* Return a relation on of dimension "dim" expressing i_[0..pos] >>= o_[0..pos] 4061 */ 4062__isl_give isl_basic_map *isl_basic_map_more_or_equal_at( 4063 __isl_take isl_space *dim, unsigned pos) 4064{ 4065 int i; 4066 isl_basic_map *bmap; 4067 4068 bmap = isl_basic_map_alloc_space(dim, 0, pos, 1); 4069 for (i = 0; i < pos; ++i) 4070 bmap = var_equal(bmap, i); 4071 bmap = var_more_or_equal(bmap, pos); 4072 return isl_basic_map_finalize(bmap); 4073} 4074 4075static __isl_give isl_map *map_lex_lte_first(__isl_take isl_space *dims, 4076 unsigned n, int equal) 4077{ 4078 struct isl_map *map; 4079 int i; 4080 4081 if (n == 0 && equal) 4082 return isl_map_universe(dims); 4083 4084 map = isl_map_alloc_space(isl_space_copy(dims), n, ISL_MAP_DISJOINT); 4085 4086 for (i = 0; i + 1 < n; ++i) 4087 map = isl_map_add_basic_map(map, 4088 isl_basic_map_less_at(isl_space_copy(dims), i)); 4089 if (n > 0) { 4090 if (equal) 4091 map = isl_map_add_basic_map(map, 4092 isl_basic_map_less_or_equal_at(dims, n - 1)); 4093 else 4094 map = isl_map_add_basic_map(map, 4095 isl_basic_map_less_at(dims, n - 1)); 4096 } else 4097 isl_space_free(dims); 4098 4099 return map; 4100} 4101 4102static __isl_give isl_map *map_lex_lte(__isl_take isl_space *dims, int equal) 4103{ 4104 if (!dims) 4105 return NULL; 4106 return map_lex_lte_first(dims, dims->n_out, equal); 4107} 4108 4109__isl_give isl_map *isl_map_lex_lt_first(__isl_take isl_space *dim, unsigned n) 4110{ 4111 return map_lex_lte_first(dim, n, 0); 4112} 4113 4114__isl_give isl_map *isl_map_lex_le_first(__isl_take isl_space *dim, unsigned n) 4115{ 4116 return map_lex_lte_first(dim, n, 1); 4117} 4118 4119__isl_give isl_map *isl_map_lex_lt(__isl_take isl_space *set_dim) 4120{ 4121 return map_lex_lte(isl_space_map_from_set(set_dim), 0); 4122} 4123 4124__isl_give isl_map *isl_map_lex_le(__isl_take isl_space *set_dim) 4125{ 4126 return map_lex_lte(isl_space_map_from_set(set_dim), 1); 4127} 4128 4129static __isl_give isl_map *map_lex_gte_first(__isl_take isl_space *dims, 4130 unsigned n, int equal) 4131{ 4132 struct isl_map *map; 4133 int i; 4134 4135 if (n == 0 && equal) 4136 return isl_map_universe(dims); 4137 4138 map = isl_map_alloc_space(isl_space_copy(dims), n, ISL_MAP_DISJOINT); 4139 4140 for (i = 0; i + 1 < n; ++i) 4141 map = isl_map_add_basic_map(map, 4142 isl_basic_map_more_at(isl_space_copy(dims), i)); 4143 if (n > 0) { 4144 if (equal) 4145 map = isl_map_add_basic_map(map, 4146 isl_basic_map_more_or_equal_at(dims, n - 1)); 4147 else 4148 map = isl_map_add_basic_map(map, 4149 isl_basic_map_more_at(dims, n - 1)); 4150 } else 4151 isl_space_free(dims); 4152 4153 return map; 4154} 4155 4156static __isl_give isl_map *map_lex_gte(__isl_take isl_space *dims, int equal) 4157{ 4158 if (!dims) 4159 return NULL; 4160 return map_lex_gte_first(dims, dims->n_out, equal); 4161} 4162 4163__isl_give isl_map *isl_map_lex_gt_first(__isl_take isl_space *dim, unsigned n) 4164{ 4165 return map_lex_gte_first(dim, n, 0); 4166} 4167 4168__isl_give isl_map *isl_map_lex_ge_first(__isl_take isl_space *dim, unsigned n) 4169{ 4170 return map_lex_gte_first(dim, n, 1); 4171} 4172 4173__isl_give isl_map *isl_map_lex_gt(__isl_take isl_space *set_dim) 4174{ 4175 return map_lex_gte(isl_space_map_from_set(set_dim), 0); 4176} 4177 4178__isl_give isl_map *isl_map_lex_ge(__isl_take isl_space *set_dim) 4179{ 4180 return map_lex_gte(isl_space_map_from_set(set_dim), 1); 4181} 4182 4183__isl_give isl_map *isl_set_lex_le_set(__isl_take isl_set *set1, 4184 __isl_take isl_set *set2) 4185{ 4186 isl_map *map; 4187 map = isl_map_lex_le(isl_set_get_space(set1)); 4188 map = isl_map_intersect_domain(map, set1); 4189 map = isl_map_intersect_range(map, set2); 4190 return map; 4191} 4192 4193__isl_give isl_map *isl_set_lex_lt_set(__isl_take isl_set *set1, 4194 __isl_take isl_set *set2) 4195{ 4196 isl_map *map; 4197 map = isl_map_lex_lt(isl_set_get_space(set1)); 4198 map = isl_map_intersect_domain(map, set1); 4199 map = isl_map_intersect_range(map, set2); 4200 return map; 4201} 4202 4203__isl_give isl_map *isl_set_lex_ge_set(__isl_take isl_set *set1, 4204 __isl_take isl_set *set2) 4205{ 4206 isl_map *map; 4207 map = isl_map_lex_ge(isl_set_get_space(set1)); 4208 map = isl_map_intersect_domain(map, set1); 4209 map = isl_map_intersect_range(map, set2); 4210 return map; 4211} 4212 4213__isl_give isl_map *isl_set_lex_gt_set(__isl_take isl_set *set1, 4214 __isl_take isl_set *set2) 4215{ 4216 isl_map *map; 4217 map = isl_map_lex_gt(isl_set_get_space(set1)); 4218 map = isl_map_intersect_domain(map, set1); 4219 map = isl_map_intersect_range(map, set2); 4220 return map; 4221} 4222 4223__isl_give isl_map *isl_map_lex_le_map(__isl_take isl_map *map1, 4224 __isl_take isl_map *map2) 4225{ 4226 isl_map *map; 4227 map = isl_map_lex_le(isl_space_range(isl_map_get_space(map1))); 4228 map = isl_map_apply_domain(map, isl_map_reverse(map1)); 4229 map = isl_map_apply_range(map, isl_map_reverse(map2)); 4230 return map; 4231} 4232 4233__isl_give isl_map *isl_map_lex_lt_map(__isl_take isl_map *map1, 4234 __isl_take isl_map *map2) 4235{ 4236 isl_map *map; 4237 map = isl_map_lex_lt(isl_space_range(isl_map_get_space(map1))); 4238 map = isl_map_apply_domain(map, isl_map_reverse(map1)); 4239 map = isl_map_apply_range(map, isl_map_reverse(map2)); 4240 return map; 4241} 4242 4243__isl_give isl_map *isl_map_lex_ge_map(__isl_take isl_map *map1, 4244 __isl_take isl_map *map2) 4245{ 4246 isl_map *map; 4247 map = isl_map_lex_ge(isl_space_range(isl_map_get_space(map1))); 4248 map = isl_map_apply_domain(map, isl_map_reverse(map1)); 4249 map = isl_map_apply_range(map, isl_map_reverse(map2)); 4250 return map; 4251} 4252 4253__isl_give isl_map *isl_map_lex_gt_map(__isl_take isl_map *map1, 4254 __isl_take isl_map *map2) 4255{ 4256 isl_map *map; 4257 map = isl_map_lex_gt(isl_space_range(isl_map_get_space(map1))); 4258 map = isl_map_apply_domain(map, isl_map_reverse(map1)); 4259 map = isl_map_apply_range(map, isl_map_reverse(map2)); 4260 return map; 4261} 4262 4263__isl_give isl_basic_map *isl_basic_map_from_basic_set( 4264 __isl_take isl_basic_set *bset, __isl_take isl_space *dim) 4265{ 4266 struct isl_basic_map *bmap; 4267 4268 bset = isl_basic_set_cow(bset); 4269 if (!bset || !dim) 4270 goto error; 4271 4272 isl_assert(bset->ctx, isl_space_compatible(bset->dim, dim), goto error); 4273 isl_space_free(bset->dim); 4274 bmap = (struct isl_basic_map *) bset; 4275 bmap->dim = dim; 4276 return isl_basic_map_finalize(bmap); 4277error: 4278 isl_basic_set_free(bset); 4279 isl_space_free(dim); 4280 return NULL; 4281} 4282 4283struct isl_basic_set *isl_basic_set_from_basic_map(struct isl_basic_map *bmap) 4284{ 4285 if (!bmap) 4286 goto error; 4287 if (bmap->dim->n_in == 0) 4288 return (struct isl_basic_set *)bmap; 4289 bmap = isl_basic_map_cow(bmap); 4290 if (!bmap) 4291 goto error; 4292 bmap->dim = isl_space_as_set_space(bmap->dim); 4293 if (!bmap->dim) 4294 goto error; 4295 bmap = isl_basic_map_finalize(bmap); 4296 return (struct isl_basic_set *)bmap; 4297error: 4298 isl_basic_map_free(bmap); 4299 return NULL; 4300} 4301 4302/* For a div d = floor(f/m), add the constraint 4303 * 4304 * f - m d >= 0 4305 */ 4306static int add_upper_div_constraint(__isl_keep isl_basic_map *bmap, 4307 unsigned pos, isl_int *div) 4308{ 4309 int i; 4310 unsigned total = isl_basic_map_total_dim(bmap); 4311 4312 i = isl_basic_map_alloc_inequality(bmap); 4313 if (i < 0) 4314 return -1; 4315 isl_seq_cpy(bmap->ineq[i], div + 1, 1 + total); 4316 isl_int_neg(bmap->ineq[i][1 + pos], div[0]); 4317 4318 return 0; 4319} 4320 4321/* For a div d = floor(f/m), add the constraint 4322 * 4323 * -(f-(n-1)) + m d >= 0 4324 */ 4325static int add_lower_div_constraint(__isl_keep isl_basic_map *bmap, 4326 unsigned pos, isl_int *div) 4327{ 4328 int i; 4329 unsigned total = isl_basic_map_total_dim(bmap); 4330 4331 i = isl_basic_map_alloc_inequality(bmap); 4332 if (i < 0) 4333 return -1; 4334 isl_seq_neg(bmap->ineq[i], div + 1, 1 + total); 4335 isl_int_set(bmap->ineq[i][1 + pos], div[0]); 4336 isl_int_add(bmap->ineq[i][0], bmap->ineq[i][0], bmap->ineq[i][1 + pos]); 4337 isl_int_sub_ui(bmap->ineq[i][0], bmap->ineq[i][0], 1); 4338 4339 return 0; 4340} 4341 4342/* For a div d = floor(f/m), add the constraints 4343 * 4344 * f - m d >= 0 4345 * -(f-(n-1)) + m d >= 0 4346 * 4347 * Note that the second constraint is the negation of 4348 * 4349 * f - m d >= n 4350 */ 4351int isl_basic_map_add_div_constraints_var(__isl_keep isl_basic_map *bmap, 4352 unsigned pos, isl_int *div) 4353{ 4354 if (add_upper_div_constraint(bmap, pos, div) < 0) 4355 return -1; 4356 if (add_lower_div_constraint(bmap, pos, div) < 0) 4357 return -1; 4358 return 0; 4359} 4360 4361int isl_basic_set_add_div_constraints_var(__isl_keep isl_basic_set *bset, 4362 unsigned pos, isl_int *div) 4363{ 4364 return isl_basic_map_add_div_constraints_var((isl_basic_map *)bset, 4365 pos, div); 4366} 4367 4368int isl_basic_map_add_div_constraints(struct isl_basic_map *bmap, unsigned div) 4369{ 4370 unsigned total = isl_basic_map_total_dim(bmap); 4371 unsigned div_pos = total - bmap->n_div + div; 4372 4373 return isl_basic_map_add_div_constraints_var(bmap, div_pos, 4374 bmap->div[div]); 4375} 4376 4377/* Add the div constraint of sign "sign" for div "div" of "bmap". 4378 * 4379 * In particular, if this div is of the form d = floor(f/m), 4380 * then add the constraint 4381 * 4382 * f - m d >= 0 4383 * 4384 * if sign < 0 or the constraint 4385 * 4386 * -(f-(n-1)) + m d >= 0 4387 * 4388 * if sign > 0. 4389 */ 4390int isl_basic_map_add_div_constraint(__isl_keep isl_basic_map *bmap, 4391 unsigned div, int sign) 4392{ 4393 unsigned total; 4394 unsigned div_pos; 4395 4396 if (!bmap) 4397 return -1; 4398 4399 total = isl_basic_map_total_dim(bmap); 4400 div_pos = total - bmap->n_div + div; 4401 4402 if (sign < 0) 4403 return add_upper_div_constraint(bmap, div_pos, bmap->div[div]); 4404 else 4405 return add_lower_div_constraint(bmap, div_pos, bmap->div[div]); 4406} 4407 4408int isl_basic_set_add_div_constraints(struct isl_basic_set *bset, unsigned div) 4409{ 4410 return isl_basic_map_add_div_constraints(bset, div); 4411} 4412 4413struct isl_basic_set *isl_basic_map_underlying_set( 4414 struct isl_basic_map *bmap) 4415{ 4416 if (!bmap) 4417 goto error; 4418 if (bmap->dim->nparam == 0 && bmap->dim->n_in == 0 && 4419 bmap->n_div == 0 && 4420 !isl_space_is_named_or_nested(bmap->dim, isl_dim_in) && 4421 !isl_space_is_named_or_nested(bmap->dim, isl_dim_out)) 4422 return (struct isl_basic_set *)bmap; 4423 bmap = isl_basic_map_cow(bmap); 4424 if (!bmap) 4425 goto error; 4426 bmap->dim = isl_space_underlying(bmap->dim, bmap->n_div); 4427 if (!bmap->dim) 4428 goto error; 4429 bmap->extra -= bmap->n_div; 4430 bmap->n_div = 0; 4431 bmap = isl_basic_map_finalize(bmap); 4432 return (struct isl_basic_set *)bmap; 4433error: 4434 isl_basic_map_free(bmap); 4435 return NULL; 4436} 4437 4438__isl_give isl_basic_set *isl_basic_set_underlying_set( 4439 __isl_take isl_basic_set *bset) 4440{ 4441 return isl_basic_map_underlying_set((isl_basic_map *)bset); 4442} 4443 4444struct isl_basic_map *isl_basic_map_overlying_set( 4445 struct isl_basic_set *bset, struct isl_basic_map *like) 4446{ 4447 struct isl_basic_map *bmap; 4448 struct isl_ctx *ctx; 4449 unsigned total; 4450 int i; 4451 4452 if (!bset || !like) 4453 goto error; 4454 ctx = bset->ctx; 4455 isl_assert(ctx, bset->n_div == 0, goto error); 4456 isl_assert(ctx, isl_basic_set_n_param(bset) == 0, goto error); 4457 isl_assert(ctx, bset->dim->n_out == isl_basic_map_total_dim(like), 4458 goto error); 4459 if (isl_space_is_equal(bset->dim, like->dim) && like->n_div == 0) { 4460 isl_basic_map_free(like); 4461 return (struct isl_basic_map *)bset; 4462 } 4463 bset = isl_basic_set_cow(bset); 4464 if (!bset) 4465 goto error; 4466 total = bset->dim->n_out + bset->extra; 4467 bmap = (struct isl_basic_map *)bset; 4468 isl_space_free(bmap->dim); 4469 bmap->dim = isl_space_copy(like->dim); 4470 if (!bmap->dim) 4471 goto error; 4472 bmap->n_div = like->n_div; 4473 bmap->extra += like->n_div; 4474 if (bmap->extra) { 4475 unsigned ltotal; 4476 isl_int **div; 4477 ltotal = total - bmap->extra + like->extra; 4478 if (ltotal > total) 4479 ltotal = total; 4480 bmap->block2 = isl_blk_extend(ctx, bmap->block2, 4481 bmap->extra * (1 + 1 + total)); 4482 if (isl_blk_is_error(bmap->block2)) 4483 goto error; 4484 div = isl_realloc_array(ctx, bmap->div, isl_int *, bmap->extra); 4485 if (!div) 4486 goto error; 4487 bmap->div = div; 4488 for (i = 0; i < bmap->extra; ++i) 4489 bmap->div[i] = bmap->block2.data + i * (1 + 1 + total); 4490 for (i = 0; i < like->n_div; ++i) { 4491 isl_seq_cpy(bmap->div[i], like->div[i], 1 + 1 + ltotal); 4492 isl_seq_clr(bmap->div[i]+1+1+ltotal, total - ltotal); 4493 } 4494 bmap = isl_basic_map_extend_constraints(bmap, 4495 0, 2 * like->n_div); 4496 for (i = 0; i < like->n_div; ++i) { 4497 if (!bmap) 4498 break; 4499 if (isl_int_is_zero(bmap->div[i][0])) 4500 continue; 4501 if (isl_basic_map_add_div_constraints(bmap, i) < 0) 4502 bmap = isl_basic_map_free(bmap); 4503 } 4504 } 4505 isl_basic_map_free(like); 4506 bmap = isl_basic_map_simplify(bmap); 4507 bmap = isl_basic_map_finalize(bmap); 4508 return bmap; 4509error: 4510 isl_basic_map_free(like); 4511 isl_basic_set_free(bset); 4512 return NULL; 4513} 4514 4515struct isl_basic_set *isl_basic_set_from_underlying_set( 4516 struct isl_basic_set *bset, struct isl_basic_set *like) 4517{ 4518 return (struct isl_basic_set *) 4519 isl_basic_map_overlying_set(bset, (struct isl_basic_map *)like); 4520} 4521 4522struct isl_set *isl_set_from_underlying_set( 4523 struct isl_set *set, struct isl_basic_set *like) 4524{ 4525 int i; 4526 4527 if (!set || !like) 4528 goto error; 4529 isl_assert(set->ctx, set->dim->n_out == isl_basic_set_total_dim(like), 4530 goto error); 4531 if (isl_space_is_equal(set->dim, like->dim) && like->n_div == 0) { 4532 isl_basic_set_free(like); 4533 return set; 4534 } 4535 set = isl_set_cow(set); 4536 if (!set) 4537 goto error; 4538 for (i = 0; i < set->n; ++i) { 4539 set->p[i] = isl_basic_set_from_underlying_set(set->p[i], 4540 isl_basic_set_copy(like)); 4541 if (!set->p[i]) 4542 goto error; 4543 } 4544 isl_space_free(set->dim); 4545 set->dim = isl_space_copy(like->dim); 4546 if (!set->dim) 4547 goto error; 4548 isl_basic_set_free(like); 4549 return set; 4550error: 4551 isl_basic_set_free(like); 4552 isl_set_free(set); 4553 return NULL; 4554} 4555 4556struct isl_set *isl_map_underlying_set(struct isl_map *map) 4557{ 4558 int i; 4559 4560 map = isl_map_cow(map); 4561 if (!map) 4562 return NULL; 4563 map->dim = isl_space_cow(map->dim); 4564 if (!map->dim) 4565 goto error; 4566 4567 for (i = 1; i < map->n; ++i) 4568 isl_assert(map->ctx, map->p[0]->n_div == map->p[i]->n_div, 4569 goto error); 4570 for (i = 0; i < map->n; ++i) { 4571 map->p[i] = (struct isl_basic_map *) 4572 isl_basic_map_underlying_set(map->p[i]); 4573 if (!map->p[i]) 4574 goto error; 4575 } 4576 if (map->n == 0) 4577 map->dim = isl_space_underlying(map->dim, 0); 4578 else { 4579 isl_space_free(map->dim); 4580 map->dim = isl_space_copy(map->p[0]->dim); 4581 } 4582 if (!map->dim) 4583 goto error; 4584 return (struct isl_set *)map; 4585error: 4586 isl_map_free(map); 4587 return NULL; 4588} 4589 4590struct isl_set *isl_set_to_underlying_set(struct isl_set *set) 4591{ 4592 return (struct isl_set *)isl_map_underlying_set((struct isl_map *)set); 4593} 4594 4595__isl_give isl_basic_map *isl_basic_map_reset_space( 4596 __isl_take isl_basic_map *bmap, __isl_take isl_space *dim) 4597{ 4598 bmap = isl_basic_map_cow(bmap); 4599 if (!bmap || !dim) 4600 goto error; 4601 4602 isl_space_free(bmap->dim); 4603 bmap->dim = dim; 4604 4605 bmap = isl_basic_map_finalize(bmap); 4606 4607 return bmap; 4608error: 4609 isl_basic_map_free(bmap); 4610 isl_space_free(dim); 4611 return NULL; 4612} 4613 4614__isl_give isl_basic_set *isl_basic_set_reset_space( 4615 __isl_take isl_basic_set *bset, __isl_take isl_space *dim) 4616{ 4617 return (isl_basic_set *)isl_basic_map_reset_space((isl_basic_map *)bset, 4618 dim); 4619} 4620 4621__isl_give isl_map *isl_map_reset_space(__isl_take isl_map *map, 4622 __isl_take isl_space *dim) 4623{ 4624 int i; 4625 4626 map = isl_map_cow(map); 4627 if (!map || !dim) 4628 goto error; 4629 4630 for (i = 0; i < map->n; ++i) { 4631 map->p[i] = isl_basic_map_reset_space(map->p[i], 4632 isl_space_copy(dim)); 4633 if (!map->p[i]) 4634 goto error; 4635 } 4636 isl_space_free(map->dim); 4637 map->dim = dim; 4638 4639 return map; 4640error: 4641 isl_map_free(map); 4642 isl_space_free(dim); 4643 return NULL; 4644} 4645 4646__isl_give isl_set *isl_set_reset_space(__isl_take isl_set *set, 4647 __isl_take isl_space *dim) 4648{ 4649 return (struct isl_set *) isl_map_reset_space((struct isl_map *)set, dim); 4650} 4651 4652/* Compute the parameter domain of the given basic set. 4653 */ 4654__isl_give isl_basic_set *isl_basic_set_params(__isl_take isl_basic_set *bset) 4655{ 4656 isl_space *space; 4657 unsigned n; 4658 4659 if (isl_basic_set_is_params(bset)) 4660 return bset; 4661 4662 n = isl_basic_set_dim(bset, isl_dim_set); 4663 bset = isl_basic_set_project_out(bset, isl_dim_set, 0, n); 4664 space = isl_basic_set_get_space(bset); 4665 space = isl_space_params(space); 4666 bset = isl_basic_set_reset_space(bset, space); 4667 return bset; 4668} 4669 4670/* Construct a zero-dimensional basic set with the given parameter domain. 4671 */ 4672__isl_give isl_basic_set *isl_basic_set_from_params( 4673 __isl_take isl_basic_set *bset) 4674{ 4675 isl_space *space; 4676 space = isl_basic_set_get_space(bset); 4677 space = isl_space_set_from_params(space); 4678 bset = isl_basic_set_reset_space(bset, space); 4679 return bset; 4680} 4681 4682/* Compute the parameter domain of the given set. 4683 */ 4684__isl_give isl_set *isl_set_params(__isl_take isl_set *set) 4685{ 4686 isl_space *space; 4687 unsigned n; 4688 4689 if (isl_set_is_params(set)) 4690 return set; 4691 4692 n = isl_set_dim(set, isl_dim_set); 4693 set = isl_set_project_out(set, isl_dim_set, 0, n); 4694 space = isl_set_get_space(set); 4695 space = isl_space_params(space); 4696 set = isl_set_reset_space(set, space); 4697 return set; 4698} 4699 4700/* Construct a zero-dimensional set with the given parameter domain. 4701 */ 4702__isl_give isl_set *isl_set_from_params(__isl_take isl_set *set) 4703{ 4704 isl_space *space; 4705 space = isl_set_get_space(set); 4706 space = isl_space_set_from_params(space); 4707 set = isl_set_reset_space(set, space); 4708 return set; 4709} 4710 4711/* Compute the parameter domain of the given map. 4712 */ 4713__isl_give isl_set *isl_map_params(__isl_take isl_map *map) 4714{ 4715 isl_space *space; 4716 unsigned n; 4717 4718 n = isl_map_dim(map, isl_dim_in); 4719 map = isl_map_project_out(map, isl_dim_in, 0, n); 4720 n = isl_map_dim(map, isl_dim_out); 4721 map = isl_map_project_out(map, isl_dim_out, 0, n); 4722 space = isl_map_get_space(map); 4723 space = isl_space_params(space); 4724 map = isl_map_reset_space(map, space); 4725 return map; 4726} 4727 4728struct isl_basic_set *isl_basic_map_domain(struct isl_basic_map *bmap) 4729{ 4730 isl_space *dim; 4731 struct isl_basic_set *domain; 4732 unsigned n_in; 4733 unsigned n_out; 4734 4735 if (!bmap) 4736 return NULL; 4737 dim = isl_space_domain(isl_basic_map_get_space(bmap)); 4738 4739 n_in = isl_basic_map_n_in(bmap); 4740 n_out = isl_basic_map_n_out(bmap); 4741 domain = isl_basic_set_from_basic_map(bmap); 4742 domain = isl_basic_set_project_out(domain, isl_dim_set, n_in, n_out); 4743 4744 domain = isl_basic_set_reset_space(domain, dim); 4745 4746 return domain; 4747} 4748 4749int isl_basic_map_may_be_set(__isl_keep isl_basic_map *bmap) 4750{ 4751 if (!bmap) 4752 return -1; 4753 return isl_space_may_be_set(bmap->dim); 4754} 4755 4756/* Is this basic map actually a set? 4757 * Users should never call this function. Outside of isl, 4758 * the type should indicate whether something is a set or a map. 4759 */ 4760int isl_basic_map_is_set(__isl_keep isl_basic_map *bmap) 4761{ 4762 if (!bmap) 4763 return -1; 4764 return isl_space_is_set(bmap->dim); 4765} 4766 4767struct isl_basic_set *isl_basic_map_range(struct isl_basic_map *bmap) 4768{ 4769 if (!bmap) 4770 return NULL; 4771 if (isl_basic_map_is_set(bmap)) 4772 return bmap; 4773 return isl_basic_map_domain(isl_basic_map_reverse(bmap)); 4774} 4775 4776__isl_give isl_basic_map *isl_basic_map_domain_map( 4777 __isl_take isl_basic_map *bmap) 4778{ 4779 int i, k; 4780 isl_space *dim; 4781 isl_basic_map *domain; 4782 int nparam, n_in, n_out; 4783 unsigned total; 4784 4785 nparam = isl_basic_map_dim(bmap, isl_dim_param); 4786 n_in = isl_basic_map_dim(bmap, isl_dim_in); 4787 n_out = isl_basic_map_dim(bmap, isl_dim_out); 4788 4789 dim = isl_space_from_range(isl_space_domain(isl_basic_map_get_space(bmap))); 4790 domain = isl_basic_map_universe(dim); 4791 4792 bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap)); 4793 bmap = isl_basic_map_apply_range(bmap, domain); 4794 bmap = isl_basic_map_extend_constraints(bmap, n_in, 0); 4795 4796 total = isl_basic_map_total_dim(bmap); 4797 4798 for (i = 0; i < n_in; ++i) { 4799 k = isl_basic_map_alloc_equality(bmap); 4800 if (k < 0) 4801 goto error; 4802 isl_seq_clr(bmap->eq[k], 1 + total); 4803 isl_int_set_si(bmap->eq[k][1 + nparam + i], -1); 4804 isl_int_set_si(bmap->eq[k][1 + nparam + n_in + n_out + i], 1); 4805 } 4806 4807 bmap = isl_basic_map_gauss(bmap, NULL); 4808 return isl_basic_map_finalize(bmap); 4809error: 4810 isl_basic_map_free(bmap); 4811 return NULL; 4812} 4813 4814__isl_give isl_basic_map *isl_basic_map_range_map( 4815 __isl_take isl_basic_map *bmap) 4816{ 4817 int i, k; 4818 isl_space *dim; 4819 isl_basic_map *range; 4820 int nparam, n_in, n_out; 4821 unsigned total; 4822 4823 nparam = isl_basic_map_dim(bmap, isl_dim_param); 4824 n_in = isl_basic_map_dim(bmap, isl_dim_in); 4825 n_out = isl_basic_map_dim(bmap, isl_dim_out); 4826 4827 dim = isl_space_from_range(isl_space_range(isl_basic_map_get_space(bmap))); 4828 range = isl_basic_map_universe(dim); 4829 4830 bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap)); 4831 bmap = isl_basic_map_apply_range(bmap, range); 4832 bmap = isl_basic_map_extend_constraints(bmap, n_out, 0); 4833 4834 total = isl_basic_map_total_dim(bmap); 4835 4836 for (i = 0; i < n_out; ++i) { 4837 k = isl_basic_map_alloc_equality(bmap); 4838 if (k < 0) 4839 goto error; 4840 isl_seq_clr(bmap->eq[k], 1 + total); 4841 isl_int_set_si(bmap->eq[k][1 + nparam + n_in + i], -1); 4842 isl_int_set_si(bmap->eq[k][1 + nparam + n_in + n_out + i], 1); 4843 } 4844 4845 bmap = isl_basic_map_gauss(bmap, NULL); 4846 return isl_basic_map_finalize(bmap); 4847error: 4848 isl_basic_map_free(bmap); 4849 return NULL; 4850} 4851 4852int isl_map_may_be_set(__isl_keep isl_map *map) 4853{ 4854 if (!map) 4855 return -1; 4856 return isl_space_may_be_set(map->dim); 4857} 4858 4859/* Is this map actually a set? 4860 * Users should never call this function. Outside of isl, 4861 * the type should indicate whether something is a set or a map. 4862 */ 4863int isl_map_is_set(__isl_keep isl_map *map) 4864{ 4865 if (!map) 4866 return -1; 4867 return isl_space_is_set(map->dim); 4868} 4869 4870struct isl_set *isl_map_range(struct isl_map *map) 4871{ 4872 int i; 4873 struct isl_set *set; 4874 4875 if (!map) 4876 goto error; 4877 if (isl_map_is_set(map)) 4878 return (isl_set *)map; 4879 4880 map = isl_map_cow(map); 4881 if (!map) 4882 goto error; 4883 4884 set = (struct isl_set *) map; 4885 set->dim = isl_space_range(set->dim); 4886 if (!set->dim) 4887 goto error; 4888 for (i = 0; i < map->n; ++i) { 4889 set->p[i] = isl_basic_map_range(map->p[i]); 4890 if (!set->p[i]) 4891 goto error; 4892 } 4893 ISL_F_CLR(set, ISL_MAP_DISJOINT); 4894 ISL_F_CLR(set, ISL_SET_NORMALIZED); 4895 return set; 4896error: 4897 isl_map_free(map); 4898 return NULL; 4899} 4900 4901__isl_give isl_map *isl_map_domain_map(__isl_take isl_map *map) 4902{ 4903 int i; 4904 isl_space *domain_dim; 4905 4906 map = isl_map_cow(map); 4907 if (!map) 4908 return NULL; 4909 4910 domain_dim = isl_space_from_range(isl_space_domain(isl_map_get_space(map))); 4911 map->dim = isl_space_from_domain(isl_space_wrap(map->dim)); 4912 map->dim = isl_space_join(map->dim, domain_dim); 4913 if (!map->dim) 4914 goto error; 4915 for (i = 0; i < map->n; ++i) { 4916 map->p[i] = isl_basic_map_domain_map(map->p[i]); 4917 if (!map->p[i]) 4918 goto error; 4919 } 4920 ISL_F_CLR(map, ISL_MAP_DISJOINT); 4921 ISL_F_CLR(map, ISL_MAP_NORMALIZED); 4922 return map; 4923error: 4924 isl_map_free(map); 4925 return NULL; 4926} 4927 4928__isl_give isl_map *isl_map_range_map(__isl_take isl_map *map) 4929{ 4930 int i; 4931 isl_space *range_dim; 4932 4933 map = isl_map_cow(map); 4934 if (!map) 4935 return NULL; 4936 4937 range_dim = isl_space_range(isl_map_get_space(map)); 4938 range_dim = isl_space_from_range(range_dim); 4939 map->dim = isl_space_from_domain(isl_space_wrap(map->dim)); 4940 map->dim = isl_space_join(map->dim, range_dim); 4941 if (!map->dim) 4942 goto error; 4943 for (i = 0; i < map->n; ++i) { 4944 map->p[i] = isl_basic_map_range_map(map->p[i]); 4945 if (!map->p[i]) 4946 goto error; 4947 } 4948 ISL_F_CLR(map, ISL_MAP_DISJOINT); 4949 ISL_F_CLR(map, ISL_MAP_NORMALIZED); 4950 return map; 4951error: 4952 isl_map_free(map); 4953 return NULL; 4954} 4955 4956__isl_give isl_map *isl_map_from_set(__isl_take isl_set *set, 4957 __isl_take isl_space *dim) 4958{ 4959 int i; 4960 struct isl_map *map = NULL; 4961 4962 set = isl_set_cow(set); 4963 if (!set || !dim) 4964 goto error; 4965 isl_assert(set->ctx, isl_space_compatible(set->dim, dim), goto error); 4966 map = (struct isl_map *)set; 4967 for (i = 0; i < set->n; ++i) { 4968 map->p[i] = isl_basic_map_from_basic_set( 4969 set->p[i], isl_space_copy(dim)); 4970 if (!map->p[i]) 4971 goto error; 4972 } 4973 isl_space_free(map->dim); 4974 map->dim = dim; 4975 return map; 4976error: 4977 isl_space_free(dim); 4978 isl_set_free(set); 4979 return NULL; 4980} 4981 4982__isl_give isl_basic_map *isl_basic_map_from_domain( 4983 __isl_take isl_basic_set *bset) 4984{ 4985 return isl_basic_map_reverse(isl_basic_map_from_range(bset)); 4986} 4987 4988__isl_give isl_basic_map *isl_basic_map_from_range( 4989 __isl_take isl_basic_set *bset) 4990{ 4991 isl_space *space; 4992 space = isl_basic_set_get_space(bset); 4993 space = isl_space_from_range(space); 4994 bset = isl_basic_set_reset_space(bset, space); 4995 return (isl_basic_map *)bset; 4996} 4997 4998struct isl_map *isl_map_from_range(struct isl_set *set) 4999{ 5000 isl_space *space; 5001 space = isl_set_get_space(set); 5002 space = isl_space_from_range(space); 5003 set = isl_set_reset_space(set, space); 5004 return (struct isl_map *)set; 5005} 5006 5007__isl_give isl_map *isl_map_from_domain(__isl_take isl_set *set) 5008{ 5009 return isl_map_reverse(isl_map_from_range(set)); 5010} 5011 5012__isl_give isl_basic_map *isl_basic_map_from_domain_and_range( 5013 __isl_take isl_basic_set *domain, __isl_take isl_basic_set *range) 5014{ 5015 return isl_basic_map_apply_range(isl_basic_map_reverse(domain), range); 5016} 5017 5018__isl_give isl_map *isl_map_from_domain_and_range(__isl_take isl_set *domain, 5019 __isl_take isl_set *range) 5020{ 5021 return isl_map_apply_range(isl_map_reverse(domain), range); 5022} 5023 5024struct isl_set *isl_set_from_map(struct isl_map *map) 5025{ 5026 int i; 5027 struct isl_set *set = NULL; 5028 5029 if (!map) 5030 return NULL; 5031 map = isl_map_cow(map); 5032 if (!map) 5033 return NULL; 5034 map->dim = isl_space_as_set_space(map->dim); 5035 if (!map->dim) 5036 goto error; 5037 set = (struct isl_set *)map; 5038 for (i = 0; i < map->n; ++i) { 5039 set->p[i] = isl_basic_set_from_basic_map(map->p[i]); 5040 if (!set->p[i]) 5041 goto error; 5042 } 5043 return set; 5044error: 5045 isl_map_free(map); 5046 return NULL; 5047} 5048 5049__isl_give isl_map *isl_map_alloc_space(__isl_take isl_space *dim, int n, 5050 unsigned flags) 5051{ 5052 struct isl_map *map; 5053 5054 if (!dim) 5055 return NULL; 5056 if (n < 0) 5057 isl_die(dim->ctx, isl_error_internal, 5058 "negative number of basic maps", goto error); 5059 map = isl_alloc(dim->ctx, struct isl_map, 5060 sizeof(struct isl_map) + 5061 (n - 1) * sizeof(struct isl_basic_map *)); 5062 if (!map) 5063 goto error; 5064 5065 map->ctx = dim->ctx; 5066 isl_ctx_ref(map->ctx); 5067 map->ref = 1; 5068 map->size = n; 5069 map->n = 0; 5070 map->dim = dim; 5071 map->flags = flags; 5072 return map; 5073error: 5074 isl_space_free(dim); 5075 return NULL; 5076} 5077 5078struct isl_map *isl_map_alloc(struct isl_ctx *ctx, 5079 unsigned nparam, unsigned in, unsigned out, int n, 5080 unsigned flags) 5081{ 5082 struct isl_map *map; 5083 isl_space *dims; 5084 5085 dims = isl_space_alloc(ctx, nparam, in, out); 5086 if (!dims) 5087 return NULL; 5088 5089 map = isl_map_alloc_space(dims, n, flags); 5090 return map; 5091} 5092 5093__isl_give isl_basic_map *isl_basic_map_empty(__isl_take isl_space *dim) 5094{ 5095 struct isl_basic_map *bmap; 5096 bmap = isl_basic_map_alloc_space(dim, 0, 1, 0); 5097 bmap = isl_basic_map_set_to_empty(bmap); 5098 return bmap; 5099} 5100 5101__isl_give isl_basic_set *isl_basic_set_empty(__isl_take isl_space *dim) 5102{ 5103 struct isl_basic_set *bset; 5104 bset = isl_basic_set_alloc_space(dim, 0, 1, 0); 5105 bset = isl_basic_set_set_to_empty(bset); 5106 return bset; 5107} 5108 5109struct isl_basic_map *isl_basic_map_empty_like(struct isl_basic_map *model) 5110{ 5111 struct isl_basic_map *bmap; 5112 if (!model) 5113 return NULL; 5114 bmap = isl_basic_map_alloc_space(isl_space_copy(model->dim), 0, 1, 0); 5115 bmap = isl_basic_map_set_to_empty(bmap); 5116 return bmap; 5117} 5118 5119struct isl_basic_map *isl_basic_map_empty_like_map(struct isl_map *model) 5120{ 5121 struct isl_basic_map *bmap; 5122 if (!model) 5123 return NULL; 5124 bmap = isl_basic_map_alloc_space(isl_space_copy(model->dim), 0, 1, 0); 5125 bmap = isl_basic_map_set_to_empty(bmap); 5126 return bmap; 5127} 5128 5129struct isl_basic_set *isl_basic_set_empty_like(struct isl_basic_set *model) 5130{ 5131 struct isl_basic_set *bset; 5132 if (!model) 5133 return NULL; 5134 bset = isl_basic_set_alloc_space(isl_space_copy(model->dim), 0, 1, 0); 5135 bset = isl_basic_set_set_to_empty(bset); 5136 return bset; 5137} 5138 5139__isl_give isl_basic_map *isl_basic_map_universe(__isl_take isl_space *dim) 5140{ 5141 struct isl_basic_map *bmap; 5142 bmap = isl_basic_map_alloc_space(dim, 0, 0, 0); 5143 bmap = isl_basic_map_finalize(bmap); 5144 return bmap; 5145} 5146 5147__isl_give isl_basic_set *isl_basic_set_universe(__isl_take isl_space *dim) 5148{ 5149 struct isl_basic_set *bset; 5150 bset = isl_basic_set_alloc_space(dim, 0, 0, 0); 5151 bset = isl_basic_set_finalize(bset); 5152 return bset; 5153} 5154 5155__isl_give isl_basic_map *isl_basic_map_nat_universe(__isl_take isl_space *dim) 5156{ 5157 int i; 5158 unsigned total = isl_space_dim(dim, isl_dim_all); 5159 isl_basic_map *bmap; 5160 5161 bmap= isl_basic_map_alloc_space(dim, 0, 0, total); 5162 for (i = 0; i < total; ++i) { 5163 int k = isl_basic_map_alloc_inequality(bmap); 5164 if (k < 0) 5165 goto error; 5166 isl_seq_clr(bmap->ineq[k], 1 + total); 5167 isl_int_set_si(bmap->ineq[k][1 + i], 1); 5168 } 5169 return bmap; 5170error: 5171 isl_basic_map_free(bmap); 5172 return NULL; 5173} 5174 5175__isl_give isl_basic_set *isl_basic_set_nat_universe(__isl_take isl_space *dim) 5176{ 5177 return isl_basic_map_nat_universe(dim); 5178} 5179 5180__isl_give isl_map *isl_map_nat_universe(__isl_take isl_space *dim) 5181{ 5182 return isl_map_from_basic_map(isl_basic_map_nat_universe(dim)); 5183} 5184 5185__isl_give isl_set *isl_set_nat_universe(__isl_take isl_space *dim) 5186{ 5187 return isl_map_nat_universe(dim); 5188} 5189 5190__isl_give isl_basic_map *isl_basic_map_universe_like( 5191 __isl_keep isl_basic_map *model) 5192{ 5193 if (!model) 5194 return NULL; 5195 return isl_basic_map_alloc_space(isl_space_copy(model->dim), 0, 0, 0); 5196} 5197 5198struct isl_basic_set *isl_basic_set_universe_like(struct isl_basic_set *model) 5199{ 5200 if (!model) 5201 return NULL; 5202 return isl_basic_set_alloc_space(isl_space_copy(model->dim), 0, 0, 0); 5203} 5204 5205__isl_give isl_basic_set *isl_basic_set_universe_like_set( 5206 __isl_keep isl_set *model) 5207{ 5208 if (!model) 5209 return NULL; 5210 return isl_basic_set_alloc_space(isl_space_copy(model->dim), 0, 0, 0); 5211} 5212 5213__isl_give isl_map *isl_map_empty(__isl_take isl_space *dim) 5214{ 5215 return isl_map_alloc_space(dim, 0, ISL_MAP_DISJOINT); 5216} 5217 5218struct isl_map *isl_map_empty_like(struct isl_map *model) 5219{ 5220 if (!model) 5221 return NULL; 5222 return isl_map_alloc_space(isl_space_copy(model->dim), 0, ISL_MAP_DISJOINT); 5223} 5224 5225struct isl_map *isl_map_empty_like_basic_map(struct isl_basic_map *model) 5226{ 5227 if (!model) 5228 return NULL; 5229 return isl_map_alloc_space(isl_space_copy(model->dim), 0, ISL_MAP_DISJOINT); 5230} 5231 5232__isl_give isl_set *isl_set_empty(__isl_take isl_space *dim) 5233{ 5234 return isl_set_alloc_space(dim, 0, ISL_MAP_DISJOINT); 5235} 5236 5237struct isl_set *isl_set_empty_like(struct isl_set *model) 5238{ 5239 if (!model) 5240 return NULL; 5241 return isl_set_empty(isl_space_copy(model->dim)); 5242} 5243 5244__isl_give isl_map *isl_map_universe(__isl_take isl_space *dim) 5245{ 5246 struct isl_map *map; 5247 if (!dim) 5248 return NULL; 5249 map = isl_map_alloc_space(isl_space_copy(dim), 1, ISL_MAP_DISJOINT); 5250 map = isl_map_add_basic_map(map, isl_basic_map_universe(dim)); 5251 return map; 5252} 5253 5254__isl_give isl_set *isl_set_universe(__isl_take isl_space *dim) 5255{ 5256 struct isl_set *set; 5257 if (!dim) 5258 return NULL; 5259 set = isl_set_alloc_space(isl_space_copy(dim), 1, ISL_MAP_DISJOINT); 5260 set = isl_set_add_basic_set(set, isl_basic_set_universe(dim)); 5261 return set; 5262} 5263 5264__isl_give isl_set *isl_set_universe_like(__isl_keep isl_set *model) 5265{ 5266 if (!model) 5267 return NULL; 5268 return isl_set_universe(isl_space_copy(model->dim)); 5269} 5270 5271struct isl_map *isl_map_dup(struct isl_map *map) 5272{ 5273 int i; 5274 struct isl_map *dup; 5275 5276 if (!map) 5277 return NULL; 5278 dup = isl_map_alloc_space(isl_space_copy(map->dim), map->n, map->flags); 5279 for (i = 0; i < map->n; ++i) 5280 dup = isl_map_add_basic_map(dup, isl_basic_map_copy(map->p[i])); 5281 return dup; 5282} 5283 5284__isl_give isl_map *isl_map_add_basic_map(__isl_take isl_map *map, 5285 __isl_take isl_basic_map *bmap) 5286{ 5287 if (!bmap || !map) 5288 goto error; 5289 if (isl_basic_map_plain_is_empty(bmap)) { 5290 isl_basic_map_free(bmap); 5291 return map; 5292 } 5293 isl_assert(map->ctx, isl_space_is_equal(map->dim, bmap->dim), goto error); 5294 isl_assert(map->ctx, map->n < map->size, goto error); 5295 map->p[map->n] = bmap; 5296 map->n++; 5297 ISL_F_CLR(map, ISL_MAP_NORMALIZED); 5298 return map; 5299error: 5300 if (map) 5301 isl_map_free(map); 5302 if (bmap) 5303 isl_basic_map_free(bmap); 5304 return NULL; 5305} 5306 5307void *isl_map_free(struct isl_map *map) 5308{ 5309 int i; 5310 5311 if (!map) 5312 return NULL; 5313 5314 if (--map->ref > 0) 5315 return NULL; 5316 5317 isl_ctx_deref(map->ctx); 5318 for (i = 0; i < map->n; ++i) 5319 isl_basic_map_free(map->p[i]); 5320 isl_space_free(map->dim); 5321 free(map); 5322 5323 return NULL; 5324} 5325 5326struct isl_map *isl_map_extend(struct isl_map *base, 5327 unsigned nparam, unsigned n_in, unsigned n_out) 5328{ 5329 int i; 5330 5331 base = isl_map_cow(base); 5332 if (!base) 5333 return NULL; 5334 5335 base->dim = isl_space_extend(base->dim, nparam, n_in, n_out); 5336 if (!base->dim) 5337 goto error; 5338 for (i = 0; i < base->n; ++i) { 5339 base->p[i] = isl_basic_map_extend_space(base->p[i], 5340 isl_space_copy(base->dim), 0, 0, 0); 5341 if (!base->p[i]) 5342 goto error; 5343 } 5344 return base; 5345error: 5346 isl_map_free(base); 5347 return NULL; 5348} 5349 5350struct isl_set *isl_set_extend(struct isl_set *base, 5351 unsigned nparam, unsigned dim) 5352{ 5353 return (struct isl_set *)isl_map_extend((struct isl_map *)base, 5354 nparam, 0, dim); 5355} 5356 5357static struct isl_basic_map *isl_basic_map_fix_pos_si( 5358 struct isl_basic_map *bmap, unsigned pos, int value) 5359{ 5360 int j; 5361 5362 bmap = isl_basic_map_cow(bmap); 5363 bmap = isl_basic_map_extend_constraints(bmap, 1, 0); 5364 j = isl_basic_map_alloc_equality(bmap); 5365 if (j < 0) 5366 goto error; 5367 isl_seq_clr(bmap->eq[j] + 1, isl_basic_map_total_dim(bmap)); 5368 isl_int_set_si(bmap->eq[j][pos], -1); 5369 isl_int_set_si(bmap->eq[j][0], value); 5370 bmap = isl_basic_map_simplify(bmap); 5371 return isl_basic_map_finalize(bmap); 5372error: 5373 isl_basic_map_free(bmap); 5374 return NULL; 5375} 5376 5377static __isl_give isl_basic_map *isl_basic_map_fix_pos( 5378 __isl_take isl_basic_map *bmap, unsigned pos, isl_int value) 5379{ 5380 int j; 5381 5382 bmap = isl_basic_map_cow(bmap); 5383 bmap = isl_basic_map_extend_constraints(bmap, 1, 0); 5384 j = isl_basic_map_alloc_equality(bmap); 5385 if (j < 0) 5386 goto error; 5387 isl_seq_clr(bmap->eq[j] + 1, isl_basic_map_total_dim(bmap)); 5388 isl_int_set_si(bmap->eq[j][pos], -1); 5389 isl_int_set(bmap->eq[j][0], value); 5390 bmap = isl_basic_map_simplify(bmap); 5391 return isl_basic_map_finalize(bmap); 5392error: 5393 isl_basic_map_free(bmap); 5394 return NULL; 5395} 5396 5397struct isl_basic_map *isl_basic_map_fix_si(struct isl_basic_map *bmap, 5398 enum isl_dim_type type, unsigned pos, int value) 5399{ 5400 if (!bmap) 5401 return NULL; 5402 isl_assert(bmap->ctx, pos < isl_basic_map_dim(bmap, type), goto error); 5403 return isl_basic_map_fix_pos_si(bmap, 5404 isl_basic_map_offset(bmap, type) + pos, value); 5405error: 5406 isl_basic_map_free(bmap); 5407 return NULL; 5408} 5409 5410__isl_give isl_basic_map *isl_basic_map_fix(__isl_take isl_basic_map *bmap, 5411 enum isl_dim_type type, unsigned pos, isl_int value) 5412{ 5413 if (!bmap) 5414 return NULL; 5415 isl_assert(bmap->ctx, pos < isl_basic_map_dim(bmap, type), goto error); 5416 return isl_basic_map_fix_pos(bmap, 5417 isl_basic_map_offset(bmap, type) + pos, value); 5418error: 5419 isl_basic_map_free(bmap); 5420 return NULL; 5421} 5422 5423/* Fix the value of the variable at position "pos" of type "type" of "bmap" 5424 * to be equal to "v". 5425 */ 5426__isl_give isl_basic_map *isl_basic_map_fix_val(__isl_take isl_basic_map *bmap, 5427 enum isl_dim_type type, unsigned pos, __isl_take isl_val *v) 5428{ 5429 if (!bmap || !v) 5430 goto error; 5431 if (!isl_val_is_int(v)) 5432 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid, 5433 "expecting integer value", goto error); 5434 if (pos >= isl_basic_map_dim(bmap, type)) 5435 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid, 5436 "index out of bounds", goto error); 5437 pos += isl_basic_map_offset(bmap, type); 5438 bmap = isl_basic_map_fix_pos(bmap, pos, v->n); 5439 isl_val_free(v); 5440 return bmap; 5441error: 5442 isl_basic_map_free(bmap); 5443 isl_val_free(v); 5444 return NULL; 5445} 5446 5447/* Fix the value of the variable at position "pos" of type "type" of "bset" 5448 * to be equal to "v". 5449 */ 5450__isl_give isl_basic_set *isl_basic_set_fix_val(__isl_take isl_basic_set *bset, 5451 enum isl_dim_type type, unsigned pos, __isl_take isl_val *v) 5452{ 5453 return isl_basic_map_fix_val(bset, type, pos, v); 5454} 5455 5456struct isl_basic_set *isl_basic_set_fix_si(struct isl_basic_set *bset, 5457 enum isl_dim_type type, unsigned pos, int value) 5458{ 5459 return (struct isl_basic_set *) 5460 isl_basic_map_fix_si((struct isl_basic_map *)bset, 5461 type, pos, value); 5462} 5463 5464__isl_give isl_basic_set *isl_basic_set_fix(__isl_take isl_basic_set *bset, 5465 enum isl_dim_type type, unsigned pos, isl_int value) 5466{ 5467 return (struct isl_basic_set *) 5468 isl_basic_map_fix((struct isl_basic_map *)bset, 5469 type, pos, value); 5470} 5471 5472struct isl_basic_map *isl_basic_map_fix_input_si(struct isl_basic_map *bmap, 5473 unsigned input, int value) 5474{ 5475 return isl_basic_map_fix_si(bmap, isl_dim_in, input, value); 5476} 5477 5478struct isl_basic_set *isl_basic_set_fix_dim_si(struct isl_basic_set *bset, 5479 unsigned dim, int value) 5480{ 5481 return (struct isl_basic_set *) 5482 isl_basic_map_fix_si((struct isl_basic_map *)bset, 5483 isl_dim_set, dim, value); 5484} 5485 5486static int remove_if_empty(__isl_keep isl_map *map, int i) 5487{ 5488 int empty = isl_basic_map_plain_is_empty(map->p[i]); 5489 5490 if (empty < 0) 5491 return -1; 5492 if (!empty) 5493 return 0; 5494 5495 isl_basic_map_free(map->p[i]); 5496 if (i != map->n - 1) { 5497 ISL_F_CLR(map, ISL_MAP_NORMALIZED); 5498 map->p[i] = map->p[map->n - 1]; 5499 } 5500 map->n--; 5501 5502 return 0; 5503} 5504 5505/* Perform "fn" on each basic map of "map", where we may not be holding 5506 * the only reference to "map". 5507 * In particular, "fn" should be a semantics preserving operation 5508 * that we want to apply to all copies of "map". We therefore need 5509 * to be careful not to modify "map" in a way that breaks "map" 5510 * in case anything goes wrong. 5511 */ 5512__isl_give isl_map *isl_map_inline_foreach_basic_map(__isl_take isl_map *map, 5513 __isl_give isl_basic_map *(*fn)(__isl_take isl_basic_map *bmap)) 5514{ 5515 struct isl_basic_map *bmap; 5516 int i; 5517 5518 if (!map) 5519 return NULL; 5520 5521 for (i = map->n - 1; i >= 0; --i) { 5522 bmap = isl_basic_map_copy(map->p[i]); 5523 bmap = fn(bmap); 5524 if (!bmap) 5525 goto error; 5526 isl_basic_map_free(map->p[i]); 5527 map->p[i] = bmap; 5528 if (remove_if_empty(map, i) < 0) 5529 goto error; 5530 } 5531 5532 return map; 5533error: 5534 isl_map_free(map); 5535 return NULL; 5536} 5537 5538struct isl_map *isl_map_fix_si(struct isl_map *map, 5539 enum isl_dim_type type, unsigned pos, int value) 5540{ 5541 int i; 5542 5543 map = isl_map_cow(map); 5544 if (!map) 5545 return NULL; 5546 5547 isl_assert(map->ctx, pos < isl_map_dim(map, type), goto error); 5548 for (i = map->n - 1; i >= 0; --i) { 5549 map->p[i] = isl_basic_map_fix_si(map->p[i], type, pos, value); 5550 if (remove_if_empty(map, i) < 0) 5551 goto error; 5552 } 5553 ISL_F_CLR(map, ISL_MAP_NORMALIZED); 5554 return map; 5555error: 5556 isl_map_free(map); 5557 return NULL; 5558} 5559 5560__isl_give isl_set *isl_set_fix_si(__isl_take isl_set *set, 5561 enum isl_dim_type type, unsigned pos, int value) 5562{ 5563 return (struct isl_set *) 5564 isl_map_fix_si((struct isl_map *)set, type, pos, value); 5565} 5566 5567__isl_give isl_map *isl_map_fix(__isl_take isl_map *map, 5568 enum isl_dim_type type, unsigned pos, isl_int value) 5569{ 5570 int i; 5571 5572 map = isl_map_cow(map); 5573 if (!map) 5574 return NULL; 5575 5576 isl_assert(map->ctx, pos < isl_map_dim(map, type), goto error); 5577 for (i = 0; i < map->n; ++i) { 5578 map->p[i] = isl_basic_map_fix(map->p[i], type, pos, value); 5579 if (!map->p[i]) 5580 goto error; 5581 } 5582 ISL_F_CLR(map, ISL_MAP_NORMALIZED); 5583 return map; 5584error: 5585 isl_map_free(map); 5586 return NULL; 5587} 5588 5589__isl_give isl_set *isl_set_fix(__isl_take isl_set *set, 5590 enum isl_dim_type type, unsigned pos, isl_int value) 5591{ 5592 return (struct isl_set *)isl_map_fix((isl_map *)set, type, pos, value); 5593} 5594 5595/* Fix the value of the variable at position "pos" of type "type" of "map" 5596 * to be equal to "v". 5597 */ 5598__isl_give isl_map *isl_map_fix_val(__isl_take isl_map *map, 5599 enum isl_dim_type type, unsigned pos, __isl_take isl_val *v) 5600{ 5601 int i; 5602 5603 map = isl_map_cow(map); 5604 if (!map || !v) 5605 goto error; 5606 5607 if (!isl_val_is_int(v)) 5608 isl_die(isl_map_get_ctx(map), isl_error_invalid, 5609 "expecting integer value", goto error); 5610 if (pos >= isl_map_dim(map, type)) 5611 isl_die(isl_map_get_ctx(map), isl_error_invalid, 5612 "index out of bounds", goto error); 5613 for (i = map->n - 1; i >= 0; --i) { 5614 map->p[i] = isl_basic_map_fix_val(map->p[i], type, pos, 5615 isl_val_copy(v)); 5616 if (remove_if_empty(map, i) < 0) 5617 goto error; 5618 } 5619 ISL_F_CLR(map, ISL_MAP_NORMALIZED); 5620 isl_val_free(v); 5621 return map; 5622error: 5623 isl_map_free(map); 5624 isl_val_free(v); 5625 return NULL; 5626} 5627 5628/* Fix the value of the variable at position "pos" of type "type" of "set" 5629 * to be equal to "v". 5630 */ 5631__isl_give isl_set *isl_set_fix_val(__isl_take isl_set *set, 5632 enum isl_dim_type type, unsigned pos, __isl_take isl_val *v) 5633{ 5634 return isl_map_fix_val(set, type, pos, v); 5635} 5636 5637struct isl_map *isl_map_fix_input_si(struct isl_map *map, 5638 unsigned input, int value) 5639{ 5640 return isl_map_fix_si(map, isl_dim_in, input, value); 5641} 5642 5643struct isl_set *isl_set_fix_dim_si(struct isl_set *set, unsigned dim, int value) 5644{ 5645 return (struct isl_set *) 5646 isl_map_fix_si((struct isl_map *)set, isl_dim_set, dim, value); 5647} 5648 5649static __isl_give isl_basic_map *basic_map_bound_si( 5650 __isl_take isl_basic_map *bmap, 5651 enum isl_dim_type type, unsigned pos, int value, int upper) 5652{ 5653 int j; 5654 5655 if (!bmap) 5656 return NULL; 5657 isl_assert(bmap->ctx, pos < isl_basic_map_dim(bmap, type), goto error); 5658 pos += isl_basic_map_offset(bmap, type); 5659 bmap = isl_basic_map_cow(bmap); 5660 bmap = isl_basic_map_extend_constraints(bmap, 0, 1); 5661 j = isl_basic_map_alloc_inequality(bmap); 5662 if (j < 0) 5663 goto error; 5664 isl_seq_clr(bmap->ineq[j], 1 + isl_basic_map_total_dim(bmap)); 5665 if (upper) { 5666 isl_int_set_si(bmap->ineq[j][pos], -1); 5667 isl_int_set_si(bmap->ineq[j][0], value); 5668 } else { 5669 isl_int_set_si(bmap->ineq[j][pos], 1); 5670 isl_int_set_si(bmap->ineq[j][0], -value); 5671 } 5672 bmap = isl_basic_map_simplify(bmap); 5673 return isl_basic_map_finalize(bmap); 5674error: 5675 isl_basic_map_free(bmap); 5676 return NULL; 5677} 5678 5679__isl_give isl_basic_map *isl_basic_map_lower_bound_si( 5680 __isl_take isl_basic_map *bmap, 5681 enum isl_dim_type type, unsigned pos, int value) 5682{ 5683 return basic_map_bound_si(bmap, type, pos, value, 0); 5684} 5685 5686/* Constrain the values of the given dimension to be no greater than "value". 5687 */ 5688__isl_give isl_basic_map *isl_basic_map_upper_bound_si( 5689 __isl_take isl_basic_map *bmap, 5690 enum isl_dim_type type, unsigned pos, int value) 5691{ 5692 return basic_map_bound_si(bmap, type, pos, value, 1); 5693} 5694 5695struct isl_basic_set *isl_basic_set_lower_bound_dim(struct isl_basic_set *bset, 5696 unsigned dim, isl_int value) 5697{ 5698 int j; 5699 5700 bset = isl_basic_set_cow(bset); 5701 bset = isl_basic_set_extend_constraints(bset, 0, 1); 5702 j = isl_basic_set_alloc_inequality(bset); 5703 if (j < 0) 5704 goto error; 5705 isl_seq_clr(bset->ineq[j], 1 + isl_basic_set_total_dim(bset)); 5706 isl_int_set_si(bset->ineq[j][1 + isl_basic_set_n_param(bset) + dim], 1); 5707 isl_int_neg(bset->ineq[j][0], value); 5708 bset = isl_basic_set_simplify(bset); 5709 return isl_basic_set_finalize(bset); 5710error: 5711 isl_basic_set_free(bset); 5712 return NULL; 5713} 5714 5715static __isl_give isl_map *map_bound_si(__isl_take isl_map *map, 5716 enum isl_dim_type type, unsigned pos, int value, int upper) 5717{ 5718 int i; 5719 5720 map = isl_map_cow(map); 5721 if (!map) 5722 return NULL; 5723 5724 isl_assert(map->ctx, pos < isl_map_dim(map, type), goto error); 5725 for (i = 0; i < map->n; ++i) { 5726 map->p[i] = basic_map_bound_si(map->p[i], 5727 type, pos, value, upper); 5728 if (!map->p[i]) 5729 goto error; 5730 } 5731 ISL_F_CLR(map, ISL_MAP_NORMALIZED); 5732 return map; 5733error: 5734 isl_map_free(map); 5735 return NULL; 5736} 5737 5738__isl_give isl_map *isl_map_lower_bound_si(__isl_take isl_map *map, 5739 enum isl_dim_type type, unsigned pos, int value) 5740{ 5741 return map_bound_si(map, type, pos, value, 0); 5742} 5743 5744__isl_give isl_map *isl_map_upper_bound_si(__isl_take isl_map *map, 5745 enum isl_dim_type type, unsigned pos, int value) 5746{ 5747 return map_bound_si(map, type, pos, value, 1); 5748} 5749 5750__isl_give isl_set *isl_set_lower_bound_si(__isl_take isl_set *set, 5751 enum isl_dim_type type, unsigned pos, int value) 5752{ 5753 return (struct isl_set *) 5754 isl_map_lower_bound_si((struct isl_map *)set, type, pos, value); 5755} 5756 5757__isl_give isl_set *isl_set_upper_bound_si(__isl_take isl_set *set, 5758 enum isl_dim_type type, unsigned pos, int value) 5759{ 5760 return isl_map_upper_bound_si(set, type, pos, value); 5761} 5762 5763/* Bound the given variable of "bmap" from below (or above is "upper" 5764 * is set) to "value". 5765 */ 5766static __isl_give isl_basic_map *basic_map_bound( 5767 __isl_take isl_basic_map *bmap, 5768 enum isl_dim_type type, unsigned pos, isl_int value, int upper) 5769{ 5770 int j; 5771 5772 if (!bmap) 5773 return NULL; 5774 if (pos >= isl_basic_map_dim(bmap, type)) 5775 isl_die(bmap->ctx, isl_error_invalid, 5776 "index out of bounds", goto error); 5777 pos += isl_basic_map_offset(bmap, type); 5778 bmap = isl_basic_map_cow(bmap); 5779 bmap = isl_basic_map_extend_constraints(bmap, 0, 1); 5780 j = isl_basic_map_alloc_inequality(bmap); 5781 if (j < 0) 5782 goto error; 5783 isl_seq_clr(bmap->ineq[j], 1 + isl_basic_map_total_dim(bmap)); 5784 if (upper) { 5785 isl_int_set_si(bmap->ineq[j][pos], -1); 5786 isl_int_set(bmap->ineq[j][0], value); 5787 } else { 5788 isl_int_set_si(bmap->ineq[j][pos], 1); 5789 isl_int_neg(bmap->ineq[j][0], value); 5790 } 5791 bmap = isl_basic_map_simplify(bmap); 5792 return isl_basic_map_finalize(bmap); 5793error: 5794 isl_basic_map_free(bmap); 5795 return NULL; 5796} 5797 5798/* Bound the given variable of "map" from below (or above is "upper" 5799 * is set) to "value". 5800 */ 5801static __isl_give isl_map *map_bound(__isl_take isl_map *map, 5802 enum isl_dim_type type, unsigned pos, isl_int value, int upper) 5803{ 5804 int i; 5805 5806 map = isl_map_cow(map); 5807 if (!map) 5808 return NULL; 5809 5810 if (pos >= isl_map_dim(map, type)) 5811 isl_die(map->ctx, isl_error_invalid, 5812 "index out of bounds", goto error); 5813 for (i = map->n - 1; i >= 0; --i) { 5814 map->p[i] = basic_map_bound(map->p[i], type, pos, value, upper); 5815 if (remove_if_empty(map, i) < 0) 5816 goto error; 5817 } 5818 ISL_F_CLR(map, ISL_MAP_NORMALIZED); 5819 return map; 5820error: 5821 isl_map_free(map); 5822 return NULL; 5823} 5824 5825__isl_give isl_map *isl_map_lower_bound(__isl_take isl_map *map, 5826 enum isl_dim_type type, unsigned pos, isl_int value) 5827{ 5828 return map_bound(map, type, pos, value, 0); 5829} 5830 5831__isl_give isl_map *isl_map_upper_bound(__isl_take isl_map *map, 5832 enum isl_dim_type type, unsigned pos, isl_int value) 5833{ 5834 return map_bound(map, type, pos, value, 1); 5835} 5836 5837__isl_give isl_set *isl_set_lower_bound(__isl_take isl_set *set, 5838 enum isl_dim_type type, unsigned pos, isl_int value) 5839{ 5840 return isl_map_lower_bound(set, type, pos, value); 5841} 5842 5843__isl_give isl_set *isl_set_upper_bound(__isl_take isl_set *set, 5844 enum isl_dim_type type, unsigned pos, isl_int value) 5845{ 5846 return isl_map_upper_bound(set, type, pos, value); 5847} 5848 5849/* Force the values of the variable at position "pos" of type "type" of "set" 5850 * to be no smaller than "value". 5851 */ 5852__isl_give isl_set *isl_set_lower_bound_val(__isl_take isl_set *set, 5853 enum isl_dim_type type, unsigned pos, __isl_take isl_val *value) 5854{ 5855 if (!value) 5856 goto error; 5857 if (!isl_val_is_int(value)) 5858 isl_die(isl_set_get_ctx(set), isl_error_invalid, 5859 "expecting integer value", goto error); 5860 set = isl_set_lower_bound(set, type, pos, value->n); 5861 isl_val_free(value); 5862 return set; 5863error: 5864 isl_val_free(value); 5865 isl_set_free(set); 5866 return NULL; 5867} 5868 5869/* Force the values of the variable at position "pos" of type "type" of "set" 5870 * to be no greater than "value". 5871 */ 5872__isl_give isl_set *isl_set_upper_bound_val(__isl_take isl_set *set, 5873 enum isl_dim_type type, unsigned pos, __isl_take isl_val *value) 5874{ 5875 if (!value) 5876 goto error; 5877 if (!isl_val_is_int(value)) 5878 isl_die(isl_set_get_ctx(set), isl_error_invalid, 5879 "expecting integer value", goto error); 5880 set = isl_set_upper_bound(set, type, pos, value->n); 5881 isl_val_free(value); 5882 return set; 5883error: 5884 isl_val_free(value); 5885 isl_set_free(set); 5886 return NULL; 5887} 5888 5889struct isl_set *isl_set_lower_bound_dim(struct isl_set *set, unsigned dim, 5890 isl_int value) 5891{ 5892 int i; 5893 5894 set = isl_set_cow(set); 5895 if (!set) 5896 return NULL; 5897 5898 isl_assert(set->ctx, dim < isl_set_n_dim(set), goto error); 5899 for (i = 0; i < set->n; ++i) { 5900 set->p[i] = isl_basic_set_lower_bound_dim(set->p[i], dim, value); 5901 if (!set->p[i]) 5902 goto error; 5903 } 5904 return set; 5905error: 5906 isl_set_free(set); 5907 return NULL; 5908} 5909 5910struct isl_map *isl_map_reverse(struct isl_map *map) 5911{ 5912 int i; 5913 5914 map = isl_map_cow(map); 5915 if (!map) 5916 return NULL; 5917 5918 map->dim = isl_space_reverse(map->dim); 5919 if (!map->dim) 5920 goto error; 5921 for (i = 0; i < map->n; ++i) { 5922 map->p[i] = isl_basic_map_reverse(map->p[i]); 5923 if (!map->p[i]) 5924 goto error; 5925 } 5926 ISL_F_CLR(map, ISL_MAP_NORMALIZED); 5927 return map; 5928error: 5929 isl_map_free(map); 5930 return NULL; 5931} 5932 5933static struct isl_map *isl_basic_map_partial_lexopt( 5934 struct isl_basic_map *bmap, struct isl_basic_set *dom, 5935 struct isl_set **empty, int max) 5936{ 5937 if (!bmap) 5938 goto error; 5939 if (bmap->ctx->opt->pip == ISL_PIP_PIP) 5940 return isl_pip_basic_map_lexopt(bmap, dom, empty, max); 5941 else 5942 return isl_tab_basic_map_partial_lexopt(bmap, dom, empty, max); 5943error: 5944 isl_basic_map_free(bmap); 5945 isl_basic_set_free(dom); 5946 if (empty) 5947 *empty = NULL; 5948 return NULL; 5949} 5950 5951struct isl_map *isl_basic_map_partial_lexmax( 5952 struct isl_basic_map *bmap, struct isl_basic_set *dom, 5953 struct isl_set **empty) 5954{ 5955 return isl_basic_map_partial_lexopt(bmap, dom, empty, 1); 5956} 5957 5958struct isl_map *isl_basic_map_partial_lexmin( 5959 struct isl_basic_map *bmap, struct isl_basic_set *dom, 5960 struct isl_set **empty) 5961{ 5962 return isl_basic_map_partial_lexopt(bmap, dom, empty, 0); 5963} 5964 5965struct isl_set *isl_basic_set_partial_lexmin( 5966 struct isl_basic_set *bset, struct isl_basic_set *dom, 5967 struct isl_set **empty) 5968{ 5969 return (struct isl_set *) 5970 isl_basic_map_partial_lexmin((struct isl_basic_map *)bset, 5971 dom, empty); 5972} 5973 5974struct isl_set *isl_basic_set_partial_lexmax( 5975 struct isl_basic_set *bset, struct isl_basic_set *dom, 5976 struct isl_set **empty) 5977{ 5978 return (struct isl_set *) 5979 isl_basic_map_partial_lexmax((struct isl_basic_map *)bset, 5980 dom, empty); 5981} 5982 5983__isl_give isl_pw_multi_aff *isl_basic_map_partial_lexmin_pw_multi_aff( 5984 __isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom, 5985 __isl_give isl_set **empty) 5986{ 5987 return isl_basic_map_partial_lexopt_pw_multi_aff(bmap, dom, empty, 0); 5988} 5989 5990__isl_give isl_pw_multi_aff *isl_basic_map_partial_lexmax_pw_multi_aff( 5991 __isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom, 5992 __isl_give isl_set **empty) 5993{ 5994 return isl_basic_map_partial_lexopt_pw_multi_aff(bmap, dom, empty, 1); 5995} 5996 5997__isl_give isl_pw_multi_aff *isl_basic_set_partial_lexmin_pw_multi_aff( 5998 __isl_take isl_basic_set *bset, __isl_take isl_basic_set *dom, 5999 __isl_give isl_set **empty) 6000{ 6001 return isl_basic_map_partial_lexmin_pw_multi_aff(bset, dom, empty); 6002} 6003 6004__isl_give isl_pw_multi_aff *isl_basic_set_partial_lexmax_pw_multi_aff( 6005 __isl_take isl_basic_set *bset, __isl_take isl_basic_set *dom, 6006 __isl_give isl_set **empty) 6007{ 6008 return isl_basic_map_partial_lexmax_pw_multi_aff(bset, dom, empty); 6009} 6010 6011__isl_give isl_pw_multi_aff *isl_basic_map_lexopt_pw_multi_aff( 6012 __isl_take isl_basic_map *bmap, int max) 6013{ 6014 isl_basic_set *dom = NULL; 6015 isl_space *dom_space; 6016 6017 if (!bmap) 6018 goto error; 6019 dom_space = isl_space_domain(isl_space_copy(bmap->dim)); 6020 dom = isl_basic_set_universe(dom_space); 6021 return isl_basic_map_partial_lexopt_pw_multi_aff(bmap, dom, NULL, max); 6022error: 6023 isl_basic_map_free(bmap); 6024 return NULL; 6025} 6026 6027__isl_give isl_pw_multi_aff *isl_basic_map_lexmin_pw_multi_aff( 6028 __isl_take isl_basic_map *bmap) 6029{ 6030 return isl_basic_map_lexopt_pw_multi_aff(bmap, 0); 6031} 6032 6033#undef TYPE 6034#define TYPE isl_pw_multi_aff 6035#undef SUFFIX 6036#define SUFFIX _pw_multi_aff 6037#undef EMPTY 6038#define EMPTY isl_pw_multi_aff_empty 6039#undef ADD 6040#define ADD isl_pw_multi_aff_union_add 6041#include "isl_map_lexopt_templ.c" 6042 6043/* Given a map "map", compute the lexicographically minimal 6044 * (or maximal) image element for each domain element in dom, 6045 * in the form of an isl_pw_multi_aff. 6046 * Set *empty to those elements in dom that do not have an image element. 6047 * 6048 * We first compute the lexicographically minimal or maximal element 6049 * in the first basic map. This results in a partial solution "res" 6050 * and a subset "todo" of dom that still need to be handled. 6051 * We then consider each of the remaining maps in "map" and successively 6052 * update both "res" and "todo". 6053 */ 6054static __isl_give isl_pw_multi_aff *isl_map_partial_lexopt_aligned_pw_multi_aff( 6055 __isl_take isl_map *map, __isl_take isl_set *dom, 6056 __isl_give isl_set **empty, int max) 6057{ 6058 int i; 6059 isl_pw_multi_aff *res; 6060 isl_set *todo; 6061 6062 if (!map || !dom) 6063 goto error; 6064 6065 if (isl_map_plain_is_empty(map)) { 6066 if (empty) 6067 *empty = dom; 6068 else 6069 isl_set_free(dom); 6070 return isl_pw_multi_aff_from_map(map); 6071 } 6072 6073 res = basic_map_partial_lexopt_pw_multi_aff( 6074 isl_basic_map_copy(map->p[0]), 6075 isl_set_copy(dom), &todo, max); 6076 6077 for (i = 1; i < map->n; ++i) { 6078 isl_pw_multi_aff *res_i; 6079 isl_set *todo_i; 6080 6081 res_i = basic_map_partial_lexopt_pw_multi_aff( 6082 isl_basic_map_copy(map->p[i]), 6083 isl_set_copy(dom), &todo_i, max); 6084 6085 if (max) 6086 res = isl_pw_multi_aff_union_lexmax(res, res_i); 6087 else 6088 res = isl_pw_multi_aff_union_lexmin(res, res_i); 6089 6090 todo = isl_set_intersect(todo, todo_i); 6091 } 6092 6093 isl_set_free(dom); 6094 isl_map_free(map); 6095 6096 if (empty) 6097 *empty = todo; 6098 else 6099 isl_set_free(todo); 6100 6101 return res; 6102error: 6103 if (empty) 6104 *empty = NULL; 6105 isl_set_free(dom); 6106 isl_map_free(map); 6107 return NULL; 6108} 6109 6110#undef TYPE 6111#define TYPE isl_map 6112#undef SUFFIX 6113#define SUFFIX 6114#undef EMPTY 6115#define EMPTY isl_map_empty 6116#undef ADD 6117#define ADD isl_map_union_disjoint 6118#include "isl_map_lexopt_templ.c" 6119 6120/* Given a map "map", compute the lexicographically minimal 6121 * (or maximal) image element for each domain element in dom. 6122 * Set *empty to those elements in dom that do not have an image element. 6123 * 6124 * We first compute the lexicographically minimal or maximal element 6125 * in the first basic map. This results in a partial solution "res" 6126 * and a subset "todo" of dom that still need to be handled. 6127 * We then consider each of the remaining maps in "map" and successively 6128 * update both "res" and "todo". 6129 * 6130 * Let res^k and todo^k be the results after k steps and let i = k + 1. 6131 * Assume we are computing the lexicographical maximum. 6132 * We first compute the lexicographically maximal element in basic map i. 6133 * This results in a partial solution res_i and a subset todo_i. 6134 * Then we combine these results with those obtain for the first k basic maps 6135 * to obtain a result that is valid for the first k+1 basic maps. 6136 * In particular, the set where there is no solution is the set where 6137 * there is no solution for the first k basic maps and also no solution 6138 * for the ith basic map, i.e., 6139 * 6140 * todo^i = todo^k * todo_i 6141 * 6142 * On dom(res^k) * dom(res_i), we need to pick the larger of the two 6143 * solutions, arbitrarily breaking ties in favor of res^k. 6144 * That is, when res^k(a) >= res_i(a), we pick res^k and 6145 * when res^k(a) < res_i(a), we pick res_i. (Here, ">=" and "<" denote 6146 * the lexicographic order.) 6147 * In practice, we compute 6148 * 6149 * res^k * (res_i . "<=") 6150 * 6151 * and 6152 * 6153 * res_i * (res^k . "<") 6154 * 6155 * Finally, we consider the symmetric difference of dom(res^k) and dom(res_i), 6156 * where only one of res^k and res_i provides a solution and we simply pick 6157 * that one, i.e., 6158 * 6159 * res^k * todo_i 6160 * and 6161 * res_i * todo^k 6162 * 6163 * Note that we only compute these intersections when dom(res^k) intersects 6164 * dom(res_i). Otherwise, the only effect of these intersections is to 6165 * potentially break up res^k and res_i into smaller pieces. 6166 * We want to avoid such splintering as much as possible. 6167 * In fact, an earlier implementation of this function would look for 6168 * better results in the domain of res^k and for extra results in todo^k, 6169 * but this would always result in a splintering according to todo^k, 6170 * even when the domain of basic map i is disjoint from the domains of 6171 * the previous basic maps. 6172 */ 6173static __isl_give isl_map *isl_map_partial_lexopt_aligned( 6174 __isl_take isl_map *map, __isl_take isl_set *dom, 6175 __isl_give isl_set **empty, int max) 6176{ 6177 int i; 6178 struct isl_map *res; 6179 struct isl_set *todo; 6180 6181 if (!map || !dom) 6182 goto error; 6183 6184 if (isl_map_plain_is_empty(map)) { 6185 if (empty) 6186 *empty = dom; 6187 else 6188 isl_set_free(dom); 6189 return map; 6190 } 6191 6192 res = basic_map_partial_lexopt(isl_basic_map_copy(map->p[0]), 6193 isl_set_copy(dom), &todo, max); 6194 6195 for (i = 1; i < map->n; ++i) { 6196 isl_map *lt, *le; 6197 isl_map *res_i; 6198 isl_set *todo_i; 6199 isl_space *dim = isl_space_range(isl_map_get_space(res)); 6200 6201 res_i = basic_map_partial_lexopt(isl_basic_map_copy(map->p[i]), 6202 isl_set_copy(dom), &todo_i, max); 6203 6204 if (max) { 6205 lt = isl_map_lex_lt(isl_space_copy(dim)); 6206 le = isl_map_lex_le(dim); 6207 } else { 6208 lt = isl_map_lex_gt(isl_space_copy(dim)); 6209 le = isl_map_lex_ge(dim); 6210 } 6211 lt = isl_map_apply_range(isl_map_copy(res), lt); 6212 lt = isl_map_intersect(lt, isl_map_copy(res_i)); 6213 le = isl_map_apply_range(isl_map_copy(res_i), le); 6214 le = isl_map_intersect(le, isl_map_copy(res)); 6215 6216 if (!isl_map_is_empty(lt) || !isl_map_is_empty(le)) { 6217 res = isl_map_intersect_domain(res, 6218 isl_set_copy(todo_i)); 6219 res_i = isl_map_intersect_domain(res_i, 6220 isl_set_copy(todo)); 6221 } 6222 6223 res = isl_map_union_disjoint(res, res_i); 6224 res = isl_map_union_disjoint(res, lt); 6225 res = isl_map_union_disjoint(res, le); 6226 6227 todo = isl_set_intersect(todo, todo_i); 6228 } 6229 6230 isl_set_free(dom); 6231 isl_map_free(map); 6232 6233 if (empty) 6234 *empty = todo; 6235 else 6236 isl_set_free(todo); 6237 6238 return res; 6239error: 6240 if (empty) 6241 *empty = NULL; 6242 isl_set_free(dom); 6243 isl_map_free(map); 6244 return NULL; 6245} 6246 6247__isl_give isl_map *isl_map_partial_lexmax( 6248 __isl_take isl_map *map, __isl_take isl_set *dom, 6249 __isl_give isl_set **empty) 6250{ 6251 return isl_map_partial_lexopt(map, dom, empty, 1); 6252} 6253 6254__isl_give isl_map *isl_map_partial_lexmin( 6255 __isl_take isl_map *map, __isl_take isl_set *dom, 6256 __isl_give isl_set **empty) 6257{ 6258 return isl_map_partial_lexopt(map, dom, empty, 0); 6259} 6260 6261__isl_give isl_set *isl_set_partial_lexmin( 6262 __isl_take isl_set *set, __isl_take isl_set *dom, 6263 __isl_give isl_set **empty) 6264{ 6265 return (struct isl_set *) 6266 isl_map_partial_lexmin((struct isl_map *)set, 6267 dom, empty); 6268} 6269 6270__isl_give isl_set *isl_set_partial_lexmax( 6271 __isl_take isl_set *set, __isl_take isl_set *dom, 6272 __isl_give isl_set **empty) 6273{ 6274 return (struct isl_set *) 6275 isl_map_partial_lexmax((struct isl_map *)set, 6276 dom, empty); 6277} 6278 6279/* Compute the lexicographic minimum (or maximum if "max" is set) 6280 * of "bmap" over its domain. 6281 * 6282 * Since we are not interested in the part of the domain space where 6283 * there is no solution, we initialize the domain to those constraints 6284 * of "bmap" that only involve the parameters and the input dimensions. 6285 * This relieves the parametric programming engine from detecting those 6286 * inequalities and transferring them to the context. More importantly, 6287 * it ensures that those inequalities are transferred first and not 6288 * intermixed with inequalities that actually split the domain. 6289 */ 6290__isl_give isl_map *isl_basic_map_lexopt(__isl_take isl_basic_map *bmap, int max) 6291{ 6292 int n_div; 6293 int n_out; 6294 isl_basic_map *copy; 6295 isl_basic_set *dom; 6296 6297 n_div = isl_basic_map_dim(bmap, isl_dim_div); 6298 n_out = isl_basic_map_dim(bmap, isl_dim_out); 6299 copy = isl_basic_map_copy(bmap); 6300 copy = isl_basic_map_drop_constraints_involving_dims(copy, 6301 isl_dim_div, 0, n_div); 6302 copy = isl_basic_map_drop_constraints_involving_dims(copy, 6303 isl_dim_out, 0, n_out); 6304 dom = isl_basic_map_domain(copy); 6305 return isl_basic_map_partial_lexopt(bmap, dom, NULL, max); 6306} 6307 6308__isl_give isl_map *isl_basic_map_lexmin(__isl_take isl_basic_map *bmap) 6309{ 6310 return isl_basic_map_lexopt(bmap, 0); 6311} 6312 6313__isl_give isl_map *isl_basic_map_lexmax(__isl_take isl_basic_map *bmap) 6314{ 6315 return isl_basic_map_lexopt(bmap, 1); 6316} 6317 6318__isl_give isl_set *isl_basic_set_lexmin(__isl_take isl_basic_set *bset) 6319{ 6320 return (isl_set *)isl_basic_map_lexmin((isl_basic_map *)bset); 6321} 6322 6323__isl_give isl_set *isl_basic_set_lexmax(__isl_take isl_basic_set *bset) 6324{ 6325 return (isl_set *)isl_basic_map_lexmax((isl_basic_map *)bset); 6326} 6327 6328/* Extract the first and only affine expression from list 6329 * and then add it to *pwaff with the given dom. 6330 * This domain is known to be disjoint from other domains 6331 * because of the way isl_basic_map_foreach_lexmax works. 6332 */ 6333static int update_dim_opt(__isl_take isl_basic_set *dom, 6334 __isl_take isl_aff_list *list, void *user) 6335{ 6336 isl_ctx *ctx = isl_basic_set_get_ctx(dom); 6337 isl_aff *aff; 6338 isl_pw_aff **pwaff = user; 6339 isl_pw_aff *pwaff_i; 6340 6341 if (!list) 6342 goto error; 6343 if (isl_aff_list_n_aff(list) != 1) 6344 isl_die(ctx, isl_error_internal, 6345 "expecting single element list", goto error); 6346 6347 aff = isl_aff_list_get_aff(list, 0); 6348 pwaff_i = isl_pw_aff_alloc(isl_set_from_basic_set(dom), aff); 6349 6350 *pwaff = isl_pw_aff_add_disjoint(*pwaff, pwaff_i); 6351 6352 isl_aff_list_free(list); 6353 6354 return 0; 6355error: 6356 isl_basic_set_free(dom); 6357 isl_aff_list_free(list); 6358 return -1; 6359} 6360 6361/* Given a basic map with one output dimension, compute the minimum or 6362 * maximum of that dimension as an isl_pw_aff. 6363 * 6364 * The isl_pw_aff is constructed by having isl_basic_map_foreach_lexopt 6365 * call update_dim_opt on each leaf of the result. 6366 */ 6367static __isl_give isl_pw_aff *basic_map_dim_opt(__isl_keep isl_basic_map *bmap, 6368 int max) 6369{ 6370 isl_space *dim = isl_basic_map_get_space(bmap); 6371 isl_pw_aff *pwaff; 6372 int r; 6373 6374 dim = isl_space_from_domain(isl_space_domain(dim)); 6375 dim = isl_space_add_dims(dim, isl_dim_out, 1); 6376 pwaff = isl_pw_aff_empty(dim); 6377 6378 r = isl_basic_map_foreach_lexopt(bmap, max, &update_dim_opt, &pwaff); 6379 if (r < 0) 6380 return isl_pw_aff_free(pwaff); 6381 6382 return pwaff; 6383} 6384 6385/* Compute the minimum or maximum of the given output dimension 6386 * as a function of the parameters and the input dimensions, 6387 * but independently of the other output dimensions. 6388 * 6389 * We first project out the other output dimension and then compute 6390 * the "lexicographic" maximum in each basic map, combining the results 6391 * using isl_pw_aff_union_max. 6392 */ 6393static __isl_give isl_pw_aff *map_dim_opt(__isl_take isl_map *map, int pos, 6394 int max) 6395{ 6396 int i; 6397 isl_pw_aff *pwaff; 6398 unsigned n_out; 6399 6400 n_out = isl_map_dim(map, isl_dim_out); 6401 map = isl_map_project_out(map, isl_dim_out, pos + 1, n_out - (pos + 1)); 6402 map = isl_map_project_out(map, isl_dim_out, 0, pos); 6403 if (!map) 6404 return NULL; 6405 6406 if (map->n == 0) { 6407 isl_space *dim = isl_map_get_space(map); 6408 dim = isl_space_domain(isl_space_from_range(dim)); 6409 isl_map_free(map); 6410 return isl_pw_aff_empty(dim); 6411 } 6412 6413 pwaff = basic_map_dim_opt(map->p[0], max); 6414 for (i = 1; i < map->n; ++i) { 6415 isl_pw_aff *pwaff_i; 6416 6417 pwaff_i = basic_map_dim_opt(map->p[i], max); 6418 pwaff = isl_pw_aff_union_opt(pwaff, pwaff_i, max); 6419 } 6420 6421 isl_map_free(map); 6422 6423 return pwaff; 6424} 6425 6426/* Compute the maximum of the given output dimension as a function of the 6427 * parameters and input dimensions, but independently of 6428 * the other output dimensions. 6429 */ 6430__isl_give isl_pw_aff *isl_map_dim_max(__isl_take isl_map *map, int pos) 6431{ 6432 return map_dim_opt(map, pos, 1); 6433} 6434 6435/* Compute the minimum or maximum of the given set dimension 6436 * as a function of the parameters, 6437 * but independently of the other set dimensions. 6438 */ 6439static __isl_give isl_pw_aff *set_dim_opt(__isl_take isl_set *set, int pos, 6440 int max) 6441{ 6442 return map_dim_opt(set, pos, max); 6443} 6444 6445/* Compute the maximum of the given set dimension as a function of the 6446 * parameters, but independently of the other set dimensions. 6447 */ 6448__isl_give isl_pw_aff *isl_set_dim_max(__isl_take isl_set *set, int pos) 6449{ 6450 return set_dim_opt(set, pos, 1); 6451} 6452 6453/* Compute the minimum of the given set dimension as a function of the 6454 * parameters, but independently of the other set dimensions. 6455 */ 6456__isl_give isl_pw_aff *isl_set_dim_min(__isl_take isl_set *set, int pos) 6457{ 6458 return set_dim_opt(set, pos, 0); 6459} 6460 6461/* Apply a preimage specified by "mat" on the parameters of "bset". 6462 * bset is assumed to have only parameters and divs. 6463 */ 6464static struct isl_basic_set *basic_set_parameter_preimage( 6465 struct isl_basic_set *bset, struct isl_mat *mat) 6466{ 6467 unsigned nparam; 6468 6469 if (!bset || !mat) 6470 goto error; 6471 6472 bset->dim = isl_space_cow(bset->dim); 6473 if (!bset->dim) 6474 goto error; 6475 6476 nparam = isl_basic_set_dim(bset, isl_dim_param); 6477 6478 isl_assert(bset->ctx, mat->n_row == 1 + nparam, goto error); 6479 6480 bset->dim->nparam = 0; 6481 bset->dim->n_out = nparam; 6482 bset = isl_basic_set_preimage(bset, mat); 6483 if (bset) { 6484 bset->dim->nparam = bset->dim->n_out; 6485 bset->dim->n_out = 0; 6486 } 6487 return bset; 6488error: 6489 isl_mat_free(mat); 6490 isl_basic_set_free(bset); 6491 return NULL; 6492} 6493 6494/* Apply a preimage specified by "mat" on the parameters of "set". 6495 * set is assumed to have only parameters and divs. 6496 */ 6497static struct isl_set *set_parameter_preimage( 6498 struct isl_set *set, struct isl_mat *mat) 6499{ 6500 isl_space *dim = NULL; 6501 unsigned nparam; 6502 6503 if (!set || !mat) 6504 goto error; 6505 6506 dim = isl_space_copy(set->dim); 6507 dim = isl_space_cow(dim); 6508 if (!dim) 6509 goto error; 6510 6511 nparam = isl_set_dim(set, isl_dim_param); 6512 6513 isl_assert(set->ctx, mat->n_row == 1 + nparam, goto error); 6514 6515 dim->nparam = 0; 6516 dim->n_out = nparam; 6517 isl_set_reset_space(set, dim); 6518 set = isl_set_preimage(set, mat); 6519 if (!set) 6520 goto error2; 6521 dim = isl_space_copy(set->dim); 6522 dim = isl_space_cow(dim); 6523 if (!dim) 6524 goto error2; 6525 dim->nparam = dim->n_out; 6526 dim->n_out = 0; 6527 isl_set_reset_space(set, dim); 6528 return set; 6529error: 6530 isl_space_free(dim); 6531 isl_mat_free(mat); 6532error2: 6533 isl_set_free(set); 6534 return NULL; 6535} 6536 6537/* Intersect the basic set "bset" with the affine space specified by the 6538 * equalities in "eq". 6539 */ 6540static struct isl_basic_set *basic_set_append_equalities( 6541 struct isl_basic_set *bset, struct isl_mat *eq) 6542{ 6543 int i, k; 6544 unsigned len; 6545 6546 if (!bset || !eq) 6547 goto error; 6548 6549 bset = isl_basic_set_extend_space(bset, isl_space_copy(bset->dim), 0, 6550 eq->n_row, 0); 6551 if (!bset) 6552 goto error; 6553 6554 len = 1 + isl_space_dim(bset->dim, isl_dim_all) + bset->extra; 6555 for (i = 0; i < eq->n_row; ++i) { 6556 k = isl_basic_set_alloc_equality(bset); 6557 if (k < 0) 6558 goto error; 6559 isl_seq_cpy(bset->eq[k], eq->row[i], eq->n_col); 6560 isl_seq_clr(bset->eq[k] + eq->n_col, len - eq->n_col); 6561 } 6562 isl_mat_free(eq); 6563 6564 bset = isl_basic_set_gauss(bset, NULL); 6565 bset = isl_basic_set_finalize(bset); 6566 6567 return bset; 6568error: 6569 isl_mat_free(eq); 6570 isl_basic_set_free(bset); 6571 return NULL; 6572} 6573 6574/* Intersect the set "set" with the affine space specified by the 6575 * equalities in "eq". 6576 */ 6577static struct isl_set *set_append_equalities(struct isl_set *set, 6578 struct isl_mat *eq) 6579{ 6580 int i; 6581 6582 if (!set || !eq) 6583 goto error; 6584 6585 for (i = 0; i < set->n; ++i) { 6586 set->p[i] = basic_set_append_equalities(set->p[i], 6587 isl_mat_copy(eq)); 6588 if (!set->p[i]) 6589 goto error; 6590 } 6591 isl_mat_free(eq); 6592 return set; 6593error: 6594 isl_mat_free(eq); 6595 isl_set_free(set); 6596 return NULL; 6597} 6598 6599/* Given a basic set "bset" that only involves parameters and existentially 6600 * quantified variables, return the index of the first equality 6601 * that only involves parameters. If there is no such equality then 6602 * return bset->n_eq. 6603 * 6604 * This function assumes that isl_basic_set_gauss has been called on "bset". 6605 */ 6606static int first_parameter_equality(__isl_keep isl_basic_set *bset) 6607{ 6608 int i, j; 6609 unsigned nparam, n_div; 6610 6611 if (!bset) 6612 return -1; 6613 6614 nparam = isl_basic_set_dim(bset, isl_dim_param); 6615 n_div = isl_basic_set_dim(bset, isl_dim_div); 6616 6617 for (i = 0, j = n_div - 1; i < bset->n_eq && j >= 0; --j) { 6618 if (!isl_int_is_zero(bset->eq[i][1 + nparam + j])) 6619 ++i; 6620 } 6621 6622 return i; 6623} 6624 6625/* Compute an explicit representation for the existentially quantified 6626 * variables in "bset" by computing the "minimal value" of the set 6627 * variables. Since there are no set variables, the computation of 6628 * the minimal value essentially computes an explicit representation 6629 * of the non-empty part(s) of "bset". 6630 * 6631 * The input only involves parameters and existentially quantified variables. 6632 * All equalities among parameters have been removed. 6633 * 6634 * Since the existentially quantified variables in the result are in general 6635 * going to be different from those in the input, we first replace 6636 * them by the minimal number of variables based on their equalities. 6637 * This should simplify the parametric integer programming. 6638 */ 6639static __isl_give isl_set *base_compute_divs(__isl_take isl_basic_set *bset) 6640{ 6641 isl_morph *morph1, *morph2; 6642 isl_set *set; 6643 unsigned n; 6644 6645 if (!bset) 6646 return NULL; 6647 if (bset->n_eq == 0) 6648 return isl_basic_set_lexmin(bset); 6649 6650 morph1 = isl_basic_set_parameter_compression(bset); 6651 bset = isl_morph_basic_set(isl_morph_copy(morph1), bset); 6652 bset = isl_basic_set_lift(bset); 6653 morph2 = isl_basic_set_variable_compression(bset, isl_dim_set); 6654 bset = isl_morph_basic_set(morph2, bset); 6655 n = isl_basic_set_dim(bset, isl_dim_set); 6656 bset = isl_basic_set_project_out(bset, isl_dim_set, 0, n); 6657 6658 set = isl_basic_set_lexmin(bset); 6659 6660 set = isl_morph_set(isl_morph_inverse(morph1), set); 6661 6662 return set; 6663} 6664 6665/* Project the given basic set onto its parameter domain, possibly introducing 6666 * new, explicit, existential variables in the constraints. 6667 * The input has parameters and (possibly implicit) existential variables. 6668 * The output has the same parameters, but only 6669 * explicit existentially quantified variables. 6670 * 6671 * The actual projection is performed by pip, but pip doesn't seem 6672 * to like equalities very much, so we first remove the equalities 6673 * among the parameters by performing a variable compression on 6674 * the parameters. Afterward, an inverse transformation is performed 6675 * and the equalities among the parameters are inserted back in. 6676 * 6677 * The variable compression on the parameters may uncover additional 6678 * equalities that were only implicit before. We therefore check 6679 * if there are any new parameter equalities in the result and 6680 * if so recurse. The removal of parameter equalities is required 6681 * for the parameter compression performed by base_compute_divs. 6682 */ 6683static struct isl_set *parameter_compute_divs(struct isl_basic_set *bset) 6684{ 6685 int i; 6686 struct isl_mat *eq; 6687 struct isl_mat *T, *T2; 6688 struct isl_set *set; 6689 unsigned nparam; 6690 6691 bset = isl_basic_set_cow(bset); 6692 if (!bset) 6693 return NULL; 6694 6695 if (bset->n_eq == 0) 6696 return base_compute_divs(bset); 6697 6698 bset = isl_basic_set_gauss(bset, NULL); 6699 if (!bset) 6700 return NULL; 6701 if (isl_basic_set_plain_is_empty(bset)) 6702 return isl_set_from_basic_set(bset); 6703 6704 i = first_parameter_equality(bset); 6705 if (i == bset->n_eq) 6706 return base_compute_divs(bset); 6707 6708 nparam = isl_basic_set_dim(bset, isl_dim_param); 6709 eq = isl_mat_sub_alloc6(bset->ctx, bset->eq, i, bset->n_eq - i, 6710 0, 1 + nparam); 6711 eq = isl_mat_cow(eq); 6712 T = isl_mat_variable_compression(isl_mat_copy(eq), &T2); 6713 if (T && T->n_col == 0) { 6714 isl_mat_free(T); 6715 isl_mat_free(T2); 6716 isl_mat_free(eq); 6717 bset = isl_basic_set_set_to_empty(bset); 6718 return isl_set_from_basic_set(bset); 6719 } 6720 bset = basic_set_parameter_preimage(bset, T); 6721 6722 i = first_parameter_equality(bset); 6723 if (!bset) 6724 set = NULL; 6725 else if (i == bset->n_eq) 6726 set = base_compute_divs(bset); 6727 else 6728 set = parameter_compute_divs(bset); 6729 set = set_parameter_preimage(set, T2); 6730 set = set_append_equalities(set, eq); 6731 return set; 6732} 6733 6734/* Insert the divs from "ls" before those of "bmap". 6735 * 6736 * The number of columns is not changed, which means that the last 6737 * dimensions of "bmap" are being reintepreted as the divs from "ls". 6738 * The caller is responsible for removing the same number of dimensions 6739 * from the space of "bmap". 6740 */ 6741static __isl_give isl_basic_map *insert_divs_from_local_space( 6742 __isl_take isl_basic_map *bmap, __isl_keep isl_local_space *ls) 6743{ 6744 int i; 6745 int n_div; 6746 int old_n_div; 6747 6748 n_div = isl_local_space_dim(ls, isl_dim_div); 6749 if (n_div == 0) 6750 return bmap; 6751 6752 old_n_div = bmap->n_div; 6753 bmap = insert_div_rows(bmap, n_div); 6754 if (!bmap) 6755 return NULL; 6756 6757 for (i = 0; i < n_div; ++i) { 6758 isl_seq_cpy(bmap->div[i], ls->div->row[i], ls->div->n_col); 6759 isl_seq_clr(bmap->div[i] + ls->div->n_col, old_n_div); 6760 } 6761 6762 return bmap; 6763} 6764 6765/* Replace the space of "bmap" by the space and divs of "ls". 6766 * 6767 * If "ls" has any divs, then we simplify the result since we may 6768 * have discovered some additional equalities that could simplify 6769 * the div expressions. 6770 */ 6771static __isl_give isl_basic_map *basic_replace_space_by_local_space( 6772 __isl_take isl_basic_map *bmap, __isl_take isl_local_space *ls) 6773{ 6774 int n_div; 6775 6776 bmap = isl_basic_map_cow(bmap); 6777 if (!bmap || !ls) 6778 goto error; 6779 6780 n_div = isl_local_space_dim(ls, isl_dim_div); 6781 bmap = insert_divs_from_local_space(bmap, ls); 6782 if (!bmap) 6783 goto error; 6784 6785 isl_space_free(bmap->dim); 6786 bmap->dim = isl_local_space_get_space(ls); 6787 if (!bmap->dim) 6788 goto error; 6789 6790 isl_local_space_free(ls); 6791 if (n_div > 0) 6792 bmap = isl_basic_map_simplify(bmap); 6793 bmap = isl_basic_map_finalize(bmap); 6794 return bmap; 6795error: 6796 isl_basic_map_free(bmap); 6797 isl_local_space_free(ls); 6798 return NULL; 6799} 6800 6801/* Replace the space of "map" by the space and divs of "ls". 6802 */ 6803static __isl_give isl_map *replace_space_by_local_space(__isl_take isl_map *map, 6804 __isl_take isl_local_space *ls) 6805{ 6806 int i; 6807 6808 map = isl_map_cow(map); 6809 if (!map || !ls) 6810 goto error; 6811 6812 for (i = 0; i < map->n; ++i) { 6813 map->p[i] = basic_replace_space_by_local_space(map->p[i], 6814 isl_local_space_copy(ls)); 6815 if (!map->p[i]) 6816 goto error; 6817 } 6818 isl_space_free(map->dim); 6819 map->dim = isl_local_space_get_space(ls); 6820 if (!map->dim) 6821 goto error; 6822 6823 isl_local_space_free(ls); 6824 return map; 6825error: 6826 isl_local_space_free(ls); 6827 isl_map_free(map); 6828 return NULL; 6829} 6830 6831/* Compute an explicit representation for the existentially 6832 * quantified variables for which do not know any explicit representation yet. 6833 * 6834 * We first sort the existentially quantified variables so that the 6835 * existentially quantified variables for which we already have an explicit 6836 * representation are placed before those for which we do not. 6837 * The input dimensions, the output dimensions and the existentially 6838 * quantified variables for which we already have an explicit 6839 * representation are then turned into parameters. 6840 * compute_divs returns a map with the same parameters and 6841 * no input or output dimensions and the dimension specification 6842 * is reset to that of the input, including the existentially quantified 6843 * variables for which we already had an explicit representation. 6844 */ 6845static struct isl_map *compute_divs(struct isl_basic_map *bmap) 6846{ 6847 struct isl_basic_set *bset; 6848 struct isl_set *set; 6849 struct isl_map *map; 6850 isl_space *dim; 6851 isl_local_space *ls; 6852 unsigned nparam; 6853 unsigned n_in; 6854 unsigned n_out; 6855 unsigned n_known; 6856 int i; 6857 6858 bmap = isl_basic_map_sort_divs(bmap); 6859 bmap = isl_basic_map_cow(bmap); 6860 if (!bmap) 6861 return NULL; 6862 6863 for (n_known = 0; n_known < bmap->n_div; ++n_known) 6864 if (isl_int_is_zero(bmap->div[n_known][0])) 6865 break; 6866 6867 nparam = isl_basic_map_dim(bmap, isl_dim_param); 6868 n_in = isl_basic_map_dim(bmap, isl_dim_in); 6869 n_out = isl_basic_map_dim(bmap, isl_dim_out); 6870 dim = isl_space_set_alloc(bmap->ctx, 6871 nparam + n_in + n_out + n_known, 0); 6872 if (!dim) 6873 goto error; 6874 6875 ls = isl_basic_map_get_local_space(bmap); 6876 ls = isl_local_space_drop_dims(ls, isl_dim_div, 6877 n_known, bmap->n_div - n_known); 6878 if (n_known > 0) { 6879 for (i = n_known; i < bmap->n_div; ++i) 6880 swap_div(bmap, i - n_known, i); 6881 bmap->n_div -= n_known; 6882 bmap->extra -= n_known; 6883 } 6884 bmap = isl_basic_map_reset_space(bmap, dim); 6885 bset = (struct isl_basic_set *)bmap; 6886 6887 set = parameter_compute_divs(bset); 6888 map = (struct isl_map *)set; 6889 map = replace_space_by_local_space(map, ls); 6890 6891 return map; 6892error: 6893 isl_basic_map_free(bmap); 6894 return NULL; 6895} 6896 6897int isl_basic_map_divs_known(__isl_keep isl_basic_map *bmap) 6898{ 6899 int i; 6900 unsigned off; 6901 6902 if (!bmap) 6903 return -1; 6904 6905 off = isl_space_dim(bmap->dim, isl_dim_all); 6906 for (i = 0; i < bmap->n_div; ++i) { 6907 if (isl_int_is_zero(bmap->div[i][0])) 6908 return 0; 6909 isl_assert(bmap->ctx, isl_int_is_zero(bmap->div[i][1+1+off+i]), 6910 return -1); 6911 } 6912 return 1; 6913} 6914 6915static int map_divs_known(__isl_keep isl_map *map) 6916{ 6917 int i; 6918 6919 if (!map) 6920 return -1; 6921 6922 for (i = 0; i < map->n; ++i) { 6923 int known = isl_basic_map_divs_known(map->p[i]); 6924 if (known <= 0) 6925 return known; 6926 } 6927 6928 return 1; 6929} 6930 6931/* If bmap contains any unknown divs, then compute explicit 6932 * expressions for them. However, this computation may be 6933 * quite expensive, so first try to remove divs that aren't 6934 * strictly needed. 6935 */ 6936struct isl_map *isl_basic_map_compute_divs(struct isl_basic_map *bmap) 6937{ 6938 int known; 6939 struct isl_map *map; 6940 6941 known = isl_basic_map_divs_known(bmap); 6942 if (known < 0) 6943 goto error; 6944 if (known) 6945 return isl_map_from_basic_map(bmap); 6946 6947 bmap = isl_basic_map_drop_redundant_divs(bmap); 6948 6949 known = isl_basic_map_divs_known(bmap); 6950 if (known < 0) 6951 goto error; 6952 if (known) 6953 return isl_map_from_basic_map(bmap); 6954 6955 map = compute_divs(bmap); 6956 return map; 6957error: 6958 isl_basic_map_free(bmap); 6959 return NULL; 6960} 6961 6962struct isl_map *isl_map_compute_divs(struct isl_map *map) 6963{ 6964 int i; 6965 int known; 6966 struct isl_map *res; 6967 6968 if (!map) 6969 return NULL; 6970 if (map->n == 0) 6971 return map; 6972 6973 known = map_divs_known(map); 6974 if (known < 0) { 6975 isl_map_free(map); 6976 return NULL; 6977 } 6978 if (known) 6979 return map; 6980 6981 res = isl_basic_map_compute_divs(isl_basic_map_copy(map->p[0])); 6982 for (i = 1 ; i < map->n; ++i) { 6983 struct isl_map *r2; 6984 r2 = isl_basic_map_compute_divs(isl_basic_map_copy(map->p[i])); 6985 if (ISL_F_ISSET(map, ISL_MAP_DISJOINT)) 6986 res = isl_map_union_disjoint(res, r2); 6987 else 6988 res = isl_map_union(res, r2); 6989 } 6990 isl_map_free(map); 6991 6992 return res; 6993} 6994 6995struct isl_set *isl_basic_set_compute_divs(struct isl_basic_set *bset) 6996{ 6997 return (struct isl_set *) 6998 isl_basic_map_compute_divs((struct isl_basic_map *)bset); 6999} 7000 7001struct isl_set *isl_set_compute_divs(struct isl_set *set) 7002{ 7003 return (struct isl_set *) 7004 isl_map_compute_divs((struct isl_map *)set); 7005} 7006 7007struct isl_set *isl_map_domain(struct isl_map *map) 7008{ 7009 int i; 7010 struct isl_set *set; 7011 7012 if (!map) 7013 goto error; 7014 7015 map = isl_map_cow(map); 7016 if (!map) 7017 return NULL; 7018 7019 set = (struct isl_set *)map; 7020 set->dim = isl_space_domain(set->dim); 7021 if (!set->dim) 7022 goto error; 7023 for (i = 0; i < map->n; ++i) { 7024 set->p[i] = isl_basic_map_domain(map->p[i]); 7025 if (!set->p[i]) 7026 goto error; 7027 } 7028 ISL_F_CLR(set, ISL_MAP_DISJOINT); 7029 ISL_F_CLR(set, ISL_SET_NORMALIZED); 7030 return set; 7031error: 7032 isl_map_free(map); 7033 return NULL; 7034} 7035 7036/* Return the union of "map1" and "map2", where we assume for now that 7037 * "map1" and "map2" are disjoint. Note that the basic maps inside 7038 * "map1" or "map2" may not be disjoint from each other. 7039 * Also note that this function is also called from isl_map_union, 7040 * which takes care of handling the situation where "map1" and "map2" 7041 * may not be disjoint. 7042 * 7043 * If one of the inputs is empty, we can simply return the other input. 7044 * Similarly, if one of the inputs is universal, then it is equal to the union. 7045 */ 7046static __isl_give isl_map *map_union_disjoint(__isl_take isl_map *map1, 7047 __isl_take isl_map *map2) 7048{ 7049 int i; 7050 unsigned flags = 0; 7051 struct isl_map *map = NULL; 7052 int is_universe; 7053 7054 if (!map1 || !map2) 7055 goto error; 7056 7057 if (map1->n == 0) { 7058 isl_map_free(map1); 7059 return map2; 7060 } 7061 if (map2->n == 0) { 7062 isl_map_free(map2); 7063 return map1; 7064 } 7065 7066 is_universe = isl_map_plain_is_universe(map1); 7067 if (is_universe < 0) 7068 goto error; 7069 if (is_universe) { 7070 isl_map_free(map2); 7071 return map1; 7072 } 7073 7074 is_universe = isl_map_plain_is_universe(map2); 7075 if (is_universe < 0) 7076 goto error; 7077 if (is_universe) { 7078 isl_map_free(map1); 7079 return map2; 7080 } 7081 7082 isl_assert(map1->ctx, isl_space_is_equal(map1->dim, map2->dim), goto error); 7083 7084 if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) && 7085 ISL_F_ISSET(map2, ISL_MAP_DISJOINT)) 7086 ISL_FL_SET(flags, ISL_MAP_DISJOINT); 7087 7088 map = isl_map_alloc_space(isl_space_copy(map1->dim), 7089 map1->n + map2->n, flags); 7090 if (!map) 7091 goto error; 7092 for (i = 0; i < map1->n; ++i) { 7093 map = isl_map_add_basic_map(map, 7094 isl_basic_map_copy(map1->p[i])); 7095 if (!map) 7096 goto error; 7097 } 7098 for (i = 0; i < map2->n; ++i) { 7099 map = isl_map_add_basic_map(map, 7100 isl_basic_map_copy(map2->p[i])); 7101 if (!map) 7102 goto error; 7103 } 7104 isl_map_free(map1); 7105 isl_map_free(map2); 7106 return map; 7107error: 7108 isl_map_free(map); 7109 isl_map_free(map1); 7110 isl_map_free(map2); 7111 return NULL; 7112} 7113 7114__isl_give isl_map *isl_map_union_disjoint(__isl_take isl_map *map1, 7115 __isl_take isl_map *map2) 7116{ 7117 return isl_map_align_params_map_map_and(map1, map2, &map_union_disjoint); 7118} 7119 7120struct isl_map *isl_map_union(struct isl_map *map1, struct isl_map *map2) 7121{ 7122 map1 = isl_map_union_disjoint(map1, map2); 7123 if (!map1) 7124 return NULL; 7125 if (map1->n > 1) 7126 ISL_F_CLR(map1, ISL_MAP_DISJOINT); 7127 return map1; 7128} 7129 7130struct isl_set *isl_set_union_disjoint( 7131 struct isl_set *set1, struct isl_set *set2) 7132{ 7133 return (struct isl_set *) 7134 isl_map_union_disjoint( 7135 (struct isl_map *)set1, (struct isl_map *)set2); 7136} 7137 7138struct isl_set *isl_set_union(struct isl_set *set1, struct isl_set *set2) 7139{ 7140 return (struct isl_set *) 7141 isl_map_union((struct isl_map *)set1, (struct isl_map *)set2); 7142} 7143 7144/* Apply "fn" to pairs of elements from "map" and "set" and collect 7145 * the results. 7146 * 7147 * "map" and "set" are assumed to be compatible and non-NULL. 7148 */ 7149static __isl_give isl_map *map_intersect_set(__isl_take isl_map *map, 7150 __isl_take isl_set *set, 7151 __isl_give isl_basic_map *fn(__isl_take isl_basic_map *bmap, 7152 __isl_take isl_basic_set *bset)) 7153{ 7154 unsigned flags = 0; 7155 struct isl_map *result; 7156 int i, j; 7157 7158 if (isl_set_plain_is_universe(set)) { 7159 isl_set_free(set); 7160 return map; 7161 } 7162 7163 if (ISL_F_ISSET(map, ISL_MAP_DISJOINT) && 7164 ISL_F_ISSET(set, ISL_MAP_DISJOINT)) 7165 ISL_FL_SET(flags, ISL_MAP_DISJOINT); 7166 7167 result = isl_map_alloc_space(isl_space_copy(map->dim), 7168 map->n * set->n, flags); 7169 for (i = 0; result && i < map->n; ++i) 7170 for (j = 0; j < set->n; ++j) { 7171 result = isl_map_add_basic_map(result, 7172 fn(isl_basic_map_copy(map->p[i]), 7173 isl_basic_set_copy(set->p[j]))); 7174 if (!result) 7175 break; 7176 } 7177 7178 isl_map_free(map); 7179 isl_set_free(set); 7180 return result; 7181} 7182 7183static __isl_give isl_map *map_intersect_range(__isl_take isl_map *map, 7184 __isl_take isl_set *set) 7185{ 7186 if (!map || !set) 7187 goto error; 7188 7189 if (!isl_map_compatible_range(map, set)) 7190 isl_die(set->ctx, isl_error_invalid, 7191 "incompatible spaces", goto error); 7192 7193 return map_intersect_set(map, set, &isl_basic_map_intersect_range); 7194error: 7195 isl_map_free(map); 7196 isl_set_free(set); 7197 return NULL; 7198} 7199 7200__isl_give isl_map *isl_map_intersect_range(__isl_take isl_map *map, 7201 __isl_take isl_set *set) 7202{ 7203 return isl_map_align_params_map_map_and(map, set, &map_intersect_range); 7204} 7205 7206static __isl_give isl_map *map_intersect_domain(__isl_take isl_map *map, 7207 __isl_take isl_set *set) 7208{ 7209 if (!map || !set) 7210 goto error; 7211 7212 if (!isl_map_compatible_domain(map, set)) 7213 isl_die(set->ctx, isl_error_invalid, 7214 "incompatible spaces", goto error); 7215 7216 return map_intersect_set(map, set, &isl_basic_map_intersect_domain); 7217error: 7218 isl_map_free(map); 7219 isl_set_free(set); 7220 return NULL; 7221} 7222 7223__isl_give isl_map *isl_map_intersect_domain(__isl_take isl_map *map, 7224 __isl_take isl_set *set) 7225{ 7226 return isl_map_align_params_map_map_and(map, set, 7227 &map_intersect_domain); 7228} 7229 7230static __isl_give isl_map *map_apply_domain(__isl_take isl_map *map1, 7231 __isl_take isl_map *map2) 7232{ 7233 if (!map1 || !map2) 7234 goto error; 7235 map1 = isl_map_reverse(map1); 7236 map1 = isl_map_apply_range(map1, map2); 7237 return isl_map_reverse(map1); 7238error: 7239 isl_map_free(map1); 7240 isl_map_free(map2); 7241 return NULL; 7242} 7243 7244__isl_give isl_map *isl_map_apply_domain(__isl_take isl_map *map1, 7245 __isl_take isl_map *map2) 7246{ 7247 return isl_map_align_params_map_map_and(map1, map2, &map_apply_domain); 7248} 7249 7250static __isl_give isl_map *map_apply_range(__isl_take isl_map *map1, 7251 __isl_take isl_map *map2) 7252{ 7253 isl_space *dim_result; 7254 struct isl_map *result; 7255 int i, j; 7256 7257 if (!map1 || !map2) 7258 goto error; 7259 7260 dim_result = isl_space_join(isl_space_copy(map1->dim), 7261 isl_space_copy(map2->dim)); 7262 7263 result = isl_map_alloc_space(dim_result, map1->n * map2->n, 0); 7264 if (!result) 7265 goto error; 7266 for (i = 0; i < map1->n; ++i) 7267 for (j = 0; j < map2->n; ++j) { 7268 result = isl_map_add_basic_map(result, 7269 isl_basic_map_apply_range( 7270 isl_basic_map_copy(map1->p[i]), 7271 isl_basic_map_copy(map2->p[j]))); 7272 if (!result) 7273 goto error; 7274 } 7275 isl_map_free(map1); 7276 isl_map_free(map2); 7277 if (result && result->n <= 1) 7278 ISL_F_SET(result, ISL_MAP_DISJOINT); 7279 return result; 7280error: 7281 isl_map_free(map1); 7282 isl_map_free(map2); 7283 return NULL; 7284} 7285 7286__isl_give isl_map *isl_map_apply_range(__isl_take isl_map *map1, 7287 __isl_take isl_map *map2) 7288{ 7289 return isl_map_align_params_map_map_and(map1, map2, &map_apply_range); 7290} 7291 7292/* 7293 * returns range - domain 7294 */ 7295struct isl_basic_set *isl_basic_map_deltas(struct isl_basic_map *bmap) 7296{ 7297 isl_space *dims, *target_dim; 7298 struct isl_basic_set *bset; 7299 unsigned dim; 7300 unsigned nparam; 7301 int i; 7302 7303 if (!bmap) 7304 goto error; 7305 isl_assert(bmap->ctx, isl_space_tuple_match(bmap->dim, isl_dim_in, 7306 bmap->dim, isl_dim_out), 7307 goto error); 7308 target_dim = isl_space_domain(isl_basic_map_get_space(bmap)); 7309 dim = isl_basic_map_n_in(bmap); 7310 nparam = isl_basic_map_n_param(bmap); 7311 bset = isl_basic_set_from_basic_map(bmap); 7312 bset = isl_basic_set_cow(bset); 7313 dims = isl_basic_set_get_space(bset); 7314 dims = isl_space_add_dims(dims, isl_dim_set, dim); 7315 bset = isl_basic_set_extend_space(bset, dims, 0, dim, 0); 7316 bset = isl_basic_set_swap_vars(bset, 2*dim); 7317 for (i = 0; i < dim; ++i) { 7318 int j = isl_basic_map_alloc_equality( 7319 (struct isl_basic_map *)bset); 7320 if (j < 0) { 7321 bset = isl_basic_set_free(bset); 7322 break; 7323 } 7324 isl_seq_clr(bset->eq[j], 1 + isl_basic_set_total_dim(bset)); 7325 isl_int_set_si(bset->eq[j][1+nparam+i], 1); 7326 isl_int_set_si(bset->eq[j][1+nparam+dim+i], 1); 7327 isl_int_set_si(bset->eq[j][1+nparam+2*dim+i], -1); 7328 } 7329 bset = isl_basic_set_project_out(bset, isl_dim_set, dim, 2*dim); 7330 bset = isl_basic_set_reset_space(bset, target_dim); 7331 return bset; 7332error: 7333 isl_basic_map_free(bmap); 7334 return NULL; 7335} 7336 7337/* 7338 * returns range - domain 7339 */ 7340__isl_give isl_set *isl_map_deltas(__isl_take isl_map *map) 7341{ 7342 int i; 7343 isl_space *dim; 7344 struct isl_set *result; 7345 7346 if (!map) 7347 return NULL; 7348 7349 isl_assert(map->ctx, isl_space_tuple_match(map->dim, isl_dim_in, 7350 map->dim, isl_dim_out), 7351 goto error); 7352 dim = isl_map_get_space(map); 7353 dim = isl_space_domain(dim); 7354 result = isl_set_alloc_space(dim, map->n, 0); 7355 if (!result) 7356 goto error; 7357 for (i = 0; i < map->n; ++i) 7358 result = isl_set_add_basic_set(result, 7359 isl_basic_map_deltas(isl_basic_map_copy(map->p[i]))); 7360 isl_map_free(map); 7361 return result; 7362error: 7363 isl_map_free(map); 7364 return NULL; 7365} 7366 7367/* 7368 * returns [domain -> range] -> range - domain 7369 */ 7370__isl_give isl_basic_map *isl_basic_map_deltas_map( 7371 __isl_take isl_basic_map *bmap) 7372{ 7373 int i, k; 7374 isl_space *dim; 7375 isl_basic_map *domain; 7376 int nparam, n; 7377 unsigned total; 7378 7379 if (!isl_space_tuple_match(bmap->dim, isl_dim_in, bmap->dim, isl_dim_out)) 7380 isl_die(bmap->ctx, isl_error_invalid, 7381 "domain and range don't match", goto error); 7382 7383 nparam = isl_basic_map_dim(bmap, isl_dim_param); 7384 n = isl_basic_map_dim(bmap, isl_dim_in); 7385 7386 dim = isl_space_from_range(isl_space_domain(isl_basic_map_get_space(bmap))); 7387 domain = isl_basic_map_universe(dim); 7388 7389 bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap)); 7390 bmap = isl_basic_map_apply_range(bmap, domain); 7391 bmap = isl_basic_map_extend_constraints(bmap, n, 0); 7392 7393 total = isl_basic_map_total_dim(bmap); 7394 7395 for (i = 0; i < n; ++i) { 7396 k = isl_basic_map_alloc_equality(bmap); 7397 if (k < 0) 7398 goto error; 7399 isl_seq_clr(bmap->eq[k], 1 + total); 7400 isl_int_set_si(bmap->eq[k][1 + nparam + i], 1); 7401 isl_int_set_si(bmap->eq[k][1 + nparam + n + i], -1); 7402 isl_int_set_si(bmap->eq[k][1 + nparam + n + n + i], 1); 7403 } 7404 7405 bmap = isl_basic_map_gauss(bmap, NULL); 7406 return isl_basic_map_finalize(bmap); 7407error: 7408 isl_basic_map_free(bmap); 7409 return NULL; 7410} 7411 7412/* 7413 * returns [domain -> range] -> range - domain 7414 */ 7415__isl_give isl_map *isl_map_deltas_map(__isl_take isl_map *map) 7416{ 7417 int i; 7418 isl_space *domain_dim; 7419 7420 if (!map) 7421 return NULL; 7422 7423 if (!isl_space_tuple_match(map->dim, isl_dim_in, map->dim, isl_dim_out)) 7424 isl_die(map->ctx, isl_error_invalid, 7425 "domain and range don't match", goto error); 7426 7427 map = isl_map_cow(map); 7428 if (!map) 7429 return NULL; 7430 7431 domain_dim = isl_space_from_range(isl_space_domain(isl_map_get_space(map))); 7432 map->dim = isl_space_from_domain(isl_space_wrap(map->dim)); 7433 map->dim = isl_space_join(map->dim, domain_dim); 7434 if (!map->dim) 7435 goto error; 7436 for (i = 0; i < map->n; ++i) { 7437 map->p[i] = isl_basic_map_deltas_map(map->p[i]); 7438 if (!map->p[i]) 7439 goto error; 7440 } 7441 ISL_F_CLR(map, ISL_MAP_NORMALIZED); 7442 return map; 7443error: 7444 isl_map_free(map); 7445 return NULL; 7446} 7447 7448static __isl_give isl_basic_map *basic_map_identity(__isl_take isl_space *dims) 7449{ 7450 struct isl_basic_map *bmap; 7451 unsigned nparam; 7452 unsigned dim; 7453 int i; 7454 7455 if (!dims) 7456 return NULL; 7457 7458 nparam = dims->nparam; 7459 dim = dims->n_out; 7460 bmap = isl_basic_map_alloc_space(dims, 0, dim, 0); 7461 if (!bmap) 7462 goto error; 7463 7464 for (i = 0; i < dim; ++i) { 7465 int j = isl_basic_map_alloc_equality(bmap); 7466 if (j < 0) 7467 goto error; 7468 isl_seq_clr(bmap->eq[j], 1 + isl_basic_map_total_dim(bmap)); 7469 isl_int_set_si(bmap->eq[j][1+nparam+i], 1); 7470 isl_int_set_si(bmap->eq[j][1+nparam+dim+i], -1); 7471 } 7472 return isl_basic_map_finalize(bmap); 7473error: 7474 isl_basic_map_free(bmap); 7475 return NULL; 7476} 7477 7478__isl_give isl_basic_map *isl_basic_map_identity(__isl_take isl_space *dim) 7479{ 7480 if (!dim) 7481 return NULL; 7482 if (dim->n_in != dim->n_out) 7483 isl_die(dim->ctx, isl_error_invalid, 7484 "number of input and output dimensions needs to be " 7485 "the same", goto error); 7486 return basic_map_identity(dim); 7487error: 7488 isl_space_free(dim); 7489 return NULL; 7490} 7491 7492struct isl_basic_map *isl_basic_map_identity_like(struct isl_basic_map *model) 7493{ 7494 if (!model || !model->dim) 7495 return NULL; 7496 return isl_basic_map_identity(isl_space_copy(model->dim)); 7497} 7498 7499__isl_give isl_map *isl_map_identity(__isl_take isl_space *dim) 7500{ 7501 return isl_map_from_basic_map(isl_basic_map_identity(dim)); 7502} 7503 7504struct isl_map *isl_map_identity_like(struct isl_map *model) 7505{ 7506 if (!model || !model->dim) 7507 return NULL; 7508 return isl_map_identity(isl_space_copy(model->dim)); 7509} 7510 7511struct isl_map *isl_map_identity_like_basic_map(struct isl_basic_map *model) 7512{ 7513 if (!model || !model->dim) 7514 return NULL; 7515 return isl_map_identity(isl_space_copy(model->dim)); 7516} 7517 7518__isl_give isl_map *isl_set_identity(__isl_take isl_set *set) 7519{ 7520 isl_space *dim = isl_set_get_space(set); 7521 isl_map *id; 7522 id = isl_map_identity(isl_space_map_from_set(dim)); 7523 return isl_map_intersect_range(id, set); 7524} 7525 7526/* Construct a basic set with all set dimensions having only non-negative 7527 * values. 7528 */ 7529__isl_give isl_basic_set *isl_basic_set_positive_orthant( 7530 __isl_take isl_space *space) 7531{ 7532 int i; 7533 unsigned nparam; 7534 unsigned dim; 7535 struct isl_basic_set *bset; 7536 7537 if (!space) 7538 return NULL; 7539 nparam = space->nparam; 7540 dim = space->n_out; 7541 bset = isl_basic_set_alloc_space(space, 0, 0, dim); 7542 if (!bset) 7543 return NULL; 7544 for (i = 0; i < dim; ++i) { 7545 int k = isl_basic_set_alloc_inequality(bset); 7546 if (k < 0) 7547 goto error; 7548 isl_seq_clr(bset->ineq[k], 1 + isl_basic_set_total_dim(bset)); 7549 isl_int_set_si(bset->ineq[k][1 + nparam + i], 1); 7550 } 7551 return bset; 7552error: 7553 isl_basic_set_free(bset); 7554 return NULL; 7555} 7556 7557/* Construct the half-space x_pos >= 0. 7558 */ 7559static __isl_give isl_basic_set *nonneg_halfspace(__isl_take isl_space *dim, 7560 int pos) 7561{ 7562 int k; 7563 isl_basic_set *nonneg; 7564 7565 nonneg = isl_basic_set_alloc_space(dim, 0, 0, 1); 7566 k = isl_basic_set_alloc_inequality(nonneg); 7567 if (k < 0) 7568 goto error; 7569 isl_seq_clr(nonneg->ineq[k], 1 + isl_basic_set_total_dim(nonneg)); 7570 isl_int_set_si(nonneg->ineq[k][pos], 1); 7571 7572 return isl_basic_set_finalize(nonneg); 7573error: 7574 isl_basic_set_free(nonneg); 7575 return NULL; 7576} 7577 7578/* Construct the half-space x_pos <= -1. 7579 */ 7580static __isl_give isl_basic_set *neg_halfspace(__isl_take isl_space *dim, int pos) 7581{ 7582 int k; 7583 isl_basic_set *neg; 7584 7585 neg = isl_basic_set_alloc_space(dim, 0, 0, 1); 7586 k = isl_basic_set_alloc_inequality(neg); 7587 if (k < 0) 7588 goto error; 7589 isl_seq_clr(neg->ineq[k], 1 + isl_basic_set_total_dim(neg)); 7590 isl_int_set_si(neg->ineq[k][0], -1); 7591 isl_int_set_si(neg->ineq[k][pos], -1); 7592 7593 return isl_basic_set_finalize(neg); 7594error: 7595 isl_basic_set_free(neg); 7596 return NULL; 7597} 7598 7599__isl_give isl_set *isl_set_split_dims(__isl_take isl_set *set, 7600 enum isl_dim_type type, unsigned first, unsigned n) 7601{ 7602 int i; 7603 isl_basic_set *nonneg; 7604 isl_basic_set *neg; 7605 7606 if (!set) 7607 return NULL; 7608 if (n == 0) 7609 return set; 7610 7611 isl_assert(set->ctx, first + n <= isl_set_dim(set, type), goto error); 7612 7613 for (i = 0; i < n; ++i) { 7614 nonneg = nonneg_halfspace(isl_set_get_space(set), 7615 pos(set->dim, type) + first + i); 7616 neg = neg_halfspace(isl_set_get_space(set), 7617 pos(set->dim, type) + first + i); 7618 7619 set = isl_set_intersect(set, isl_basic_set_union(nonneg, neg)); 7620 } 7621 7622 return set; 7623error: 7624 isl_set_free(set); 7625 return NULL; 7626} 7627 7628static int foreach_orthant(__isl_take isl_set *set, int *signs, int first, 7629 int len, int (*fn)(__isl_take isl_set *orthant, int *signs, void *user), 7630 void *user) 7631{ 7632 isl_set *half; 7633 7634 if (!set) 7635 return -1; 7636 if (isl_set_plain_is_empty(set)) { 7637 isl_set_free(set); 7638 return 0; 7639 } 7640 if (first == len) 7641 return fn(set, signs, user); 7642 7643 signs[first] = 1; 7644 half = isl_set_from_basic_set(nonneg_halfspace(isl_set_get_space(set), 7645 1 + first)); 7646 half = isl_set_intersect(half, isl_set_copy(set)); 7647 if (foreach_orthant(half, signs, first + 1, len, fn, user) < 0) 7648 goto error; 7649 7650 signs[first] = -1; 7651 half = isl_set_from_basic_set(neg_halfspace(isl_set_get_space(set), 7652 1 + first)); 7653 half = isl_set_intersect(half, set); 7654 return foreach_orthant(half, signs, first + 1, len, fn, user); 7655error: 7656 isl_set_free(set); 7657 return -1; 7658} 7659 7660/* Call "fn" on the intersections of "set" with each of the orthants 7661 * (except for obviously empty intersections). The orthant is identified 7662 * by the signs array, with each entry having value 1 or -1 according 7663 * to the sign of the corresponding variable. 7664 */ 7665int isl_set_foreach_orthant(__isl_keep isl_set *set, 7666 int (*fn)(__isl_take isl_set *orthant, int *signs, void *user), 7667 void *user) 7668{ 7669 unsigned nparam; 7670 unsigned nvar; 7671 int *signs; 7672 int r; 7673 7674 if (!set) 7675 return -1; 7676 if (isl_set_plain_is_empty(set)) 7677 return 0; 7678 7679 nparam = isl_set_dim(set, isl_dim_param); 7680 nvar = isl_set_dim(set, isl_dim_set); 7681 7682 signs = isl_alloc_array(set->ctx, int, nparam + nvar); 7683 7684 r = foreach_orthant(isl_set_copy(set), signs, 0, nparam + nvar, 7685 fn, user); 7686 7687 free(signs); 7688 7689 return r; 7690} 7691 7692int isl_set_is_equal(struct isl_set *set1, struct isl_set *set2) 7693{ 7694 return isl_map_is_equal((struct isl_map *)set1, (struct isl_map *)set2); 7695} 7696 7697int isl_basic_map_is_subset( 7698 struct isl_basic_map *bmap1, struct isl_basic_map *bmap2) 7699{ 7700 int is_subset; 7701 struct isl_map *map1; 7702 struct isl_map *map2; 7703 7704 if (!bmap1 || !bmap2) 7705 return -1; 7706 7707 map1 = isl_map_from_basic_map(isl_basic_map_copy(bmap1)); 7708 map2 = isl_map_from_basic_map(isl_basic_map_copy(bmap2)); 7709 7710 is_subset = isl_map_is_subset(map1, map2); 7711 7712 isl_map_free(map1); 7713 isl_map_free(map2); 7714 7715 return is_subset; 7716} 7717 7718int isl_basic_set_is_subset(__isl_keep isl_basic_set *bset1, 7719 __isl_keep isl_basic_set *bset2) 7720{ 7721 return isl_basic_map_is_subset(bset1, bset2); 7722} 7723 7724int isl_basic_map_is_equal( 7725 struct isl_basic_map *bmap1, struct isl_basic_map *bmap2) 7726{ 7727 int is_subset; 7728 7729 if (!bmap1 || !bmap2) 7730 return -1; 7731 is_subset = isl_basic_map_is_subset(bmap1, bmap2); 7732 if (is_subset != 1) 7733 return is_subset; 7734 is_subset = isl_basic_map_is_subset(bmap2, bmap1); 7735 return is_subset; 7736} 7737 7738int isl_basic_set_is_equal( 7739 struct isl_basic_set *bset1, struct isl_basic_set *bset2) 7740{ 7741 return isl_basic_map_is_equal( 7742 (struct isl_basic_map *)bset1, (struct isl_basic_map *)bset2); 7743} 7744 7745int isl_map_is_empty(struct isl_map *map) 7746{ 7747 int i; 7748 int is_empty; 7749 7750 if (!map) 7751 return -1; 7752 for (i = 0; i < map->n; ++i) { 7753 is_empty = isl_basic_map_is_empty(map->p[i]); 7754 if (is_empty < 0) 7755 return -1; 7756 if (!is_empty) 7757 return 0; 7758 } 7759 return 1; 7760} 7761 7762int isl_map_plain_is_empty(__isl_keep isl_map *map) 7763{ 7764 return map ? map->n == 0 : -1; 7765} 7766 7767int isl_map_fast_is_empty(__isl_keep isl_map *map) 7768{ 7769 return isl_map_plain_is_empty(map); 7770} 7771 7772int isl_set_plain_is_empty(struct isl_set *set) 7773{ 7774 return set ? set->n == 0 : -1; 7775} 7776 7777int isl_set_fast_is_empty(__isl_keep isl_set *set) 7778{ 7779 return isl_set_plain_is_empty(set); 7780} 7781 7782int isl_set_is_empty(struct isl_set *set) 7783{ 7784 return isl_map_is_empty((struct isl_map *)set); 7785} 7786 7787int isl_map_has_equal_space(__isl_keep isl_map *map1, __isl_keep isl_map *map2) 7788{ 7789 if (!map1 || !map2) 7790 return -1; 7791 7792 return isl_space_is_equal(map1->dim, map2->dim); 7793} 7794 7795int isl_set_has_equal_space(__isl_keep isl_set *set1, __isl_keep isl_set *set2) 7796{ 7797 if (!set1 || !set2) 7798 return -1; 7799 7800 return isl_space_is_equal(set1->dim, set2->dim); 7801} 7802 7803static int map_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2) 7804{ 7805 int is_subset; 7806 7807 if (!map1 || !map2) 7808 return -1; 7809 is_subset = isl_map_is_subset(map1, map2); 7810 if (is_subset != 1) 7811 return is_subset; 7812 is_subset = isl_map_is_subset(map2, map1); 7813 return is_subset; 7814} 7815 7816int isl_map_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2) 7817{ 7818 return isl_map_align_params_map_map_and_test(map1, map2, &map_is_equal); 7819} 7820 7821int isl_basic_map_is_strict_subset( 7822 struct isl_basic_map *bmap1, struct isl_basic_map *bmap2) 7823{ 7824 int is_subset; 7825 7826 if (!bmap1 || !bmap2) 7827 return -1; 7828 is_subset = isl_basic_map_is_subset(bmap1, bmap2); 7829 if (is_subset != 1) 7830 return is_subset; 7831 is_subset = isl_basic_map_is_subset(bmap2, bmap1); 7832 if (is_subset == -1) 7833 return is_subset; 7834 return !is_subset; 7835} 7836 7837int isl_map_is_strict_subset(struct isl_map *map1, struct isl_map *map2) 7838{ 7839 int is_subset; 7840 7841 if (!map1 || !map2) 7842 return -1; 7843 is_subset = isl_map_is_subset(map1, map2); 7844 if (is_subset != 1) 7845 return is_subset; 7846 is_subset = isl_map_is_subset(map2, map1); 7847 if (is_subset == -1) 7848 return is_subset; 7849 return !is_subset; 7850} 7851 7852int isl_set_is_strict_subset(__isl_keep isl_set *set1, __isl_keep isl_set *set2) 7853{ 7854 return isl_map_is_strict_subset((isl_map *)set1, (isl_map *)set2); 7855} 7856 7857int isl_basic_map_is_universe(struct isl_basic_map *bmap) 7858{ 7859 if (!bmap) 7860 return -1; 7861 return bmap->n_eq == 0 && bmap->n_ineq == 0; 7862} 7863 7864int isl_basic_set_is_universe(struct isl_basic_set *bset) 7865{ 7866 if (!bset) 7867 return -1; 7868 return bset->n_eq == 0 && bset->n_ineq == 0; 7869} 7870 7871int isl_map_plain_is_universe(__isl_keep isl_map *map) 7872{ 7873 int i; 7874 7875 if (!map) 7876 return -1; 7877 7878 for (i = 0; i < map->n; ++i) { 7879 int r = isl_basic_map_is_universe(map->p[i]); 7880 if (r < 0 || r) 7881 return r; 7882 } 7883 7884 return 0; 7885} 7886 7887int isl_set_plain_is_universe(__isl_keep isl_set *set) 7888{ 7889 return isl_map_plain_is_universe((isl_map *) set); 7890} 7891 7892int isl_set_fast_is_universe(__isl_keep isl_set *set) 7893{ 7894 return isl_set_plain_is_universe(set); 7895} 7896 7897int isl_basic_map_is_empty(struct isl_basic_map *bmap) 7898{ 7899 struct isl_basic_set *bset = NULL; 7900 struct isl_vec *sample = NULL; 7901 int empty; 7902 unsigned total; 7903 7904 if (!bmap) 7905 return -1; 7906 7907 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY)) 7908 return 1; 7909 7910 if (isl_basic_map_is_universe(bmap)) 7911 return 0; 7912 7913 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL)) { 7914 struct isl_basic_map *copy = isl_basic_map_copy(bmap); 7915 copy = isl_basic_map_remove_redundancies(copy); 7916 empty = isl_basic_map_plain_is_empty(copy); 7917 isl_basic_map_free(copy); 7918 return empty; 7919 } 7920 7921 total = 1 + isl_basic_map_total_dim(bmap); 7922 if (bmap->sample && bmap->sample->size == total) { 7923 int contains = isl_basic_map_contains(bmap, bmap->sample); 7924 if (contains < 0) 7925 return -1; 7926 if (contains) 7927 return 0; 7928 } 7929 isl_vec_free(bmap->sample); 7930 bmap->sample = NULL; 7931 bset = isl_basic_map_underlying_set(isl_basic_map_copy(bmap)); 7932 if (!bset) 7933 return -1; 7934 sample = isl_basic_set_sample_vec(bset); 7935 if (!sample) 7936 return -1; 7937 empty = sample->size == 0; 7938 isl_vec_free(bmap->sample); 7939 bmap->sample = sample; 7940 if (empty) 7941 ISL_F_SET(bmap, ISL_BASIC_MAP_EMPTY); 7942 7943 return empty; 7944} 7945 7946int isl_basic_map_plain_is_empty(__isl_keep isl_basic_map *bmap) 7947{ 7948 if (!bmap) 7949 return -1; 7950 return ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY); 7951} 7952 7953int isl_basic_map_fast_is_empty(__isl_keep isl_basic_map *bmap) 7954{ 7955 return isl_basic_map_plain_is_empty(bmap); 7956} 7957 7958int isl_basic_set_plain_is_empty(__isl_keep isl_basic_set *bset) 7959{ 7960 if (!bset) 7961 return -1; 7962 return ISL_F_ISSET(bset, ISL_BASIC_SET_EMPTY); 7963} 7964 7965int isl_basic_set_fast_is_empty(__isl_keep isl_basic_set *bset) 7966{ 7967 return isl_basic_set_plain_is_empty(bset); 7968} 7969 7970int isl_basic_set_is_empty(struct isl_basic_set *bset) 7971{ 7972 return isl_basic_map_is_empty((struct isl_basic_map *)bset); 7973} 7974 7975struct isl_map *isl_basic_map_union( 7976 struct isl_basic_map *bmap1, struct isl_basic_map *bmap2) 7977{ 7978 struct isl_map *map; 7979 if (!bmap1 || !bmap2) 7980 goto error; 7981 7982 isl_assert(bmap1->ctx, isl_space_is_equal(bmap1->dim, bmap2->dim), goto error); 7983 7984 map = isl_map_alloc_space(isl_space_copy(bmap1->dim), 2, 0); 7985 if (!map) 7986 goto error; 7987 map = isl_map_add_basic_map(map, bmap1); 7988 map = isl_map_add_basic_map(map, bmap2); 7989 return map; 7990error: 7991 isl_basic_map_free(bmap1); 7992 isl_basic_map_free(bmap2); 7993 return NULL; 7994} 7995 7996struct isl_set *isl_basic_set_union( 7997 struct isl_basic_set *bset1, struct isl_basic_set *bset2) 7998{ 7999 return (struct isl_set *)isl_basic_map_union( 8000 (struct isl_basic_map *)bset1, 8001 (struct isl_basic_map *)bset2); 8002} 8003 8004/* Order divs such that any div only depends on previous divs */ 8005struct isl_basic_map *isl_basic_map_order_divs(struct isl_basic_map *bmap) 8006{ 8007 int i; 8008 unsigned off; 8009 8010 if (!bmap) 8011 return NULL; 8012 8013 off = isl_space_dim(bmap->dim, isl_dim_all); 8014 8015 for (i = 0; i < bmap->n_div; ++i) { 8016 int pos; 8017 if (isl_int_is_zero(bmap->div[i][0])) 8018 continue; 8019 pos = isl_seq_first_non_zero(bmap->div[i]+1+1+off+i, 8020 bmap->n_div-i); 8021 if (pos == -1) 8022 continue; 8023 isl_basic_map_swap_div(bmap, i, i + pos); 8024 --i; 8025 } 8026 return bmap; 8027} 8028 8029struct isl_basic_set *isl_basic_set_order_divs(struct isl_basic_set *bset) 8030{ 8031 return (struct isl_basic_set *) 8032 isl_basic_map_order_divs((struct isl_basic_map *)bset); 8033} 8034 8035__isl_give isl_map *isl_map_order_divs(__isl_take isl_map *map) 8036{ 8037 int i; 8038 8039 if (!map) 8040 return 0; 8041 8042 for (i = 0; i < map->n; ++i) { 8043 map->p[i] = isl_basic_map_order_divs(map->p[i]); 8044 if (!map->p[i]) 8045 goto error; 8046 } 8047 8048 return map; 8049error: 8050 isl_map_free(map); 8051 return NULL; 8052} 8053 8054/* Apply the expansion computed by isl_merge_divs. 8055 * The expansion itself is given by "exp" while the resulting 8056 * list of divs is given by "div". 8057 */ 8058__isl_give isl_basic_set *isl_basic_set_expand_divs( 8059 __isl_take isl_basic_set *bset, __isl_take isl_mat *div, int *exp) 8060{ 8061 int i, j; 8062 int n_div; 8063 8064 bset = isl_basic_set_cow(bset); 8065 if (!bset || !div) 8066 goto error; 8067 8068 if (div->n_row < bset->n_div) 8069 isl_die(isl_mat_get_ctx(div), isl_error_invalid, 8070 "not an expansion", goto error); 8071 8072 n_div = bset->n_div; 8073 bset = isl_basic_map_extend_space(bset, isl_space_copy(bset->dim), 8074 div->n_row - n_div, 0, 8075 2 * (div->n_row - n_div)); 8076 8077 for (i = n_div; i < div->n_row; ++i) 8078 if (isl_basic_set_alloc_div(bset) < 0) 8079 goto error; 8080 8081 j = n_div - 1; 8082 for (i = div->n_row - 1; i >= 0; --i) { 8083 if (j >= 0 && exp[j] == i) { 8084 if (i != j) 8085 isl_basic_map_swap_div(bset, i, j); 8086 j--; 8087 } else { 8088 isl_seq_cpy(bset->div[i], div->row[i], div->n_col); 8089 if (isl_basic_map_add_div_constraints(bset, i) < 0) 8090 goto error; 8091 } 8092 } 8093 8094 isl_mat_free(div); 8095 return bset; 8096error: 8097 isl_basic_set_free(bset); 8098 isl_mat_free(div); 8099 return NULL; 8100} 8101 8102/* Look for a div in dst that corresponds to the div "div" in src. 8103 * The divs before "div" in src and dst are assumed to be the same. 8104 * 8105 * Returns -1 if no corresponding div was found and the position 8106 * of the corresponding div in dst otherwise. 8107 */ 8108static int find_div(struct isl_basic_map *dst, 8109 struct isl_basic_map *src, unsigned div) 8110{ 8111 int i; 8112 8113 unsigned total = isl_space_dim(src->dim, isl_dim_all); 8114 8115 isl_assert(dst->ctx, div <= dst->n_div, return -1); 8116 for (i = div; i < dst->n_div; ++i) 8117 if (isl_seq_eq(dst->div[i], src->div[div], 1+1+total+div) && 8118 isl_seq_first_non_zero(dst->div[i]+1+1+total+div, 8119 dst->n_div - div) == -1) 8120 return i; 8121 return -1; 8122} 8123 8124struct isl_basic_map *isl_basic_map_align_divs( 8125 struct isl_basic_map *dst, struct isl_basic_map *src) 8126{ 8127 int i; 8128 unsigned total; 8129 8130 if (!dst || !src) 8131 goto error; 8132 8133 if (src->n_div == 0) 8134 return dst; 8135 8136 for (i = 0; i < src->n_div; ++i) 8137 isl_assert(src->ctx, !isl_int_is_zero(src->div[i][0]), goto error); 8138 8139 src = isl_basic_map_order_divs(src); 8140 dst = isl_basic_map_cow(dst); 8141 if (!dst) 8142 return NULL; 8143 dst = isl_basic_map_extend_space(dst, isl_space_copy(dst->dim), 8144 src->n_div, 0, 2 * src->n_div); 8145 if (!dst) 8146 return NULL; 8147 total = isl_space_dim(src->dim, isl_dim_all); 8148 for (i = 0; i < src->n_div; ++i) { 8149 int j = find_div(dst, src, i); 8150 if (j < 0) { 8151 j = isl_basic_map_alloc_div(dst); 8152 if (j < 0) 8153 goto error; 8154 isl_seq_cpy(dst->div[j], src->div[i], 1+1+total+i); 8155 isl_seq_clr(dst->div[j]+1+1+total+i, dst->n_div - i); 8156 if (isl_basic_map_add_div_constraints(dst, j) < 0) 8157 goto error; 8158 } 8159 if (j != i) 8160 isl_basic_map_swap_div(dst, i, j); 8161 } 8162 return dst; 8163error: 8164 isl_basic_map_free(dst); 8165 return NULL; 8166} 8167 8168struct isl_basic_set *isl_basic_set_align_divs( 8169 struct isl_basic_set *dst, struct isl_basic_set *src) 8170{ 8171 return (struct isl_basic_set *)isl_basic_map_align_divs( 8172 (struct isl_basic_map *)dst, (struct isl_basic_map *)src); 8173} 8174 8175struct isl_map *isl_map_align_divs(struct isl_map *map) 8176{ 8177 int i; 8178 8179 if (!map) 8180 return NULL; 8181 if (map->n == 0) 8182 return map; 8183 map = isl_map_compute_divs(map); 8184 map = isl_map_cow(map); 8185 if (!map) 8186 return NULL; 8187 8188 for (i = 1; i < map->n; ++i) 8189 map->p[0] = isl_basic_map_align_divs(map->p[0], map->p[i]); 8190 for (i = 1; i < map->n; ++i) { 8191 map->p[i] = isl_basic_map_align_divs(map->p[i], map->p[0]); 8192 if (!map->p[i]) 8193 return isl_map_free(map); 8194 } 8195 8196 ISL_F_CLR(map, ISL_MAP_NORMALIZED); 8197 return map; 8198} 8199 8200struct isl_set *isl_set_align_divs(struct isl_set *set) 8201{ 8202 return (struct isl_set *)isl_map_align_divs((struct isl_map *)set); 8203} 8204 8205static __isl_give isl_set *set_apply( __isl_take isl_set *set, 8206 __isl_take isl_map *map) 8207{ 8208 if (!set || !map) 8209 goto error; 8210 isl_assert(set->ctx, isl_map_compatible_domain(map, set), goto error); 8211 map = isl_map_intersect_domain(map, set); 8212 set = isl_map_range(map); 8213 return set; 8214error: 8215 isl_set_free(set); 8216 isl_map_free(map); 8217 return NULL; 8218} 8219 8220__isl_give isl_set *isl_set_apply( __isl_take isl_set *set, 8221 __isl_take isl_map *map) 8222{ 8223 return isl_map_align_params_map_map_and(set, map, &set_apply); 8224} 8225 8226/* There is no need to cow as removing empty parts doesn't change 8227 * the meaning of the set. 8228 */ 8229struct isl_map *isl_map_remove_empty_parts(struct isl_map *map) 8230{ 8231 int i; 8232 8233 if (!map) 8234 return NULL; 8235 8236 for (i = map->n - 1; i >= 0; --i) 8237 remove_if_empty(map, i); 8238 8239 return map; 8240} 8241 8242struct isl_set *isl_set_remove_empty_parts(struct isl_set *set) 8243{ 8244 return (struct isl_set *) 8245 isl_map_remove_empty_parts((struct isl_map *)set); 8246} 8247 8248struct isl_basic_map *isl_map_copy_basic_map(struct isl_map *map) 8249{ 8250 struct isl_basic_map *bmap; 8251 if (!map || map->n == 0) 8252 return NULL; 8253 bmap = map->p[map->n-1]; 8254 isl_assert(map->ctx, ISL_F_ISSET(bmap, ISL_BASIC_SET_FINAL), return NULL); 8255 return isl_basic_map_copy(bmap); 8256} 8257 8258struct isl_basic_set *isl_set_copy_basic_set(struct isl_set *set) 8259{ 8260 return (struct isl_basic_set *) 8261 isl_map_copy_basic_map((struct isl_map *)set); 8262} 8263 8264__isl_give isl_map *isl_map_drop_basic_map(__isl_take isl_map *map, 8265 __isl_keep isl_basic_map *bmap) 8266{ 8267 int i; 8268 8269 if (!map || !bmap) 8270 goto error; 8271 for (i = map->n-1; i >= 0; --i) { 8272 if (map->p[i] != bmap) 8273 continue; 8274 map = isl_map_cow(map); 8275 if (!map) 8276 goto error; 8277 isl_basic_map_free(map->p[i]); 8278 if (i != map->n-1) { 8279 ISL_F_CLR(map, ISL_SET_NORMALIZED); 8280 map->p[i] = map->p[map->n-1]; 8281 } 8282 map->n--; 8283 return map; 8284 } 8285 return map; 8286error: 8287 isl_map_free(map); 8288 return NULL; 8289} 8290 8291struct isl_set *isl_set_drop_basic_set(struct isl_set *set, 8292 struct isl_basic_set *bset) 8293{ 8294 return (struct isl_set *)isl_map_drop_basic_map((struct isl_map *)set, 8295 (struct isl_basic_map *)bset); 8296} 8297 8298/* Given two basic sets bset1 and bset2, compute the maximal difference 8299 * between the values of dimension pos in bset1 and those in bset2 8300 * for any common value of the parameters and dimensions preceding pos. 8301 */ 8302static enum isl_lp_result basic_set_maximal_difference_at( 8303 __isl_keep isl_basic_set *bset1, __isl_keep isl_basic_set *bset2, 8304 int pos, isl_int *opt) 8305{ 8306 isl_space *dims; 8307 struct isl_basic_map *bmap1 = NULL; 8308 struct isl_basic_map *bmap2 = NULL; 8309 struct isl_ctx *ctx; 8310 struct isl_vec *obj; 8311 unsigned total; 8312 unsigned nparam; 8313 unsigned dim1, dim2; 8314 enum isl_lp_result res; 8315 8316 if (!bset1 || !bset2) 8317 return isl_lp_error; 8318 8319 nparam = isl_basic_set_n_param(bset1); 8320 dim1 = isl_basic_set_n_dim(bset1); 8321 dim2 = isl_basic_set_n_dim(bset2); 8322 dims = isl_space_alloc(bset1->ctx, nparam, pos, dim1 - pos); 8323 bmap1 = isl_basic_map_from_basic_set(isl_basic_set_copy(bset1), dims); 8324 dims = isl_space_alloc(bset2->ctx, nparam, pos, dim2 - pos); 8325 bmap2 = isl_basic_map_from_basic_set(isl_basic_set_copy(bset2), dims); 8326 if (!bmap1 || !bmap2) 8327 goto error; 8328 bmap1 = isl_basic_map_cow(bmap1); 8329 bmap1 = isl_basic_map_extend(bmap1, nparam, 8330 pos, (dim1 - pos) + (dim2 - pos), 8331 bmap2->n_div, bmap2->n_eq, bmap2->n_ineq); 8332 bmap1 = add_constraints(bmap1, bmap2, 0, dim1 - pos); 8333 if (!bmap1) 8334 goto error; 8335 total = isl_basic_map_total_dim(bmap1); 8336 ctx = bmap1->ctx; 8337 obj = isl_vec_alloc(ctx, 1 + total); 8338 if (!obj) 8339 goto error2; 8340 isl_seq_clr(obj->block.data, 1 + total); 8341 isl_int_set_si(obj->block.data[1+nparam+pos], 1); 8342 isl_int_set_si(obj->block.data[1+nparam+pos+(dim1-pos)], -1); 8343 res = isl_basic_map_solve_lp(bmap1, 1, obj->block.data, ctx->one, 8344 opt, NULL, NULL); 8345 isl_basic_map_free(bmap1); 8346 isl_vec_free(obj); 8347 return res; 8348error: 8349 isl_basic_map_free(bmap2); 8350error2: 8351 isl_basic_map_free(bmap1); 8352 return isl_lp_error; 8353} 8354 8355/* Given two _disjoint_ basic sets bset1 and bset2, check whether 8356 * for any common value of the parameters and dimensions preceding pos 8357 * in both basic sets, the values of dimension pos in bset1 are 8358 * smaller or larger than those in bset2. 8359 * 8360 * Returns 8361 * 1 if bset1 follows bset2 8362 * -1 if bset1 precedes bset2 8363 * 0 if bset1 and bset2 are incomparable 8364 * -2 if some error occurred. 8365 */ 8366int isl_basic_set_compare_at(struct isl_basic_set *bset1, 8367 struct isl_basic_set *bset2, int pos) 8368{ 8369 isl_int opt; 8370 enum isl_lp_result res; 8371 int cmp; 8372 8373 isl_int_init(opt); 8374 8375 res = basic_set_maximal_difference_at(bset1, bset2, pos, &opt); 8376 8377 if (res == isl_lp_empty) 8378 cmp = 0; 8379 else if ((res == isl_lp_ok && isl_int_is_pos(opt)) || 8380 res == isl_lp_unbounded) 8381 cmp = 1; 8382 else if (res == isl_lp_ok && isl_int_is_neg(opt)) 8383 cmp = -1; 8384 else 8385 cmp = -2; 8386 8387 isl_int_clear(opt); 8388 return cmp; 8389} 8390 8391/* Given two basic sets bset1 and bset2, check whether 8392 * for any common value of the parameters and dimensions preceding pos 8393 * there is a value of dimension pos in bset1 that is larger 8394 * than a value of the same dimension in bset2. 8395 * 8396 * Return 8397 * 1 if there exists such a pair 8398 * 0 if there is no such pair, but there is a pair of equal values 8399 * -1 otherwise 8400 * -2 if some error occurred. 8401 */ 8402int isl_basic_set_follows_at(__isl_keep isl_basic_set *bset1, 8403 __isl_keep isl_basic_set *bset2, int pos) 8404{ 8405 isl_int opt; 8406 enum isl_lp_result res; 8407 int cmp; 8408 8409 isl_int_init(opt); 8410 8411 res = basic_set_maximal_difference_at(bset1, bset2, pos, &opt); 8412 8413 if (res == isl_lp_empty) 8414 cmp = -1; 8415 else if ((res == isl_lp_ok && isl_int_is_pos(opt)) || 8416 res == isl_lp_unbounded) 8417 cmp = 1; 8418 else if (res == isl_lp_ok && isl_int_is_neg(opt)) 8419 cmp = -1; 8420 else if (res == isl_lp_ok) 8421 cmp = 0; 8422 else 8423 cmp = -2; 8424 8425 isl_int_clear(opt); 8426 return cmp; 8427} 8428 8429/* Given two sets set1 and set2, check whether 8430 * for any common value of the parameters and dimensions preceding pos 8431 * there is a value of dimension pos in set1 that is larger 8432 * than a value of the same dimension in set2. 8433 * 8434 * Return 8435 * 1 if there exists such a pair 8436 * 0 if there is no such pair, but there is a pair of equal values 8437 * -1 otherwise 8438 * -2 if some error occurred. 8439 */ 8440int isl_set_follows_at(__isl_keep isl_set *set1, 8441 __isl_keep isl_set *set2, int pos) 8442{ 8443 int i, j; 8444 int follows = -1; 8445 8446 if (!set1 || !set2) 8447 return -2; 8448 8449 for (i = 0; i < set1->n; ++i) 8450 for (j = 0; j < set2->n; ++j) { 8451 int f; 8452 f = isl_basic_set_follows_at(set1->p[i], set2->p[j], pos); 8453 if (f == 1 || f == -2) 8454 return f; 8455 if (f > follows) 8456 follows = f; 8457 } 8458 8459 return follows; 8460} 8461 8462static int isl_basic_map_plain_has_fixed_var(__isl_keep isl_basic_map *bmap, 8463 unsigned pos, isl_int *val) 8464{ 8465 int i; 8466 int d; 8467 unsigned total; 8468 8469 if (!bmap) 8470 return -1; 8471 total = isl_basic_map_total_dim(bmap); 8472 for (i = 0, d = total-1; i < bmap->n_eq && d+1 > pos; ++i) { 8473 for (; d+1 > pos; --d) 8474 if (!isl_int_is_zero(bmap->eq[i][1+d])) 8475 break; 8476 if (d != pos) 8477 continue; 8478 if (isl_seq_first_non_zero(bmap->eq[i]+1, d) != -1) 8479 return 0; 8480 if (isl_seq_first_non_zero(bmap->eq[i]+1+d+1, total-d-1) != -1) 8481 return 0; 8482 if (!isl_int_is_one(bmap->eq[i][1+d])) 8483 return 0; 8484 if (val) 8485 isl_int_neg(*val, bmap->eq[i][0]); 8486 return 1; 8487 } 8488 return 0; 8489} 8490 8491static int isl_map_plain_has_fixed_var(__isl_keep isl_map *map, 8492 unsigned pos, isl_int *val) 8493{ 8494 int i; 8495 isl_int v; 8496 isl_int tmp; 8497 int fixed; 8498 8499 if (!map) 8500 return -1; 8501 if (map->n == 0) 8502 return 0; 8503 if (map->n == 1) 8504 return isl_basic_map_plain_has_fixed_var(map->p[0], pos, val); 8505 isl_int_init(v); 8506 isl_int_init(tmp); 8507 fixed = isl_basic_map_plain_has_fixed_var(map->p[0], pos, &v); 8508 for (i = 1; fixed == 1 && i < map->n; ++i) { 8509 fixed = isl_basic_map_plain_has_fixed_var(map->p[i], pos, &tmp); 8510 if (fixed == 1 && isl_int_ne(tmp, v)) 8511 fixed = 0; 8512 } 8513 if (val) 8514 isl_int_set(*val, v); 8515 isl_int_clear(tmp); 8516 isl_int_clear(v); 8517 return fixed; 8518} 8519 8520static int isl_basic_set_plain_has_fixed_var(__isl_keep isl_basic_set *bset, 8521 unsigned pos, isl_int *val) 8522{ 8523 return isl_basic_map_plain_has_fixed_var((struct isl_basic_map *)bset, 8524 pos, val); 8525} 8526 8527static int isl_set_plain_has_fixed_var(__isl_keep isl_set *set, unsigned pos, 8528 isl_int *val) 8529{ 8530 return isl_map_plain_has_fixed_var((struct isl_map *)set, pos, val); 8531} 8532 8533int isl_basic_map_plain_is_fixed(__isl_keep isl_basic_map *bmap, 8534 enum isl_dim_type type, unsigned pos, isl_int *val) 8535{ 8536 if (pos >= isl_basic_map_dim(bmap, type)) 8537 return -1; 8538 return isl_basic_map_plain_has_fixed_var(bmap, 8539 isl_basic_map_offset(bmap, type) - 1 + pos, val); 8540} 8541 8542/* If "bmap" obviously lies on a hyperplane where the given dimension 8543 * has a fixed value, then return that value. 8544 * Otherwise return NaN. 8545 */ 8546__isl_give isl_val *isl_basic_map_plain_get_val_if_fixed( 8547 __isl_keep isl_basic_map *bmap, 8548 enum isl_dim_type type, unsigned pos) 8549{ 8550 isl_ctx *ctx; 8551 isl_val *v; 8552 int fixed; 8553 8554 if (!bmap) 8555 return NULL; 8556 ctx = isl_basic_map_get_ctx(bmap); 8557 v = isl_val_alloc(ctx); 8558 if (!v) 8559 return NULL; 8560 fixed = isl_basic_map_plain_is_fixed(bmap, type, pos, &v->n); 8561 if (fixed < 0) 8562 return isl_val_free(v); 8563 if (fixed) { 8564 isl_int_set_si(v->d, 1); 8565 return v; 8566 } 8567 isl_val_free(v); 8568 return isl_val_nan(ctx); 8569} 8570 8571int isl_map_plain_is_fixed(__isl_keep isl_map *map, 8572 enum isl_dim_type type, unsigned pos, isl_int *val) 8573{ 8574 if (pos >= isl_map_dim(map, type)) 8575 return -1; 8576 return isl_map_plain_has_fixed_var(map, 8577 map_offset(map, type) - 1 + pos, val); 8578} 8579 8580/* If "map" obviously lies on a hyperplane where the given dimension 8581 * has a fixed value, then return that value. 8582 * Otherwise return NaN. 8583 */ 8584__isl_give isl_val *isl_map_plain_get_val_if_fixed(__isl_keep isl_map *map, 8585 enum isl_dim_type type, unsigned pos) 8586{ 8587 isl_ctx *ctx; 8588 isl_val *v; 8589 int fixed; 8590 8591 if (!map) 8592 return NULL; 8593 ctx = isl_map_get_ctx(map); 8594 v = isl_val_alloc(ctx); 8595 if (!v) 8596 return NULL; 8597 fixed = isl_map_plain_is_fixed(map, type, pos, &v->n); 8598 if (fixed < 0) 8599 return isl_val_free(v); 8600 if (fixed) { 8601 isl_int_set_si(v->d, 1); 8602 return v; 8603 } 8604 isl_val_free(v); 8605 return isl_val_nan(ctx); 8606} 8607 8608/* If "set" obviously lies on a hyperplane where the given dimension 8609 * has a fixed value, then return that value. 8610 * Otherwise return NaN. 8611 */ 8612__isl_give isl_val *isl_set_plain_get_val_if_fixed(__isl_keep isl_set *set, 8613 enum isl_dim_type type, unsigned pos) 8614{ 8615 return isl_map_plain_get_val_if_fixed(set, type, pos); 8616} 8617 8618int isl_set_plain_is_fixed(__isl_keep isl_set *set, 8619 enum isl_dim_type type, unsigned pos, isl_int *val) 8620{ 8621 return isl_map_plain_is_fixed(set, type, pos, val); 8622} 8623 8624int isl_map_fast_is_fixed(__isl_keep isl_map *map, 8625 enum isl_dim_type type, unsigned pos, isl_int *val) 8626{ 8627 return isl_map_plain_is_fixed(map, type, pos, val); 8628} 8629 8630/* Check if dimension dim has fixed value and if so and if val is not NULL, 8631 * then return this fixed value in *val. 8632 */ 8633int isl_basic_set_plain_dim_is_fixed(__isl_keep isl_basic_set *bset, 8634 unsigned dim, isl_int *val) 8635{ 8636 return isl_basic_set_plain_has_fixed_var(bset, 8637 isl_basic_set_n_param(bset) + dim, val); 8638} 8639 8640/* Check if dimension dim has fixed value and if so and if val is not NULL, 8641 * then return this fixed value in *val. 8642 */ 8643int isl_set_plain_dim_is_fixed(__isl_keep isl_set *set, 8644 unsigned dim, isl_int *val) 8645{ 8646 return isl_set_plain_has_fixed_var(set, isl_set_n_param(set) + dim, val); 8647} 8648 8649int isl_set_fast_dim_is_fixed(__isl_keep isl_set *set, 8650 unsigned dim, isl_int *val) 8651{ 8652 return isl_set_plain_dim_is_fixed(set, dim, val); 8653} 8654 8655/* Check if input variable in has fixed value and if so and if val is not NULL, 8656 * then return this fixed value in *val. 8657 */ 8658int isl_map_plain_input_is_fixed(__isl_keep isl_map *map, 8659 unsigned in, isl_int *val) 8660{ 8661 return isl_map_plain_has_fixed_var(map, isl_map_n_param(map) + in, val); 8662} 8663 8664/* Check if dimension dim has an (obvious) fixed lower bound and if so 8665 * and if val is not NULL, then return this lower bound in *val. 8666 */ 8667int isl_basic_set_plain_dim_has_fixed_lower_bound( 8668 __isl_keep isl_basic_set *bset, unsigned dim, isl_int *val) 8669{ 8670 int i, i_eq = -1, i_ineq = -1; 8671 isl_int *c; 8672 unsigned total; 8673 unsigned nparam; 8674 8675 if (!bset) 8676 return -1; 8677 total = isl_basic_set_total_dim(bset); 8678 nparam = isl_basic_set_n_param(bset); 8679 for (i = 0; i < bset->n_eq; ++i) { 8680 if (isl_int_is_zero(bset->eq[i][1+nparam+dim])) 8681 continue; 8682 if (i_eq != -1) 8683 return 0; 8684 i_eq = i; 8685 } 8686 for (i = 0; i < bset->n_ineq; ++i) { 8687 if (!isl_int_is_pos(bset->ineq[i][1+nparam+dim])) 8688 continue; 8689 if (i_eq != -1 || i_ineq != -1) 8690 return 0; 8691 i_ineq = i; 8692 } 8693 if (i_eq == -1 && i_ineq == -1) 8694 return 0; 8695 c = i_eq != -1 ? bset->eq[i_eq] : bset->ineq[i_ineq]; 8696 /* The coefficient should always be one due to normalization. */ 8697 if (!isl_int_is_one(c[1+nparam+dim])) 8698 return 0; 8699 if (isl_seq_first_non_zero(c+1, nparam+dim) != -1) 8700 return 0; 8701 if (isl_seq_first_non_zero(c+1+nparam+dim+1, 8702 total - nparam - dim - 1) != -1) 8703 return 0; 8704 if (val) 8705 isl_int_neg(*val, c[0]); 8706 return 1; 8707} 8708 8709int isl_set_plain_dim_has_fixed_lower_bound(__isl_keep isl_set *set, 8710 unsigned dim, isl_int *val) 8711{ 8712 int i; 8713 isl_int v; 8714 isl_int tmp; 8715 int fixed; 8716 8717 if (!set) 8718 return -1; 8719 if (set->n == 0) 8720 return 0; 8721 if (set->n == 1) 8722 return isl_basic_set_plain_dim_has_fixed_lower_bound(set->p[0], 8723 dim, val); 8724 isl_int_init(v); 8725 isl_int_init(tmp); 8726 fixed = isl_basic_set_plain_dim_has_fixed_lower_bound(set->p[0], 8727 dim, &v); 8728 for (i = 1; fixed == 1 && i < set->n; ++i) { 8729 fixed = isl_basic_set_plain_dim_has_fixed_lower_bound(set->p[i], 8730 dim, &tmp); 8731 if (fixed == 1 && isl_int_ne(tmp, v)) 8732 fixed = 0; 8733 } 8734 if (val) 8735 isl_int_set(*val, v); 8736 isl_int_clear(tmp); 8737 isl_int_clear(v); 8738 return fixed; 8739} 8740 8741struct constraint { 8742 unsigned size; 8743 isl_int *c; 8744}; 8745 8746/* uset_gist depends on constraints without existentially quantified 8747 * variables sorting first. 8748 */ 8749static int qsort_constraint_cmp(const void *p1, const void *p2) 8750{ 8751 const struct constraint *c1 = (const struct constraint *)p1; 8752 const struct constraint *c2 = (const struct constraint *)p2; 8753 int l1, l2; 8754 unsigned size = isl_min(c1->size, c2->size); 8755 8756 l1 = isl_seq_last_non_zero(c1->c + 1, size); 8757 l2 = isl_seq_last_non_zero(c2->c + 1, size); 8758 8759 if (l1 != l2) 8760 return l1 - l2; 8761 8762 return isl_seq_cmp(c1->c + 1, c2->c + 1, size); 8763} 8764 8765static struct isl_basic_map *isl_basic_map_sort_constraints( 8766 struct isl_basic_map *bmap) 8767{ 8768 int i; 8769 struct constraint *c; 8770 unsigned total; 8771 8772 if (!bmap) 8773 return NULL; 8774 if (bmap->n_ineq == 0) 8775 return bmap; 8776 total = isl_basic_map_total_dim(bmap); 8777 c = isl_alloc_array(bmap->ctx, struct constraint, bmap->n_ineq); 8778 if (!c) 8779 goto error; 8780 for (i = 0; i < bmap->n_ineq; ++i) { 8781 c[i].size = total; 8782 c[i].c = bmap->ineq[i]; 8783 } 8784 qsort(c, bmap->n_ineq, sizeof(struct constraint), qsort_constraint_cmp); 8785 for (i = 0; i < bmap->n_ineq; ++i) 8786 bmap->ineq[i] = c[i].c; 8787 free(c); 8788 return bmap; 8789error: 8790 isl_basic_map_free(bmap); 8791 return NULL; 8792} 8793 8794__isl_give isl_basic_set *isl_basic_set_sort_constraints( 8795 __isl_take isl_basic_set *bset) 8796{ 8797 return (struct isl_basic_set *)isl_basic_map_sort_constraints( 8798 (struct isl_basic_map *)bset); 8799} 8800 8801struct isl_basic_map *isl_basic_map_normalize(struct isl_basic_map *bmap) 8802{ 8803 if (!bmap) 8804 return NULL; 8805 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_NORMALIZED)) 8806 return bmap; 8807 bmap = isl_basic_map_remove_redundancies(bmap); 8808 bmap = isl_basic_map_sort_constraints(bmap); 8809 if (bmap) 8810 ISL_F_SET(bmap, ISL_BASIC_MAP_NORMALIZED); 8811 return bmap; 8812} 8813 8814struct isl_basic_set *isl_basic_set_normalize(struct isl_basic_set *bset) 8815{ 8816 return (struct isl_basic_set *)isl_basic_map_normalize( 8817 (struct isl_basic_map *)bset); 8818} 8819 8820int isl_basic_map_plain_cmp(const __isl_keep isl_basic_map *bmap1, 8821 const __isl_keep isl_basic_map *bmap2) 8822{ 8823 int i, cmp; 8824 unsigned total; 8825 8826 if (bmap1 == bmap2) 8827 return 0; 8828 if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_RATIONAL) != 8829 ISL_F_ISSET(bmap2, ISL_BASIC_MAP_RATIONAL)) 8830 return ISL_F_ISSET(bmap1, ISL_BASIC_MAP_RATIONAL) ? -1 : 1; 8831 if (isl_basic_map_n_param(bmap1) != isl_basic_map_n_param(bmap2)) 8832 return isl_basic_map_n_param(bmap1) - isl_basic_map_n_param(bmap2); 8833 if (isl_basic_map_n_in(bmap1) != isl_basic_map_n_in(bmap2)) 8834 return isl_basic_map_n_out(bmap1) - isl_basic_map_n_out(bmap2); 8835 if (isl_basic_map_n_out(bmap1) != isl_basic_map_n_out(bmap2)) 8836 return isl_basic_map_n_out(bmap1) - isl_basic_map_n_out(bmap2); 8837 if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_EMPTY) && 8838 ISL_F_ISSET(bmap2, ISL_BASIC_MAP_EMPTY)) 8839 return 0; 8840 if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_EMPTY)) 8841 return 1; 8842 if (ISL_F_ISSET(bmap2, ISL_BASIC_MAP_EMPTY)) 8843 return -1; 8844 if (bmap1->n_eq != bmap2->n_eq) 8845 return bmap1->n_eq - bmap2->n_eq; 8846 if (bmap1->n_ineq != bmap2->n_ineq) 8847 return bmap1->n_ineq - bmap2->n_ineq; 8848 if (bmap1->n_div != bmap2->n_div) 8849 return bmap1->n_div - bmap2->n_div; 8850 total = isl_basic_map_total_dim(bmap1); 8851 for (i = 0; i < bmap1->n_eq; ++i) { 8852 cmp = isl_seq_cmp(bmap1->eq[i], bmap2->eq[i], 1+total); 8853 if (cmp) 8854 return cmp; 8855 } 8856 for (i = 0; i < bmap1->n_ineq; ++i) { 8857 cmp = isl_seq_cmp(bmap1->ineq[i], bmap2->ineq[i], 1+total); 8858 if (cmp) 8859 return cmp; 8860 } 8861 for (i = 0; i < bmap1->n_div; ++i) { 8862 cmp = isl_seq_cmp(bmap1->div[i], bmap2->div[i], 1+1+total); 8863 if (cmp) 8864 return cmp; 8865 } 8866 return 0; 8867} 8868 8869int isl_basic_set_plain_cmp(const __isl_keep isl_basic_set *bset1, 8870 const __isl_keep isl_basic_set *bset2) 8871{ 8872 return isl_basic_map_plain_cmp(bset1, bset2); 8873} 8874 8875int isl_set_plain_cmp(__isl_keep isl_set *set1, __isl_keep isl_set *set2) 8876{ 8877 int i, cmp; 8878 8879 if (set1 == set2) 8880 return 0; 8881 if (set1->n != set2->n) 8882 return set1->n - set2->n; 8883 8884 for (i = 0; i < set1->n; ++i) { 8885 cmp = isl_basic_set_plain_cmp(set1->p[i], set2->p[i]); 8886 if (cmp) 8887 return cmp; 8888 } 8889 8890 return 0; 8891} 8892 8893int isl_basic_map_plain_is_equal(__isl_keep isl_basic_map *bmap1, 8894 __isl_keep isl_basic_map *bmap2) 8895{ 8896 return isl_basic_map_plain_cmp(bmap1, bmap2) == 0; 8897} 8898 8899int isl_basic_set_plain_is_equal(__isl_keep isl_basic_set *bset1, 8900 __isl_keep isl_basic_set *bset2) 8901{ 8902 return isl_basic_map_plain_is_equal((isl_basic_map *)bset1, 8903 (isl_basic_map *)bset2); 8904} 8905 8906static int qsort_bmap_cmp(const void *p1, const void *p2) 8907{ 8908 const struct isl_basic_map *bmap1 = *(const struct isl_basic_map **)p1; 8909 const struct isl_basic_map *bmap2 = *(const struct isl_basic_map **)p2; 8910 8911 return isl_basic_map_plain_cmp(bmap1, bmap2); 8912} 8913 8914/* We normalize in place, but if anything goes wrong we need 8915 * to return NULL, so we need to make sure we don't change the 8916 * meaning of any possible other copies of map. 8917 */ 8918struct isl_map *isl_map_normalize(struct isl_map *map) 8919{ 8920 int i, j; 8921 struct isl_basic_map *bmap; 8922 8923 if (!map) 8924 return NULL; 8925 if (ISL_F_ISSET(map, ISL_MAP_NORMALIZED)) 8926 return map; 8927 for (i = 0; i < map->n; ++i) { 8928 bmap = isl_basic_map_normalize(isl_basic_map_copy(map->p[i])); 8929 if (!bmap) 8930 goto error; 8931 isl_basic_map_free(map->p[i]); 8932 map->p[i] = bmap; 8933 } 8934 qsort(map->p, map->n, sizeof(struct isl_basic_map *), qsort_bmap_cmp); 8935 ISL_F_SET(map, ISL_MAP_NORMALIZED); 8936 map = isl_map_remove_empty_parts(map); 8937 if (!map) 8938 return NULL; 8939 for (i = map->n - 1; i >= 1; --i) { 8940 if (!isl_basic_map_plain_is_equal(map->p[i-1], map->p[i])) 8941 continue; 8942 isl_basic_map_free(map->p[i-1]); 8943 for (j = i; j < map->n; ++j) 8944 map->p[j-1] = map->p[j]; 8945 map->n--; 8946 } 8947 return map; 8948error: 8949 isl_map_free(map); 8950 return NULL; 8951 8952} 8953 8954struct isl_set *isl_set_normalize(struct isl_set *set) 8955{ 8956 return (struct isl_set *)isl_map_normalize((struct isl_map *)set); 8957} 8958 8959int isl_map_plain_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2) 8960{ 8961 int i; 8962 int equal; 8963 8964 if (!map1 || !map2) 8965 return -1; 8966 8967 if (map1 == map2) 8968 return 1; 8969 if (!isl_space_is_equal(map1->dim, map2->dim)) 8970 return 0; 8971 8972 map1 = isl_map_copy(map1); 8973 map2 = isl_map_copy(map2); 8974 map1 = isl_map_normalize(map1); 8975 map2 = isl_map_normalize(map2); 8976 if (!map1 || !map2) 8977 goto error; 8978 equal = map1->n == map2->n; 8979 for (i = 0; equal && i < map1->n; ++i) { 8980 equal = isl_basic_map_plain_is_equal(map1->p[i], map2->p[i]); 8981 if (equal < 0) 8982 goto error; 8983 } 8984 isl_map_free(map1); 8985 isl_map_free(map2); 8986 return equal; 8987error: 8988 isl_map_free(map1); 8989 isl_map_free(map2); 8990 return -1; 8991} 8992 8993int isl_map_fast_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2) 8994{ 8995 return isl_map_plain_is_equal(map1, map2); 8996} 8997 8998int isl_set_plain_is_equal(__isl_keep isl_set *set1, __isl_keep isl_set *set2) 8999{ 9000 return isl_map_plain_is_equal((struct isl_map *)set1, 9001 (struct isl_map *)set2); 9002} 9003 9004int isl_set_fast_is_equal(__isl_keep isl_set *set1, __isl_keep isl_set *set2) 9005{ 9006 return isl_set_plain_is_equal(set1, set2); 9007} 9008 9009/* Return an interval that ranges from min to max (inclusive) 9010 */ 9011struct isl_basic_set *isl_basic_set_interval(struct isl_ctx *ctx, 9012 isl_int min, isl_int max) 9013{ 9014 int k; 9015 struct isl_basic_set *bset = NULL; 9016 9017 bset = isl_basic_set_alloc(ctx, 0, 1, 0, 0, 2); 9018 if (!bset) 9019 goto error; 9020 9021 k = isl_basic_set_alloc_inequality(bset); 9022 if (k < 0) 9023 goto error; 9024 isl_int_set_si(bset->ineq[k][1], 1); 9025 isl_int_neg(bset->ineq[k][0], min); 9026 9027 k = isl_basic_set_alloc_inequality(bset); 9028 if (k < 0) 9029 goto error; 9030 isl_int_set_si(bset->ineq[k][1], -1); 9031 isl_int_set(bset->ineq[k][0], max); 9032 9033 return bset; 9034error: 9035 isl_basic_set_free(bset); 9036 return NULL; 9037} 9038 9039/* Return the Cartesian product of the basic sets in list (in the given order). 9040 */ 9041__isl_give isl_basic_set *isl_basic_set_list_product( 9042 __isl_take struct isl_basic_set_list *list) 9043{ 9044 int i; 9045 unsigned dim; 9046 unsigned nparam; 9047 unsigned extra; 9048 unsigned n_eq; 9049 unsigned n_ineq; 9050 struct isl_basic_set *product = NULL; 9051 9052 if (!list) 9053 goto error; 9054 isl_assert(list->ctx, list->n > 0, goto error); 9055 isl_assert(list->ctx, list->p[0], goto error); 9056 nparam = isl_basic_set_n_param(list->p[0]); 9057 dim = isl_basic_set_n_dim(list->p[0]); 9058 extra = list->p[0]->n_div; 9059 n_eq = list->p[0]->n_eq; 9060 n_ineq = list->p[0]->n_ineq; 9061 for (i = 1; i < list->n; ++i) { 9062 isl_assert(list->ctx, list->p[i], goto error); 9063 isl_assert(list->ctx, 9064 nparam == isl_basic_set_n_param(list->p[i]), goto error); 9065 dim += isl_basic_set_n_dim(list->p[i]); 9066 extra += list->p[i]->n_div; 9067 n_eq += list->p[i]->n_eq; 9068 n_ineq += list->p[i]->n_ineq; 9069 } 9070 product = isl_basic_set_alloc(list->ctx, nparam, dim, extra, 9071 n_eq, n_ineq); 9072 if (!product) 9073 goto error; 9074 dim = 0; 9075 for (i = 0; i < list->n; ++i) { 9076 isl_basic_set_add_constraints(product, 9077 isl_basic_set_copy(list->p[i]), dim); 9078 dim += isl_basic_set_n_dim(list->p[i]); 9079 } 9080 isl_basic_set_list_free(list); 9081 return product; 9082error: 9083 isl_basic_set_free(product); 9084 isl_basic_set_list_free(list); 9085 return NULL; 9086} 9087 9088struct isl_basic_map *isl_basic_map_product( 9089 struct isl_basic_map *bmap1, struct isl_basic_map *bmap2) 9090{ 9091 isl_space *dim_result = NULL; 9092 struct isl_basic_map *bmap; 9093 unsigned in1, in2, out1, out2, nparam, total, pos; 9094 struct isl_dim_map *dim_map1, *dim_map2; 9095 9096 if (!bmap1 || !bmap2) 9097 goto error; 9098 9099 isl_assert(bmap1->ctx, isl_space_match(bmap1->dim, isl_dim_param, 9100 bmap2->dim, isl_dim_param), goto error); 9101 dim_result = isl_space_product(isl_space_copy(bmap1->dim), 9102 isl_space_copy(bmap2->dim)); 9103 9104 in1 = isl_basic_map_n_in(bmap1); 9105 in2 = isl_basic_map_n_in(bmap2); 9106 out1 = isl_basic_map_n_out(bmap1); 9107 out2 = isl_basic_map_n_out(bmap2); 9108 nparam = isl_basic_map_n_param(bmap1); 9109 9110 total = nparam + in1 + in2 + out1 + out2 + bmap1->n_div + bmap2->n_div; 9111 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total); 9112 dim_map2 = isl_dim_map_alloc(bmap1->ctx, total); 9113 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0); 9114 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0); 9115 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam); 9116 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos += in1); 9117 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in2); 9118 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += out1); 9119 isl_dim_map_div(dim_map1, bmap1, pos += out2); 9120 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div); 9121 9122 bmap = isl_basic_map_alloc_space(dim_result, 9123 bmap1->n_div + bmap2->n_div, 9124 bmap1->n_eq + bmap2->n_eq, 9125 bmap1->n_ineq + bmap2->n_ineq); 9126 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1); 9127 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2); 9128 bmap = isl_basic_map_simplify(bmap); 9129 return isl_basic_map_finalize(bmap); 9130error: 9131 isl_basic_map_free(bmap1); 9132 isl_basic_map_free(bmap2); 9133 return NULL; 9134} 9135 9136__isl_give isl_basic_map *isl_basic_map_flat_product( 9137 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2) 9138{ 9139 isl_basic_map *prod; 9140 9141 prod = isl_basic_map_product(bmap1, bmap2); 9142 prod = isl_basic_map_flatten(prod); 9143 return prod; 9144} 9145 9146__isl_give isl_basic_set *isl_basic_set_flat_product( 9147 __isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2) 9148{ 9149 return isl_basic_map_flat_range_product(bset1, bset2); 9150} 9151 9152__isl_give isl_basic_map *isl_basic_map_domain_product( 9153 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2) 9154{ 9155 isl_space *space_result = NULL; 9156 isl_basic_map *bmap; 9157 unsigned in1, in2, out, nparam, total, pos; 9158 struct isl_dim_map *dim_map1, *dim_map2; 9159 9160 if (!bmap1 || !bmap2) 9161 goto error; 9162 9163 space_result = isl_space_domain_product(isl_space_copy(bmap1->dim), 9164 isl_space_copy(bmap2->dim)); 9165 9166 in1 = isl_basic_map_dim(bmap1, isl_dim_in); 9167 in2 = isl_basic_map_dim(bmap2, isl_dim_in); 9168 out = isl_basic_map_dim(bmap1, isl_dim_out); 9169 nparam = isl_basic_map_dim(bmap1, isl_dim_param); 9170 9171 total = nparam + in1 + in2 + out + bmap1->n_div + bmap2->n_div; 9172 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total); 9173 dim_map2 = isl_dim_map_alloc(bmap1->ctx, total); 9174 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0); 9175 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0); 9176 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam); 9177 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos += in1); 9178 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in2); 9179 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos); 9180 isl_dim_map_div(dim_map1, bmap1, pos += out); 9181 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div); 9182 9183 bmap = isl_basic_map_alloc_space(space_result, 9184 bmap1->n_div + bmap2->n_div, 9185 bmap1->n_eq + bmap2->n_eq, 9186 bmap1->n_ineq + bmap2->n_ineq); 9187 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1); 9188 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2); 9189 bmap = isl_basic_map_simplify(bmap); 9190 return isl_basic_map_finalize(bmap); 9191error: 9192 isl_basic_map_free(bmap1); 9193 isl_basic_map_free(bmap2); 9194 return NULL; 9195} 9196 9197__isl_give isl_basic_map *isl_basic_map_range_product( 9198 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2) 9199{ 9200 isl_space *dim_result = NULL; 9201 isl_basic_map *bmap; 9202 unsigned in, out1, out2, nparam, total, pos; 9203 struct isl_dim_map *dim_map1, *dim_map2; 9204 9205 if (!bmap1 || !bmap2) 9206 goto error; 9207 9208 if (!isl_space_match(bmap1->dim, isl_dim_param, 9209 bmap2->dim, isl_dim_param)) 9210 isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid, 9211 "parameters don't match", goto error); 9212 9213 dim_result = isl_space_range_product(isl_space_copy(bmap1->dim), 9214 isl_space_copy(bmap2->dim)); 9215 9216 in = isl_basic_map_dim(bmap1, isl_dim_in); 9217 out1 = isl_basic_map_n_out(bmap1); 9218 out2 = isl_basic_map_n_out(bmap2); 9219 nparam = isl_basic_map_n_param(bmap1); 9220 9221 total = nparam + in + out1 + out2 + bmap1->n_div + bmap2->n_div; 9222 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total); 9223 dim_map2 = isl_dim_map_alloc(bmap1->ctx, total); 9224 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0); 9225 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0); 9226 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam); 9227 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos); 9228 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in); 9229 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += out1); 9230 isl_dim_map_div(dim_map1, bmap1, pos += out2); 9231 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div); 9232 9233 bmap = isl_basic_map_alloc_space(dim_result, 9234 bmap1->n_div + bmap2->n_div, 9235 bmap1->n_eq + bmap2->n_eq, 9236 bmap1->n_ineq + bmap2->n_ineq); 9237 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1); 9238 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2); 9239 bmap = isl_basic_map_simplify(bmap); 9240 return isl_basic_map_finalize(bmap); 9241error: 9242 isl_basic_map_free(bmap1); 9243 isl_basic_map_free(bmap2); 9244 return NULL; 9245} 9246 9247__isl_give isl_basic_map *isl_basic_map_flat_range_product( 9248 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2) 9249{ 9250 isl_basic_map *prod; 9251 9252 prod = isl_basic_map_range_product(bmap1, bmap2); 9253 prod = isl_basic_map_flatten_range(prod); 9254 return prod; 9255} 9256 9257static __isl_give isl_map *map_product(__isl_take isl_map *map1, 9258 __isl_take isl_map *map2, 9259 __isl_give isl_space *(*dim_product)(__isl_take isl_space *left, 9260 __isl_take isl_space *right), 9261 __isl_give isl_basic_map *(*basic_map_product)( 9262 __isl_take isl_basic_map *left, __isl_take isl_basic_map *right)) 9263{ 9264 unsigned flags = 0; 9265 struct isl_map *result; 9266 int i, j; 9267 9268 if (!map1 || !map2) 9269 goto error; 9270 9271 isl_assert(map1->ctx, isl_space_match(map1->dim, isl_dim_param, 9272 map2->dim, isl_dim_param), goto error); 9273 9274 if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) && 9275 ISL_F_ISSET(map2, ISL_MAP_DISJOINT)) 9276 ISL_FL_SET(flags, ISL_MAP_DISJOINT); 9277 9278 result = isl_map_alloc_space(dim_product(isl_space_copy(map1->dim), 9279 isl_space_copy(map2->dim)), 9280 map1->n * map2->n, flags); 9281 if (!result) 9282 goto error; 9283 for (i = 0; i < map1->n; ++i) 9284 for (j = 0; j < map2->n; ++j) { 9285 struct isl_basic_map *part; 9286 part = basic_map_product(isl_basic_map_copy(map1->p[i]), 9287 isl_basic_map_copy(map2->p[j])); 9288 if (isl_basic_map_is_empty(part)) 9289 isl_basic_map_free(part); 9290 else 9291 result = isl_map_add_basic_map(result, part); 9292 if (!result) 9293 goto error; 9294 } 9295 isl_map_free(map1); 9296 isl_map_free(map2); 9297 return result; 9298error: 9299 isl_map_free(map1); 9300 isl_map_free(map2); 9301 return NULL; 9302} 9303 9304/* Given two maps A -> B and C -> D, construct a map [A -> C] -> [B -> D] 9305 */ 9306static __isl_give isl_map *map_product_aligned(__isl_take isl_map *map1, 9307 __isl_take isl_map *map2) 9308{ 9309 return map_product(map1, map2, &isl_space_product, &isl_basic_map_product); 9310} 9311 9312__isl_give isl_map *isl_map_product(__isl_take isl_map *map1, 9313 __isl_take isl_map *map2) 9314{ 9315 return isl_map_align_params_map_map_and(map1, map2, &map_product_aligned); 9316} 9317 9318/* Given two maps A -> B and C -> D, construct a map (A, C) -> (B, D) 9319 */ 9320__isl_give isl_map *isl_map_flat_product(__isl_take isl_map *map1, 9321 __isl_take isl_map *map2) 9322{ 9323 isl_map *prod; 9324 9325 prod = isl_map_product(map1, map2); 9326 prod = isl_map_flatten(prod); 9327 return prod; 9328} 9329 9330/* Given two set A and B, construct its Cartesian product A x B. 9331 */ 9332struct isl_set *isl_set_product(struct isl_set *set1, struct isl_set *set2) 9333{ 9334 return isl_map_range_product(set1, set2); 9335} 9336 9337__isl_give isl_set *isl_set_flat_product(__isl_take isl_set *set1, 9338 __isl_take isl_set *set2) 9339{ 9340 return isl_map_flat_range_product(set1, set2); 9341} 9342 9343/* Given two maps A -> B and C -> D, construct a map [A -> C] -> (B * D) 9344 */ 9345static __isl_give isl_map *map_domain_product_aligned(__isl_take isl_map *map1, 9346 __isl_take isl_map *map2) 9347{ 9348 return map_product(map1, map2, &isl_space_domain_product, 9349 &isl_basic_map_domain_product); 9350} 9351 9352/* Given two maps A -> B and C -> D, construct a map (A * C) -> [B -> D] 9353 */ 9354static __isl_give isl_map *map_range_product_aligned(__isl_take isl_map *map1, 9355 __isl_take isl_map *map2) 9356{ 9357 return map_product(map1, map2, &isl_space_range_product, 9358 &isl_basic_map_range_product); 9359} 9360 9361__isl_give isl_map *isl_map_domain_product(__isl_take isl_map *map1, 9362 __isl_take isl_map *map2) 9363{ 9364 return isl_map_align_params_map_map_and(map1, map2, 9365 &map_domain_product_aligned); 9366} 9367 9368__isl_give isl_map *isl_map_range_product(__isl_take isl_map *map1, 9369 __isl_take isl_map *map2) 9370{ 9371 return isl_map_align_params_map_map_and(map1, map2, 9372 &map_range_product_aligned); 9373} 9374 9375/* Given two maps A -> B and C -> D, construct a map (A, C) -> (B * D) 9376 */ 9377__isl_give isl_map *isl_map_flat_domain_product(__isl_take isl_map *map1, 9378 __isl_take isl_map *map2) 9379{ 9380 isl_map *prod; 9381 9382 prod = isl_map_domain_product(map1, map2); 9383 prod = isl_map_flatten_domain(prod); 9384 return prod; 9385} 9386 9387/* Given two maps A -> B and C -> D, construct a map (A * C) -> (B, D) 9388 */ 9389__isl_give isl_map *isl_map_flat_range_product(__isl_take isl_map *map1, 9390 __isl_take isl_map *map2) 9391{ 9392 isl_map *prod; 9393 9394 prod = isl_map_range_product(map1, map2); 9395 prod = isl_map_flatten_range(prod); 9396 return prod; 9397} 9398 9399uint32_t isl_basic_map_get_hash(__isl_keep isl_basic_map *bmap) 9400{ 9401 int i; 9402 uint32_t hash = isl_hash_init(); 9403 unsigned total; 9404 9405 if (!bmap) 9406 return 0; 9407 bmap = isl_basic_map_copy(bmap); 9408 bmap = isl_basic_map_normalize(bmap); 9409 if (!bmap) 9410 return 0; 9411 total = isl_basic_map_total_dim(bmap); 9412 isl_hash_byte(hash, bmap->n_eq & 0xFF); 9413 for (i = 0; i < bmap->n_eq; ++i) { 9414 uint32_t c_hash; 9415 c_hash = isl_seq_get_hash(bmap->eq[i], 1 + total); 9416 isl_hash_hash(hash, c_hash); 9417 } 9418 isl_hash_byte(hash, bmap->n_ineq & 0xFF); 9419 for (i = 0; i < bmap->n_ineq; ++i) { 9420 uint32_t c_hash; 9421 c_hash = isl_seq_get_hash(bmap->ineq[i], 1 + total); 9422 isl_hash_hash(hash, c_hash); 9423 } 9424 isl_hash_byte(hash, bmap->n_div & 0xFF); 9425 for (i = 0; i < bmap->n_div; ++i) { 9426 uint32_t c_hash; 9427 if (isl_int_is_zero(bmap->div[i][0])) 9428 continue; 9429 isl_hash_byte(hash, i & 0xFF); 9430 c_hash = isl_seq_get_hash(bmap->div[i], 1 + 1 + total); 9431 isl_hash_hash(hash, c_hash); 9432 } 9433 isl_basic_map_free(bmap); 9434 return hash; 9435} 9436 9437uint32_t isl_basic_set_get_hash(__isl_keep isl_basic_set *bset) 9438{ 9439 return isl_basic_map_get_hash((isl_basic_map *)bset); 9440} 9441 9442uint32_t isl_map_get_hash(__isl_keep isl_map *map) 9443{ 9444 int i; 9445 uint32_t hash; 9446 9447 if (!map) 9448 return 0; 9449 map = isl_map_copy(map); 9450 map = isl_map_normalize(map); 9451 if (!map) 9452 return 0; 9453 9454 hash = isl_hash_init(); 9455 for (i = 0; i < map->n; ++i) { 9456 uint32_t bmap_hash; 9457 bmap_hash = isl_basic_map_get_hash(map->p[i]); 9458 isl_hash_hash(hash, bmap_hash); 9459 } 9460 9461 isl_map_free(map); 9462 9463 return hash; 9464} 9465 9466uint32_t isl_set_get_hash(__isl_keep isl_set *set) 9467{ 9468 return isl_map_get_hash((isl_map *)set); 9469} 9470 9471/* Check if the value for dimension dim is completely determined 9472 * by the values of the other parameters and variables. 9473 * That is, check if dimension dim is involved in an equality. 9474 */ 9475int isl_basic_set_dim_is_unique(struct isl_basic_set *bset, unsigned dim) 9476{ 9477 int i; 9478 unsigned nparam; 9479 9480 if (!bset) 9481 return -1; 9482 nparam = isl_basic_set_n_param(bset); 9483 for (i = 0; i < bset->n_eq; ++i) 9484 if (!isl_int_is_zero(bset->eq[i][1 + nparam + dim])) 9485 return 1; 9486 return 0; 9487} 9488 9489/* Check if the value for dimension dim is completely determined 9490 * by the values of the other parameters and variables. 9491 * That is, check if dimension dim is involved in an equality 9492 * for each of the subsets. 9493 */ 9494int isl_set_dim_is_unique(struct isl_set *set, unsigned dim) 9495{ 9496 int i; 9497 9498 if (!set) 9499 return -1; 9500 for (i = 0; i < set->n; ++i) { 9501 int unique; 9502 unique = isl_basic_set_dim_is_unique(set->p[i], dim); 9503 if (unique != 1) 9504 return unique; 9505 } 9506 return 1; 9507} 9508 9509int isl_set_n_basic_set(__isl_keep isl_set *set) 9510{ 9511 return set ? set->n : 0; 9512} 9513 9514int isl_map_foreach_basic_map(__isl_keep isl_map *map, 9515 int (*fn)(__isl_take isl_basic_map *bmap, void *user), void *user) 9516{ 9517 int i; 9518 9519 if (!map) 9520 return -1; 9521 9522 for (i = 0; i < map->n; ++i) 9523 if (fn(isl_basic_map_copy(map->p[i]), user) < 0) 9524 return -1; 9525 9526 return 0; 9527} 9528 9529int isl_set_foreach_basic_set(__isl_keep isl_set *set, 9530 int (*fn)(__isl_take isl_basic_set *bset, void *user), void *user) 9531{ 9532 int i; 9533 9534 if (!set) 9535 return -1; 9536 9537 for (i = 0; i < set->n; ++i) 9538 if (fn(isl_basic_set_copy(set->p[i]), user) < 0) 9539 return -1; 9540 9541 return 0; 9542} 9543 9544__isl_give isl_basic_set *isl_basic_set_lift(__isl_take isl_basic_set *bset) 9545{ 9546 isl_space *dim; 9547 9548 if (!bset) 9549 return NULL; 9550 9551 bset = isl_basic_set_cow(bset); 9552 if (!bset) 9553 return NULL; 9554 9555 dim = isl_basic_set_get_space(bset); 9556 dim = isl_space_lift(dim, bset->n_div); 9557 if (!dim) 9558 goto error; 9559 isl_space_free(bset->dim); 9560 bset->dim = dim; 9561 bset->extra -= bset->n_div; 9562 bset->n_div = 0; 9563 9564 bset = isl_basic_set_finalize(bset); 9565 9566 return bset; 9567error: 9568 isl_basic_set_free(bset); 9569 return NULL; 9570} 9571 9572__isl_give isl_set *isl_set_lift(__isl_take isl_set *set) 9573{ 9574 int i; 9575 isl_space *dim; 9576 unsigned n_div; 9577 9578 set = isl_set_align_divs(set); 9579 9580 if (!set) 9581 return NULL; 9582 9583 set = isl_set_cow(set); 9584 if (!set) 9585 return NULL; 9586 9587 n_div = set->p[0]->n_div; 9588 dim = isl_set_get_space(set); 9589 dim = isl_space_lift(dim, n_div); 9590 if (!dim) 9591 goto error; 9592 isl_space_free(set->dim); 9593 set->dim = dim; 9594 9595 for (i = 0; i < set->n; ++i) { 9596 set->p[i] = isl_basic_set_lift(set->p[i]); 9597 if (!set->p[i]) 9598 goto error; 9599 } 9600 9601 return set; 9602error: 9603 isl_set_free(set); 9604 return NULL; 9605} 9606 9607__isl_give isl_map *isl_set_lifting(__isl_take isl_set *set) 9608{ 9609 isl_space *dim; 9610 struct isl_basic_map *bmap; 9611 unsigned n_set; 9612 unsigned n_div; 9613 unsigned n_param; 9614 unsigned total; 9615 int i, k, l; 9616 9617 set = isl_set_align_divs(set); 9618 9619 if (!set) 9620 return NULL; 9621 9622 dim = isl_set_get_space(set); 9623 if (set->n == 0 || set->p[0]->n_div == 0) { 9624 isl_set_free(set); 9625 return isl_map_identity(isl_space_map_from_set(dim)); 9626 } 9627 9628 n_div = set->p[0]->n_div; 9629 dim = isl_space_map_from_set(dim); 9630 n_param = isl_space_dim(dim, isl_dim_param); 9631 n_set = isl_space_dim(dim, isl_dim_in); 9632 dim = isl_space_extend(dim, n_param, n_set, n_set + n_div); 9633 bmap = isl_basic_map_alloc_space(dim, 0, n_set, 2 * n_div); 9634 for (i = 0; i < n_set; ++i) 9635 bmap = var_equal(bmap, i); 9636 9637 total = n_param + n_set + n_set + n_div; 9638 for (i = 0; i < n_div; ++i) { 9639 k = isl_basic_map_alloc_inequality(bmap); 9640 if (k < 0) 9641 goto error; 9642 isl_seq_cpy(bmap->ineq[k], set->p[0]->div[i]+1, 1+n_param); 9643 isl_seq_clr(bmap->ineq[k]+1+n_param, n_set); 9644 isl_seq_cpy(bmap->ineq[k]+1+n_param+n_set, 9645 set->p[0]->div[i]+1+1+n_param, n_set + n_div); 9646 isl_int_neg(bmap->ineq[k][1+n_param+n_set+n_set+i], 9647 set->p[0]->div[i][0]); 9648 9649 l = isl_basic_map_alloc_inequality(bmap); 9650 if (l < 0) 9651 goto error; 9652 isl_seq_neg(bmap->ineq[l], bmap->ineq[k], 1 + total); 9653 isl_int_add(bmap->ineq[l][0], bmap->ineq[l][0], 9654 set->p[0]->div[i][0]); 9655 isl_int_sub_ui(bmap->ineq[l][0], bmap->ineq[l][0], 1); 9656 } 9657 9658 isl_set_free(set); 9659 bmap = isl_basic_map_simplify(bmap); 9660 bmap = isl_basic_map_finalize(bmap); 9661 return isl_map_from_basic_map(bmap); 9662error: 9663 isl_set_free(set); 9664 isl_basic_map_free(bmap); 9665 return NULL; 9666} 9667 9668int isl_basic_set_size(__isl_keep isl_basic_set *bset) 9669{ 9670 unsigned dim; 9671 int size = 0; 9672 9673 if (!bset) 9674 return -1; 9675 9676 dim = isl_basic_set_total_dim(bset); 9677 size += bset->n_eq * (1 + dim); 9678 size += bset->n_ineq * (1 + dim); 9679 size += bset->n_div * (2 + dim); 9680 9681 return size; 9682} 9683 9684int isl_set_size(__isl_keep isl_set *set) 9685{ 9686 int i; 9687 int size = 0; 9688 9689 if (!set) 9690 return -1; 9691 9692 for (i = 0; i < set->n; ++i) 9693 size += isl_basic_set_size(set->p[i]); 9694 9695 return size; 9696} 9697 9698/* Check if there is any lower bound (if lower == 0) and/or upper 9699 * bound (if upper == 0) on the specified dim. 9700 */ 9701static int basic_map_dim_is_bounded(__isl_keep isl_basic_map *bmap, 9702 enum isl_dim_type type, unsigned pos, int lower, int upper) 9703{ 9704 int i; 9705 9706 if (!bmap) 9707 return -1; 9708 9709 isl_assert(bmap->ctx, pos < isl_basic_map_dim(bmap, type), return -1); 9710 9711 pos += isl_basic_map_offset(bmap, type); 9712 9713 for (i = 0; i < bmap->n_div; ++i) { 9714 if (isl_int_is_zero(bmap->div[i][0])) 9715 continue; 9716 if (!isl_int_is_zero(bmap->div[i][1 + pos])) 9717 return 1; 9718 } 9719 9720 for (i = 0; i < bmap->n_eq; ++i) 9721 if (!isl_int_is_zero(bmap->eq[i][pos])) 9722 return 1; 9723 9724 for (i = 0; i < bmap->n_ineq; ++i) { 9725 int sgn = isl_int_sgn(bmap->ineq[i][pos]); 9726 if (sgn > 0) 9727 lower = 1; 9728 if (sgn < 0) 9729 upper = 1; 9730 } 9731 9732 return lower && upper; 9733} 9734 9735int isl_basic_map_dim_is_bounded(__isl_keep isl_basic_map *bmap, 9736 enum isl_dim_type type, unsigned pos) 9737{ 9738 return basic_map_dim_is_bounded(bmap, type, pos, 0, 0); 9739} 9740 9741int isl_basic_map_dim_has_lower_bound(__isl_keep isl_basic_map *bmap, 9742 enum isl_dim_type type, unsigned pos) 9743{ 9744 return basic_map_dim_is_bounded(bmap, type, pos, 0, 1); 9745} 9746 9747int isl_basic_map_dim_has_upper_bound(__isl_keep isl_basic_map *bmap, 9748 enum isl_dim_type type, unsigned pos) 9749{ 9750 return basic_map_dim_is_bounded(bmap, type, pos, 1, 0); 9751} 9752 9753int isl_map_dim_is_bounded(__isl_keep isl_map *map, 9754 enum isl_dim_type type, unsigned pos) 9755{ 9756 int i; 9757 9758 if (!map) 9759 return -1; 9760 9761 for (i = 0; i < map->n; ++i) { 9762 int bounded; 9763 bounded = isl_basic_map_dim_is_bounded(map->p[i], type, pos); 9764 if (bounded < 0 || !bounded) 9765 return bounded; 9766 } 9767 9768 return 1; 9769} 9770 9771/* Return 1 if the specified dim is involved in both an upper bound 9772 * and a lower bound. 9773 */ 9774int isl_set_dim_is_bounded(__isl_keep isl_set *set, 9775 enum isl_dim_type type, unsigned pos) 9776{ 9777 return isl_map_dim_is_bounded((isl_map *)set, type, pos); 9778} 9779 9780/* Does "map" have a bound (according to "fn") for any of its basic maps? 9781 */ 9782static int has_any_bound(__isl_keep isl_map *map, 9783 enum isl_dim_type type, unsigned pos, 9784 int (*fn)(__isl_keep isl_basic_map *bmap, 9785 enum isl_dim_type type, unsigned pos)) 9786{ 9787 int i; 9788 9789 if (!map) 9790 return -1; 9791 9792 for (i = 0; i < map->n; ++i) { 9793 int bounded; 9794 bounded = fn(map->p[i], type, pos); 9795 if (bounded < 0 || bounded) 9796 return bounded; 9797 } 9798 9799 return 0; 9800} 9801 9802/* Return 1 if the specified dim is involved in any lower bound. 9803 */ 9804int isl_set_dim_has_any_lower_bound(__isl_keep isl_set *set, 9805 enum isl_dim_type type, unsigned pos) 9806{ 9807 return has_any_bound(set, type, pos, 9808 &isl_basic_map_dim_has_lower_bound); 9809} 9810 9811/* Return 1 if the specified dim is involved in any upper bound. 9812 */ 9813int isl_set_dim_has_any_upper_bound(__isl_keep isl_set *set, 9814 enum isl_dim_type type, unsigned pos) 9815{ 9816 return has_any_bound(set, type, pos, 9817 &isl_basic_map_dim_has_upper_bound); 9818} 9819 9820/* Does "map" have a bound (according to "fn") for all of its basic maps? 9821 */ 9822static int has_bound(__isl_keep isl_map *map, 9823 enum isl_dim_type type, unsigned pos, 9824 int (*fn)(__isl_keep isl_basic_map *bmap, 9825 enum isl_dim_type type, unsigned pos)) 9826{ 9827 int i; 9828 9829 if (!map) 9830 return -1; 9831 9832 for (i = 0; i < map->n; ++i) { 9833 int bounded; 9834 bounded = fn(map->p[i], type, pos); 9835 if (bounded < 0 || !bounded) 9836 return bounded; 9837 } 9838 9839 return 1; 9840} 9841 9842/* Return 1 if the specified dim has a lower bound (in each of its basic sets). 9843 */ 9844int isl_set_dim_has_lower_bound(__isl_keep isl_set *set, 9845 enum isl_dim_type type, unsigned pos) 9846{ 9847 return has_bound(set, type, pos, &isl_basic_map_dim_has_lower_bound); 9848} 9849 9850/* Return 1 if the specified dim has an upper bound (in each of its basic sets). 9851 */ 9852int isl_set_dim_has_upper_bound(__isl_keep isl_set *set, 9853 enum isl_dim_type type, unsigned pos) 9854{ 9855 return has_bound(set, type, pos, &isl_basic_map_dim_has_upper_bound); 9856} 9857 9858/* For each of the "n" variables starting at "first", determine 9859 * the sign of the variable and put the results in the first "n" 9860 * elements of the array "signs". 9861 * Sign 9862 * 1 means that the variable is non-negative 9863 * -1 means that the variable is non-positive 9864 * 0 means the variable attains both positive and negative values. 9865 */ 9866int isl_basic_set_vars_get_sign(__isl_keep isl_basic_set *bset, 9867 unsigned first, unsigned n, int *signs) 9868{ 9869 isl_vec *bound = NULL; 9870 struct isl_tab *tab = NULL; 9871 struct isl_tab_undo *snap; 9872 int i; 9873 9874 if (!bset || !signs) 9875 return -1; 9876 9877 bound = isl_vec_alloc(bset->ctx, 1 + isl_basic_set_total_dim(bset)); 9878 tab = isl_tab_from_basic_set(bset, 0); 9879 if (!bound || !tab) 9880 goto error; 9881 9882 isl_seq_clr(bound->el, bound->size); 9883 isl_int_set_si(bound->el[0], -1); 9884 9885 snap = isl_tab_snap(tab); 9886 for (i = 0; i < n; ++i) { 9887 int empty; 9888 9889 isl_int_set_si(bound->el[1 + first + i], -1); 9890 if (isl_tab_add_ineq(tab, bound->el) < 0) 9891 goto error; 9892 empty = tab->empty; 9893 isl_int_set_si(bound->el[1 + first + i], 0); 9894 if (isl_tab_rollback(tab, snap) < 0) 9895 goto error; 9896 9897 if (empty) { 9898 signs[i] = 1; 9899 continue; 9900 } 9901 9902 isl_int_set_si(bound->el[1 + first + i], 1); 9903 if (isl_tab_add_ineq(tab, bound->el) < 0) 9904 goto error; 9905 empty = tab->empty; 9906 isl_int_set_si(bound->el[1 + first + i], 0); 9907 if (isl_tab_rollback(tab, snap) < 0) 9908 goto error; 9909 9910 signs[i] = empty ? -1 : 0; 9911 } 9912 9913 isl_tab_free(tab); 9914 isl_vec_free(bound); 9915 return 0; 9916error: 9917 isl_tab_free(tab); 9918 isl_vec_free(bound); 9919 return -1; 9920} 9921 9922int isl_basic_set_dims_get_sign(__isl_keep isl_basic_set *bset, 9923 enum isl_dim_type type, unsigned first, unsigned n, int *signs) 9924{ 9925 if (!bset || !signs) 9926 return -1; 9927 isl_assert(bset->ctx, first + n <= isl_basic_set_dim(bset, type), 9928 return -1); 9929 9930 first += pos(bset->dim, type) - 1; 9931 return isl_basic_set_vars_get_sign(bset, first, n, signs); 9932} 9933 9934/* Check if the given basic map is obviously single-valued. 9935 * In particular, for each output dimension, check that there is 9936 * an equality that defines the output dimension in terms of 9937 * earlier dimensions. 9938 */ 9939int isl_basic_map_plain_is_single_valued(__isl_keep isl_basic_map *bmap) 9940{ 9941 int i, j; 9942 unsigned total; 9943 unsigned n_out; 9944 unsigned o_out; 9945 9946 if (!bmap) 9947 return -1; 9948 9949 total = 1 + isl_basic_map_total_dim(bmap); 9950 n_out = isl_basic_map_dim(bmap, isl_dim_out); 9951 o_out = isl_basic_map_offset(bmap, isl_dim_out); 9952 9953 for (i = 0; i < n_out; ++i) { 9954 for (j = 0; j < bmap->n_eq; ++j) { 9955 if (isl_int_is_zero(bmap->eq[j][o_out + i])) 9956 continue; 9957 if (isl_seq_first_non_zero(bmap->eq[j] + o_out + i + 1, 9958 total - (o_out + i + 1)) == -1) 9959 break; 9960 } 9961 if (j >= bmap->n_eq) 9962 return 0; 9963 } 9964 9965 return 1; 9966} 9967 9968/* Check if the given basic map is single-valued. 9969 * We simply compute 9970 * 9971 * M \circ M^-1 9972 * 9973 * and check if the result is a subset of the identity mapping. 9974 */ 9975int isl_basic_map_is_single_valued(__isl_keep isl_basic_map *bmap) 9976{ 9977 isl_space *space; 9978 isl_basic_map *test; 9979 isl_basic_map *id; 9980 int sv; 9981 9982 sv = isl_basic_map_plain_is_single_valued(bmap); 9983 if (sv < 0 || sv) 9984 return sv; 9985 9986 test = isl_basic_map_reverse(isl_basic_map_copy(bmap)); 9987 test = isl_basic_map_apply_range(test, isl_basic_map_copy(bmap)); 9988 9989 space = isl_basic_map_get_space(bmap); 9990 space = isl_space_map_from_set(isl_space_range(space)); 9991 id = isl_basic_map_identity(space); 9992 9993 sv = isl_basic_map_is_subset(test, id); 9994 9995 isl_basic_map_free(test); 9996 isl_basic_map_free(id); 9997 9998 return sv; 9999} 10000 10001/* Check if the given map is obviously single-valued. 10002 */ 10003int isl_map_plain_is_single_valued(__isl_keep isl_map *map) 10004{ 10005 if (!map) 10006 return -1; 10007 if (map->n == 0) 10008 return 1; 10009 if (map->n >= 2) 10010 return 0; 10011 10012 return isl_basic_map_plain_is_single_valued(map->p[0]); 10013} 10014 10015/* Check if the given map is single-valued. 10016 * We simply compute 10017 * 10018 * M \circ M^-1 10019 * 10020 * and check if the result is a subset of the identity mapping. 10021 */ 10022int isl_map_is_single_valued(__isl_keep isl_map *map) 10023{ 10024 isl_space *dim; 10025 isl_map *test; 10026 isl_map *id; 10027 int sv; 10028 10029 sv = isl_map_plain_is_single_valued(map); 10030 if (sv < 0 || sv) 10031 return sv; 10032 10033 test = isl_map_reverse(isl_map_copy(map)); 10034 test = isl_map_apply_range(test, isl_map_copy(map)); 10035 10036 dim = isl_space_map_from_set(isl_space_range(isl_map_get_space(map))); 10037 id = isl_map_identity(dim); 10038 10039 sv = isl_map_is_subset(test, id); 10040 10041 isl_map_free(test); 10042 isl_map_free(id); 10043 10044 return sv; 10045} 10046 10047int isl_map_is_injective(__isl_keep isl_map *map) 10048{ 10049 int in; 10050 10051 map = isl_map_copy(map); 10052 map = isl_map_reverse(map); 10053 in = isl_map_is_single_valued(map); 10054 isl_map_free(map); 10055 10056 return in; 10057} 10058 10059/* Check if the given map is obviously injective. 10060 */ 10061int isl_map_plain_is_injective(__isl_keep isl_map *map) 10062{ 10063 int in; 10064 10065 map = isl_map_copy(map); 10066 map = isl_map_reverse(map); 10067 in = isl_map_plain_is_single_valued(map); 10068 isl_map_free(map); 10069 10070 return in; 10071} 10072 10073int isl_map_is_bijective(__isl_keep isl_map *map) 10074{ 10075 int sv; 10076 10077 sv = isl_map_is_single_valued(map); 10078 if (sv < 0 || !sv) 10079 return sv; 10080 10081 return isl_map_is_injective(map); 10082} 10083 10084int isl_set_is_singleton(__isl_keep isl_set *set) 10085{ 10086 return isl_map_is_single_valued((isl_map *)set); 10087} 10088 10089int isl_map_is_translation(__isl_keep isl_map *map) 10090{ 10091 int ok; 10092 isl_set *delta; 10093 10094 delta = isl_map_deltas(isl_map_copy(map)); 10095 ok = isl_set_is_singleton(delta); 10096 isl_set_free(delta); 10097 10098 return ok; 10099} 10100 10101static int unique(isl_int *p, unsigned pos, unsigned len) 10102{ 10103 if (isl_seq_first_non_zero(p, pos) != -1) 10104 return 0; 10105 if (isl_seq_first_non_zero(p + pos + 1, len - pos - 1) != -1) 10106 return 0; 10107 return 1; 10108} 10109 10110int isl_basic_set_is_box(__isl_keep isl_basic_set *bset) 10111{ 10112 int i, j; 10113 unsigned nvar; 10114 unsigned ovar; 10115 10116 if (!bset) 10117 return -1; 10118 10119 if (isl_basic_set_dim(bset, isl_dim_div) != 0) 10120 return 0; 10121 10122 nvar = isl_basic_set_dim(bset, isl_dim_set); 10123 ovar = isl_space_offset(bset->dim, isl_dim_set); 10124 for (j = 0; j < nvar; ++j) { 10125 int lower = 0, upper = 0; 10126 for (i = 0; i < bset->n_eq; ++i) { 10127 if (isl_int_is_zero(bset->eq[i][1 + ovar + j])) 10128 continue; 10129 if (!unique(bset->eq[i] + 1 + ovar, j, nvar)) 10130 return 0; 10131 break; 10132 } 10133 if (i < bset->n_eq) 10134 continue; 10135 for (i = 0; i < bset->n_ineq; ++i) { 10136 if (isl_int_is_zero(bset->ineq[i][1 + ovar + j])) 10137 continue; 10138 if (!unique(bset->ineq[i] + 1 + ovar, j, nvar)) 10139 return 0; 10140 if (isl_int_is_pos(bset->ineq[i][1 + ovar + j])) 10141 lower = 1; 10142 else 10143 upper = 1; 10144 } 10145 if (!lower || !upper) 10146 return 0; 10147 } 10148 10149 return 1; 10150} 10151 10152int isl_set_is_box(__isl_keep isl_set *set) 10153{ 10154 if (!set) 10155 return -1; 10156 if (set->n != 1) 10157 return 0; 10158 10159 return isl_basic_set_is_box(set->p[0]); 10160} 10161 10162int isl_basic_set_is_wrapping(__isl_keep isl_basic_set *bset) 10163{ 10164 if (!bset) 10165 return -1; 10166 10167 return isl_space_is_wrapping(bset->dim); 10168} 10169 10170int isl_set_is_wrapping(__isl_keep isl_set *set) 10171{ 10172 if (!set) 10173 return -1; 10174 10175 return isl_space_is_wrapping(set->dim); 10176} 10177 10178__isl_give isl_basic_set *isl_basic_map_wrap(__isl_take isl_basic_map *bmap) 10179{ 10180 bmap = isl_basic_map_cow(bmap); 10181 if (!bmap) 10182 return NULL; 10183 10184 bmap->dim = isl_space_wrap(bmap->dim); 10185 if (!bmap->dim) 10186 goto error; 10187 10188 bmap = isl_basic_map_finalize(bmap); 10189 10190 return (isl_basic_set *)bmap; 10191error: 10192 isl_basic_map_free(bmap); 10193 return NULL; 10194} 10195 10196__isl_give isl_set *isl_map_wrap(__isl_take isl_map *map) 10197{ 10198 int i; 10199 10200 map = isl_map_cow(map); 10201 if (!map) 10202 return NULL; 10203 10204 for (i = 0; i < map->n; ++i) { 10205 map->p[i] = (isl_basic_map *)isl_basic_map_wrap(map->p[i]); 10206 if (!map->p[i]) 10207 goto error; 10208 } 10209 map->dim = isl_space_wrap(map->dim); 10210 if (!map->dim) 10211 goto error; 10212 10213 return (isl_set *)map; 10214error: 10215 isl_map_free(map); 10216 return NULL; 10217} 10218 10219__isl_give isl_basic_map *isl_basic_set_unwrap(__isl_take isl_basic_set *bset) 10220{ 10221 bset = isl_basic_set_cow(bset); 10222 if (!bset) 10223 return NULL; 10224 10225 bset->dim = isl_space_unwrap(bset->dim); 10226 if (!bset->dim) 10227 goto error; 10228 10229 bset = isl_basic_set_finalize(bset); 10230 10231 return (isl_basic_map *)bset; 10232error: 10233 isl_basic_set_free(bset); 10234 return NULL; 10235} 10236 10237__isl_give isl_map *isl_set_unwrap(__isl_take isl_set *set) 10238{ 10239 int i; 10240 10241 if (!set) 10242 return NULL; 10243 10244 if (!isl_set_is_wrapping(set)) 10245 isl_die(set->ctx, isl_error_invalid, "not a wrapping set", 10246 goto error); 10247 10248 set = isl_set_cow(set); 10249 if (!set) 10250 return NULL; 10251 10252 for (i = 0; i < set->n; ++i) { 10253 set->p[i] = (isl_basic_set *)isl_basic_set_unwrap(set->p[i]); 10254 if (!set->p[i]) 10255 goto error; 10256 } 10257 10258 set->dim = isl_space_unwrap(set->dim); 10259 if (!set->dim) 10260 goto error; 10261 10262 return (isl_map *)set; 10263error: 10264 isl_set_free(set); 10265 return NULL; 10266} 10267 10268__isl_give isl_basic_map *isl_basic_map_reset(__isl_take isl_basic_map *bmap, 10269 enum isl_dim_type type) 10270{ 10271 if (!bmap) 10272 return NULL; 10273 10274 if (!isl_space_is_named_or_nested(bmap->dim, type)) 10275 return bmap; 10276 10277 bmap = isl_basic_map_cow(bmap); 10278 if (!bmap) 10279 return NULL; 10280 10281 bmap->dim = isl_space_reset(bmap->dim, type); 10282 if (!bmap->dim) 10283 goto error; 10284 10285 bmap = isl_basic_map_finalize(bmap); 10286 10287 return bmap; 10288error: 10289 isl_basic_map_free(bmap); 10290 return NULL; 10291} 10292 10293__isl_give isl_map *isl_map_reset(__isl_take isl_map *map, 10294 enum isl_dim_type type) 10295{ 10296 int i; 10297 10298 if (!map) 10299 return NULL; 10300 10301 if (!isl_space_is_named_or_nested(map->dim, type)) 10302 return map; 10303 10304 map = isl_map_cow(map); 10305 if (!map) 10306 return NULL; 10307 10308 for (i = 0; i < map->n; ++i) { 10309 map->p[i] = isl_basic_map_reset(map->p[i], type); 10310 if (!map->p[i]) 10311 goto error; 10312 } 10313 map->dim = isl_space_reset(map->dim, type); 10314 if (!map->dim) 10315 goto error; 10316 10317 return map; 10318error: 10319 isl_map_free(map); 10320 return NULL; 10321} 10322 10323__isl_give isl_basic_map *isl_basic_map_flatten(__isl_take isl_basic_map *bmap) 10324{ 10325 if (!bmap) 10326 return NULL; 10327 10328 if (!bmap->dim->nested[0] && !bmap->dim->nested[1]) 10329 return bmap; 10330 10331 bmap = isl_basic_map_cow(bmap); 10332 if (!bmap) 10333 return NULL; 10334 10335 bmap->dim = isl_space_flatten(bmap->dim); 10336 if (!bmap->dim) 10337 goto error; 10338 10339 bmap = isl_basic_map_finalize(bmap); 10340 10341 return bmap; 10342error: 10343 isl_basic_map_free(bmap); 10344 return NULL; 10345} 10346 10347__isl_give isl_basic_set *isl_basic_set_flatten(__isl_take isl_basic_set *bset) 10348{ 10349 return (isl_basic_set *)isl_basic_map_flatten((isl_basic_map *)bset); 10350} 10351 10352__isl_give isl_basic_map *isl_basic_map_flatten_domain( 10353 __isl_take isl_basic_map *bmap) 10354{ 10355 if (!bmap) 10356 return NULL; 10357 10358 if (!bmap->dim->nested[0]) 10359 return bmap; 10360 10361 bmap = isl_basic_map_cow(bmap); 10362 if (!bmap) 10363 return NULL; 10364 10365 bmap->dim = isl_space_flatten_domain(bmap->dim); 10366 if (!bmap->dim) 10367 goto error; 10368 10369 bmap = isl_basic_map_finalize(bmap); 10370 10371 return bmap; 10372error: 10373 isl_basic_map_free(bmap); 10374 return NULL; 10375} 10376 10377__isl_give isl_basic_map *isl_basic_map_flatten_range( 10378 __isl_take isl_basic_map *bmap) 10379{ 10380 if (!bmap) 10381 return NULL; 10382 10383 if (!bmap->dim->nested[1]) 10384 return bmap; 10385 10386 bmap = isl_basic_map_cow(bmap); 10387 if (!bmap) 10388 return NULL; 10389 10390 bmap->dim = isl_space_flatten_range(bmap->dim); 10391 if (!bmap->dim) 10392 goto error; 10393 10394 bmap = isl_basic_map_finalize(bmap); 10395 10396 return bmap; 10397error: 10398 isl_basic_map_free(bmap); 10399 return NULL; 10400} 10401 10402__isl_give isl_map *isl_map_flatten(__isl_take isl_map *map) 10403{ 10404 int i; 10405 10406 if (!map) 10407 return NULL; 10408 10409 if (!map->dim->nested[0] && !map->dim->nested[1]) 10410 return map; 10411 10412 map = isl_map_cow(map); 10413 if (!map) 10414 return NULL; 10415 10416 for (i = 0; i < map->n; ++i) { 10417 map->p[i] = isl_basic_map_flatten(map->p[i]); 10418 if (!map->p[i]) 10419 goto error; 10420 } 10421 map->dim = isl_space_flatten(map->dim); 10422 if (!map->dim) 10423 goto error; 10424 10425 return map; 10426error: 10427 isl_map_free(map); 10428 return NULL; 10429} 10430 10431__isl_give isl_set *isl_set_flatten(__isl_take isl_set *set) 10432{ 10433 return (isl_set *)isl_map_flatten((isl_map *)set); 10434} 10435 10436__isl_give isl_map *isl_set_flatten_map(__isl_take isl_set *set) 10437{ 10438 isl_space *dim, *flat_dim; 10439 isl_map *map; 10440 10441 dim = isl_set_get_space(set); 10442 flat_dim = isl_space_flatten(isl_space_copy(dim)); 10443 map = isl_map_identity(isl_space_join(isl_space_reverse(dim), flat_dim)); 10444 map = isl_map_intersect_domain(map, set); 10445 10446 return map; 10447} 10448 10449__isl_give isl_map *isl_map_flatten_domain(__isl_take isl_map *map) 10450{ 10451 int i; 10452 10453 if (!map) 10454 return NULL; 10455 10456 if (!map->dim->nested[0]) 10457 return map; 10458 10459 map = isl_map_cow(map); 10460 if (!map) 10461 return NULL; 10462 10463 for (i = 0; i < map->n; ++i) { 10464 map->p[i] = isl_basic_map_flatten_domain(map->p[i]); 10465 if (!map->p[i]) 10466 goto error; 10467 } 10468 map->dim = isl_space_flatten_domain(map->dim); 10469 if (!map->dim) 10470 goto error; 10471 10472 return map; 10473error: 10474 isl_map_free(map); 10475 return NULL; 10476} 10477 10478__isl_give isl_map *isl_map_flatten_range(__isl_take isl_map *map) 10479{ 10480 int i; 10481 10482 if (!map) 10483 return NULL; 10484 10485 if (!map->dim->nested[1]) 10486 return map; 10487 10488 map = isl_map_cow(map); 10489 if (!map) 10490 return NULL; 10491 10492 for (i = 0; i < map->n; ++i) { 10493 map->p[i] = isl_basic_map_flatten_range(map->p[i]); 10494 if (!map->p[i]) 10495 goto error; 10496 } 10497 map->dim = isl_space_flatten_range(map->dim); 10498 if (!map->dim) 10499 goto error; 10500 10501 return map; 10502error: 10503 isl_map_free(map); 10504 return NULL; 10505} 10506 10507/* Reorder the dimensions of "bmap" according to the given dim_map 10508 * and set the dimension specification to "dim". 10509 */ 10510__isl_give isl_basic_map *isl_basic_map_realign(__isl_take isl_basic_map *bmap, 10511 __isl_take isl_space *dim, __isl_take struct isl_dim_map *dim_map) 10512{ 10513 isl_basic_map *res; 10514 unsigned flags; 10515 10516 bmap = isl_basic_map_cow(bmap); 10517 if (!bmap || !dim || !dim_map) 10518 goto error; 10519 10520 flags = bmap->flags; 10521 ISL_FL_CLR(flags, ISL_BASIC_MAP_FINAL); 10522 ISL_FL_CLR(flags, ISL_BASIC_MAP_NORMALIZED); 10523 ISL_FL_CLR(flags, ISL_BASIC_MAP_NORMALIZED_DIVS); 10524 res = isl_basic_map_alloc_space(dim, 10525 bmap->n_div, bmap->n_eq, bmap->n_ineq); 10526 res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map); 10527 if (res) 10528 res->flags = flags; 10529 res = isl_basic_map_finalize(res); 10530 return res; 10531error: 10532 free(dim_map); 10533 isl_basic_map_free(bmap); 10534 isl_space_free(dim); 10535 return NULL; 10536} 10537 10538/* Reorder the dimensions of "map" according to given reordering. 10539 */ 10540__isl_give isl_map *isl_map_realign(__isl_take isl_map *map, 10541 __isl_take isl_reordering *r) 10542{ 10543 int i; 10544 struct isl_dim_map *dim_map; 10545 10546 map = isl_map_cow(map); 10547 dim_map = isl_dim_map_from_reordering(r); 10548 if (!map || !r || !dim_map) 10549 goto error; 10550 10551 for (i = 0; i < map->n; ++i) { 10552 struct isl_dim_map *dim_map_i; 10553 10554 dim_map_i = isl_dim_map_extend(dim_map, map->p[i]); 10555 10556 map->p[i] = isl_basic_map_realign(map->p[i], 10557 isl_space_copy(r->dim), dim_map_i); 10558 10559 if (!map->p[i]) 10560 goto error; 10561 } 10562 10563 map = isl_map_reset_space(map, isl_space_copy(r->dim)); 10564 10565 isl_reordering_free(r); 10566 free(dim_map); 10567 return map; 10568error: 10569 free(dim_map); 10570 isl_map_free(map); 10571 isl_reordering_free(r); 10572 return NULL; 10573} 10574 10575__isl_give isl_set *isl_set_realign(__isl_take isl_set *set, 10576 __isl_take isl_reordering *r) 10577{ 10578 return (isl_set *)isl_map_realign((isl_map *)set, r); 10579} 10580 10581__isl_give isl_map *isl_map_align_params(__isl_take isl_map *map, 10582 __isl_take isl_space *model) 10583{ 10584 isl_ctx *ctx; 10585 10586 if (!map || !model) 10587 goto error; 10588 10589 ctx = isl_space_get_ctx(model); 10590 if (!isl_space_has_named_params(model)) 10591 isl_die(ctx, isl_error_invalid, 10592 "model has unnamed parameters", goto error); 10593 if (!isl_space_has_named_params(map->dim)) 10594 isl_die(ctx, isl_error_invalid, 10595 "relation has unnamed parameters", goto error); 10596 if (!isl_space_match(map->dim, isl_dim_param, model, isl_dim_param)) { 10597 isl_reordering *exp; 10598 10599 model = isl_space_drop_dims(model, isl_dim_in, 10600 0, isl_space_dim(model, isl_dim_in)); 10601 model = isl_space_drop_dims(model, isl_dim_out, 10602 0, isl_space_dim(model, isl_dim_out)); 10603 exp = isl_parameter_alignment_reordering(map->dim, model); 10604 exp = isl_reordering_extend_space(exp, isl_map_get_space(map)); 10605 map = isl_map_realign(map, exp); 10606 } 10607 10608 isl_space_free(model); 10609 return map; 10610error: 10611 isl_space_free(model); 10612 isl_map_free(map); 10613 return NULL; 10614} 10615 10616__isl_give isl_set *isl_set_align_params(__isl_take isl_set *set, 10617 __isl_take isl_space *model) 10618{ 10619 return isl_map_align_params(set, model); 10620} 10621 10622/* Align the parameters of "bmap" to those of "model", introducing 10623 * additional parameters if needed. 10624 */ 10625__isl_give isl_basic_map *isl_basic_map_align_params( 10626 __isl_take isl_basic_map *bmap, __isl_take isl_space *model) 10627{ 10628 isl_ctx *ctx; 10629 10630 if (!bmap || !model) 10631 goto error; 10632 10633 ctx = isl_space_get_ctx(model); 10634 if (!isl_space_has_named_params(model)) 10635 isl_die(ctx, isl_error_invalid, 10636 "model has unnamed parameters", goto error); 10637 if (!isl_space_has_named_params(bmap->dim)) 10638 isl_die(ctx, isl_error_invalid, 10639 "relation has unnamed parameters", goto error); 10640 if (!isl_space_match(bmap->dim, isl_dim_param, model, isl_dim_param)) { 10641 isl_reordering *exp; 10642 struct isl_dim_map *dim_map; 10643 10644 model = isl_space_drop_dims(model, isl_dim_in, 10645 0, isl_space_dim(model, isl_dim_in)); 10646 model = isl_space_drop_dims(model, isl_dim_out, 10647 0, isl_space_dim(model, isl_dim_out)); 10648 exp = isl_parameter_alignment_reordering(bmap->dim, model); 10649 exp = isl_reordering_extend_space(exp, 10650 isl_basic_map_get_space(bmap)); 10651 dim_map = isl_dim_map_from_reordering(exp); 10652 bmap = isl_basic_map_realign(bmap, 10653 exp ? isl_space_copy(exp->dim) : NULL, 10654 isl_dim_map_extend(dim_map, bmap)); 10655 isl_reordering_free(exp); 10656 free(dim_map); 10657 } 10658 10659 isl_space_free(model); 10660 return bmap; 10661error: 10662 isl_space_free(model); 10663 isl_basic_map_free(bmap); 10664 return NULL; 10665} 10666 10667/* Align the parameters of "bset" to those of "model", introducing 10668 * additional parameters if needed. 10669 */ 10670__isl_give isl_basic_set *isl_basic_set_align_params( 10671 __isl_take isl_basic_set *bset, __isl_take isl_space *model) 10672{ 10673 return isl_basic_map_align_params(bset, model); 10674} 10675 10676__isl_give isl_mat *isl_basic_map_equalities_matrix( 10677 __isl_keep isl_basic_map *bmap, enum isl_dim_type c1, 10678 enum isl_dim_type c2, enum isl_dim_type c3, 10679 enum isl_dim_type c4, enum isl_dim_type c5) 10680{ 10681 enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 }; 10682 struct isl_mat *mat; 10683 int i, j, k; 10684 int pos; 10685 10686 if (!bmap) 10687 return NULL; 10688 mat = isl_mat_alloc(bmap->ctx, bmap->n_eq, 10689 isl_basic_map_total_dim(bmap) + 1); 10690 if (!mat) 10691 return NULL; 10692 for (i = 0; i < bmap->n_eq; ++i) 10693 for (j = 0, pos = 0; j < 5; ++j) { 10694 int off = isl_basic_map_offset(bmap, c[j]); 10695 for (k = 0; k < isl_basic_map_dim(bmap, c[j]); ++k) { 10696 isl_int_set(mat->row[i][pos], 10697 bmap->eq[i][off + k]); 10698 ++pos; 10699 } 10700 } 10701 10702 return mat; 10703} 10704 10705__isl_give isl_mat *isl_basic_map_inequalities_matrix( 10706 __isl_keep isl_basic_map *bmap, enum isl_dim_type c1, 10707 enum isl_dim_type c2, enum isl_dim_type c3, 10708 enum isl_dim_type c4, enum isl_dim_type c5) 10709{ 10710 enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 }; 10711 struct isl_mat *mat; 10712 int i, j, k; 10713 int pos; 10714 10715 if (!bmap) 10716 return NULL; 10717 mat = isl_mat_alloc(bmap->ctx, bmap->n_ineq, 10718 isl_basic_map_total_dim(bmap) + 1); 10719 if (!mat) 10720 return NULL; 10721 for (i = 0; i < bmap->n_ineq; ++i) 10722 for (j = 0, pos = 0; j < 5; ++j) { 10723 int off = isl_basic_map_offset(bmap, c[j]); 10724 for (k = 0; k < isl_basic_map_dim(bmap, c[j]); ++k) { 10725 isl_int_set(mat->row[i][pos], 10726 bmap->ineq[i][off + k]); 10727 ++pos; 10728 } 10729 } 10730 10731 return mat; 10732} 10733 10734__isl_give isl_basic_map *isl_basic_map_from_constraint_matrices( 10735 __isl_take isl_space *dim, 10736 __isl_take isl_mat *eq, __isl_take isl_mat *ineq, enum isl_dim_type c1, 10737 enum isl_dim_type c2, enum isl_dim_type c3, 10738 enum isl_dim_type c4, enum isl_dim_type c5) 10739{ 10740 enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 }; 10741 isl_basic_map *bmap; 10742 unsigned total; 10743 unsigned extra; 10744 int i, j, k, l; 10745 int pos; 10746 10747 if (!dim || !eq || !ineq) 10748 goto error; 10749 10750 if (eq->n_col != ineq->n_col) 10751 isl_die(dim->ctx, isl_error_invalid, 10752 "equalities and inequalities matrices should have " 10753 "same number of columns", goto error); 10754 10755 total = 1 + isl_space_dim(dim, isl_dim_all); 10756 10757 if (eq->n_col < total) 10758 isl_die(dim->ctx, isl_error_invalid, 10759 "number of columns too small", goto error); 10760 10761 extra = eq->n_col - total; 10762 10763 bmap = isl_basic_map_alloc_space(isl_space_copy(dim), extra, 10764 eq->n_row, ineq->n_row); 10765 if (!bmap) 10766 goto error; 10767 for (i = 0; i < extra; ++i) { 10768 k = isl_basic_map_alloc_div(bmap); 10769 if (k < 0) 10770 goto error; 10771 isl_int_set_si(bmap->div[k][0], 0); 10772 } 10773 for (i = 0; i < eq->n_row; ++i) { 10774 l = isl_basic_map_alloc_equality(bmap); 10775 if (l < 0) 10776 goto error; 10777 for (j = 0, pos = 0; j < 5; ++j) { 10778 int off = isl_basic_map_offset(bmap, c[j]); 10779 for (k = 0; k < isl_basic_map_dim(bmap, c[j]); ++k) { 10780 isl_int_set(bmap->eq[l][off + k], 10781 eq->row[i][pos]); 10782 ++pos; 10783 } 10784 } 10785 } 10786 for (i = 0; i < ineq->n_row; ++i) { 10787 l = isl_basic_map_alloc_inequality(bmap); 10788 if (l < 0) 10789 goto error; 10790 for (j = 0, pos = 0; j < 5; ++j) { 10791 int off = isl_basic_map_offset(bmap, c[j]); 10792 for (k = 0; k < isl_basic_map_dim(bmap, c[j]); ++k) { 10793 isl_int_set(bmap->ineq[l][off + k], 10794 ineq->row[i][pos]); 10795 ++pos; 10796 } 10797 } 10798 } 10799 10800 isl_space_free(dim); 10801 isl_mat_free(eq); 10802 isl_mat_free(ineq); 10803 10804 bmap = isl_basic_map_simplify(bmap); 10805 return isl_basic_map_finalize(bmap); 10806error: 10807 isl_space_free(dim); 10808 isl_mat_free(eq); 10809 isl_mat_free(ineq); 10810 return NULL; 10811} 10812 10813__isl_give isl_mat *isl_basic_set_equalities_matrix( 10814 __isl_keep isl_basic_set *bset, enum isl_dim_type c1, 10815 enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4) 10816{ 10817 return isl_basic_map_equalities_matrix((isl_basic_map *)bset, 10818 c1, c2, c3, c4, isl_dim_in); 10819} 10820 10821__isl_give isl_mat *isl_basic_set_inequalities_matrix( 10822 __isl_keep isl_basic_set *bset, enum isl_dim_type c1, 10823 enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4) 10824{ 10825 return isl_basic_map_inequalities_matrix((isl_basic_map *)bset, 10826 c1, c2, c3, c4, isl_dim_in); 10827} 10828 10829__isl_give isl_basic_set *isl_basic_set_from_constraint_matrices( 10830 __isl_take isl_space *dim, 10831 __isl_take isl_mat *eq, __isl_take isl_mat *ineq, enum isl_dim_type c1, 10832 enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4) 10833{ 10834 return (isl_basic_set*) 10835 isl_basic_map_from_constraint_matrices(dim, eq, ineq, 10836 c1, c2, c3, c4, isl_dim_in); 10837} 10838 10839int isl_basic_map_can_zip(__isl_keep isl_basic_map *bmap) 10840{ 10841 if (!bmap) 10842 return -1; 10843 10844 return isl_space_can_zip(bmap->dim); 10845} 10846 10847int isl_map_can_zip(__isl_keep isl_map *map) 10848{ 10849 if (!map) 10850 return -1; 10851 10852 return isl_space_can_zip(map->dim); 10853} 10854 10855/* Given a basic map (A -> B) -> (C -> D), return the corresponding basic map 10856 * (A -> C) -> (B -> D). 10857 */ 10858__isl_give isl_basic_map *isl_basic_map_zip(__isl_take isl_basic_map *bmap) 10859{ 10860 unsigned pos; 10861 unsigned n1; 10862 unsigned n2; 10863 10864 if (!bmap) 10865 return NULL; 10866 10867 if (!isl_basic_map_can_zip(bmap)) 10868 isl_die(bmap->ctx, isl_error_invalid, 10869 "basic map cannot be zipped", goto error); 10870 pos = isl_basic_map_offset(bmap, isl_dim_in) + 10871 isl_space_dim(bmap->dim->nested[0], isl_dim_in); 10872 n1 = isl_space_dim(bmap->dim->nested[0], isl_dim_out); 10873 n2 = isl_space_dim(bmap->dim->nested[1], isl_dim_in); 10874 bmap = isl_basic_map_cow(bmap); 10875 bmap = isl_basic_map_swap_vars(bmap, pos, n1, n2); 10876 if (!bmap) 10877 return NULL; 10878 bmap->dim = isl_space_zip(bmap->dim); 10879 if (!bmap->dim) 10880 goto error; 10881 return bmap; 10882error: 10883 isl_basic_map_free(bmap); 10884 return NULL; 10885} 10886 10887/* Given a map (A -> B) -> (C -> D), return the corresponding map 10888 * (A -> C) -> (B -> D). 10889 */ 10890__isl_give isl_map *isl_map_zip(__isl_take isl_map *map) 10891{ 10892 int i; 10893 10894 if (!map) 10895 return NULL; 10896 10897 if (!isl_map_can_zip(map)) 10898 isl_die(map->ctx, isl_error_invalid, "map cannot be zipped", 10899 goto error); 10900 10901 map = isl_map_cow(map); 10902 if (!map) 10903 return NULL; 10904 10905 for (i = 0; i < map->n; ++i) { 10906 map->p[i] = isl_basic_map_zip(map->p[i]); 10907 if (!map->p[i]) 10908 goto error; 10909 } 10910 10911 map->dim = isl_space_zip(map->dim); 10912 if (!map->dim) 10913 goto error; 10914 10915 return map; 10916error: 10917 isl_map_free(map); 10918 return NULL; 10919} 10920 10921/* Can we apply isl_basic_map_curry to "bmap"? 10922 * That is, does it have a nested relation in its domain? 10923 */ 10924int isl_basic_map_can_curry(__isl_keep isl_basic_map *bmap) 10925{ 10926 if (!bmap) 10927 return -1; 10928 10929 return isl_space_can_curry(bmap->dim); 10930} 10931 10932/* Can we apply isl_map_curry to "map"? 10933 * That is, does it have a nested relation in its domain? 10934 */ 10935int isl_map_can_curry(__isl_keep isl_map *map) 10936{ 10937 if (!map) 10938 return -1; 10939 10940 return isl_space_can_curry(map->dim); 10941} 10942 10943/* Given a basic map (A -> B) -> C, return the corresponding basic map 10944 * A -> (B -> C). 10945 */ 10946__isl_give isl_basic_map *isl_basic_map_curry(__isl_take isl_basic_map *bmap) 10947{ 10948 10949 if (!bmap) 10950 return NULL; 10951 10952 if (!isl_basic_map_can_curry(bmap)) 10953 isl_die(bmap->ctx, isl_error_invalid, 10954 "basic map cannot be curried", goto error); 10955 bmap = isl_basic_map_cow(bmap); 10956 if (!bmap) 10957 return NULL; 10958 bmap->dim = isl_space_curry(bmap->dim); 10959 if (!bmap->dim) 10960 goto error; 10961 return bmap; 10962error: 10963 isl_basic_map_free(bmap); 10964 return NULL; 10965} 10966 10967/* Given a map (A -> B) -> C, return the corresponding map 10968 * A -> (B -> C). 10969 */ 10970__isl_give isl_map *isl_map_curry(__isl_take isl_map *map) 10971{ 10972 int i; 10973 10974 if (!map) 10975 return NULL; 10976 10977 if (!isl_map_can_curry(map)) 10978 isl_die(map->ctx, isl_error_invalid, "map cannot be curried", 10979 goto error); 10980 10981 map = isl_map_cow(map); 10982 if (!map) 10983 return NULL; 10984 10985 for (i = 0; i < map->n; ++i) { 10986 map->p[i] = isl_basic_map_curry(map->p[i]); 10987 if (!map->p[i]) 10988 goto error; 10989 } 10990 10991 map->dim = isl_space_curry(map->dim); 10992 if (!map->dim) 10993 goto error; 10994 10995 return map; 10996error: 10997 isl_map_free(map); 10998 return NULL; 10999} 11000 11001/* Can we apply isl_basic_map_uncurry to "bmap"? 11002 * That is, does it have a nested relation in its domain? 11003 */ 11004int isl_basic_map_can_uncurry(__isl_keep isl_basic_map *bmap) 11005{ 11006 if (!bmap) 11007 return -1; 11008 11009 return isl_space_can_uncurry(bmap->dim); 11010} 11011 11012/* Can we apply isl_map_uncurry to "map"? 11013 * That is, does it have a nested relation in its domain? 11014 */ 11015int isl_map_can_uncurry(__isl_keep isl_map *map) 11016{ 11017 if (!map) 11018 return -1; 11019 11020 return isl_space_can_uncurry(map->dim); 11021} 11022 11023/* Given a basic map A -> (B -> C), return the corresponding basic map 11024 * (A -> B) -> C. 11025 */ 11026__isl_give isl_basic_map *isl_basic_map_uncurry(__isl_take isl_basic_map *bmap) 11027{ 11028 11029 if (!bmap) 11030 return NULL; 11031 11032 if (!isl_basic_map_can_uncurry(bmap)) 11033 isl_die(bmap->ctx, isl_error_invalid, 11034 "basic map cannot be uncurried", 11035 return isl_basic_map_free(bmap)); 11036 bmap = isl_basic_map_cow(bmap); 11037 if (!bmap) 11038 return NULL; 11039 bmap->dim = isl_space_uncurry(bmap->dim); 11040 if (!bmap->dim) 11041 return isl_basic_map_free(bmap); 11042 return bmap; 11043} 11044 11045/* Given a map A -> (B -> C), return the corresponding map 11046 * (A -> B) -> C. 11047 */ 11048__isl_give isl_map *isl_map_uncurry(__isl_take isl_map *map) 11049{ 11050 int i; 11051 11052 if (!map) 11053 return NULL; 11054 11055 if (!isl_map_can_uncurry(map)) 11056 isl_die(map->ctx, isl_error_invalid, "map cannot be uncurried", 11057 return isl_map_free(map)); 11058 11059 map = isl_map_cow(map); 11060 if (!map) 11061 return NULL; 11062 11063 for (i = 0; i < map->n; ++i) { 11064 map->p[i] = isl_basic_map_uncurry(map->p[i]); 11065 if (!map->p[i]) 11066 return isl_map_free(map); 11067 } 11068 11069 map->dim = isl_space_uncurry(map->dim); 11070 if (!map->dim) 11071 return isl_map_free(map); 11072 11073 return map; 11074} 11075 11076/* Construct a basic map mapping the domain of the affine expression 11077 * to a one-dimensional range prescribed by the affine expression. 11078 */ 11079__isl_give isl_basic_map *isl_basic_map_from_aff(__isl_take isl_aff *aff) 11080{ 11081 int k; 11082 int pos; 11083 isl_local_space *ls; 11084 isl_basic_map *bmap; 11085 11086 if (!aff) 11087 return NULL; 11088 11089 ls = isl_aff_get_local_space(aff); 11090 bmap = isl_basic_map_from_local_space(ls); 11091 bmap = isl_basic_map_extend_constraints(bmap, 1, 0); 11092 k = isl_basic_map_alloc_equality(bmap); 11093 if (k < 0) 11094 goto error; 11095 11096 pos = isl_basic_map_offset(bmap, isl_dim_out); 11097 isl_seq_cpy(bmap->eq[k], aff->v->el + 1, pos); 11098 isl_int_neg(bmap->eq[k][pos], aff->v->el[0]); 11099 isl_seq_cpy(bmap->eq[k] + pos + 1, aff->v->el + 1 + pos, 11100 aff->v->size - (pos + 1)); 11101 11102 isl_aff_free(aff); 11103 bmap = isl_basic_map_finalize(bmap); 11104 return bmap; 11105error: 11106 isl_aff_free(aff); 11107 isl_basic_map_free(bmap); 11108 return NULL; 11109} 11110 11111/* Construct a map mapping the domain of the affine expression 11112 * to a one-dimensional range prescribed by the affine expression. 11113 */ 11114__isl_give isl_map *isl_map_from_aff(__isl_take isl_aff *aff) 11115{ 11116 isl_basic_map *bmap; 11117 11118 bmap = isl_basic_map_from_aff(aff); 11119 return isl_map_from_basic_map(bmap); 11120} 11121 11122/* Construct a basic map mapping the domain the multi-affine expression 11123 * to its range, with each dimension in the range equated to the 11124 * corresponding affine expression. 11125 */ 11126__isl_give isl_basic_map *isl_basic_map_from_multi_aff( 11127 __isl_take isl_multi_aff *maff) 11128{ 11129 int i; 11130 isl_space *space; 11131 isl_basic_map *bmap; 11132 11133 if (!maff) 11134 return NULL; 11135 11136 if (isl_space_dim(maff->space, isl_dim_out) != maff->n) 11137 isl_die(isl_multi_aff_get_ctx(maff), isl_error_internal, 11138 "invalid space", return isl_multi_aff_free(maff)); 11139 11140 space = isl_space_domain(isl_multi_aff_get_space(maff)); 11141 bmap = isl_basic_map_universe(isl_space_from_domain(space)); 11142 11143 for (i = 0; i < maff->n; ++i) { 11144 isl_aff *aff; 11145 isl_basic_map *bmap_i; 11146 11147 aff = isl_aff_copy(maff->p[i]); 11148 bmap_i = isl_basic_map_from_aff(aff); 11149 11150 bmap = isl_basic_map_flat_range_product(bmap, bmap_i); 11151 } 11152 11153 bmap = isl_basic_map_reset_space(bmap, isl_multi_aff_get_space(maff)); 11154 11155 isl_multi_aff_free(maff); 11156 return bmap; 11157} 11158 11159/* Construct a map mapping the domain the multi-affine expression 11160 * to its range, with each dimension in the range equated to the 11161 * corresponding affine expression. 11162 */ 11163__isl_give isl_map *isl_map_from_multi_aff(__isl_take isl_multi_aff *maff) 11164{ 11165 isl_basic_map *bmap; 11166 11167 bmap = isl_basic_map_from_multi_aff(maff); 11168 return isl_map_from_basic_map(bmap); 11169} 11170 11171/* Construct a basic map mapping a domain in the given space to 11172 * to an n-dimensional range, with n the number of elements in the list, 11173 * where each coordinate in the range is prescribed by the 11174 * corresponding affine expression. 11175 * The domains of all affine expressions in the list are assumed to match 11176 * domain_dim. 11177 */ 11178__isl_give isl_basic_map *isl_basic_map_from_aff_list( 11179 __isl_take isl_space *domain_dim, __isl_take isl_aff_list *list) 11180{ 11181 int i; 11182 isl_space *dim; 11183 isl_basic_map *bmap; 11184 11185 if (!list) 11186 return NULL; 11187 11188 dim = isl_space_from_domain(domain_dim); 11189 bmap = isl_basic_map_universe(dim); 11190 11191 for (i = 0; i < list->n; ++i) { 11192 isl_aff *aff; 11193 isl_basic_map *bmap_i; 11194 11195 aff = isl_aff_copy(list->p[i]); 11196 bmap_i = isl_basic_map_from_aff(aff); 11197 11198 bmap = isl_basic_map_flat_range_product(bmap, bmap_i); 11199 } 11200 11201 isl_aff_list_free(list); 11202 return bmap; 11203} 11204 11205__isl_give isl_set *isl_set_equate(__isl_take isl_set *set, 11206 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2) 11207{ 11208 return isl_map_equate(set, type1, pos1, type2, pos2); 11209} 11210 11211/* Construct a basic map where the given dimensions are equal to each other. 11212 */ 11213static __isl_give isl_basic_map *equator(__isl_take isl_space *space, 11214 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2) 11215{ 11216 isl_basic_map *bmap = NULL; 11217 int i; 11218 11219 if (!space) 11220 return NULL; 11221 11222 if (pos1 >= isl_space_dim(space, type1)) 11223 isl_die(isl_space_get_ctx(space), isl_error_invalid, 11224 "index out of bounds", goto error); 11225 if (pos2 >= isl_space_dim(space, type2)) 11226 isl_die(isl_space_get_ctx(space), isl_error_invalid, 11227 "index out of bounds", goto error); 11228 11229 if (type1 == type2 && pos1 == pos2) 11230 return isl_basic_map_universe(space); 11231 11232 bmap = isl_basic_map_alloc_space(isl_space_copy(space), 0, 1, 0); 11233 i = isl_basic_map_alloc_equality(bmap); 11234 if (i < 0) 11235 goto error; 11236 isl_seq_clr(bmap->eq[i], 1 + isl_basic_map_total_dim(bmap)); 11237 pos1 += isl_basic_map_offset(bmap, type1); 11238 pos2 += isl_basic_map_offset(bmap, type2); 11239 isl_int_set_si(bmap->eq[i][pos1], -1); 11240 isl_int_set_si(bmap->eq[i][pos2], 1); 11241 bmap = isl_basic_map_finalize(bmap); 11242 isl_space_free(space); 11243 return bmap; 11244error: 11245 isl_space_free(space); 11246 isl_basic_map_free(bmap); 11247 return NULL; 11248} 11249 11250/* Add a constraint imposing that the given two dimensions are equal. 11251 */ 11252__isl_give isl_basic_map *isl_basic_map_equate(__isl_take isl_basic_map *bmap, 11253 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2) 11254{ 11255 isl_basic_map *eq; 11256 11257 eq = equator(isl_basic_map_get_space(bmap), type1, pos1, type2, pos2); 11258 11259 bmap = isl_basic_map_intersect(bmap, eq); 11260 11261 return bmap; 11262} 11263 11264/* Add a constraint imposing that the given two dimensions are equal. 11265 */ 11266__isl_give isl_map *isl_map_equate(__isl_take isl_map *map, 11267 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2) 11268{ 11269 isl_basic_map *bmap; 11270 11271 bmap = equator(isl_map_get_space(map), type1, pos1, type2, pos2); 11272 11273 map = isl_map_intersect(map, isl_map_from_basic_map(bmap)); 11274 11275 return map; 11276} 11277 11278/* Add a constraint imposing that the given two dimensions have opposite values. 11279 */ 11280__isl_give isl_map *isl_map_oppose(__isl_take isl_map *map, 11281 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2) 11282{ 11283 isl_basic_map *bmap = NULL; 11284 int i; 11285 11286 if (!map) 11287 return NULL; 11288 11289 if (pos1 >= isl_map_dim(map, type1)) 11290 isl_die(map->ctx, isl_error_invalid, 11291 "index out of bounds", goto error); 11292 if (pos2 >= isl_map_dim(map, type2)) 11293 isl_die(map->ctx, isl_error_invalid, 11294 "index out of bounds", goto error); 11295 11296 bmap = isl_basic_map_alloc_space(isl_map_get_space(map), 0, 1, 0); 11297 i = isl_basic_map_alloc_equality(bmap); 11298 if (i < 0) 11299 goto error; 11300 isl_seq_clr(bmap->eq[i], 1 + isl_basic_map_total_dim(bmap)); 11301 pos1 += isl_basic_map_offset(bmap, type1); 11302 pos2 += isl_basic_map_offset(bmap, type2); 11303 isl_int_set_si(bmap->eq[i][pos1], 1); 11304 isl_int_set_si(bmap->eq[i][pos2], 1); 11305 bmap = isl_basic_map_finalize(bmap); 11306 11307 map = isl_map_intersect(map, isl_map_from_basic_map(bmap)); 11308 11309 return map; 11310error: 11311 isl_basic_map_free(bmap); 11312 isl_map_free(map); 11313 return NULL; 11314} 11315 11316/* Add a constraint imposing that the value of the first dimension is 11317 * greater than or equal to that of the second. 11318 */ 11319__isl_give isl_basic_map *isl_basic_map_order_ge(__isl_take isl_basic_map *bmap, 11320 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2) 11321{ 11322 isl_constraint *c; 11323 isl_local_space *ls; 11324 11325 if (!bmap) 11326 return NULL; 11327 11328 if (pos1 >= isl_basic_map_dim(bmap, type1)) 11329 isl_die(bmap->ctx, isl_error_invalid, 11330 "index out of bounds", return isl_basic_map_free(bmap)); 11331 if (pos2 >= isl_basic_map_dim(bmap, type2)) 11332 isl_die(bmap->ctx, isl_error_invalid, 11333 "index out of bounds", return isl_basic_map_free(bmap)); 11334 11335 if (type1 == type2 && pos1 == pos2) 11336 return bmap; 11337 11338 ls = isl_local_space_from_space(isl_basic_map_get_space(bmap)); 11339 c = isl_inequality_alloc(ls); 11340 c = isl_constraint_set_coefficient_si(c, type1, pos1, 1); 11341 c = isl_constraint_set_coefficient_si(c, type2, pos2, -1); 11342 bmap = isl_basic_map_add_constraint(bmap, c); 11343 11344 return bmap; 11345} 11346 11347/* Construct a basic map where the value of the first dimension is 11348 * greater than that of the second. 11349 */ 11350static __isl_give isl_basic_map *greator(__isl_take isl_space *space, 11351 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2) 11352{ 11353 isl_basic_map *bmap = NULL; 11354 int i; 11355 11356 if (!space) 11357 return NULL; 11358 11359 if (pos1 >= isl_space_dim(space, type1)) 11360 isl_die(isl_space_get_ctx(space), isl_error_invalid, 11361 "index out of bounds", goto error); 11362 if (pos2 >= isl_space_dim(space, type2)) 11363 isl_die(isl_space_get_ctx(space), isl_error_invalid, 11364 "index out of bounds", goto error); 11365 11366 if (type1 == type2 && pos1 == pos2) 11367 return isl_basic_map_empty(space); 11368 11369 bmap = isl_basic_map_alloc_space(space, 0, 0, 1); 11370 i = isl_basic_map_alloc_inequality(bmap); 11371 if (i < 0) 11372 goto error; 11373 isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap)); 11374 pos1 += isl_basic_map_offset(bmap, type1); 11375 pos2 += isl_basic_map_offset(bmap, type2); 11376 isl_int_set_si(bmap->ineq[i][pos1], 1); 11377 isl_int_set_si(bmap->ineq[i][pos2], -1); 11378 isl_int_set_si(bmap->ineq[i][0], -1); 11379 bmap = isl_basic_map_finalize(bmap); 11380 11381 return bmap; 11382error: 11383 isl_space_free(space); 11384 isl_basic_map_free(bmap); 11385 return NULL; 11386} 11387 11388/* Add a constraint imposing that the value of the first dimension is 11389 * greater than that of the second. 11390 */ 11391__isl_give isl_basic_map *isl_basic_map_order_gt(__isl_take isl_basic_map *bmap, 11392 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2) 11393{ 11394 isl_basic_map *gt; 11395 11396 gt = greator(isl_basic_map_get_space(bmap), type1, pos1, type2, pos2); 11397 11398 bmap = isl_basic_map_intersect(bmap, gt); 11399 11400 return bmap; 11401} 11402 11403/* Add a constraint imposing that the value of the first dimension is 11404 * greater than that of the second. 11405 */ 11406__isl_give isl_map *isl_map_order_gt(__isl_take isl_map *map, 11407 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2) 11408{ 11409 isl_basic_map *bmap; 11410 11411 bmap = greator(isl_map_get_space(map), type1, pos1, type2, pos2); 11412 11413 map = isl_map_intersect(map, isl_map_from_basic_map(bmap)); 11414 11415 return map; 11416} 11417 11418/* Add a constraint imposing that the value of the first dimension is 11419 * smaller than that of the second. 11420 */ 11421__isl_give isl_map *isl_map_order_lt(__isl_take isl_map *map, 11422 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2) 11423{ 11424 return isl_map_order_gt(map, type2, pos2, type1, pos1); 11425} 11426 11427__isl_give isl_aff *isl_basic_map_get_div(__isl_keep isl_basic_map *bmap, 11428 int pos) 11429{ 11430 isl_aff *div; 11431 isl_local_space *ls; 11432 11433 if (!bmap) 11434 return NULL; 11435 11436 if (!isl_basic_map_divs_known(bmap)) 11437 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid, 11438 "some divs are unknown", return NULL); 11439 11440 ls = isl_basic_map_get_local_space(bmap); 11441 div = isl_local_space_get_div(ls, pos); 11442 isl_local_space_free(ls); 11443 11444 return div; 11445} 11446 11447__isl_give isl_aff *isl_basic_set_get_div(__isl_keep isl_basic_set *bset, 11448 int pos) 11449{ 11450 return isl_basic_map_get_div(bset, pos); 11451} 11452 11453/* Plug in "subs" for dimension "type", "pos" of "bset". 11454 * 11455 * Let i be the dimension to replace and let "subs" be of the form 11456 * 11457 * f/d 11458 * 11459 * Any integer division with a non-zero coefficient for i, 11460 * 11461 * floor((a i + g)/m) 11462 * 11463 * is replaced by 11464 * 11465 * floor((a f + d g)/(m d)) 11466 * 11467 * Constraints of the form 11468 * 11469 * a i + g 11470 * 11471 * are replaced by 11472 * 11473 * a f + d g 11474 * 11475 * We currently require that "subs" is an integral expression. 11476 * Handling rational expressions may require us to add stride constraints 11477 * as we do in isl_basic_set_preimage_multi_aff. 11478 */ 11479__isl_give isl_basic_set *isl_basic_set_substitute( 11480 __isl_take isl_basic_set *bset, 11481 enum isl_dim_type type, unsigned pos, __isl_keep isl_aff *subs) 11482{ 11483 int i; 11484 isl_int v; 11485 isl_ctx *ctx; 11486 11487 if (bset && isl_basic_set_plain_is_empty(bset)) 11488 return bset; 11489 11490 bset = isl_basic_set_cow(bset); 11491 if (!bset || !subs) 11492 goto error; 11493 11494 ctx = isl_basic_set_get_ctx(bset); 11495 if (!isl_space_is_equal(bset->dim, subs->ls->dim)) 11496 isl_die(ctx, isl_error_invalid, 11497 "spaces don't match", goto error); 11498 if (isl_local_space_dim(subs->ls, isl_dim_div) != 0) 11499 isl_die(ctx, isl_error_unsupported, 11500 "cannot handle divs yet", goto error); 11501 if (!isl_int_is_one(subs->v->el[0])) 11502 isl_die(ctx, isl_error_invalid, 11503 "can only substitute integer expressions", goto error); 11504 11505 pos += isl_basic_set_offset(bset, type); 11506 11507 isl_int_init(v); 11508 11509 for (i = 0; i < bset->n_eq; ++i) { 11510 if (isl_int_is_zero(bset->eq[i][pos])) 11511 continue; 11512 isl_int_set(v, bset->eq[i][pos]); 11513 isl_int_set_si(bset->eq[i][pos], 0); 11514 isl_seq_combine(bset->eq[i], subs->v->el[0], bset->eq[i], 11515 v, subs->v->el + 1, subs->v->size - 1); 11516 } 11517 11518 for (i = 0; i < bset->n_ineq; ++i) { 11519 if (isl_int_is_zero(bset->ineq[i][pos])) 11520 continue; 11521 isl_int_set(v, bset->ineq[i][pos]); 11522 isl_int_set_si(bset->ineq[i][pos], 0); 11523 isl_seq_combine(bset->ineq[i], subs->v->el[0], bset->ineq[i], 11524 v, subs->v->el + 1, subs->v->size - 1); 11525 } 11526 11527 for (i = 0; i < bset->n_div; ++i) { 11528 if (isl_int_is_zero(bset->div[i][1 + pos])) 11529 continue; 11530 isl_int_set(v, bset->div[i][1 + pos]); 11531 isl_int_set_si(bset->div[i][1 + pos], 0); 11532 isl_seq_combine(bset->div[i] + 1, 11533 subs->v->el[0], bset->div[i] + 1, 11534 v, subs->v->el + 1, subs->v->size - 1); 11535 isl_int_mul(bset->div[i][0], bset->div[i][0], subs->v->el[0]); 11536 } 11537 11538 isl_int_clear(v); 11539 11540 bset = isl_basic_set_simplify(bset); 11541 return isl_basic_set_finalize(bset); 11542error: 11543 isl_basic_set_free(bset); 11544 return NULL; 11545} 11546 11547/* Plug in "subs" for dimension "type", "pos" of "set". 11548 */ 11549__isl_give isl_set *isl_set_substitute(__isl_take isl_set *set, 11550 enum isl_dim_type type, unsigned pos, __isl_keep isl_aff *subs) 11551{ 11552 int i; 11553 11554 if (set && isl_set_plain_is_empty(set)) 11555 return set; 11556 11557 set = isl_set_cow(set); 11558 if (!set || !subs) 11559 goto error; 11560 11561 for (i = set->n - 1; i >= 0; --i) { 11562 set->p[i] = isl_basic_set_substitute(set->p[i], type, pos, subs); 11563 if (remove_if_empty(set, i) < 0) 11564 goto error; 11565 } 11566 11567 return set; 11568error: 11569 isl_set_free(set); 11570 return NULL; 11571} 11572 11573/* Check if the range of "ma" is compatible with the domain or range 11574 * (depending on "type") of "bmap". 11575 * Return -1 if anything is wrong. 11576 */ 11577static int check_basic_map_compatible_range_multi_aff( 11578 __isl_keep isl_basic_map *bmap, enum isl_dim_type type, 11579 __isl_keep isl_multi_aff *ma) 11580{ 11581 int m; 11582 isl_space *ma_space; 11583 11584 ma_space = isl_multi_aff_get_space(ma); 11585 m = isl_space_tuple_match(bmap->dim, type, ma_space, isl_dim_out); 11586 isl_space_free(ma_space); 11587 if (m >= 0 && !m) 11588 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid, 11589 "spaces don't match", return -1); 11590 return m; 11591} 11592 11593/* Copy the divs from "ma" to "bmap", adding zeros for the "n_before" 11594 * coefficients before the transformed range of dimensions, 11595 * the "n_after" coefficients after the transformed range of dimensions 11596 * and the coefficients of the other divs in "bmap". 11597 */ 11598static int set_ma_divs(__isl_keep isl_basic_map *bmap, 11599 __isl_keep isl_multi_aff *ma, int n_before, int n_after, int n_div) 11600{ 11601 int i; 11602 int n_param; 11603 int n_set; 11604 isl_local_space *ls; 11605 11606 if (n_div == 0) 11607 return 0; 11608 11609 ls = isl_aff_get_domain_local_space(ma->p[0]); 11610 if (!ls) 11611 return -1; 11612 11613 n_param = isl_local_space_dim(ls, isl_dim_param); 11614 n_set = isl_local_space_dim(ls, isl_dim_set); 11615 for (i = 0; i < n_div; ++i) { 11616 int o_bmap = 0, o_ls = 0; 11617 11618 isl_seq_cpy(bmap->div[i], ls->div->row[i], 1 + 1 + n_param); 11619 o_bmap += 1 + 1 + n_param; 11620 o_ls += 1 + 1 + n_param; 11621 isl_seq_clr(bmap->div[i] + o_bmap, n_before); 11622 o_bmap += n_before; 11623 isl_seq_cpy(bmap->div[i] + o_bmap, 11624 ls->div->row[i] + o_ls, n_set); 11625 o_bmap += n_set; 11626 o_ls += n_set; 11627 isl_seq_clr(bmap->div[i] + o_bmap, n_after); 11628 o_bmap += n_after; 11629 isl_seq_cpy(bmap->div[i] + o_bmap, 11630 ls->div->row[i] + o_ls, n_div); 11631 o_bmap += n_div; 11632 o_ls += n_div; 11633 isl_seq_clr(bmap->div[i] + o_bmap, bmap->n_div - n_div); 11634 if (isl_basic_set_add_div_constraints(bmap, i) < 0) 11635 goto error; 11636 } 11637 11638 isl_local_space_free(ls); 11639 return 0; 11640error: 11641 isl_local_space_free(ls); 11642 return -1; 11643} 11644 11645/* How many stride constraints does "ma" enforce? 11646 * That is, how many of the affine expressions have a denominator 11647 * different from one? 11648 */ 11649static int multi_aff_strides(__isl_keep isl_multi_aff *ma) 11650{ 11651 int i; 11652 int strides = 0; 11653 11654 for (i = 0; i < ma->n; ++i) 11655 if (!isl_int_is_one(ma->p[i]->v->el[0])) 11656 strides++; 11657 11658 return strides; 11659} 11660 11661/* For each affine expression in ma of the form 11662 * 11663 * x_i = (f_i y + h_i)/m_i 11664 * 11665 * with m_i different from one, add a constraint to "bmap" 11666 * of the form 11667 * 11668 * f_i y + h_i = m_i alpha_i 11669 * 11670 * with alpha_i an additional existentially quantified variable. 11671 */ 11672static __isl_give isl_basic_map *add_ma_strides( 11673 __isl_take isl_basic_map *bmap, __isl_keep isl_multi_aff *ma, 11674 int n_before, int n_after) 11675{ 11676 int i, k; 11677 int div; 11678 int total; 11679 int n_param; 11680 int n_in; 11681 int n_div; 11682 11683 total = isl_basic_map_total_dim(bmap); 11684 n_param = isl_multi_aff_dim(ma, isl_dim_param); 11685 n_in = isl_multi_aff_dim(ma, isl_dim_in); 11686 n_div = isl_multi_aff_dim(ma, isl_dim_div); 11687 for (i = 0; i < ma->n; ++i) { 11688 int o_bmap = 0, o_ma = 1; 11689 11690 if (isl_int_is_one(ma->p[i]->v->el[0])) 11691 continue; 11692 div = isl_basic_map_alloc_div(bmap); 11693 k = isl_basic_map_alloc_equality(bmap); 11694 if (div < 0 || k < 0) 11695 goto error; 11696 isl_int_set_si(bmap->div[div][0], 0); 11697 isl_seq_cpy(bmap->eq[k] + o_bmap, 11698 ma->p[i]->v->el + o_ma, 1 + n_param); 11699 o_bmap += 1 + n_param; 11700 o_ma += 1 + n_param; 11701 isl_seq_clr(bmap->eq[k] + o_bmap, n_before); 11702 o_bmap += n_before; 11703 isl_seq_cpy(bmap->eq[k] + o_bmap, 11704 ma->p[i]->v->el + o_ma, n_in); 11705 o_bmap += n_in; 11706 o_ma += n_in; 11707 isl_seq_clr(bmap->eq[k] + o_bmap, n_after); 11708 o_bmap += n_after; 11709 isl_seq_cpy(bmap->eq[k] + o_bmap, 11710 ma->p[i]->v->el + o_ma, n_div); 11711 o_bmap += n_div; 11712 o_ma += n_div; 11713 isl_seq_clr(bmap->eq[k] + o_bmap, 1 + total - o_bmap); 11714 isl_int_neg(bmap->eq[k][1 + total], ma->p[i]->v->el[0]); 11715 total++; 11716 } 11717 11718 return bmap; 11719error: 11720 isl_basic_map_free(bmap); 11721 return NULL; 11722} 11723 11724/* Replace the domain or range space (depending on "type) of "space" by "set". 11725 */ 11726static __isl_give isl_space *isl_space_set(__isl_take isl_space *space, 11727 enum isl_dim_type type, __isl_take isl_space *set) 11728{ 11729 if (type == isl_dim_in) { 11730 space = isl_space_range(space); 11731 space = isl_space_map_from_domain_and_range(set, space); 11732 } else { 11733 space = isl_space_domain(space); 11734 space = isl_space_map_from_domain_and_range(space, set); 11735 } 11736 11737 return space; 11738} 11739 11740/* Compute the preimage of the domain or range (depending on "type") 11741 * of "bmap" under the function represented by "ma". 11742 * In other words, plug in "ma" in the domain or range of "bmap". 11743 * The result is a basic map that lives in the same space as "bmap" 11744 * except that the domain or range has been replaced by 11745 * the domain space of "ma". 11746 * 11747 * If bmap is represented by 11748 * 11749 * A(p) + S u + B x + T v + C(divs) >= 0, 11750 * 11751 * where u and x are input and output dimensions if type == isl_dim_out 11752 * while x and v are input and output dimensions if type == isl_dim_in, 11753 * and ma is represented by 11754 * 11755 * x = D(p) + F(y) + G(divs') 11756 * 11757 * then the result is 11758 * 11759 * A(p) + B D(p) + S u + B F(y) + T v + B G(divs') + C(divs) >= 0 11760 * 11761 * The divs in the input set are similarly adjusted. 11762 * In particular 11763 * 11764 * floor((a_i(p) + s u + b_i x + t v + c_i(divs))/n_i) 11765 * 11766 * becomes 11767 * 11768 * floor((a_i(p) + b_i D(p) + s u + b_i F(y) + t v + 11769 * B_i G(divs') + c_i(divs))/n_i) 11770 * 11771 * If bmap is not a rational map and if F(y) involves any denominators 11772 * 11773 * x_i = (f_i y + h_i)/m_i 11774 * 11775 * then additional constraints are added to ensure that we only 11776 * map back integer points. That is we enforce 11777 * 11778 * f_i y + h_i = m_i alpha_i 11779 * 11780 * with alpha_i an additional existentially quantified variable. 11781 * 11782 * We first copy over the divs from "ma". 11783 * Then we add the modified constraints and divs from "bmap". 11784 * Finally, we add the stride constraints, if needed. 11785 */ 11786__isl_give isl_basic_map *isl_basic_map_preimage_multi_aff( 11787 __isl_take isl_basic_map *bmap, enum isl_dim_type type, 11788 __isl_take isl_multi_aff *ma) 11789{ 11790 int i, k; 11791 isl_space *space; 11792 isl_basic_map *res = NULL; 11793 int n_before, n_after, n_div_bmap, n_div_ma; 11794 isl_int f, c1, c2, g; 11795 int rational, strides; 11796 11797 isl_int_init(f); 11798 isl_int_init(c1); 11799 isl_int_init(c2); 11800 isl_int_init(g); 11801 11802 ma = isl_multi_aff_align_divs(ma); 11803 if (!bmap || !ma) 11804 goto error; 11805 if (check_basic_map_compatible_range_multi_aff(bmap, type, ma) < 0) 11806 goto error; 11807 11808 if (type == isl_dim_in) { 11809 n_before = 0; 11810 n_after = isl_basic_map_dim(bmap, isl_dim_out); 11811 } else { 11812 n_before = isl_basic_map_dim(bmap, isl_dim_in); 11813 n_after = 0; 11814 } 11815 n_div_bmap = isl_basic_map_dim(bmap, isl_dim_div); 11816 n_div_ma = ma->n ? isl_aff_dim(ma->p[0], isl_dim_div) : 0; 11817 11818 space = isl_multi_aff_get_domain_space(ma); 11819 space = isl_space_set(isl_basic_map_get_space(bmap), type, space); 11820 rational = isl_basic_map_is_rational(bmap); 11821 strides = rational ? 0 : multi_aff_strides(ma); 11822 res = isl_basic_map_alloc_space(space, n_div_ma + n_div_bmap + strides, 11823 bmap->n_eq + strides, bmap->n_ineq + 2 * n_div_ma); 11824 if (rational) 11825 res = isl_basic_map_set_rational(res); 11826 11827 for (i = 0; i < n_div_ma + n_div_bmap; ++i) 11828 if (isl_basic_map_alloc_div(res) < 0) 11829 goto error; 11830 11831 if (set_ma_divs(res, ma, n_before, n_after, n_div_ma) < 0) 11832 goto error; 11833 11834 for (i = 0; i < bmap->n_eq; ++i) { 11835 k = isl_basic_map_alloc_equality(res); 11836 if (k < 0) 11837 goto error; 11838 isl_seq_preimage(res->eq[k], bmap->eq[i], ma, n_before, 11839 n_after, n_div_ma, n_div_bmap, f, c1, c2, g, 0); 11840 } 11841 11842 for (i = 0; i < bmap->n_ineq; ++i) { 11843 k = isl_basic_map_alloc_inequality(res); 11844 if (k < 0) 11845 goto error; 11846 isl_seq_preimage(res->ineq[k], bmap->ineq[i], ma, n_before, 11847 n_after, n_div_ma, n_div_bmap, f, c1, c2, g, 0); 11848 } 11849 11850 for (i = 0; i < bmap->n_div; ++i) { 11851 if (isl_int_is_zero(bmap->div[i][0])) { 11852 isl_int_set_si(res->div[n_div_ma + i][0], 0); 11853 continue; 11854 } 11855 isl_seq_preimage(res->div[n_div_ma + i], bmap->div[i], ma, 11856 n_before, n_after, n_div_ma, n_div_bmap, 11857 f, c1, c2, g, 1); 11858 } 11859 11860 if (strides) 11861 res = add_ma_strides(res, ma, n_before, n_after); 11862 11863 isl_int_clear(f); 11864 isl_int_clear(c1); 11865 isl_int_clear(c2); 11866 isl_int_clear(g); 11867 isl_basic_map_free(bmap); 11868 isl_multi_aff_free(ma); 11869 res = isl_basic_set_simplify(res); 11870 return isl_basic_map_finalize(res); 11871error: 11872 isl_int_clear(f); 11873 isl_int_clear(c1); 11874 isl_int_clear(c2); 11875 isl_int_clear(g); 11876 isl_basic_map_free(bmap); 11877 isl_multi_aff_free(ma); 11878 isl_basic_map_free(res); 11879 return NULL; 11880} 11881 11882/* Compute the preimage of "bset" under the function represented by "ma". 11883 * In other words, plug in "ma" in "bset". The result is a basic set 11884 * that lives in the domain space of "ma". 11885 */ 11886__isl_give isl_basic_set *isl_basic_set_preimage_multi_aff( 11887 __isl_take isl_basic_set *bset, __isl_take isl_multi_aff *ma) 11888{ 11889 return isl_basic_map_preimage_multi_aff(bset, isl_dim_set, ma); 11890} 11891 11892/* Check if the range of "ma" is compatible with the domain or range 11893 * (depending on "type") of "map". 11894 * Return -1 if anything is wrong. 11895 */ 11896static int check_map_compatible_range_multi_aff( 11897 __isl_keep isl_map *map, enum isl_dim_type type, 11898 __isl_keep isl_multi_aff *ma) 11899{ 11900 int m; 11901 isl_space *ma_space; 11902 11903 ma_space = isl_multi_aff_get_space(ma); 11904 m = isl_space_tuple_match(map->dim, type, ma_space, isl_dim_out); 11905 isl_space_free(ma_space); 11906 if (m >= 0 && !m) 11907 isl_die(isl_map_get_ctx(map), isl_error_invalid, 11908 "spaces don't match", return -1); 11909 return m; 11910} 11911 11912/* Compute the preimage of the domain or range (depending on "type") 11913 * of "map" under the function represented by "ma". 11914 * In other words, plug in "ma" in the domain or range of "map". 11915 * The result is a map that lives in the same space as "map" 11916 * except that the domain or range has been replaced by 11917 * the domain space of "ma". 11918 * 11919 * The parameters are assumed to have been aligned. 11920 */ 11921static __isl_give isl_map *map_preimage_multi_aff(__isl_take isl_map *map, 11922 enum isl_dim_type type, __isl_take isl_multi_aff *ma) 11923{ 11924 int i; 11925 isl_space *space; 11926 11927 map = isl_map_cow(map); 11928 ma = isl_multi_aff_align_divs(ma); 11929 if (!map || !ma) 11930 goto error; 11931 if (check_map_compatible_range_multi_aff(map, type, ma) < 0) 11932 goto error; 11933 11934 for (i = 0; i < map->n; ++i) { 11935 map->p[i] = isl_basic_map_preimage_multi_aff(map->p[i], type, 11936 isl_multi_aff_copy(ma)); 11937 if (!map->p[i]) 11938 goto error; 11939 } 11940 11941 space = isl_multi_aff_get_domain_space(ma); 11942 space = isl_space_set(isl_map_get_space(map), type, space); 11943 11944 isl_space_free(map->dim); 11945 map->dim = space; 11946 if (!map->dim) 11947 goto error; 11948 11949 isl_multi_aff_free(ma); 11950 if (map->n > 1) 11951 ISL_F_CLR(map, ISL_MAP_DISJOINT); 11952 ISL_F_CLR(map, ISL_SET_NORMALIZED); 11953 return map; 11954error: 11955 isl_multi_aff_free(ma); 11956 isl_map_free(map); 11957 return NULL; 11958} 11959 11960/* Compute the preimage of the domain or range (depending on "type") 11961 * of "map" under the function represented by "ma". 11962 * In other words, plug in "ma" in the domain or range of "map". 11963 * The result is a map that lives in the same space as "map" 11964 * except that the domain or range has been replaced by 11965 * the domain space of "ma". 11966 */ 11967__isl_give isl_map *isl_map_preimage_multi_aff(__isl_take isl_map *map, 11968 enum isl_dim_type type, __isl_take isl_multi_aff *ma) 11969{ 11970 if (!map || !ma) 11971 goto error; 11972 11973 if (isl_space_match(map->dim, isl_dim_param, ma->space, isl_dim_param)) 11974 return map_preimage_multi_aff(map, type, ma); 11975 11976 if (!isl_space_has_named_params(map->dim) || 11977 !isl_space_has_named_params(ma->space)) 11978 isl_die(map->ctx, isl_error_invalid, 11979 "unaligned unnamed parameters", goto error); 11980 map = isl_map_align_params(map, isl_multi_aff_get_space(ma)); 11981 ma = isl_multi_aff_align_params(ma, isl_map_get_space(map)); 11982 11983 return map_preimage_multi_aff(map, type, ma); 11984error: 11985 isl_multi_aff_free(ma); 11986 return isl_map_free(map); 11987} 11988 11989/* Compute the preimage of "set" under the function represented by "ma". 11990 * In other words, plug in "ma" "set". The result is a set 11991 * that lives in the domain space of "ma". 11992 */ 11993__isl_give isl_set *isl_set_preimage_multi_aff(__isl_take isl_set *set, 11994 __isl_take isl_multi_aff *ma) 11995{ 11996 return isl_map_preimage_multi_aff(set, isl_dim_set, ma); 11997} 11998 11999/* Compute the preimage of the domain of "map" under the function 12000 * represented by "ma". 12001 * In other words, plug in "ma" in the domain of "map". 12002 * The result is a map that lives in the same space as "map" 12003 * except that the domain has been replaced by the domain space of "ma". 12004 */ 12005__isl_give isl_map *isl_map_preimage_domain_multi_aff(__isl_take isl_map *map, 12006 __isl_take isl_multi_aff *ma) 12007{ 12008 return isl_map_preimage_multi_aff(map, isl_dim_in, ma); 12009} 12010 12011/* Compute the preimage of "set" under the function represented by "pma". 12012 * In other words, plug in "pma" in "set. The result is a set 12013 * that lives in the domain space of "pma". 12014 */ 12015static __isl_give isl_set *set_preimage_pw_multi_aff(__isl_take isl_set *set, 12016 __isl_take isl_pw_multi_aff *pma) 12017{ 12018 int i; 12019 isl_set *res; 12020 12021 if (!pma) 12022 goto error; 12023 12024 if (pma->n == 0) { 12025 isl_pw_multi_aff_free(pma); 12026 res = isl_set_empty(isl_set_get_space(set)); 12027 isl_set_free(set); 12028 return res; 12029 } 12030 12031 res = isl_set_preimage_multi_aff(isl_set_copy(set), 12032 isl_multi_aff_copy(pma->p[0].maff)); 12033 res = isl_set_intersect(res, isl_set_copy(pma->p[0].set)); 12034 12035 for (i = 1; i < pma->n; ++i) { 12036 isl_set *res_i; 12037 12038 res_i = isl_set_preimage_multi_aff(isl_set_copy(set), 12039 isl_multi_aff_copy(pma->p[i].maff)); 12040 res_i = isl_set_intersect(res_i, isl_set_copy(pma->p[i].set)); 12041 res = isl_set_union(res, res_i); 12042 } 12043 12044 isl_pw_multi_aff_free(pma); 12045 isl_set_free(set); 12046 return res; 12047error: 12048 isl_pw_multi_aff_free(pma); 12049 isl_set_free(set); 12050 return NULL; 12051} 12052 12053__isl_give isl_set *isl_set_preimage_pw_multi_aff(__isl_take isl_set *set, 12054 __isl_take isl_pw_multi_aff *pma) 12055{ 12056 if (!set || !pma) 12057 goto error; 12058 12059 if (isl_space_match(set->dim, isl_dim_param, pma->dim, isl_dim_param)) 12060 return set_preimage_pw_multi_aff(set, pma); 12061 12062 if (!isl_space_has_named_params(set->dim) || 12063 !isl_space_has_named_params(pma->dim)) 12064 isl_die(set->ctx, isl_error_invalid, 12065 "unaligned unnamed parameters", goto error); 12066 set = isl_set_align_params(set, isl_pw_multi_aff_get_space(pma)); 12067 pma = isl_pw_multi_aff_align_params(pma, isl_set_get_space(set)); 12068 12069 return set_preimage_pw_multi_aff(set, pma); 12070error: 12071 isl_pw_multi_aff_free(pma); 12072 return isl_set_free(set); 12073} 12074