1/* 2 * Copyright 2011 INRIA Saclay 3 * Copyright 2011 Sven Verdoolaege 4 * Copyright 2012-2014 Ecole Normale Superieure 5 * Copyright 2014 INRIA Rocquencourt 6 * Copyright 2016 Sven Verdoolaege 7 * Copyright 2018,2020 Cerebras Systems 8 * Copyright 2021 Sven Verdoolaege 9 * Copyright 2022 Cerebras Systems 10 * 11 * Use of this software is governed by the MIT license 12 * 13 * Written by Sven Verdoolaege, INRIA Saclay - Ile-de-France, 14 * Parc Club Orsay Universite, ZAC des vignes, 4 rue Jacques Monod, 15 * 91893 Orsay, France 16 * and Ecole Normale Superieure, 45 rue d���Ulm, 75230 Paris, France 17 * and Inria Paris - Rocquencourt, Domaine de Voluceau - Rocquencourt, 18 * B.P. 105 - 78153 Le Chesnay, France 19 * and Cerebras Systems, 175 S San Antonio Rd, Los Altos, CA, USA 20 * and Cerebras Systems, 1237 E Arques Ave, Sunnyvale, CA, USA 21 */ 22 23#include <isl_ctx_private.h> 24#include <isl_map_private.h> 25#include <isl_union_map_private.h> 26#include <isl_aff_private.h> 27#include <isl_space_private.h> 28#include <isl_local_space_private.h> 29#include <isl_vec_private.h> 30#include <isl_mat_private.h> 31#include <isl_id_private.h> 32#include <isl/constraint.h> 33#include <isl_seq.h> 34#include <isl/set.h> 35#include <isl_val_private.h> 36#include <isl_point_private.h> 37#include <isl_config.h> 38 39#undef EL_BASE 40#define EL_BASE aff 41 42#include <isl_list_templ.c> 43#include <isl_list_read_templ.c> 44 45#undef EL_BASE 46#define EL_BASE pw_aff 47 48#include <isl_list_templ.c> 49#include <isl_list_read_templ.c> 50 51#undef EL_BASE 52#define EL_BASE pw_multi_aff 53 54#include <isl_list_templ.c> 55#include <isl_list_read_templ.c> 56 57#undef EL_BASE 58#define EL_BASE union_pw_aff 59 60#include <isl_list_templ.c> 61#include <isl_list_read_templ.c> 62 63#undef EL_BASE 64#define EL_BASE union_pw_multi_aff 65 66#include <isl_list_templ.c> 67 68/* Construct an isl_aff from the given domain local space "ls" and 69 * coefficients "v", where the local space is known to be valid 70 * for an affine expression. 71 */ 72static __isl_give isl_aff *isl_aff_alloc_vec_validated( 73 __isl_take isl_local_space *ls, __isl_take isl_vec *v) 74{ 75 isl_aff *aff; 76 77 if (!ls || !v) 78 goto error; 79 80 aff = isl_calloc_type(v->ctx, struct isl_aff); 81 if (!aff) 82 goto error; 83 84 aff->ref = 1; 85 aff->ls = ls; 86 aff->v = v; 87 88 return aff; 89error: 90 isl_local_space_free(ls); 91 isl_vec_free(v); 92 return NULL; 93} 94 95/* Construct an isl_aff from the given domain local space "ls" and 96 * coefficients "v". 97 * 98 * First check that "ls" is a valid domain local space 99 * for an affine expression. 100 */ 101__isl_give isl_aff *isl_aff_alloc_vec(__isl_take isl_local_space *ls, 102 __isl_take isl_vec *v) 103{ 104 isl_ctx *ctx; 105 106 if (!ls) 107 return NULL; 108 109 ctx = isl_local_space_get_ctx(ls); 110 if (!isl_local_space_divs_known(ls)) 111 isl_die(ctx, isl_error_invalid, "local space has unknown divs", 112 goto error); 113 if (!isl_local_space_is_set(ls)) 114 isl_die(ctx, isl_error_invalid, 115 "domain of affine expression should be a set", 116 goto error); 117 return isl_aff_alloc_vec_validated(ls, v); 118error: 119 isl_local_space_free(ls); 120 isl_vec_free(v); 121 return NULL; 122} 123 124__isl_give isl_aff *isl_aff_alloc(__isl_take isl_local_space *ls) 125{ 126 isl_ctx *ctx; 127 isl_vec *v; 128 isl_size total; 129 130 if (!ls) 131 return NULL; 132 133 ctx = isl_local_space_get_ctx(ls); 134 135 total = isl_local_space_dim(ls, isl_dim_all); 136 if (total < 0) 137 goto error; 138 v = isl_vec_alloc(ctx, 1 + 1 + total); 139 return isl_aff_alloc_vec(ls, v); 140error: 141 isl_local_space_free(ls); 142 return NULL; 143} 144 145__isl_give isl_aff *isl_aff_copy(__isl_keep isl_aff *aff) 146{ 147 if (!aff) 148 return NULL; 149 150 aff->ref++; 151 return aff; 152} 153 154__isl_give isl_aff *isl_aff_dup(__isl_keep isl_aff *aff) 155{ 156 if (!aff) 157 return NULL; 158 159 return isl_aff_alloc_vec_validated(isl_local_space_copy(aff->ls), 160 isl_vec_copy(aff->v)); 161} 162 163__isl_give isl_aff *isl_aff_cow(__isl_take isl_aff *aff) 164{ 165 if (!aff) 166 return NULL; 167 168 if (aff->ref == 1) 169 return aff; 170 aff->ref--; 171 return isl_aff_dup(aff); 172} 173 174/* Return a copy of the rational affine expression of "aff". 175 */ 176static __isl_give isl_vec *isl_aff_get_rat_aff(__isl_keep isl_aff *aff) 177{ 178 if (!aff) 179 return NULL; 180 return isl_vec_copy(aff->v); 181} 182 183/* Return the rational affine expression of "aff". 184 * This may be either a copy or the expression itself 185 * if there is only one reference to "aff". 186 * This allows the expression to be modified inplace 187 * if both the "aff" and its expression have only a single reference. 188 * The caller is not allowed to modify "aff" between this call and 189 * a subsequent call to isl_aff_restore_rat_aff. 190 * The only exception is that isl_aff_free can be called instead. 191 */ 192static __isl_give isl_vec *isl_aff_take_rat_aff(__isl_keep isl_aff *aff) 193{ 194 isl_vec *v; 195 196 if (!aff) 197 return NULL; 198 if (aff->ref != 1) 199 return isl_aff_get_rat_aff(aff); 200 v = aff->v; 201 aff->v = NULL; 202 return v; 203} 204 205/* Set the rational affine expression of "aff" to "v", 206 * where the rational affine expression of "aff" may be missing 207 * due to a preceding call to isl_aff_take_rat_aff. 208 * However, in this case, "aff" only has a single reference and 209 * then the call to isl_aff_cow has no effect. 210 */ 211static __isl_give isl_aff *isl_aff_restore_rat_aff(__isl_keep isl_aff *aff, 212 __isl_take isl_vec *v) 213{ 214 if (!aff || !v) 215 goto error; 216 217 if (aff->v == v) { 218 isl_vec_free(v); 219 return aff; 220 } 221 222 aff = isl_aff_cow(aff); 223 if (!aff) 224 goto error; 225 isl_vec_free(aff->v); 226 aff->v = v; 227 228 return aff; 229error: 230 isl_aff_free(aff); 231 isl_vec_free(v); 232 return NULL; 233} 234 235__isl_give isl_aff *isl_aff_zero_on_domain(__isl_take isl_local_space *ls) 236{ 237 isl_aff *aff; 238 239 aff = isl_aff_alloc(ls); 240 if (!aff) 241 return NULL; 242 243 isl_int_set_si(aff->v->el[0], 1); 244 isl_seq_clr(aff->v->el + 1, aff->v->size - 1); 245 246 return aff; 247} 248 249/* Return an affine expression that is equal to zero on domain space "space". 250 */ 251__isl_give isl_aff *isl_aff_zero_on_domain_space(__isl_take isl_space *space) 252{ 253 return isl_aff_zero_on_domain(isl_local_space_from_space(space)); 254} 255 256/* This function performs the same operation as isl_aff_zero_on_domain_space, 257 * but is considered as a function on an isl_space when exported. 258 */ 259__isl_give isl_aff *isl_space_zero_aff_on_domain(__isl_take isl_space *space) 260{ 261 return isl_aff_zero_on_domain_space(space); 262} 263 264/* Return a piecewise affine expression defined on the specified domain 265 * that is equal to zero. 266 */ 267__isl_give isl_pw_aff *isl_pw_aff_zero_on_domain(__isl_take isl_local_space *ls) 268{ 269 return isl_pw_aff_from_aff(isl_aff_zero_on_domain(ls)); 270} 271 272/* Change "aff" into a NaN. 273 * 274 * Note that this function gets called from isl_aff_nan_on_domain, 275 * so "aff" may not have been initialized yet. 276 */ 277static __isl_give isl_aff *isl_aff_set_nan(__isl_take isl_aff *aff) 278{ 279 isl_vec *v; 280 281 v = isl_aff_take_rat_aff(aff); 282 v = isl_vec_clr(v); 283 aff = isl_aff_restore_rat_aff(aff, v); 284 285 return aff; 286} 287 288/* Return an affine expression defined on the specified domain 289 * that represents NaN. 290 */ 291__isl_give isl_aff *isl_aff_nan_on_domain(__isl_take isl_local_space *ls) 292{ 293 isl_aff *aff; 294 295 aff = isl_aff_alloc(ls); 296 return isl_aff_set_nan(aff); 297} 298 299/* Return an affine expression defined on the specified domain space 300 * that represents NaN. 301 */ 302__isl_give isl_aff *isl_aff_nan_on_domain_space(__isl_take isl_space *space) 303{ 304 return isl_aff_nan_on_domain(isl_local_space_from_space(space)); 305} 306 307/* Return a piecewise affine expression defined on the specified domain space 308 * that represents NaN. 309 */ 310__isl_give isl_pw_aff *isl_pw_aff_nan_on_domain_space( 311 __isl_take isl_space *space) 312{ 313 return isl_pw_aff_from_aff(isl_aff_nan_on_domain_space(space)); 314} 315 316/* Return a piecewise affine expression defined on the specified domain 317 * that represents NaN. 318 */ 319__isl_give isl_pw_aff *isl_pw_aff_nan_on_domain(__isl_take isl_local_space *ls) 320{ 321 return isl_pw_aff_from_aff(isl_aff_nan_on_domain(ls)); 322} 323 324/* Return an affine expression that is equal to "val" on 325 * domain local space "ls". 326 * 327 * Note that the encoding for the special value NaN 328 * is the same in isl_val and isl_aff, so this does not need 329 * to be treated in any special way. 330 */ 331__isl_give isl_aff *isl_aff_val_on_domain(__isl_take isl_local_space *ls, 332 __isl_take isl_val *val) 333{ 334 isl_aff *aff; 335 336 if (!ls || !val) 337 goto error; 338 if (!isl_val_is_rat(val) && !isl_val_is_nan(val)) 339 isl_die(isl_val_get_ctx(val), isl_error_invalid, 340 "expecting rational value or NaN", goto error); 341 342 aff = isl_aff_alloc(isl_local_space_copy(ls)); 343 if (!aff) 344 goto error; 345 346 isl_seq_clr(aff->v->el + 2, aff->v->size - 2); 347 isl_int_set(aff->v->el[1], val->n); 348 isl_int_set(aff->v->el[0], val->d); 349 350 isl_local_space_free(ls); 351 isl_val_free(val); 352 return aff; 353error: 354 isl_local_space_free(ls); 355 isl_val_free(val); 356 return NULL; 357} 358 359/* Return an affine expression that is equal to "val" on domain space "space". 360 */ 361__isl_give isl_aff *isl_aff_val_on_domain_space(__isl_take isl_space *space, 362 __isl_take isl_val *val) 363{ 364 return isl_aff_val_on_domain(isl_local_space_from_space(space), val); 365} 366 367/* Return an affine expression that is equal to the specified dimension 368 * in "ls". 369 */ 370__isl_give isl_aff *isl_aff_var_on_domain(__isl_take isl_local_space *ls, 371 enum isl_dim_type type, unsigned pos) 372{ 373 isl_space *space; 374 isl_aff *aff; 375 376 if (!ls) 377 return NULL; 378 379 space = isl_local_space_get_space(ls); 380 if (!space) 381 goto error; 382 if (isl_space_is_map(space)) 383 isl_die(isl_space_get_ctx(space), isl_error_invalid, 384 "expecting (parameter) set space", goto error); 385 if (isl_local_space_check_range(ls, type, pos, 1) < 0) 386 goto error; 387 388 isl_space_free(space); 389 aff = isl_aff_alloc(ls); 390 if (!aff) 391 return NULL; 392 393 pos += isl_local_space_offset(aff->ls, type); 394 395 isl_int_set_si(aff->v->el[0], 1); 396 isl_seq_clr(aff->v->el + 1, aff->v->size - 1); 397 isl_int_set_si(aff->v->el[1 + pos], 1); 398 399 return aff; 400error: 401 isl_local_space_free(ls); 402 isl_space_free(space); 403 return NULL; 404} 405 406/* Return a piecewise affine expression that is equal to 407 * the specified dimension in "ls". 408 */ 409__isl_give isl_pw_aff *isl_pw_aff_var_on_domain(__isl_take isl_local_space *ls, 410 enum isl_dim_type type, unsigned pos) 411{ 412 return isl_pw_aff_from_aff(isl_aff_var_on_domain(ls, type, pos)); 413} 414 415/* Return an affine expression that is equal to the parameter 416 * in the domain space "space" with identifier "id". 417 */ 418__isl_give isl_aff *isl_aff_param_on_domain_space_id( 419 __isl_take isl_space *space, __isl_take isl_id *id) 420{ 421 int pos; 422 isl_local_space *ls; 423 424 if (!space || !id) 425 goto error; 426 pos = isl_space_find_dim_by_id(space, isl_dim_param, id); 427 if (pos < 0) 428 isl_die(isl_space_get_ctx(space), isl_error_invalid, 429 "parameter not found in space", goto error); 430 isl_id_free(id); 431 ls = isl_local_space_from_space(space); 432 return isl_aff_var_on_domain(ls, isl_dim_param, pos); 433error: 434 isl_space_free(space); 435 isl_id_free(id); 436 return NULL; 437} 438 439/* This function performs the same operation as 440 * isl_aff_param_on_domain_space_id, 441 * but is considered as a function on an isl_space when exported. 442 */ 443__isl_give isl_aff *isl_space_param_aff_on_domain_id( 444 __isl_take isl_space *space, __isl_take isl_id *id) 445{ 446 return isl_aff_param_on_domain_space_id(space, id); 447} 448 449__isl_null isl_aff *isl_aff_free(__isl_take isl_aff *aff) 450{ 451 if (!aff) 452 return NULL; 453 454 if (--aff->ref > 0) 455 return NULL; 456 457 isl_local_space_free(aff->ls); 458 isl_vec_free(aff->v); 459 460 free(aff); 461 462 return NULL; 463} 464 465isl_ctx *isl_aff_get_ctx(__isl_keep isl_aff *aff) 466{ 467 return aff ? isl_local_space_get_ctx(aff->ls) : NULL; 468} 469 470/* Return a hash value that digests "aff". 471 */ 472uint32_t isl_aff_get_hash(__isl_keep isl_aff *aff) 473{ 474 uint32_t hash, ls_hash, v_hash; 475 476 if (!aff) 477 return 0; 478 479 hash = isl_hash_init(); 480 ls_hash = isl_local_space_get_hash(aff->ls); 481 isl_hash_hash(hash, ls_hash); 482 v_hash = isl_vec_get_hash(aff->v); 483 isl_hash_hash(hash, v_hash); 484 485 return hash; 486} 487 488/* Return the domain local space of "aff". 489 */ 490static __isl_keep isl_local_space *isl_aff_peek_domain_local_space( 491 __isl_keep isl_aff *aff) 492{ 493 return aff ? aff->ls : NULL; 494} 495 496/* Return the number of variables of the given type in the domain of "aff". 497 */ 498isl_size isl_aff_domain_dim(__isl_keep isl_aff *aff, enum isl_dim_type type) 499{ 500 isl_local_space *ls; 501 502 ls = isl_aff_peek_domain_local_space(aff); 503 return isl_local_space_dim(ls, type); 504} 505 506/* Externally, an isl_aff has a map space, but internally, the 507 * ls field corresponds to the domain of that space. 508 */ 509isl_size isl_aff_dim(__isl_keep isl_aff *aff, enum isl_dim_type type) 510{ 511 if (!aff) 512 return isl_size_error; 513 if (type == isl_dim_out) 514 return 1; 515 if (type == isl_dim_in) 516 type = isl_dim_set; 517 return isl_aff_domain_dim(aff, type); 518} 519 520/* Return the offset of the first coefficient of type "type" in 521 * the domain of "aff". 522 */ 523isl_size isl_aff_domain_offset(__isl_keep isl_aff *aff, enum isl_dim_type type) 524{ 525 isl_local_space *ls; 526 527 ls = isl_aff_peek_domain_local_space(aff); 528 return isl_local_space_offset(ls, type); 529} 530 531/* Return the position of the dimension of the given type and name 532 * in "aff". 533 * Return -1 if no such dimension can be found. 534 */ 535int isl_aff_find_dim_by_name(__isl_keep isl_aff *aff, enum isl_dim_type type, 536 const char *name) 537{ 538 if (!aff) 539 return -1; 540 if (type == isl_dim_out) 541 return -1; 542 if (type == isl_dim_in) 543 type = isl_dim_set; 544 return isl_local_space_find_dim_by_name(aff->ls, type, name); 545} 546 547/* Return the domain space of "aff". 548 */ 549static __isl_keep isl_space *isl_aff_peek_domain_space(__isl_keep isl_aff *aff) 550{ 551 return aff ? isl_local_space_peek_space(aff->ls) : NULL; 552} 553 554__isl_give isl_space *isl_aff_get_domain_space(__isl_keep isl_aff *aff) 555{ 556 return isl_space_copy(isl_aff_peek_domain_space(aff)); 557} 558 559__isl_give isl_space *isl_aff_get_space(__isl_keep isl_aff *aff) 560{ 561 isl_space *space; 562 if (!aff) 563 return NULL; 564 space = isl_local_space_get_space(aff->ls); 565 space = isl_space_from_domain(space); 566 space = isl_space_add_dims(space, isl_dim_out, 1); 567 return space; 568} 569 570/* Return a copy of the domain space of "aff". 571 */ 572__isl_give isl_local_space *isl_aff_get_domain_local_space( 573 __isl_keep isl_aff *aff) 574{ 575 return isl_local_space_copy(isl_aff_peek_domain_local_space(aff)); 576} 577 578__isl_give isl_local_space *isl_aff_get_local_space(__isl_keep isl_aff *aff) 579{ 580 isl_local_space *ls; 581 if (!aff) 582 return NULL; 583 ls = isl_local_space_copy(aff->ls); 584 ls = isl_local_space_from_domain(ls); 585 ls = isl_local_space_add_dims(ls, isl_dim_out, 1); 586 return ls; 587} 588 589/* Return the local space of the domain of "aff". 590 * This may be either a copy or the local space itself 591 * if there is only one reference to "aff". 592 * This allows the local space to be modified inplace 593 * if both the expression and its local space have only a single reference. 594 * The caller is not allowed to modify "aff" between this call and 595 * a subsequent call to isl_aff_restore_domain_local_space. 596 * The only exception is that isl_aff_free can be called instead. 597 */ 598__isl_give isl_local_space *isl_aff_take_domain_local_space( 599 __isl_keep isl_aff *aff) 600{ 601 isl_local_space *ls; 602 603 if (!aff) 604 return NULL; 605 if (aff->ref != 1) 606 return isl_aff_get_domain_local_space(aff); 607 ls = aff->ls; 608 aff->ls = NULL; 609 return ls; 610} 611 612/* Set the local space of the domain of "aff" to "ls", 613 * where the local space of "aff" may be missing 614 * due to a preceding call to isl_aff_take_domain_local_space. 615 * However, in this case, "aff" only has a single reference and 616 * then the call to isl_aff_cow has no effect. 617 */ 618__isl_give isl_aff *isl_aff_restore_domain_local_space( 619 __isl_keep isl_aff *aff, __isl_take isl_local_space *ls) 620{ 621 if (!aff || !ls) 622 goto error; 623 624 if (aff->ls == ls) { 625 isl_local_space_free(ls); 626 return aff; 627 } 628 629 aff = isl_aff_cow(aff); 630 if (!aff) 631 goto error; 632 isl_local_space_free(aff->ls); 633 aff->ls = ls; 634 635 return aff; 636error: 637 isl_aff_free(aff); 638 isl_local_space_free(ls); 639 return NULL; 640} 641 642/* Externally, an isl_aff has a map space, but internally, the 643 * ls field corresponds to the domain of that space. 644 */ 645const char *isl_aff_get_dim_name(__isl_keep isl_aff *aff, 646 enum isl_dim_type type, unsigned pos) 647{ 648 if (!aff) 649 return NULL; 650 if (type == isl_dim_out) 651 return NULL; 652 if (type == isl_dim_in) 653 type = isl_dim_set; 654 return isl_local_space_get_dim_name(aff->ls, type, pos); 655} 656 657__isl_give isl_aff *isl_aff_reset_domain_space(__isl_take isl_aff *aff, 658 __isl_take isl_space *space) 659{ 660 aff = isl_aff_cow(aff); 661 if (!aff || !space) 662 goto error; 663 664 aff->ls = isl_local_space_reset_space(aff->ls, space); 665 if (!aff->ls) 666 return isl_aff_free(aff); 667 668 return aff; 669error: 670 isl_aff_free(aff); 671 isl_space_free(space); 672 return NULL; 673} 674 675/* Reset the space of "aff". This function is called from isl_pw_templ.c 676 * and doesn't know if the space of an element object is represented 677 * directly or through its domain. It therefore passes along both. 678 */ 679__isl_give isl_aff *isl_aff_reset_space_and_domain(__isl_take isl_aff *aff, 680 __isl_take isl_space *space, __isl_take isl_space *domain) 681{ 682 isl_space_free(space); 683 return isl_aff_reset_domain_space(aff, domain); 684} 685 686/* Reorder the dimensions of the domain of "aff" according 687 * to the given reordering. 688 */ 689__isl_give isl_aff *isl_aff_realign_domain(__isl_take isl_aff *aff, 690 __isl_take isl_reordering *r) 691{ 692 aff = isl_aff_cow(aff); 693 if (!aff) 694 goto error; 695 696 r = isl_reordering_extend(r, aff->ls->div->n_row); 697 aff->v = isl_vec_reorder(aff->v, 2, isl_reordering_copy(r)); 698 aff->ls = isl_local_space_realign(aff->ls, r); 699 700 if (!aff->v || !aff->ls) 701 return isl_aff_free(aff); 702 703 return aff; 704error: 705 isl_aff_free(aff); 706 isl_reordering_free(r); 707 return NULL; 708} 709 710__isl_give isl_aff *isl_aff_align_params(__isl_take isl_aff *aff, 711 __isl_take isl_space *model) 712{ 713 isl_space *domain_space; 714 isl_bool equal_params; 715 716 domain_space = isl_aff_peek_domain_space(aff); 717 equal_params = isl_space_has_equal_params(domain_space, model); 718 if (equal_params < 0) 719 goto error; 720 if (!equal_params) { 721 isl_reordering *exp; 722 723 exp = isl_parameter_alignment_reordering(domain_space, model); 724 aff = isl_aff_realign_domain(aff, exp); 725 } 726 727 isl_space_free(model); 728 return aff; 729error: 730 isl_space_free(model); 731 isl_aff_free(aff); 732 return NULL; 733} 734 735#undef TYPE 736#define TYPE isl_aff 737#include "isl_unbind_params_templ.c" 738 739/* Is "aff" obviously equal to zero? 740 * 741 * If the denominator is zero, then "aff" is not equal to zero. 742 */ 743isl_bool isl_aff_plain_is_zero(__isl_keep isl_aff *aff) 744{ 745 int pos; 746 747 if (!aff) 748 return isl_bool_error; 749 750 if (isl_int_is_zero(aff->v->el[0])) 751 return isl_bool_false; 752 pos = isl_seq_first_non_zero(aff->v->el + 1, aff->v->size - 1); 753 return isl_bool_ok(pos < 0); 754} 755 756/* Does "aff" represent NaN? 757 */ 758isl_bool isl_aff_is_nan(__isl_keep isl_aff *aff) 759{ 760 if (!aff) 761 return isl_bool_error; 762 763 return isl_bool_ok(isl_seq_first_non_zero(aff->v->el, 2) < 0); 764} 765 766/* Are "aff1" and "aff2" obviously equal? 767 * 768 * NaN is not equal to anything, not even to another NaN. 769 */ 770isl_bool isl_aff_plain_is_equal(__isl_keep isl_aff *aff1, 771 __isl_keep isl_aff *aff2) 772{ 773 isl_bool equal; 774 775 if (!aff1 || !aff2) 776 return isl_bool_error; 777 778 if (isl_aff_is_nan(aff1) || isl_aff_is_nan(aff2)) 779 return isl_bool_false; 780 781 equal = isl_local_space_is_equal(aff1->ls, aff2->ls); 782 if (equal < 0 || !equal) 783 return equal; 784 785 return isl_vec_is_equal(aff1->v, aff2->v); 786} 787 788/* Return the common denominator of "aff" in "v". 789 * 790 * We cannot return anything meaningful in case of a NaN. 791 */ 792isl_stat isl_aff_get_denominator(__isl_keep isl_aff *aff, isl_int *v) 793{ 794 if (!aff) 795 return isl_stat_error; 796 if (isl_aff_is_nan(aff)) 797 isl_die(isl_aff_get_ctx(aff), isl_error_invalid, 798 "cannot get denominator of NaN", return isl_stat_error); 799 isl_int_set(*v, aff->v->el[0]); 800 return isl_stat_ok; 801} 802 803/* Return the common denominator of "aff". 804 */ 805__isl_give isl_val *isl_aff_get_denominator_val(__isl_keep isl_aff *aff) 806{ 807 isl_ctx *ctx; 808 809 if (!aff) 810 return NULL; 811 812 ctx = isl_aff_get_ctx(aff); 813 if (isl_aff_is_nan(aff)) 814 return isl_val_nan(ctx); 815 return isl_val_int_from_isl_int(ctx, aff->v->el[0]); 816} 817 818/* Return the constant term of "aff". 819 */ 820__isl_give isl_val *isl_aff_get_constant_val(__isl_keep isl_aff *aff) 821{ 822 isl_ctx *ctx; 823 isl_val *v; 824 825 if (!aff) 826 return NULL; 827 828 ctx = isl_aff_get_ctx(aff); 829 if (isl_aff_is_nan(aff)) 830 return isl_val_nan(ctx); 831 v = isl_val_rat_from_isl_int(ctx, aff->v->el[1], aff->v->el[0]); 832 return isl_val_normalize(v); 833} 834 835/* Return the coefficient of the variable of type "type" at position "pos" 836 * of "aff". 837 */ 838__isl_give isl_val *isl_aff_get_coefficient_val(__isl_keep isl_aff *aff, 839 enum isl_dim_type type, int pos) 840{ 841 isl_ctx *ctx; 842 isl_val *v; 843 844 if (!aff) 845 return NULL; 846 847 ctx = isl_aff_get_ctx(aff); 848 if (type == isl_dim_out) 849 isl_die(ctx, isl_error_invalid, 850 "output/set dimension does not have a coefficient", 851 return NULL); 852 if (type == isl_dim_in) 853 type = isl_dim_set; 854 855 if (isl_local_space_check_range(aff->ls, type, pos, 1) < 0) 856 return NULL; 857 858 if (isl_aff_is_nan(aff)) 859 return isl_val_nan(ctx); 860 pos += isl_local_space_offset(aff->ls, type); 861 v = isl_val_rat_from_isl_int(ctx, aff->v->el[1 + pos], aff->v->el[0]); 862 return isl_val_normalize(v); 863} 864 865/* Return the sign of the coefficient of the variable of type "type" 866 * at position "pos" of "aff". 867 */ 868int isl_aff_coefficient_sgn(__isl_keep isl_aff *aff, enum isl_dim_type type, 869 int pos) 870{ 871 isl_ctx *ctx; 872 873 if (!aff) 874 return 0; 875 876 ctx = isl_aff_get_ctx(aff); 877 if (type == isl_dim_out) 878 isl_die(ctx, isl_error_invalid, 879 "output/set dimension does not have a coefficient", 880 return 0); 881 if (type == isl_dim_in) 882 type = isl_dim_set; 883 884 if (isl_local_space_check_range(aff->ls, type, pos, 1) < 0) 885 return 0; 886 887 pos += isl_local_space_offset(aff->ls, type); 888 return isl_int_sgn(aff->v->el[1 + pos]); 889} 890 891/* Replace the numerator of the constant term of "aff" by "v". 892 * 893 * A NaN is unaffected by this operation. 894 */ 895__isl_give isl_aff *isl_aff_set_constant(__isl_take isl_aff *aff, isl_int v) 896{ 897 if (!aff) 898 return NULL; 899 if (isl_aff_is_nan(aff)) 900 return aff; 901 aff = isl_aff_cow(aff); 902 if (!aff) 903 return NULL; 904 905 aff->v = isl_vec_cow(aff->v); 906 if (!aff->v) 907 return isl_aff_free(aff); 908 909 isl_int_set(aff->v->el[1], v); 910 911 return aff; 912} 913 914/* Replace the constant term of "aff" by "v". 915 * 916 * A NaN is unaffected by this operation. 917 */ 918__isl_give isl_aff *isl_aff_set_constant_val(__isl_take isl_aff *aff, 919 __isl_take isl_val *v) 920{ 921 if (!aff || !v) 922 goto error; 923 924 if (isl_aff_is_nan(aff)) { 925 isl_val_free(v); 926 return aff; 927 } 928 929 if (!isl_val_is_rat(v)) 930 isl_die(isl_aff_get_ctx(aff), isl_error_invalid, 931 "expecting rational value", goto error); 932 933 if (isl_int_eq(aff->v->el[1], v->n) && 934 isl_int_eq(aff->v->el[0], v->d)) { 935 isl_val_free(v); 936 return aff; 937 } 938 939 aff = isl_aff_cow(aff); 940 if (!aff) 941 goto error; 942 aff->v = isl_vec_cow(aff->v); 943 if (!aff->v) 944 goto error; 945 946 if (isl_int_eq(aff->v->el[0], v->d)) { 947 isl_int_set(aff->v->el[1], v->n); 948 } else if (isl_int_is_one(v->d)) { 949 isl_int_mul(aff->v->el[1], aff->v->el[0], v->n); 950 } else { 951 isl_seq_scale(aff->v->el + 1, 952 aff->v->el + 1, v->d, aff->v->size - 1); 953 isl_int_mul(aff->v->el[1], aff->v->el[0], v->n); 954 isl_int_mul(aff->v->el[0], aff->v->el[0], v->d); 955 aff->v = isl_vec_normalize(aff->v); 956 if (!aff->v) 957 goto error; 958 } 959 960 isl_val_free(v); 961 return aff; 962error: 963 isl_aff_free(aff); 964 isl_val_free(v); 965 return NULL; 966} 967 968/* Add "v" to the constant term of "aff". 969 * 970 * A NaN is unaffected by this operation. 971 */ 972__isl_give isl_aff *isl_aff_add_constant(__isl_take isl_aff *aff, isl_int v) 973{ 974 if (isl_int_is_zero(v)) 975 return aff; 976 977 if (!aff) 978 return NULL; 979 if (isl_aff_is_nan(aff)) 980 return aff; 981 aff = isl_aff_cow(aff); 982 if (!aff) 983 return NULL; 984 985 aff->v = isl_vec_cow(aff->v); 986 if (!aff->v) 987 return isl_aff_free(aff); 988 989 isl_int_addmul(aff->v->el[1], aff->v->el[0], v); 990 991 return aff; 992} 993 994/* Add "v" to the constant term of "aff", 995 * in case "aff" is a rational expression. 996 */ 997static __isl_give isl_aff *isl_aff_add_rat_constant_val(__isl_take isl_aff *aff, 998 __isl_take isl_val *v) 999{ 1000 aff = isl_aff_cow(aff); 1001 if (!aff) 1002 goto error; 1003 1004 aff->v = isl_vec_cow(aff->v); 1005 if (!aff->v) 1006 goto error; 1007 1008 if (isl_int_is_one(v->d)) { 1009 isl_int_addmul(aff->v->el[1], aff->v->el[0], v->n); 1010 } else if (isl_int_eq(aff->v->el[0], v->d)) { 1011 isl_int_add(aff->v->el[1], aff->v->el[1], v->n); 1012 aff->v = isl_vec_normalize(aff->v); 1013 if (!aff->v) 1014 goto error; 1015 } else { 1016 isl_seq_scale(aff->v->el + 1, 1017 aff->v->el + 1, v->d, aff->v->size - 1); 1018 isl_int_addmul(aff->v->el[1], aff->v->el[0], v->n); 1019 isl_int_mul(aff->v->el[0], aff->v->el[0], v->d); 1020 aff->v = isl_vec_normalize(aff->v); 1021 if (!aff->v) 1022 goto error; 1023 } 1024 1025 isl_val_free(v); 1026 return aff; 1027error: 1028 isl_aff_free(aff); 1029 isl_val_free(v); 1030 return NULL; 1031} 1032 1033/* Return the first argument and free the second. 1034 */ 1035static __isl_give isl_aff *pick_free(__isl_take isl_aff *aff, 1036 __isl_take isl_val *v) 1037{ 1038 isl_val_free(v); 1039 return aff; 1040} 1041 1042/* Replace the first argument by NaN and free the second argument. 1043 */ 1044static __isl_give isl_aff *set_nan_free_val(__isl_take isl_aff *aff, 1045 __isl_take isl_val *v) 1046{ 1047 isl_val_free(v); 1048 return isl_aff_set_nan(aff); 1049} 1050 1051/* Add "v" to the constant term of "aff". 1052 * 1053 * A NaN is unaffected by this operation. 1054 * Conversely, adding a NaN turns "aff" into a NaN. 1055 */ 1056__isl_give isl_aff *isl_aff_add_constant_val(__isl_take isl_aff *aff, 1057 __isl_take isl_val *v) 1058{ 1059 isl_bool is_nan, is_zero, is_rat; 1060 1061 is_nan = isl_aff_is_nan(aff); 1062 is_zero = isl_val_is_zero(v); 1063 if (is_nan < 0 || is_zero < 0) 1064 goto error; 1065 if (is_nan || is_zero) 1066 return pick_free(aff, v); 1067 1068 is_nan = isl_val_is_nan(v); 1069 is_rat = isl_val_is_rat(v); 1070 if (is_nan < 0 || is_rat < 0) 1071 goto error; 1072 if (is_nan) 1073 return set_nan_free_val(aff, v); 1074 if (!is_rat) 1075 isl_die(isl_aff_get_ctx(aff), isl_error_invalid, 1076 "expecting rational value or NaN", goto error); 1077 1078 return isl_aff_add_rat_constant_val(aff, v); 1079error: 1080 isl_aff_free(aff); 1081 isl_val_free(v); 1082 return NULL; 1083} 1084 1085__isl_give isl_aff *isl_aff_add_constant_si(__isl_take isl_aff *aff, int v) 1086{ 1087 isl_int t; 1088 1089 isl_int_init(t); 1090 isl_int_set_si(t, v); 1091 aff = isl_aff_add_constant(aff, t); 1092 isl_int_clear(t); 1093 1094 return aff; 1095} 1096 1097/* Add "v" to the numerator of the constant term of "aff". 1098 * 1099 * A NaN is unaffected by this operation. 1100 */ 1101__isl_give isl_aff *isl_aff_add_constant_num(__isl_take isl_aff *aff, isl_int v) 1102{ 1103 if (isl_int_is_zero(v)) 1104 return aff; 1105 1106 if (!aff) 1107 return NULL; 1108 if (isl_aff_is_nan(aff)) 1109 return aff; 1110 aff = isl_aff_cow(aff); 1111 if (!aff) 1112 return NULL; 1113 1114 aff->v = isl_vec_cow(aff->v); 1115 if (!aff->v) 1116 return isl_aff_free(aff); 1117 1118 isl_int_add(aff->v->el[1], aff->v->el[1], v); 1119 1120 return aff; 1121} 1122 1123/* Add "v" to the numerator of the constant term of "aff". 1124 * 1125 * A NaN is unaffected by this operation. 1126 */ 1127__isl_give isl_aff *isl_aff_add_constant_num_si(__isl_take isl_aff *aff, int v) 1128{ 1129 isl_int t; 1130 1131 if (v == 0) 1132 return aff; 1133 1134 isl_int_init(t); 1135 isl_int_set_si(t, v); 1136 aff = isl_aff_add_constant_num(aff, t); 1137 isl_int_clear(t); 1138 1139 return aff; 1140} 1141 1142/* Replace the numerator of the constant term of "aff" by "v". 1143 * 1144 * A NaN is unaffected by this operation. 1145 */ 1146__isl_give isl_aff *isl_aff_set_constant_si(__isl_take isl_aff *aff, int v) 1147{ 1148 if (!aff) 1149 return NULL; 1150 if (isl_aff_is_nan(aff)) 1151 return aff; 1152 aff = isl_aff_cow(aff); 1153 if (!aff) 1154 return NULL; 1155 1156 aff->v = isl_vec_cow(aff->v); 1157 if (!aff->v) 1158 return isl_aff_free(aff); 1159 1160 isl_int_set_si(aff->v->el[1], v); 1161 1162 return aff; 1163} 1164 1165/* Replace the numerator of the coefficient of the variable of type "type" 1166 * at position "pos" of "aff" by "v". 1167 * 1168 * A NaN is unaffected by this operation. 1169 */ 1170__isl_give isl_aff *isl_aff_set_coefficient(__isl_take isl_aff *aff, 1171 enum isl_dim_type type, int pos, isl_int v) 1172{ 1173 if (!aff) 1174 return NULL; 1175 1176 if (type == isl_dim_out) 1177 isl_die(aff->v->ctx, isl_error_invalid, 1178 "output/set dimension does not have a coefficient", 1179 return isl_aff_free(aff)); 1180 if (type == isl_dim_in) 1181 type = isl_dim_set; 1182 1183 if (isl_local_space_check_range(aff->ls, type, pos, 1) < 0) 1184 return isl_aff_free(aff); 1185 1186 if (isl_aff_is_nan(aff)) 1187 return aff; 1188 aff = isl_aff_cow(aff); 1189 if (!aff) 1190 return NULL; 1191 1192 aff->v = isl_vec_cow(aff->v); 1193 if (!aff->v) 1194 return isl_aff_free(aff); 1195 1196 pos += isl_local_space_offset(aff->ls, type); 1197 isl_int_set(aff->v->el[1 + pos], v); 1198 1199 return aff; 1200} 1201 1202/* Replace the numerator of the coefficient of the variable of type "type" 1203 * at position "pos" of "aff" by "v". 1204 * 1205 * A NaN is unaffected by this operation. 1206 */ 1207__isl_give isl_aff *isl_aff_set_coefficient_si(__isl_take isl_aff *aff, 1208 enum isl_dim_type type, int pos, int v) 1209{ 1210 if (!aff) 1211 return NULL; 1212 1213 if (type == isl_dim_out) 1214 isl_die(aff->v->ctx, isl_error_invalid, 1215 "output/set dimension does not have a coefficient", 1216 return isl_aff_free(aff)); 1217 if (type == isl_dim_in) 1218 type = isl_dim_set; 1219 1220 if (isl_local_space_check_range(aff->ls, type, pos, 1) < 0) 1221 return isl_aff_free(aff); 1222 1223 if (isl_aff_is_nan(aff)) 1224 return aff; 1225 pos += isl_local_space_offset(aff->ls, type); 1226 if (isl_int_cmp_si(aff->v->el[1 + pos], v) == 0) 1227 return aff; 1228 1229 aff = isl_aff_cow(aff); 1230 if (!aff) 1231 return NULL; 1232 1233 aff->v = isl_vec_cow(aff->v); 1234 if (!aff->v) 1235 return isl_aff_free(aff); 1236 1237 isl_int_set_si(aff->v->el[1 + pos], v); 1238 1239 return aff; 1240} 1241 1242/* Replace the coefficient of the variable of type "type" at position "pos" 1243 * of "aff" by "v". 1244 * 1245 * A NaN is unaffected by this operation. 1246 */ 1247__isl_give isl_aff *isl_aff_set_coefficient_val(__isl_take isl_aff *aff, 1248 enum isl_dim_type type, int pos, __isl_take isl_val *v) 1249{ 1250 if (!aff || !v) 1251 goto error; 1252 1253 if (type == isl_dim_out) 1254 isl_die(aff->v->ctx, isl_error_invalid, 1255 "output/set dimension does not have a coefficient", 1256 goto error); 1257 if (type == isl_dim_in) 1258 type = isl_dim_set; 1259 1260 if (isl_local_space_check_range(aff->ls, type, pos, 1) < 0) 1261 return isl_aff_free(aff); 1262 1263 if (isl_aff_is_nan(aff)) { 1264 isl_val_free(v); 1265 return aff; 1266 } 1267 if (!isl_val_is_rat(v)) 1268 isl_die(isl_aff_get_ctx(aff), isl_error_invalid, 1269 "expecting rational value", goto error); 1270 1271 pos += isl_local_space_offset(aff->ls, type); 1272 if (isl_int_eq(aff->v->el[1 + pos], v->n) && 1273 isl_int_eq(aff->v->el[0], v->d)) { 1274 isl_val_free(v); 1275 return aff; 1276 } 1277 1278 aff = isl_aff_cow(aff); 1279 if (!aff) 1280 goto error; 1281 aff->v = isl_vec_cow(aff->v); 1282 if (!aff->v) 1283 goto error; 1284 1285 if (isl_int_eq(aff->v->el[0], v->d)) { 1286 isl_int_set(aff->v->el[1 + pos], v->n); 1287 } else if (isl_int_is_one(v->d)) { 1288 isl_int_mul(aff->v->el[1 + pos], aff->v->el[0], v->n); 1289 } else { 1290 isl_seq_scale(aff->v->el + 1, 1291 aff->v->el + 1, v->d, aff->v->size - 1); 1292 isl_int_mul(aff->v->el[1 + pos], aff->v->el[0], v->n); 1293 isl_int_mul(aff->v->el[0], aff->v->el[0], v->d); 1294 aff->v = isl_vec_normalize(aff->v); 1295 if (!aff->v) 1296 goto error; 1297 } 1298 1299 isl_val_free(v); 1300 return aff; 1301error: 1302 isl_aff_free(aff); 1303 isl_val_free(v); 1304 return NULL; 1305} 1306 1307/* Add "v" to the coefficient of the variable of type "type" 1308 * at position "pos" of "aff". 1309 * 1310 * A NaN is unaffected by this operation. 1311 */ 1312__isl_give isl_aff *isl_aff_add_coefficient(__isl_take isl_aff *aff, 1313 enum isl_dim_type type, int pos, isl_int v) 1314{ 1315 if (!aff) 1316 return NULL; 1317 1318 if (type == isl_dim_out) 1319 isl_die(aff->v->ctx, isl_error_invalid, 1320 "output/set dimension does not have a coefficient", 1321 return isl_aff_free(aff)); 1322 if (type == isl_dim_in) 1323 type = isl_dim_set; 1324 1325 if (isl_local_space_check_range(aff->ls, type, pos, 1) < 0) 1326 return isl_aff_free(aff); 1327 1328 if (isl_aff_is_nan(aff)) 1329 return aff; 1330 aff = isl_aff_cow(aff); 1331 if (!aff) 1332 return NULL; 1333 1334 aff->v = isl_vec_cow(aff->v); 1335 if (!aff->v) 1336 return isl_aff_free(aff); 1337 1338 pos += isl_local_space_offset(aff->ls, type); 1339 isl_int_addmul(aff->v->el[1 + pos], aff->v->el[0], v); 1340 1341 return aff; 1342} 1343 1344/* Add "v" to the coefficient of the variable of type "type" 1345 * at position "pos" of "aff". 1346 * 1347 * A NaN is unaffected by this operation. 1348 */ 1349__isl_give isl_aff *isl_aff_add_coefficient_val(__isl_take isl_aff *aff, 1350 enum isl_dim_type type, int pos, __isl_take isl_val *v) 1351{ 1352 if (!aff || !v) 1353 goto error; 1354 1355 if (isl_val_is_zero(v)) { 1356 isl_val_free(v); 1357 return aff; 1358 } 1359 1360 if (type == isl_dim_out) 1361 isl_die(aff->v->ctx, isl_error_invalid, 1362 "output/set dimension does not have a coefficient", 1363 goto error); 1364 if (type == isl_dim_in) 1365 type = isl_dim_set; 1366 1367 if (isl_local_space_check_range(aff->ls, type, pos, 1) < 0) 1368 goto error; 1369 1370 if (isl_aff_is_nan(aff)) { 1371 isl_val_free(v); 1372 return aff; 1373 } 1374 if (!isl_val_is_rat(v)) 1375 isl_die(isl_aff_get_ctx(aff), isl_error_invalid, 1376 "expecting rational value", goto error); 1377 1378 aff = isl_aff_cow(aff); 1379 if (!aff) 1380 goto error; 1381 1382 aff->v = isl_vec_cow(aff->v); 1383 if (!aff->v) 1384 goto error; 1385 1386 pos += isl_local_space_offset(aff->ls, type); 1387 if (isl_int_is_one(v->d)) { 1388 isl_int_addmul(aff->v->el[1 + pos], aff->v->el[0], v->n); 1389 } else if (isl_int_eq(aff->v->el[0], v->d)) { 1390 isl_int_add(aff->v->el[1 + pos], aff->v->el[1 + pos], v->n); 1391 aff->v = isl_vec_normalize(aff->v); 1392 if (!aff->v) 1393 goto error; 1394 } else { 1395 isl_seq_scale(aff->v->el + 1, 1396 aff->v->el + 1, v->d, aff->v->size - 1); 1397 isl_int_addmul(aff->v->el[1 + pos], aff->v->el[0], v->n); 1398 isl_int_mul(aff->v->el[0], aff->v->el[0], v->d); 1399 aff->v = isl_vec_normalize(aff->v); 1400 if (!aff->v) 1401 goto error; 1402 } 1403 1404 isl_val_free(v); 1405 return aff; 1406error: 1407 isl_aff_free(aff); 1408 isl_val_free(v); 1409 return NULL; 1410} 1411 1412__isl_give isl_aff *isl_aff_add_coefficient_si(__isl_take isl_aff *aff, 1413 enum isl_dim_type type, int pos, int v) 1414{ 1415 isl_int t; 1416 1417 isl_int_init(t); 1418 isl_int_set_si(t, v); 1419 aff = isl_aff_add_coefficient(aff, type, pos, t); 1420 isl_int_clear(t); 1421 1422 return aff; 1423} 1424 1425__isl_give isl_aff *isl_aff_get_div(__isl_keep isl_aff *aff, int pos) 1426{ 1427 if (!aff) 1428 return NULL; 1429 1430 return isl_local_space_get_div(aff->ls, pos); 1431} 1432 1433/* Return the negation of "aff". 1434 * 1435 * As a special case, -NaN = NaN. 1436 */ 1437__isl_give isl_aff *isl_aff_neg(__isl_take isl_aff *aff) 1438{ 1439 if (!aff) 1440 return NULL; 1441 if (isl_aff_is_nan(aff)) 1442 return aff; 1443 aff = isl_aff_cow(aff); 1444 if (!aff) 1445 return NULL; 1446 aff->v = isl_vec_cow(aff->v); 1447 if (!aff->v) 1448 return isl_aff_free(aff); 1449 1450 isl_seq_neg(aff->v->el + 1, aff->v->el + 1, aff->v->size - 1); 1451 1452 return aff; 1453} 1454 1455/* Remove divs from the local space that do not appear in the affine 1456 * expression. 1457 * We currently only remove divs at the end. 1458 * Some intermediate divs may also not appear directly in the affine 1459 * expression, but we would also need to check that no other divs are 1460 * defined in terms of them. 1461 */ 1462__isl_give isl_aff *isl_aff_remove_unused_divs(__isl_take isl_aff *aff) 1463{ 1464 int pos; 1465 isl_size off; 1466 isl_size n; 1467 1468 n = isl_aff_domain_dim(aff, isl_dim_div); 1469 off = isl_aff_domain_offset(aff, isl_dim_div); 1470 if (n < 0 || off < 0) 1471 return isl_aff_free(aff); 1472 1473 pos = isl_seq_last_non_zero(aff->v->el + 1 + off, n) + 1; 1474 if (pos == n) 1475 return aff; 1476 1477 aff = isl_aff_cow(aff); 1478 if (!aff) 1479 return NULL; 1480 1481 aff->ls = isl_local_space_drop_dims(aff->ls, isl_dim_div, pos, n - pos); 1482 aff->v = isl_vec_drop_els(aff->v, 1 + off + pos, n - pos); 1483 if (!aff->ls || !aff->v) 1484 return isl_aff_free(aff); 1485 1486 return aff; 1487} 1488 1489/* Look for any divs in the aff->ls with a denominator equal to one 1490 * and plug them into the affine expression and any subsequent divs 1491 * that may reference the div. 1492 */ 1493static __isl_give isl_aff *plug_in_integral_divs(__isl_take isl_aff *aff) 1494{ 1495 int i; 1496 isl_size n; 1497 int len; 1498 isl_int v; 1499 isl_vec *vec; 1500 isl_local_space *ls; 1501 isl_size off; 1502 1503 n = isl_aff_domain_dim(aff, isl_dim_div); 1504 off = isl_aff_domain_offset(aff, isl_dim_div); 1505 if (n < 0 || off < 0) 1506 return isl_aff_free(aff); 1507 len = aff->v->size; 1508 for (i = 0; i < n; ++i) { 1509 if (!isl_int_is_one(aff->ls->div->row[i][0])) 1510 continue; 1511 ls = isl_local_space_copy(aff->ls); 1512 ls = isl_local_space_substitute_seq(ls, isl_dim_div, i, 1513 aff->ls->div->row[i], len, i + 1, n - (i + 1)); 1514 vec = isl_vec_copy(aff->v); 1515 vec = isl_vec_cow(vec); 1516 if (!ls || !vec) 1517 goto error; 1518 1519 isl_int_init(v); 1520 1521 isl_seq_substitute(vec->el, off + i, aff->ls->div->row[i], 1522 len, len, v); 1523 1524 isl_int_clear(v); 1525 1526 isl_vec_free(aff->v); 1527 aff->v = vec; 1528 isl_local_space_free(aff->ls); 1529 aff->ls = ls; 1530 } 1531 1532 return aff; 1533error: 1534 isl_vec_free(vec); 1535 isl_local_space_free(ls); 1536 return isl_aff_free(aff); 1537} 1538 1539/* Look for any divs j that appear with a unit coefficient inside 1540 * the definitions of other divs i and plug them into the definitions 1541 * of the divs i. 1542 * 1543 * In particular, an expression of the form 1544 * 1545 * floor((f(..) + floor(g(..)/n))/m) 1546 * 1547 * is simplified to 1548 * 1549 * floor((n * f(..) + g(..))/(n * m)) 1550 * 1551 * This simplification is correct because we can move the expression 1552 * f(..) into the inner floor in the original expression to obtain 1553 * 1554 * floor(floor((n * f(..) + g(..))/n)/m) 1555 * 1556 * from which we can derive the simplified expression. 1557 */ 1558static __isl_give isl_aff *plug_in_unit_divs(__isl_take isl_aff *aff) 1559{ 1560 int i, j; 1561 isl_size n; 1562 isl_size off; 1563 1564 n = isl_aff_domain_dim(aff, isl_dim_div); 1565 off = isl_aff_domain_offset(aff, isl_dim_div); 1566 if (n < 0 || off < 0) 1567 return isl_aff_free(aff); 1568 for (i = 1; i < n; ++i) { 1569 for (j = 0; j < i; ++j) { 1570 if (!isl_int_is_one(aff->ls->div->row[i][1 + off + j])) 1571 continue; 1572 aff->ls = isl_local_space_substitute_seq(aff->ls, 1573 isl_dim_div, j, aff->ls->div->row[j], 1574 aff->v->size, i, 1); 1575 if (!aff->ls) 1576 return isl_aff_free(aff); 1577 } 1578 } 1579 1580 return aff; 1581} 1582 1583/* Swap divs "a" and "b" in "aff", which is assumed to be non-NULL. 1584 * 1585 * Even though this function is only called on isl_affs with a single 1586 * reference, we are careful to only change aff->v and aff->ls together. 1587 */ 1588static __isl_give isl_aff *swap_div(__isl_take isl_aff *aff, int a, int b) 1589{ 1590 isl_size off = isl_aff_domain_offset(aff, isl_dim_div); 1591 isl_local_space *ls; 1592 isl_vec *v; 1593 1594 if (off < 0) 1595 return isl_aff_free(aff); 1596 1597 ls = isl_local_space_copy(aff->ls); 1598 ls = isl_local_space_swap_div(ls, a, b); 1599 v = isl_vec_copy(aff->v); 1600 v = isl_vec_cow(v); 1601 if (!ls || !v) 1602 goto error; 1603 1604 isl_int_swap(v->el[1 + off + a], v->el[1 + off + b]); 1605 isl_vec_free(aff->v); 1606 aff->v = v; 1607 isl_local_space_free(aff->ls); 1608 aff->ls = ls; 1609 1610 return aff; 1611error: 1612 isl_vec_free(v); 1613 isl_local_space_free(ls); 1614 return isl_aff_free(aff); 1615} 1616 1617/* Merge divs "a" and "b" in "aff", which is assumed to be non-NULL. 1618 * 1619 * We currently do not actually remove div "b", but simply add its 1620 * coefficient to that of "a" and then zero it out. 1621 */ 1622static __isl_give isl_aff *merge_divs(__isl_take isl_aff *aff, int a, int b) 1623{ 1624 isl_size off = isl_aff_domain_offset(aff, isl_dim_div); 1625 1626 if (off < 0) 1627 return isl_aff_free(aff); 1628 1629 if (isl_int_is_zero(aff->v->el[1 + off + b])) 1630 return aff; 1631 1632 aff->v = isl_vec_cow(aff->v); 1633 if (!aff->v) 1634 return isl_aff_free(aff); 1635 1636 isl_int_add(aff->v->el[1 + off + a], 1637 aff->v->el[1 + off + a], aff->v->el[1 + off + b]); 1638 isl_int_set_si(aff->v->el[1 + off + b], 0); 1639 1640 return aff; 1641} 1642 1643/* Sort the divs in the local space of "aff" according to 1644 * the comparison function "cmp_row" in isl_local_space.c, 1645 * combining the coefficients of identical divs. 1646 * 1647 * Reordering divs does not change the semantics of "aff", 1648 * so there is no need to call isl_aff_cow. 1649 * Moreover, this function is currently only called on isl_affs 1650 * with a single reference. 1651 */ 1652static __isl_give isl_aff *sort_divs(__isl_take isl_aff *aff) 1653{ 1654 isl_size n; 1655 int i, j; 1656 1657 n = isl_aff_dim(aff, isl_dim_div); 1658 if (n < 0) 1659 return isl_aff_free(aff); 1660 for (i = 1; i < n; ++i) { 1661 for (j = i - 1; j >= 0; --j) { 1662 int cmp = isl_mat_cmp_div(aff->ls->div, j, j + 1); 1663 if (cmp < 0) 1664 break; 1665 if (cmp == 0) 1666 aff = merge_divs(aff, j, j + 1); 1667 else 1668 aff = swap_div(aff, j, j + 1); 1669 if (!aff) 1670 return NULL; 1671 } 1672 } 1673 1674 return aff; 1675} 1676 1677/* Normalize the representation of "aff". 1678 * 1679 * This function should only be called on "new" isl_affs, i.e., 1680 * with only a single reference. We therefore do not need to 1681 * worry about affecting other instances. 1682 */ 1683__isl_give isl_aff *isl_aff_normalize(__isl_take isl_aff *aff) 1684{ 1685 if (!aff) 1686 return NULL; 1687 aff->v = isl_vec_normalize(aff->v); 1688 if (!aff->v) 1689 return isl_aff_free(aff); 1690 aff = plug_in_integral_divs(aff); 1691 aff = plug_in_unit_divs(aff); 1692 aff = sort_divs(aff); 1693 aff = isl_aff_remove_unused_divs(aff); 1694 return aff; 1695} 1696 1697/* Given f, return floor(f). 1698 * If f is an integer expression, then just return f. 1699 * If f is a constant, then return the constant floor(f). 1700 * Otherwise, if f = g/m, write g = q m + r, 1701 * create a new div d = [r/m] and return the expression q + d. 1702 * The coefficients in r are taken to lie between -m/2 and m/2. 1703 * 1704 * reduce_div_coefficients performs the same normalization. 1705 * 1706 * As a special case, floor(NaN) = NaN. 1707 */ 1708__isl_give isl_aff *isl_aff_floor(__isl_take isl_aff *aff) 1709{ 1710 int i; 1711 int size; 1712 isl_ctx *ctx; 1713 isl_vec *div; 1714 1715 if (!aff) 1716 return NULL; 1717 1718 if (isl_aff_is_nan(aff)) 1719 return aff; 1720 if (isl_int_is_one(aff->v->el[0])) 1721 return aff; 1722 1723 aff = isl_aff_cow(aff); 1724 if (!aff) 1725 return NULL; 1726 1727 aff->v = isl_vec_cow(aff->v); 1728 if (!aff->v) 1729 return isl_aff_free(aff); 1730 1731 if (isl_aff_is_cst(aff)) { 1732 isl_int_fdiv_q(aff->v->el[1], aff->v->el[1], aff->v->el[0]); 1733 isl_int_set_si(aff->v->el[0], 1); 1734 return aff; 1735 } 1736 1737 div = isl_vec_copy(aff->v); 1738 div = isl_vec_cow(div); 1739 if (!div) 1740 return isl_aff_free(aff); 1741 1742 ctx = isl_aff_get_ctx(aff); 1743 isl_int_fdiv_q(aff->v->el[0], aff->v->el[0], ctx->two); 1744 for (i = 1; i < aff->v->size; ++i) { 1745 isl_int_fdiv_r(div->el[i], div->el[i], div->el[0]); 1746 isl_int_fdiv_q(aff->v->el[i], aff->v->el[i], div->el[0]); 1747 if (isl_int_gt(div->el[i], aff->v->el[0])) { 1748 isl_int_sub(div->el[i], div->el[i], div->el[0]); 1749 isl_int_add_ui(aff->v->el[i], aff->v->el[i], 1); 1750 } 1751 } 1752 1753 aff->ls = isl_local_space_add_div(aff->ls, div); 1754 if (!aff->ls) 1755 return isl_aff_free(aff); 1756 1757 size = aff->v->size; 1758 aff->v = isl_vec_extend(aff->v, size + 1); 1759 if (!aff->v) 1760 return isl_aff_free(aff); 1761 isl_int_set_si(aff->v->el[0], 1); 1762 isl_int_set_si(aff->v->el[size], 1); 1763 1764 aff = isl_aff_normalize(aff); 1765 1766 return aff; 1767} 1768 1769/* Compute 1770 * 1771 * aff mod m = aff - m * floor(aff/m) 1772 * 1773 * with m an integer value. 1774 */ 1775__isl_give isl_aff *isl_aff_mod_val(__isl_take isl_aff *aff, 1776 __isl_take isl_val *m) 1777{ 1778 isl_aff *res; 1779 1780 if (!aff || !m) 1781 goto error; 1782 1783 if (!isl_val_is_int(m)) 1784 isl_die(isl_val_get_ctx(m), isl_error_invalid, 1785 "expecting integer modulo", goto error); 1786 1787 res = isl_aff_copy(aff); 1788 aff = isl_aff_scale_down_val(aff, isl_val_copy(m)); 1789 aff = isl_aff_floor(aff); 1790 aff = isl_aff_scale_val(aff, m); 1791 res = isl_aff_sub(res, aff); 1792 1793 return res; 1794error: 1795 isl_aff_free(aff); 1796 isl_val_free(m); 1797 return NULL; 1798} 1799 1800/* Compute 1801 * 1802 * pwaff mod m = pwaff - m * floor(pwaff/m) 1803 */ 1804__isl_give isl_pw_aff *isl_pw_aff_mod(__isl_take isl_pw_aff *pwaff, isl_int m) 1805{ 1806 isl_pw_aff *res; 1807 1808 res = isl_pw_aff_copy(pwaff); 1809 pwaff = isl_pw_aff_scale_down(pwaff, m); 1810 pwaff = isl_pw_aff_floor(pwaff); 1811 pwaff = isl_pw_aff_scale(pwaff, m); 1812 res = isl_pw_aff_sub(res, pwaff); 1813 1814 return res; 1815} 1816 1817/* Compute 1818 * 1819 * pa mod m = pa - m * floor(pa/m) 1820 * 1821 * with m an integer value. 1822 */ 1823__isl_give isl_pw_aff *isl_pw_aff_mod_val(__isl_take isl_pw_aff *pa, 1824 __isl_take isl_val *m) 1825{ 1826 if (!pa || !m) 1827 goto error; 1828 if (!isl_val_is_int(m)) 1829 isl_die(isl_pw_aff_get_ctx(pa), isl_error_invalid, 1830 "expecting integer modulo", goto error); 1831 pa = isl_pw_aff_mod(pa, m->n); 1832 isl_val_free(m); 1833 return pa; 1834error: 1835 isl_pw_aff_free(pa); 1836 isl_val_free(m); 1837 return NULL; 1838} 1839 1840/* Given f, return ceil(f). 1841 * If f is an integer expression, then just return f. 1842 * Otherwise, let f be the expression 1843 * 1844 * e/m 1845 * 1846 * then return 1847 * 1848 * floor((e + m - 1)/m) 1849 * 1850 * As a special case, ceil(NaN) = NaN. 1851 */ 1852__isl_give isl_aff *isl_aff_ceil(__isl_take isl_aff *aff) 1853{ 1854 if (!aff) 1855 return NULL; 1856 1857 if (isl_aff_is_nan(aff)) 1858 return aff; 1859 if (isl_int_is_one(aff->v->el[0])) 1860 return aff; 1861 1862 aff = isl_aff_cow(aff); 1863 if (!aff) 1864 return NULL; 1865 aff->v = isl_vec_cow(aff->v); 1866 if (!aff->v) 1867 return isl_aff_free(aff); 1868 1869 isl_int_add(aff->v->el[1], aff->v->el[1], aff->v->el[0]); 1870 isl_int_sub_ui(aff->v->el[1], aff->v->el[1], 1); 1871 aff = isl_aff_floor(aff); 1872 1873 return aff; 1874} 1875 1876/* Apply the expansion computed by isl_merge_divs. 1877 * The expansion itself is given by "exp" while the resulting 1878 * list of divs is given by "div". 1879 */ 1880__isl_give isl_aff *isl_aff_expand_divs(__isl_take isl_aff *aff, 1881 __isl_take isl_mat *div, int *exp) 1882{ 1883 isl_size old_n_div; 1884 isl_size new_n_div; 1885 isl_size offset; 1886 1887 aff = isl_aff_cow(aff); 1888 1889 offset = isl_aff_domain_offset(aff, isl_dim_div); 1890 old_n_div = isl_aff_domain_dim(aff, isl_dim_div); 1891 new_n_div = isl_mat_rows(div); 1892 if (offset < 0 || old_n_div < 0 || new_n_div < 0) 1893 goto error; 1894 1895 aff->v = isl_vec_expand(aff->v, 1 + offset, old_n_div, exp, new_n_div); 1896 aff->ls = isl_local_space_replace_divs(aff->ls, div); 1897 if (!aff->v || !aff->ls) 1898 return isl_aff_free(aff); 1899 return aff; 1900error: 1901 isl_aff_free(aff); 1902 isl_mat_free(div); 1903 return NULL; 1904} 1905 1906/* Add two affine expressions that live in the same local space. 1907 */ 1908static __isl_give isl_aff *add_expanded(__isl_take isl_aff *aff1, 1909 __isl_take isl_aff *aff2) 1910{ 1911 isl_int gcd, f; 1912 1913 aff1 = isl_aff_cow(aff1); 1914 if (!aff1 || !aff2) 1915 goto error; 1916 1917 aff1->v = isl_vec_cow(aff1->v); 1918 if (!aff1->v) 1919 goto error; 1920 1921 isl_int_init(gcd); 1922 isl_int_init(f); 1923 isl_int_gcd(gcd, aff1->v->el[0], aff2->v->el[0]); 1924 isl_int_divexact(f, aff2->v->el[0], gcd); 1925 isl_seq_scale(aff1->v->el + 1, aff1->v->el + 1, f, aff1->v->size - 1); 1926 isl_int_divexact(f, aff1->v->el[0], gcd); 1927 isl_seq_addmul(aff1->v->el + 1, f, aff2->v->el + 1, aff1->v->size - 1); 1928 isl_int_divexact(f, aff2->v->el[0], gcd); 1929 isl_int_mul(aff1->v->el[0], aff1->v->el[0], f); 1930 isl_int_clear(f); 1931 isl_int_clear(gcd); 1932 1933 isl_aff_free(aff2); 1934 aff1 = isl_aff_normalize(aff1); 1935 return aff1; 1936error: 1937 isl_aff_free(aff1); 1938 isl_aff_free(aff2); 1939 return NULL; 1940} 1941 1942/* Replace one of the arguments by a NaN and free the other one. 1943 */ 1944static __isl_give isl_aff *set_nan_free(__isl_take isl_aff *aff1, 1945 __isl_take isl_aff *aff2) 1946{ 1947 isl_aff_free(aff2); 1948 return isl_aff_set_nan(aff1); 1949} 1950 1951/* Return the sum of "aff1" and "aff2". 1952 * 1953 * If either of the two is NaN, then the result is NaN. 1954 */ 1955__isl_give isl_aff *isl_aff_add(__isl_take isl_aff *aff1, 1956 __isl_take isl_aff *aff2) 1957{ 1958 isl_ctx *ctx; 1959 int *exp1 = NULL; 1960 int *exp2 = NULL; 1961 isl_mat *div; 1962 isl_size n_div1, n_div2; 1963 1964 if (!aff1 || !aff2) 1965 goto error; 1966 1967 ctx = isl_aff_get_ctx(aff1); 1968 if (!isl_space_is_equal(aff1->ls->dim, aff2->ls->dim)) 1969 isl_die(ctx, isl_error_invalid, 1970 "spaces don't match", goto error); 1971 1972 if (isl_aff_is_nan(aff1)) { 1973 isl_aff_free(aff2); 1974 return aff1; 1975 } 1976 if (isl_aff_is_nan(aff2)) { 1977 isl_aff_free(aff1); 1978 return aff2; 1979 } 1980 1981 n_div1 = isl_aff_dim(aff1, isl_dim_div); 1982 n_div2 = isl_aff_dim(aff2, isl_dim_div); 1983 if (n_div1 < 0 || n_div2 < 0) 1984 goto error; 1985 if (n_div1 == 0 && n_div2 == 0) 1986 return add_expanded(aff1, aff2); 1987 1988 exp1 = isl_alloc_array(ctx, int, n_div1); 1989 exp2 = isl_alloc_array(ctx, int, n_div2); 1990 if ((n_div1 && !exp1) || (n_div2 && !exp2)) 1991 goto error; 1992 1993 div = isl_merge_divs(aff1->ls->div, aff2->ls->div, exp1, exp2); 1994 aff1 = isl_aff_expand_divs(aff1, isl_mat_copy(div), exp1); 1995 aff2 = isl_aff_expand_divs(aff2, div, exp2); 1996 free(exp1); 1997 free(exp2); 1998 1999 return add_expanded(aff1, aff2); 2000error: 2001 free(exp1); 2002 free(exp2); 2003 isl_aff_free(aff1); 2004 isl_aff_free(aff2); 2005 return NULL; 2006} 2007 2008__isl_give isl_aff *isl_aff_sub(__isl_take isl_aff *aff1, 2009 __isl_take isl_aff *aff2) 2010{ 2011 return isl_aff_add(aff1, isl_aff_neg(aff2)); 2012} 2013 2014/* Return the result of scaling "aff" by a factor of "f". 2015 * 2016 * As a special case, f * NaN = NaN. 2017 */ 2018__isl_give isl_aff *isl_aff_scale(__isl_take isl_aff *aff, isl_int f) 2019{ 2020 isl_int gcd; 2021 2022 if (!aff) 2023 return NULL; 2024 if (isl_aff_is_nan(aff)) 2025 return aff; 2026 2027 if (isl_int_is_one(f)) 2028 return aff; 2029 2030 aff = isl_aff_cow(aff); 2031 if (!aff) 2032 return NULL; 2033 aff->v = isl_vec_cow(aff->v); 2034 if (!aff->v) 2035 return isl_aff_free(aff); 2036 2037 if (isl_int_is_pos(f) && isl_int_is_divisible_by(aff->v->el[0], f)) { 2038 isl_int_divexact(aff->v->el[0], aff->v->el[0], f); 2039 return aff; 2040 } 2041 2042 isl_int_init(gcd); 2043 isl_int_gcd(gcd, aff->v->el[0], f); 2044 isl_int_divexact(aff->v->el[0], aff->v->el[0], gcd); 2045 isl_int_divexact(gcd, f, gcd); 2046 isl_seq_scale(aff->v->el + 1, aff->v->el + 1, gcd, aff->v->size - 1); 2047 isl_int_clear(gcd); 2048 2049 return aff; 2050} 2051 2052/* Multiple "aff" by "v". 2053 */ 2054__isl_give isl_aff *isl_aff_scale_val(__isl_take isl_aff *aff, 2055 __isl_take isl_val *v) 2056{ 2057 if (!aff || !v) 2058 goto error; 2059 2060 if (isl_val_is_one(v)) { 2061 isl_val_free(v); 2062 return aff; 2063 } 2064 2065 if (!isl_val_is_rat(v)) 2066 isl_die(isl_aff_get_ctx(aff), isl_error_invalid, 2067 "expecting rational factor", goto error); 2068 2069 aff = isl_aff_scale(aff, v->n); 2070 aff = isl_aff_scale_down(aff, v->d); 2071 2072 isl_val_free(v); 2073 return aff; 2074error: 2075 isl_aff_free(aff); 2076 isl_val_free(v); 2077 return NULL; 2078} 2079 2080/* Return the result of scaling "aff" down by a factor of "f". 2081 * 2082 * As a special case, NaN/f = NaN. 2083 */ 2084__isl_give isl_aff *isl_aff_scale_down(__isl_take isl_aff *aff, isl_int f) 2085{ 2086 isl_int gcd; 2087 2088 if (!aff) 2089 return NULL; 2090 if (isl_aff_is_nan(aff)) 2091 return aff; 2092 2093 if (isl_int_is_one(f)) 2094 return aff; 2095 2096 aff = isl_aff_cow(aff); 2097 if (!aff) 2098 return NULL; 2099 2100 if (isl_int_is_zero(f)) 2101 isl_die(isl_aff_get_ctx(aff), isl_error_invalid, 2102 "cannot scale down by zero", return isl_aff_free(aff)); 2103 2104 aff->v = isl_vec_cow(aff->v); 2105 if (!aff->v) 2106 return isl_aff_free(aff); 2107 2108 isl_int_init(gcd); 2109 isl_seq_gcd(aff->v->el + 1, aff->v->size - 1, &gcd); 2110 isl_int_gcd(gcd, gcd, f); 2111 isl_seq_scale_down(aff->v->el + 1, aff->v->el + 1, gcd, aff->v->size - 1); 2112 isl_int_divexact(gcd, f, gcd); 2113 isl_int_mul(aff->v->el[0], aff->v->el[0], gcd); 2114 isl_int_clear(gcd); 2115 2116 return aff; 2117} 2118 2119/* Divide "aff" by "v". 2120 */ 2121__isl_give isl_aff *isl_aff_scale_down_val(__isl_take isl_aff *aff, 2122 __isl_take isl_val *v) 2123{ 2124 if (!aff || !v) 2125 goto error; 2126 2127 if (isl_val_is_one(v)) { 2128 isl_val_free(v); 2129 return aff; 2130 } 2131 2132 if (!isl_val_is_rat(v)) 2133 isl_die(isl_aff_get_ctx(aff), isl_error_invalid, 2134 "expecting rational factor", goto error); 2135 if (!isl_val_is_pos(v)) 2136 isl_die(isl_aff_get_ctx(aff), isl_error_invalid, 2137 "factor needs to be positive", goto error); 2138 2139 aff = isl_aff_scale(aff, v->d); 2140 aff = isl_aff_scale_down(aff, v->n); 2141 2142 isl_val_free(v); 2143 return aff; 2144error: 2145 isl_aff_free(aff); 2146 isl_val_free(v); 2147 return NULL; 2148} 2149 2150__isl_give isl_aff *isl_aff_scale_down_ui(__isl_take isl_aff *aff, unsigned f) 2151{ 2152 isl_int v; 2153 2154 if (f == 1) 2155 return aff; 2156 2157 isl_int_init(v); 2158 isl_int_set_ui(v, f); 2159 aff = isl_aff_scale_down(aff, v); 2160 isl_int_clear(v); 2161 2162 return aff; 2163} 2164 2165__isl_give isl_aff *isl_aff_set_dim_name(__isl_take isl_aff *aff, 2166 enum isl_dim_type type, unsigned pos, const char *s) 2167{ 2168 aff = isl_aff_cow(aff); 2169 if (!aff) 2170 return NULL; 2171 if (type == isl_dim_out) 2172 isl_die(aff->v->ctx, isl_error_invalid, 2173 "cannot set name of output/set dimension", 2174 return isl_aff_free(aff)); 2175 if (type == isl_dim_in) 2176 type = isl_dim_set; 2177 aff->ls = isl_local_space_set_dim_name(aff->ls, type, pos, s); 2178 if (!aff->ls) 2179 return isl_aff_free(aff); 2180 2181 return aff; 2182} 2183 2184__isl_give isl_aff *isl_aff_set_dim_id(__isl_take isl_aff *aff, 2185 enum isl_dim_type type, unsigned pos, __isl_take isl_id *id) 2186{ 2187 aff = isl_aff_cow(aff); 2188 if (!aff) 2189 goto error; 2190 if (type == isl_dim_out) 2191 isl_die(aff->v->ctx, isl_error_invalid, 2192 "cannot set name of output/set dimension", 2193 goto error); 2194 if (type == isl_dim_in) 2195 type = isl_dim_set; 2196 aff->ls = isl_local_space_set_dim_id(aff->ls, type, pos, id); 2197 if (!aff->ls) 2198 return isl_aff_free(aff); 2199 2200 return aff; 2201error: 2202 isl_id_free(id); 2203 isl_aff_free(aff); 2204 return NULL; 2205} 2206 2207/* Replace the identifier of the input tuple of "aff" by "id". 2208 * type is currently required to be equal to isl_dim_in 2209 */ 2210__isl_give isl_aff *isl_aff_set_tuple_id(__isl_take isl_aff *aff, 2211 enum isl_dim_type type, __isl_take isl_id *id) 2212{ 2213 aff = isl_aff_cow(aff); 2214 if (!aff) 2215 goto error; 2216 if (type != isl_dim_in) 2217 isl_die(aff->v->ctx, isl_error_invalid, 2218 "cannot only set id of input tuple", goto error); 2219 aff->ls = isl_local_space_set_tuple_id(aff->ls, isl_dim_set, id); 2220 if (!aff->ls) 2221 return isl_aff_free(aff); 2222 2223 return aff; 2224error: 2225 isl_id_free(id); 2226 isl_aff_free(aff); 2227 return NULL; 2228} 2229 2230/* Exploit the equalities in "eq" to simplify the affine expression 2231 * and the expressions of the integer divisions in the local space. 2232 * The integer divisions in this local space are assumed to appear 2233 * as regular dimensions in "eq". 2234 */ 2235static __isl_give isl_aff *isl_aff_substitute_equalities_lifted( 2236 __isl_take isl_aff *aff, __isl_take isl_basic_set *eq) 2237{ 2238 int i, j; 2239 unsigned o_div; 2240 unsigned n_div; 2241 2242 if (!eq) 2243 goto error; 2244 if (eq->n_eq == 0) { 2245 isl_basic_set_free(eq); 2246 return aff; 2247 } 2248 2249 aff = isl_aff_cow(aff); 2250 if (!aff) 2251 goto error; 2252 2253 aff->ls = isl_local_space_substitute_equalities(aff->ls, 2254 isl_basic_set_copy(eq)); 2255 aff->v = isl_vec_cow(aff->v); 2256 if (!aff->ls || !aff->v) 2257 goto error; 2258 2259 o_div = isl_basic_set_offset(eq, isl_dim_div); 2260 n_div = eq->n_div; 2261 for (i = 0; i < eq->n_eq; ++i) { 2262 j = isl_seq_last_non_zero(eq->eq[i], o_div + n_div); 2263 if (j < 0 || j == 0 || j >= o_div) 2264 continue; 2265 2266 isl_seq_elim(aff->v->el + 1, eq->eq[i], j, o_div, 2267 &aff->v->el[0]); 2268 } 2269 2270 isl_basic_set_free(eq); 2271 aff = isl_aff_normalize(aff); 2272 return aff; 2273error: 2274 isl_basic_set_free(eq); 2275 isl_aff_free(aff); 2276 return NULL; 2277} 2278 2279/* Exploit the equalities in "eq" to simplify the affine expression 2280 * and the expressions of the integer divisions in the local space. 2281 */ 2282__isl_give isl_aff *isl_aff_substitute_equalities(__isl_take isl_aff *aff, 2283 __isl_take isl_basic_set *eq) 2284{ 2285 isl_size n_div; 2286 2287 n_div = isl_aff_domain_dim(aff, isl_dim_div); 2288 if (n_div < 0) 2289 goto error; 2290 if (n_div > 0) 2291 eq = isl_basic_set_add_dims(eq, isl_dim_set, n_div); 2292 return isl_aff_substitute_equalities_lifted(aff, eq); 2293error: 2294 isl_basic_set_free(eq); 2295 isl_aff_free(aff); 2296 return NULL; 2297} 2298 2299/* Look for equalities among the variables shared by context and aff 2300 * and the integer divisions of aff, if any. 2301 * The equalities are then used to eliminate coefficients and/or integer 2302 * divisions from aff. 2303 */ 2304__isl_give isl_aff *isl_aff_gist(__isl_take isl_aff *aff, 2305 __isl_take isl_set *context) 2306{ 2307 isl_local_space *ls; 2308 isl_basic_set *hull; 2309 2310 ls = isl_aff_get_domain_local_space(aff); 2311 context = isl_local_space_lift_set(ls, context); 2312 2313 hull = isl_set_affine_hull(context); 2314 return isl_aff_substitute_equalities_lifted(aff, hull); 2315} 2316 2317__isl_give isl_aff *isl_aff_gist_params(__isl_take isl_aff *aff, 2318 __isl_take isl_set *context) 2319{ 2320 isl_set *dom_context = isl_set_universe(isl_aff_get_domain_space(aff)); 2321 dom_context = isl_set_intersect_params(dom_context, context); 2322 return isl_aff_gist(aff, dom_context); 2323} 2324 2325/* Return a basic set containing those elements in the space 2326 * of aff where it is positive. "rational" should not be set. 2327 * 2328 * If "aff" is NaN, then it is not positive. 2329 */ 2330static __isl_give isl_basic_set *aff_pos_basic_set(__isl_take isl_aff *aff, 2331 int rational, void *user) 2332{ 2333 isl_constraint *ineq; 2334 isl_basic_set *bset; 2335 isl_val *c; 2336 2337 if (!aff) 2338 return NULL; 2339 if (isl_aff_is_nan(aff)) { 2340 isl_space *space = isl_aff_get_domain_space(aff); 2341 isl_aff_free(aff); 2342 return isl_basic_set_empty(space); 2343 } 2344 if (rational) 2345 isl_die(isl_aff_get_ctx(aff), isl_error_unsupported, 2346 "rational sets not supported", goto error); 2347 2348 ineq = isl_inequality_from_aff(aff); 2349 c = isl_constraint_get_constant_val(ineq); 2350 c = isl_val_sub_ui(c, 1); 2351 ineq = isl_constraint_set_constant_val(ineq, c); 2352 2353 bset = isl_basic_set_from_constraint(ineq); 2354 bset = isl_basic_set_simplify(bset); 2355 return bset; 2356error: 2357 isl_aff_free(aff); 2358 return NULL; 2359} 2360 2361/* Return a basic set containing those elements in the space 2362 * of aff where it is non-negative. 2363 * If "rational" is set, then return a rational basic set. 2364 * 2365 * If "aff" is NaN, then it is not non-negative (it's not negative either). 2366 */ 2367static __isl_give isl_basic_set *aff_nonneg_basic_set( 2368 __isl_take isl_aff *aff, int rational, void *user) 2369{ 2370 isl_constraint *ineq; 2371 isl_basic_set *bset; 2372 2373 if (!aff) 2374 return NULL; 2375 if (isl_aff_is_nan(aff)) { 2376 isl_space *space = isl_aff_get_domain_space(aff); 2377 isl_aff_free(aff); 2378 return isl_basic_set_empty(space); 2379 } 2380 2381 ineq = isl_inequality_from_aff(aff); 2382 2383 bset = isl_basic_set_from_constraint(ineq); 2384 if (rational) 2385 bset = isl_basic_set_set_rational(bset); 2386 bset = isl_basic_set_simplify(bset); 2387 return bset; 2388} 2389 2390/* Return a basic set containing those elements in the space 2391 * of aff where it is non-negative. 2392 */ 2393__isl_give isl_basic_set *isl_aff_nonneg_basic_set(__isl_take isl_aff *aff) 2394{ 2395 return aff_nonneg_basic_set(aff, 0, NULL); 2396} 2397 2398/* Return a basic set containing those elements in the domain space 2399 * of "aff" where it is positive. 2400 */ 2401__isl_give isl_basic_set *isl_aff_pos_basic_set(__isl_take isl_aff *aff) 2402{ 2403 aff = isl_aff_add_constant_num_si(aff, -1); 2404 return isl_aff_nonneg_basic_set(aff); 2405} 2406 2407/* Return a basic set containing those elements in the domain space 2408 * of aff where it is negative. 2409 */ 2410__isl_give isl_basic_set *isl_aff_neg_basic_set(__isl_take isl_aff *aff) 2411{ 2412 aff = isl_aff_neg(aff); 2413 return isl_aff_pos_basic_set(aff); 2414} 2415 2416/* Return a basic set containing those elements in the space 2417 * of aff where it is zero. 2418 * If "rational" is set, then return a rational basic set. 2419 * 2420 * If "aff" is NaN, then it is not zero. 2421 */ 2422static __isl_give isl_basic_set *aff_zero_basic_set(__isl_take isl_aff *aff, 2423 int rational, void *user) 2424{ 2425 isl_constraint *ineq; 2426 isl_basic_set *bset; 2427 2428 if (!aff) 2429 return NULL; 2430 if (isl_aff_is_nan(aff)) { 2431 isl_space *space = isl_aff_get_domain_space(aff); 2432 isl_aff_free(aff); 2433 return isl_basic_set_empty(space); 2434 } 2435 2436 ineq = isl_equality_from_aff(aff); 2437 2438 bset = isl_basic_set_from_constraint(ineq); 2439 if (rational) 2440 bset = isl_basic_set_set_rational(bset); 2441 bset = isl_basic_set_simplify(bset); 2442 return bset; 2443} 2444 2445/* Return a basic set containing those elements in the space 2446 * of aff where it is zero. 2447 */ 2448__isl_give isl_basic_set *isl_aff_zero_basic_set(__isl_take isl_aff *aff) 2449{ 2450 return aff_zero_basic_set(aff, 0, NULL); 2451} 2452 2453/* Return a basic set containing those elements in the shared space 2454 * of aff1 and aff2 where aff1 is greater than or equal to aff2. 2455 */ 2456__isl_give isl_basic_set *isl_aff_ge_basic_set(__isl_take isl_aff *aff1, 2457 __isl_take isl_aff *aff2) 2458{ 2459 aff1 = isl_aff_sub(aff1, aff2); 2460 2461 return isl_aff_nonneg_basic_set(aff1); 2462} 2463 2464/* Return a basic set containing those elements in the shared domain space 2465 * of "aff1" and "aff2" where "aff1" is greater than "aff2". 2466 */ 2467__isl_give isl_basic_set *isl_aff_gt_basic_set(__isl_take isl_aff *aff1, 2468 __isl_take isl_aff *aff2) 2469{ 2470 aff1 = isl_aff_sub(aff1, aff2); 2471 2472 return isl_aff_pos_basic_set(aff1); 2473} 2474 2475/* Return a set containing those elements in the shared space 2476 * of aff1 and aff2 where aff1 is greater than or equal to aff2. 2477 */ 2478__isl_give isl_set *isl_aff_ge_set(__isl_take isl_aff *aff1, 2479 __isl_take isl_aff *aff2) 2480{ 2481 return isl_set_from_basic_set(isl_aff_ge_basic_set(aff1, aff2)); 2482} 2483 2484/* Return a set containing those elements in the shared domain space 2485 * of aff1 and aff2 where aff1 is greater than aff2. 2486 * 2487 * If either of the two inputs is NaN, then the result is empty, 2488 * as comparisons with NaN always return false. 2489 */ 2490__isl_give isl_set *isl_aff_gt_set(__isl_take isl_aff *aff1, 2491 __isl_take isl_aff *aff2) 2492{ 2493 return isl_set_from_basic_set(isl_aff_gt_basic_set(aff1, aff2)); 2494} 2495 2496/* Return a basic set containing those elements in the shared space 2497 * of aff1 and aff2 where aff1 is smaller than or equal to aff2. 2498 */ 2499__isl_give isl_basic_set *isl_aff_le_basic_set(__isl_take isl_aff *aff1, 2500 __isl_take isl_aff *aff2) 2501{ 2502 return isl_aff_ge_basic_set(aff2, aff1); 2503} 2504 2505/* Return a basic set containing those elements in the shared domain space 2506 * of "aff1" and "aff2" where "aff1" is smaller than "aff2". 2507 */ 2508__isl_give isl_basic_set *isl_aff_lt_basic_set(__isl_take isl_aff *aff1, 2509 __isl_take isl_aff *aff2) 2510{ 2511 return isl_aff_gt_basic_set(aff2, aff1); 2512} 2513 2514/* Return a set containing those elements in the shared space 2515 * of aff1 and aff2 where aff1 is smaller than or equal to aff2. 2516 */ 2517__isl_give isl_set *isl_aff_le_set(__isl_take isl_aff *aff1, 2518 __isl_take isl_aff *aff2) 2519{ 2520 return isl_aff_ge_set(aff2, aff1); 2521} 2522 2523/* Return a set containing those elements in the shared domain space 2524 * of "aff1" and "aff2" where "aff1" is smaller than "aff2". 2525 */ 2526__isl_give isl_set *isl_aff_lt_set(__isl_take isl_aff *aff1, 2527 __isl_take isl_aff *aff2) 2528{ 2529 return isl_set_from_basic_set(isl_aff_lt_basic_set(aff1, aff2)); 2530} 2531 2532/* Return a basic set containing those elements in the shared space 2533 * of aff1 and aff2 where aff1 and aff2 are equal. 2534 */ 2535__isl_give isl_basic_set *isl_aff_eq_basic_set(__isl_take isl_aff *aff1, 2536 __isl_take isl_aff *aff2) 2537{ 2538 aff1 = isl_aff_sub(aff1, aff2); 2539 2540 return isl_aff_zero_basic_set(aff1); 2541} 2542 2543/* Return a set containing those elements in the shared space 2544 * of aff1 and aff2 where aff1 and aff2 are equal. 2545 */ 2546__isl_give isl_set *isl_aff_eq_set(__isl_take isl_aff *aff1, 2547 __isl_take isl_aff *aff2) 2548{ 2549 return isl_set_from_basic_set(isl_aff_eq_basic_set(aff1, aff2)); 2550} 2551 2552/* Return a set containing those elements in the shared domain space 2553 * of aff1 and aff2 where aff1 and aff2 are not equal. 2554 * 2555 * If either of the two inputs is NaN, then the result is empty, 2556 * as comparisons with NaN always return false. 2557 */ 2558__isl_give isl_set *isl_aff_ne_set(__isl_take isl_aff *aff1, 2559 __isl_take isl_aff *aff2) 2560{ 2561 isl_set *set_lt, *set_gt; 2562 2563 set_lt = isl_aff_lt_set(isl_aff_copy(aff1), 2564 isl_aff_copy(aff2)); 2565 set_gt = isl_aff_gt_set(aff1, aff2); 2566 return isl_set_union_disjoint(set_lt, set_gt); 2567} 2568 2569__isl_give isl_aff *isl_aff_add_on_domain(__isl_keep isl_set *dom, 2570 __isl_take isl_aff *aff1, __isl_take isl_aff *aff2) 2571{ 2572 aff1 = isl_aff_add(aff1, aff2); 2573 aff1 = isl_aff_gist(aff1, isl_set_copy(dom)); 2574 return aff1; 2575} 2576 2577isl_bool isl_aff_is_empty(__isl_keep isl_aff *aff) 2578{ 2579 if (!aff) 2580 return isl_bool_error; 2581 2582 return isl_bool_false; 2583} 2584 2585#undef TYPE 2586#define TYPE isl_aff 2587static 2588#include "check_type_range_templ.c" 2589 2590/* Check whether the given affine expression has non-zero coefficient 2591 * for any dimension in the given range or if any of these dimensions 2592 * appear with non-zero coefficients in any of the integer divisions 2593 * involved in the affine expression. 2594 */ 2595isl_bool isl_aff_involves_dims(__isl_keep isl_aff *aff, 2596 enum isl_dim_type type, unsigned first, unsigned n) 2597{ 2598 int i; 2599 int *active = NULL; 2600 isl_bool involves = isl_bool_false; 2601 2602 if (!aff) 2603 return isl_bool_error; 2604 if (n == 0) 2605 return isl_bool_false; 2606 if (isl_aff_check_range(aff, type, first, n) < 0) 2607 return isl_bool_error; 2608 2609 active = isl_local_space_get_active(aff->ls, aff->v->el + 2); 2610 if (!active) 2611 goto error; 2612 2613 first += isl_local_space_offset(aff->ls, type) - 1; 2614 for (i = 0; i < n; ++i) 2615 if (active[first + i]) { 2616 involves = isl_bool_true; 2617 break; 2618 } 2619 2620 free(active); 2621 2622 return involves; 2623error: 2624 free(active); 2625 return isl_bool_error; 2626} 2627 2628/* Does "aff" involve any local variables, i.e., integer divisions? 2629 */ 2630isl_bool isl_aff_involves_locals(__isl_keep isl_aff *aff) 2631{ 2632 isl_size n; 2633 2634 n = isl_aff_dim(aff, isl_dim_div); 2635 if (n < 0) 2636 return isl_bool_error; 2637 return isl_bool_ok(n > 0); 2638} 2639 2640__isl_give isl_aff *isl_aff_drop_dims(__isl_take isl_aff *aff, 2641 enum isl_dim_type type, unsigned first, unsigned n) 2642{ 2643 if (!aff) 2644 return NULL; 2645 if (type == isl_dim_out) 2646 isl_die(isl_aff_get_ctx(aff), isl_error_invalid, 2647 "cannot drop output/set dimension", 2648 return isl_aff_free(aff)); 2649 if (type == isl_dim_in) 2650 type = isl_dim_set; 2651 if (n == 0 && !isl_local_space_is_named_or_nested(aff->ls, type)) 2652 return aff; 2653 2654 if (isl_local_space_check_range(aff->ls, type, first, n) < 0) 2655 return isl_aff_free(aff); 2656 2657 aff = isl_aff_cow(aff); 2658 if (!aff) 2659 return NULL; 2660 2661 aff->ls = isl_local_space_drop_dims(aff->ls, type, first, n); 2662 if (!aff->ls) 2663 return isl_aff_free(aff); 2664 2665 first += 1 + isl_local_space_offset(aff->ls, type); 2666 aff->v = isl_vec_drop_els(aff->v, first, n); 2667 if (!aff->v) 2668 return isl_aff_free(aff); 2669 2670 return aff; 2671} 2672 2673/* Is the domain of "aff" a product? 2674 */ 2675static isl_bool isl_aff_domain_is_product(__isl_keep isl_aff *aff) 2676{ 2677 return isl_space_is_product(isl_aff_peek_domain_space(aff)); 2678} 2679 2680#undef TYPE 2681#define TYPE isl_aff 2682#include <isl_domain_factor_templ.c> 2683 2684/* Project the domain of the affine expression onto its parameter space. 2685 * The affine expression may not involve any of the domain dimensions. 2686 */ 2687__isl_give isl_aff *isl_aff_project_domain_on_params(__isl_take isl_aff *aff) 2688{ 2689 isl_space *space; 2690 isl_size n; 2691 2692 n = isl_aff_dim(aff, isl_dim_in); 2693 if (n < 0) 2694 return isl_aff_free(aff); 2695 aff = isl_aff_drop_domain(aff, 0, n); 2696 space = isl_aff_get_domain_space(aff); 2697 space = isl_space_params(space); 2698 aff = isl_aff_reset_domain_space(aff, space); 2699 return aff; 2700} 2701 2702/* Convert an affine expression defined over a parameter domain 2703 * into one that is defined over a zero-dimensional set. 2704 */ 2705__isl_give isl_aff *isl_aff_from_range(__isl_take isl_aff *aff) 2706{ 2707 isl_local_space *ls; 2708 2709 ls = isl_aff_take_domain_local_space(aff); 2710 ls = isl_local_space_set_from_params(ls); 2711 aff = isl_aff_restore_domain_local_space(aff, ls); 2712 2713 return aff; 2714} 2715 2716__isl_give isl_aff *isl_aff_insert_dims(__isl_take isl_aff *aff, 2717 enum isl_dim_type type, unsigned first, unsigned n) 2718{ 2719 if (!aff) 2720 return NULL; 2721 if (type == isl_dim_out) 2722 isl_die(isl_aff_get_ctx(aff), isl_error_invalid, 2723 "cannot insert output/set dimensions", 2724 return isl_aff_free(aff)); 2725 if (type == isl_dim_in) 2726 type = isl_dim_set; 2727 if (n == 0 && !isl_local_space_is_named_or_nested(aff->ls, type)) 2728 return aff; 2729 2730 if (isl_local_space_check_range(aff->ls, type, first, 0) < 0) 2731 return isl_aff_free(aff); 2732 2733 aff = isl_aff_cow(aff); 2734 if (!aff) 2735 return NULL; 2736 2737 aff->ls = isl_local_space_insert_dims(aff->ls, type, first, n); 2738 if (!aff->ls) 2739 return isl_aff_free(aff); 2740 2741 first += 1 + isl_local_space_offset(aff->ls, type); 2742 aff->v = isl_vec_insert_zero_els(aff->v, first, n); 2743 if (!aff->v) 2744 return isl_aff_free(aff); 2745 2746 return aff; 2747} 2748 2749__isl_give isl_aff *isl_aff_add_dims(__isl_take isl_aff *aff, 2750 enum isl_dim_type type, unsigned n) 2751{ 2752 isl_size pos; 2753 2754 pos = isl_aff_dim(aff, type); 2755 if (pos < 0) 2756 return isl_aff_free(aff); 2757 2758 return isl_aff_insert_dims(aff, type, pos, n); 2759} 2760 2761/* Move the "n" dimensions of "src_type" starting at "src_pos" of "aff" 2762 * to dimensions of "dst_type" at "dst_pos". 2763 * 2764 * We only support moving input dimensions to parameters and vice versa. 2765 */ 2766__isl_give isl_aff *isl_aff_move_dims(__isl_take isl_aff *aff, 2767 enum isl_dim_type dst_type, unsigned dst_pos, 2768 enum isl_dim_type src_type, unsigned src_pos, unsigned n) 2769{ 2770 unsigned g_dst_pos; 2771 unsigned g_src_pos; 2772 isl_size src_off, dst_off; 2773 2774 if (!aff) 2775 return NULL; 2776 if (n == 0 && 2777 !isl_local_space_is_named_or_nested(aff->ls, src_type) && 2778 !isl_local_space_is_named_or_nested(aff->ls, dst_type)) 2779 return aff; 2780 2781 if (dst_type == isl_dim_out || src_type == isl_dim_out) 2782 isl_die(isl_aff_get_ctx(aff), isl_error_invalid, 2783 "cannot move output/set dimension", 2784 return isl_aff_free(aff)); 2785 if (dst_type == isl_dim_div || src_type == isl_dim_div) 2786 isl_die(isl_aff_get_ctx(aff), isl_error_invalid, 2787 "cannot move divs", return isl_aff_free(aff)); 2788 if (dst_type == isl_dim_in) 2789 dst_type = isl_dim_set; 2790 if (src_type == isl_dim_in) 2791 src_type = isl_dim_set; 2792 2793 if (isl_local_space_check_range(aff->ls, src_type, src_pos, n) < 0) 2794 return isl_aff_free(aff); 2795 if (dst_type == src_type) 2796 isl_die(isl_aff_get_ctx(aff), isl_error_unsupported, 2797 "moving dims within the same type not supported", 2798 return isl_aff_free(aff)); 2799 2800 aff = isl_aff_cow(aff); 2801 src_off = isl_aff_domain_offset(aff, src_type); 2802 dst_off = isl_aff_domain_offset(aff, dst_type); 2803 if (src_off < 0 || dst_off < 0) 2804 return isl_aff_free(aff); 2805 2806 g_src_pos = 1 + src_off + src_pos; 2807 g_dst_pos = 1 + dst_off + dst_pos; 2808 if (dst_type > src_type) 2809 g_dst_pos -= n; 2810 2811 aff->v = isl_vec_move_els(aff->v, g_dst_pos, g_src_pos, n); 2812 aff->ls = isl_local_space_move_dims(aff->ls, dst_type, dst_pos, 2813 src_type, src_pos, n); 2814 if (!aff->v || !aff->ls) 2815 return isl_aff_free(aff); 2816 2817 aff = sort_divs(aff); 2818 2819 return aff; 2820} 2821 2822/* Given an affine function on a domain (A -> B), 2823 * interchange A and B in the wrapped domain 2824 * to obtain a function on the domain (B -> A). 2825 * 2826 * Since this may change the position of some variables, 2827 * it may also change the normalized order of the local variables. 2828 * Restore this order. Since sort_divs assumes the input 2829 * has a single reference, an explicit isl_aff_cow is required. 2830 */ 2831__isl_give isl_aff *isl_aff_domain_reverse(__isl_take isl_aff *aff) 2832{ 2833 isl_space *space; 2834 isl_local_space *ls; 2835 isl_vec *v; 2836 isl_size n_in, n_out; 2837 unsigned offset; 2838 2839 space = isl_aff_peek_domain_space(aff); 2840 offset = isl_space_offset(space, isl_dim_set); 2841 n_in = isl_space_wrapped_dim(space, isl_dim_set, isl_dim_in); 2842 n_out = isl_space_wrapped_dim(space, isl_dim_set, isl_dim_out); 2843 if (offset < 0 || n_in < 0 || n_out < 0) 2844 return isl_aff_free(aff); 2845 2846 v = isl_aff_take_rat_aff(aff); 2847 v = isl_vec_move_els(v, 1 + 1 + offset, 1 + 1 + offset + n_in, n_out); 2848 aff = isl_aff_restore_rat_aff(aff, v); 2849 2850 ls = isl_aff_take_domain_local_space(aff); 2851 ls = isl_local_space_wrapped_reverse(ls); 2852 aff = isl_aff_restore_domain_local_space(aff, ls); 2853 2854 aff = isl_aff_cow(aff); 2855 aff = sort_divs(aff); 2856 2857 return aff; 2858} 2859 2860/* Return a zero isl_aff in the given space. 2861 * 2862 * This is a helper function for isl_pw_*_as_* that ensures a uniform 2863 * interface over all piecewise types. 2864 */ 2865static __isl_give isl_aff *isl_aff_zero_in_space(__isl_take isl_space *space) 2866{ 2867 isl_local_space *ls; 2868 2869 ls = isl_local_space_from_space(isl_space_domain(space)); 2870 return isl_aff_zero_on_domain(ls); 2871} 2872 2873#define isl_aff_involves_nan isl_aff_is_nan 2874 2875#undef PW 2876#define PW isl_pw_aff 2877#undef BASE 2878#define BASE aff 2879#undef EL_IS_ZERO 2880#define EL_IS_ZERO is_empty 2881#undef ZERO 2882#define ZERO empty 2883#undef IS_ZERO 2884#define IS_ZERO is_empty 2885#undef FIELD 2886#define FIELD aff 2887#undef DEFAULT_IS_ZERO 2888#define DEFAULT_IS_ZERO 0 2889 2890#include <isl_pw_templ.c> 2891#include <isl_pw_un_op_templ.c> 2892#include <isl_pw_add_constant_val_templ.c> 2893#include <isl_pw_add_disjoint_templ.c> 2894#include <isl_pw_bind_domain_templ.c> 2895#include <isl_pw_domain_reverse_templ.c> 2896#include <isl_pw_eval.c> 2897#include <isl_pw_hash.c> 2898#include <isl_pw_fix_templ.c> 2899#include <isl_pw_from_range_templ.c> 2900#include <isl_pw_insert_dims_templ.c> 2901#include <isl_pw_insert_domain_templ.c> 2902#include <isl_pw_move_dims_templ.c> 2903#include <isl_pw_neg_templ.c> 2904#include <isl_pw_pullback_templ.c> 2905#include <isl_pw_scale_templ.c> 2906#include <isl_pw_sub_templ.c> 2907#include <isl_pw_union_opt.c> 2908 2909#undef BASE 2910#define BASE pw_aff 2911 2912#include <isl_union_single.c> 2913#include <isl_union_neg.c> 2914#include <isl_union_sub_templ.c> 2915 2916#undef BASE 2917#define BASE aff 2918 2919#include <isl_union_pw_templ.c> 2920 2921/* Compute a piecewise quasi-affine expression with a domain that 2922 * is the union of those of pwaff1 and pwaff2 and such that on each 2923 * cell, the quasi-affine expression is the maximum of those of pwaff1 2924 * and pwaff2. If only one of pwaff1 or pwaff2 is defined on a given 2925 * cell, then the associated expression is the defined one. 2926 */ 2927__isl_give isl_pw_aff *isl_pw_aff_union_max(__isl_take isl_pw_aff *pwaff1, 2928 __isl_take isl_pw_aff *pwaff2) 2929{ 2930 isl_pw_aff_align_params_bin(&pwaff1, &pwaff2); 2931 return isl_pw_aff_union_opt_cmp(pwaff1, pwaff2, &isl_aff_ge_set); 2932} 2933 2934/* Compute a piecewise quasi-affine expression with a domain that 2935 * is the union of those of pwaff1 and pwaff2 and such that on each 2936 * cell, the quasi-affine expression is the minimum of those of pwaff1 2937 * and pwaff2. If only one of pwaff1 or pwaff2 is defined on a given 2938 * cell, then the associated expression is the defined one. 2939 */ 2940__isl_give isl_pw_aff *isl_pw_aff_union_min(__isl_take isl_pw_aff *pwaff1, 2941 __isl_take isl_pw_aff *pwaff2) 2942{ 2943 isl_pw_aff_align_params_bin(&pwaff1, &pwaff2); 2944 return isl_pw_aff_union_opt_cmp(pwaff1, pwaff2, &isl_aff_le_set); 2945} 2946 2947__isl_give isl_pw_aff *isl_pw_aff_union_opt(__isl_take isl_pw_aff *pwaff1, 2948 __isl_take isl_pw_aff *pwaff2, int max) 2949{ 2950 if (max) 2951 return isl_pw_aff_union_max(pwaff1, pwaff2); 2952 else 2953 return isl_pw_aff_union_min(pwaff1, pwaff2); 2954} 2955 2956/* Is the domain of "pa" a product? 2957 */ 2958static isl_bool isl_pw_aff_domain_is_product(__isl_keep isl_pw_aff *pa) 2959{ 2960 return isl_space_domain_is_wrapping(isl_pw_aff_peek_space(pa)); 2961} 2962 2963#undef TYPE 2964#define TYPE isl_pw_aff 2965#include <isl_domain_factor_templ.c> 2966 2967/* Return a set containing those elements in the domain 2968 * of "pwaff" where it satisfies "fn" (if complement is 0) or 2969 * does not satisfy "fn" (if complement is 1). 2970 * 2971 * The pieces with a NaN never belong to the result since 2972 * NaN does not satisfy any property. 2973 */ 2974static __isl_give isl_set *pw_aff_locus(__isl_take isl_pw_aff *pwaff, 2975 __isl_give isl_basic_set *(*fn)(__isl_take isl_aff *aff, int rational, 2976 void *user), 2977 int complement, void *user) 2978{ 2979 int i; 2980 isl_set *set; 2981 2982 if (!pwaff) 2983 return NULL; 2984 2985 set = isl_set_empty(isl_pw_aff_get_domain_space(pwaff)); 2986 2987 for (i = 0; i < pwaff->n; ++i) { 2988 isl_basic_set *bset; 2989 isl_set *set_i, *locus; 2990 isl_bool rational; 2991 2992 if (isl_aff_is_nan(pwaff->p[i].aff)) 2993 continue; 2994 2995 rational = isl_set_has_rational(pwaff->p[i].set); 2996 bset = fn(isl_aff_copy(pwaff->p[i].aff), rational, user); 2997 locus = isl_set_from_basic_set(bset); 2998 set_i = isl_set_copy(pwaff->p[i].set); 2999 if (complement) 3000 set_i = isl_set_subtract(set_i, locus); 3001 else 3002 set_i = isl_set_intersect(set_i, locus); 3003 set = isl_set_union_disjoint(set, set_i); 3004 } 3005 3006 isl_pw_aff_free(pwaff); 3007 3008 return set; 3009} 3010 3011/* Return a set containing those elements in the domain 3012 * of "pa" where it is positive. 3013 */ 3014__isl_give isl_set *isl_pw_aff_pos_set(__isl_take isl_pw_aff *pa) 3015{ 3016 return pw_aff_locus(pa, &aff_pos_basic_set, 0, NULL); 3017} 3018 3019/* Return a set containing those elements in the domain 3020 * of pwaff where it is non-negative. 3021 */ 3022__isl_give isl_set *isl_pw_aff_nonneg_set(__isl_take isl_pw_aff *pwaff) 3023{ 3024 return pw_aff_locus(pwaff, &aff_nonneg_basic_set, 0, NULL); 3025} 3026 3027/* Return a set containing those elements in the domain 3028 * of pwaff where it is zero. 3029 */ 3030__isl_give isl_set *isl_pw_aff_zero_set(__isl_take isl_pw_aff *pwaff) 3031{ 3032 return pw_aff_locus(pwaff, &aff_zero_basic_set, 0, NULL); 3033} 3034 3035/* Return a set containing those elements in the domain 3036 * of pwaff where it is not zero. 3037 */ 3038__isl_give isl_set *isl_pw_aff_non_zero_set(__isl_take isl_pw_aff *pwaff) 3039{ 3040 return pw_aff_locus(pwaff, &aff_zero_basic_set, 1, NULL); 3041} 3042 3043/* Bind the affine function "aff" to the parameter "id", 3044 * returning the elements in the domain where the affine expression 3045 * is equal to the parameter. 3046 */ 3047__isl_give isl_basic_set *isl_aff_bind_id(__isl_take isl_aff *aff, 3048 __isl_take isl_id *id) 3049{ 3050 isl_space *space; 3051 isl_aff *aff_id; 3052 3053 space = isl_aff_get_domain_space(aff); 3054 space = isl_space_add_param_id(space, isl_id_copy(id)); 3055 3056 aff = isl_aff_align_params(aff, isl_space_copy(space)); 3057 aff_id = isl_aff_param_on_domain_space_id(space, id); 3058 3059 return isl_aff_eq_basic_set(aff, aff_id); 3060} 3061 3062/* Wrapper around isl_aff_bind_id for use as pw_aff_locus callback. 3063 * "rational" should not be set. 3064 */ 3065static __isl_give isl_basic_set *aff_bind_id(__isl_take isl_aff *aff, 3066 int rational, void *user) 3067{ 3068 isl_id *id = user; 3069 3070 if (!aff) 3071 return NULL; 3072 if (rational) 3073 isl_die(isl_aff_get_ctx(aff), isl_error_unsupported, 3074 "rational binding not supported", goto error); 3075 return isl_aff_bind_id(aff, isl_id_copy(id)); 3076error: 3077 isl_aff_free(aff); 3078 return NULL; 3079} 3080 3081/* Bind the piecewise affine function "pa" to the parameter "id", 3082 * returning the elements in the domain where the expression 3083 * is equal to the parameter. 3084 */ 3085__isl_give isl_set *isl_pw_aff_bind_id(__isl_take isl_pw_aff *pa, 3086 __isl_take isl_id *id) 3087{ 3088 isl_set *bound; 3089 3090 bound = pw_aff_locus(pa, &aff_bind_id, 0, id); 3091 isl_id_free(id); 3092 3093 return bound; 3094} 3095 3096/* Return a set containing those elements in the shared domain 3097 * of pwaff1 and pwaff2 where pwaff1 is greater than (or equal) to pwaff2. 3098 * 3099 * We compute the difference on the shared domain and then construct 3100 * the set of values where this difference is non-negative. 3101 * If strict is set, we first subtract 1 from the difference. 3102 * If equal is set, we only return the elements where pwaff1 and pwaff2 3103 * are equal. 3104 */ 3105static __isl_give isl_set *pw_aff_gte_set(__isl_take isl_pw_aff *pwaff1, 3106 __isl_take isl_pw_aff *pwaff2, int strict, int equal) 3107{ 3108 isl_set *set1, *set2; 3109 3110 set1 = isl_pw_aff_domain(isl_pw_aff_copy(pwaff1)); 3111 set2 = isl_pw_aff_domain(isl_pw_aff_copy(pwaff2)); 3112 set1 = isl_set_intersect(set1, set2); 3113 pwaff1 = isl_pw_aff_intersect_domain(pwaff1, isl_set_copy(set1)); 3114 pwaff2 = isl_pw_aff_intersect_domain(pwaff2, isl_set_copy(set1)); 3115 pwaff1 = isl_pw_aff_add(pwaff1, isl_pw_aff_neg(pwaff2)); 3116 3117 if (strict) { 3118 isl_space *space = isl_set_get_space(set1); 3119 isl_aff *aff; 3120 aff = isl_aff_zero_on_domain(isl_local_space_from_space(space)); 3121 aff = isl_aff_add_constant_si(aff, -1); 3122 pwaff1 = isl_pw_aff_add(pwaff1, isl_pw_aff_alloc(set1, aff)); 3123 } else 3124 isl_set_free(set1); 3125 3126 if (equal) 3127 return isl_pw_aff_zero_set(pwaff1); 3128 return isl_pw_aff_nonneg_set(pwaff1); 3129} 3130 3131/* Return a set containing those elements in the shared domain 3132 * of pwaff1 and pwaff2 where pwaff1 is equal to pwaff2. 3133 */ 3134__isl_give isl_set *isl_pw_aff_eq_set(__isl_take isl_pw_aff *pwaff1, 3135 __isl_take isl_pw_aff *pwaff2) 3136{ 3137 isl_pw_aff_align_params_bin(&pwaff1, &pwaff2); 3138 return pw_aff_gte_set(pwaff1, pwaff2, 0, 1); 3139} 3140 3141/* Return a set containing those elements in the shared domain 3142 * of pwaff1 and pwaff2 where pwaff1 is greater than or equal to pwaff2. 3143 */ 3144__isl_give isl_set *isl_pw_aff_ge_set(__isl_take isl_pw_aff *pwaff1, 3145 __isl_take isl_pw_aff *pwaff2) 3146{ 3147 isl_pw_aff_align_params_bin(&pwaff1, &pwaff2); 3148 return pw_aff_gte_set(pwaff1, pwaff2, 0, 0); 3149} 3150 3151/* Return a set containing those elements in the shared domain 3152 * of pwaff1 and pwaff2 where pwaff1 is strictly greater than pwaff2. 3153 */ 3154__isl_give isl_set *isl_pw_aff_gt_set(__isl_take isl_pw_aff *pwaff1, 3155 __isl_take isl_pw_aff *pwaff2) 3156{ 3157 isl_pw_aff_align_params_bin(&pwaff1, &pwaff2); 3158 return pw_aff_gte_set(pwaff1, pwaff2, 1, 0); 3159} 3160 3161__isl_give isl_set *isl_pw_aff_le_set(__isl_take isl_pw_aff *pwaff1, 3162 __isl_take isl_pw_aff *pwaff2) 3163{ 3164 return isl_pw_aff_ge_set(pwaff2, pwaff1); 3165} 3166 3167__isl_give isl_set *isl_pw_aff_lt_set(__isl_take isl_pw_aff *pwaff1, 3168 __isl_take isl_pw_aff *pwaff2) 3169{ 3170 return isl_pw_aff_gt_set(pwaff2, pwaff1); 3171} 3172 3173/* Return a map containing pairs of elements in the domains of "pa1" and "pa2" 3174 * where the function values are ordered in the same way as "order", 3175 * which returns a set in the shared domain of its two arguments. 3176 * 3177 * Let "pa1" and "pa2" be defined on domains A and B respectively. 3178 * We first pull back the two functions such that they are defined on 3179 * the domain [A -> B]. Then we apply "order", resulting in a set 3180 * in the space [A -> B]. Finally, we unwrap this set to obtain 3181 * a map in the space A -> B. 3182 */ 3183static __isl_give isl_map *isl_pw_aff_order_map( 3184 __isl_take isl_pw_aff *pa1, __isl_take isl_pw_aff *pa2, 3185 __isl_give isl_set *(*order)(__isl_take isl_pw_aff *pa1, 3186 __isl_take isl_pw_aff *pa2)) 3187{ 3188 isl_space *space1, *space2; 3189 isl_multi_aff *ma; 3190 isl_set *set; 3191 3192 isl_pw_aff_align_params_bin(&pa1, &pa2); 3193 space1 = isl_space_domain(isl_pw_aff_get_space(pa1)); 3194 space2 = isl_space_domain(isl_pw_aff_get_space(pa2)); 3195 space1 = isl_space_map_from_domain_and_range(space1, space2); 3196 ma = isl_multi_aff_domain_map(isl_space_copy(space1)); 3197 pa1 = isl_pw_aff_pullback_multi_aff(pa1, ma); 3198 ma = isl_multi_aff_range_map(space1); 3199 pa2 = isl_pw_aff_pullback_multi_aff(pa2, ma); 3200 set = order(pa1, pa2); 3201 3202 return isl_set_unwrap(set); 3203} 3204 3205/* Return a map containing pairs of elements in the domains of "pa1" and "pa2" 3206 * where the function values are equal. 3207 */ 3208__isl_give isl_map *isl_pw_aff_eq_map(__isl_take isl_pw_aff *pa1, 3209 __isl_take isl_pw_aff *pa2) 3210{ 3211 return isl_pw_aff_order_map(pa1, pa2, &isl_pw_aff_eq_set); 3212} 3213 3214/* Return a map containing pairs of elements in the domains of "pa1" and "pa2" 3215 * where the function value of "pa1" is less than or equal to 3216 * the function value of "pa2". 3217 */ 3218__isl_give isl_map *isl_pw_aff_le_map(__isl_take isl_pw_aff *pa1, 3219 __isl_take isl_pw_aff *pa2) 3220{ 3221 return isl_pw_aff_order_map(pa1, pa2, &isl_pw_aff_le_set); 3222} 3223 3224/* Return a map containing pairs of elements in the domains of "pa1" and "pa2" 3225 * where the function value of "pa1" is less than the function value of "pa2". 3226 */ 3227__isl_give isl_map *isl_pw_aff_lt_map(__isl_take isl_pw_aff *pa1, 3228 __isl_take isl_pw_aff *pa2) 3229{ 3230 return isl_pw_aff_order_map(pa1, pa2, &isl_pw_aff_lt_set); 3231} 3232 3233/* Return a map containing pairs of elements in the domains of "pa1" and "pa2" 3234 * where the function value of "pa1" is greater than or equal to 3235 * the function value of "pa2". 3236 */ 3237__isl_give isl_map *isl_pw_aff_ge_map(__isl_take isl_pw_aff *pa1, 3238 __isl_take isl_pw_aff *pa2) 3239{ 3240 return isl_pw_aff_order_map(pa1, pa2, &isl_pw_aff_ge_set); 3241} 3242 3243/* Return a map containing pairs of elements in the domains of "pa1" and "pa2" 3244 * where the function value of "pa1" is greater than the function value 3245 * of "pa2". 3246 */ 3247__isl_give isl_map *isl_pw_aff_gt_map(__isl_take isl_pw_aff *pa1, 3248 __isl_take isl_pw_aff *pa2) 3249{ 3250 return isl_pw_aff_order_map(pa1, pa2, &isl_pw_aff_gt_set); 3251} 3252 3253/* Return a set containing those elements in the shared domain 3254 * of the elements of list1 and list2 where each element in list1 3255 * has the relation specified by "fn" with each element in list2. 3256 */ 3257static __isl_give isl_set *pw_aff_list_set(__isl_take isl_pw_aff_list *list1, 3258 __isl_take isl_pw_aff_list *list2, 3259 __isl_give isl_set *(*fn)(__isl_take isl_pw_aff *pwaff1, 3260 __isl_take isl_pw_aff *pwaff2)) 3261{ 3262 int i, j; 3263 isl_ctx *ctx; 3264 isl_set *set; 3265 3266 if (!list1 || !list2) 3267 goto error; 3268 3269 ctx = isl_pw_aff_list_get_ctx(list1); 3270 if (list1->n < 1 || list2->n < 1) 3271 isl_die(ctx, isl_error_invalid, 3272 "list should contain at least one element", goto error); 3273 3274 set = isl_set_universe(isl_pw_aff_get_domain_space(list1->p[0])); 3275 for (i = 0; i < list1->n; ++i) 3276 for (j = 0; j < list2->n; ++j) { 3277 isl_set *set_ij; 3278 3279 set_ij = fn(isl_pw_aff_copy(list1->p[i]), 3280 isl_pw_aff_copy(list2->p[j])); 3281 set = isl_set_intersect(set, set_ij); 3282 } 3283 3284 isl_pw_aff_list_free(list1); 3285 isl_pw_aff_list_free(list2); 3286 return set; 3287error: 3288 isl_pw_aff_list_free(list1); 3289 isl_pw_aff_list_free(list2); 3290 return NULL; 3291} 3292 3293/* Return a set containing those elements in the shared domain 3294 * of the elements of list1 and list2 where each element in list1 3295 * is equal to each element in list2. 3296 */ 3297__isl_give isl_set *isl_pw_aff_list_eq_set(__isl_take isl_pw_aff_list *list1, 3298 __isl_take isl_pw_aff_list *list2) 3299{ 3300 return pw_aff_list_set(list1, list2, &isl_pw_aff_eq_set); 3301} 3302 3303__isl_give isl_set *isl_pw_aff_list_ne_set(__isl_take isl_pw_aff_list *list1, 3304 __isl_take isl_pw_aff_list *list2) 3305{ 3306 return pw_aff_list_set(list1, list2, &isl_pw_aff_ne_set); 3307} 3308 3309/* Return a set containing those elements in the shared domain 3310 * of the elements of list1 and list2 where each element in list1 3311 * is less than or equal to each element in list2. 3312 */ 3313__isl_give isl_set *isl_pw_aff_list_le_set(__isl_take isl_pw_aff_list *list1, 3314 __isl_take isl_pw_aff_list *list2) 3315{ 3316 return pw_aff_list_set(list1, list2, &isl_pw_aff_le_set); 3317} 3318 3319__isl_give isl_set *isl_pw_aff_list_lt_set(__isl_take isl_pw_aff_list *list1, 3320 __isl_take isl_pw_aff_list *list2) 3321{ 3322 return pw_aff_list_set(list1, list2, &isl_pw_aff_lt_set); 3323} 3324 3325__isl_give isl_set *isl_pw_aff_list_ge_set(__isl_take isl_pw_aff_list *list1, 3326 __isl_take isl_pw_aff_list *list2) 3327{ 3328 return pw_aff_list_set(list1, list2, &isl_pw_aff_ge_set); 3329} 3330 3331__isl_give isl_set *isl_pw_aff_list_gt_set(__isl_take isl_pw_aff_list *list1, 3332 __isl_take isl_pw_aff_list *list2) 3333{ 3334 return pw_aff_list_set(list1, list2, &isl_pw_aff_gt_set); 3335} 3336 3337 3338/* Return a set containing those elements in the shared domain 3339 * of pwaff1 and pwaff2 where pwaff1 is not equal to pwaff2. 3340 */ 3341__isl_give isl_set *isl_pw_aff_ne_set(__isl_take isl_pw_aff *pwaff1, 3342 __isl_take isl_pw_aff *pwaff2) 3343{ 3344 isl_set *set_lt, *set_gt; 3345 3346 isl_pw_aff_align_params_bin(&pwaff1, &pwaff2); 3347 set_lt = isl_pw_aff_lt_set(isl_pw_aff_copy(pwaff1), 3348 isl_pw_aff_copy(pwaff2)); 3349 set_gt = isl_pw_aff_gt_set(pwaff1, pwaff2); 3350 return isl_set_union_disjoint(set_lt, set_gt); 3351} 3352 3353__isl_give isl_pw_aff *isl_pw_aff_scale_down(__isl_take isl_pw_aff *pwaff, 3354 isl_int v) 3355{ 3356 int i; 3357 3358 if (isl_int_is_one(v)) 3359 return pwaff; 3360 if (!isl_int_is_pos(v)) 3361 isl_die(isl_pw_aff_get_ctx(pwaff), isl_error_invalid, 3362 "factor needs to be positive", 3363 return isl_pw_aff_free(pwaff)); 3364 pwaff = isl_pw_aff_cow(pwaff); 3365 if (!pwaff) 3366 return NULL; 3367 if (pwaff->n == 0) 3368 return pwaff; 3369 3370 for (i = 0; i < pwaff->n; ++i) { 3371 pwaff->p[i].aff = isl_aff_scale_down(pwaff->p[i].aff, v); 3372 if (!pwaff->p[i].aff) 3373 return isl_pw_aff_free(pwaff); 3374 } 3375 3376 return pwaff; 3377} 3378 3379__isl_give isl_pw_aff *isl_pw_aff_floor(__isl_take isl_pw_aff *pwaff) 3380{ 3381 struct isl_pw_aff_un_op_control control = { .fn_base = &isl_aff_floor }; 3382 return isl_pw_aff_un_op(pwaff, &control); 3383} 3384 3385__isl_give isl_pw_aff *isl_pw_aff_ceil(__isl_take isl_pw_aff *pwaff) 3386{ 3387 struct isl_pw_aff_un_op_control control = { .fn_base = &isl_aff_ceil }; 3388 return isl_pw_aff_un_op(pwaff, &control); 3389} 3390 3391/* Assuming that "cond1" and "cond2" are disjoint, 3392 * return an affine expression that is equal to pwaff1 on cond1 3393 * and to pwaff2 on cond2. 3394 */ 3395static __isl_give isl_pw_aff *isl_pw_aff_select( 3396 __isl_take isl_set *cond1, __isl_take isl_pw_aff *pwaff1, 3397 __isl_take isl_set *cond2, __isl_take isl_pw_aff *pwaff2) 3398{ 3399 pwaff1 = isl_pw_aff_intersect_domain(pwaff1, cond1); 3400 pwaff2 = isl_pw_aff_intersect_domain(pwaff2, cond2); 3401 3402 return isl_pw_aff_add_disjoint(pwaff1, pwaff2); 3403} 3404 3405/* Return an affine expression that is equal to pwaff_true for elements 3406 * where "cond" is non-zero and to pwaff_false for elements where "cond" 3407 * is zero. 3408 * That is, return cond ? pwaff_true : pwaff_false; 3409 * 3410 * If "cond" involves and NaN, then we conservatively return a NaN 3411 * on its entire domain. In principle, we could consider the pieces 3412 * where it is NaN separately from those where it is not. 3413 * 3414 * If "pwaff_true" and "pwaff_false" are obviously equal to each other, 3415 * then only use the domain of "cond" to restrict the domain. 3416 */ 3417__isl_give isl_pw_aff *isl_pw_aff_cond(__isl_take isl_pw_aff *cond, 3418 __isl_take isl_pw_aff *pwaff_true, __isl_take isl_pw_aff *pwaff_false) 3419{ 3420 isl_set *cond_true, *cond_false; 3421 isl_bool equal; 3422 3423 if (!cond) 3424 goto error; 3425 if (isl_pw_aff_involves_nan(cond)) { 3426 isl_space *space = isl_pw_aff_get_domain_space(cond); 3427 isl_local_space *ls = isl_local_space_from_space(space); 3428 isl_pw_aff_free(cond); 3429 isl_pw_aff_free(pwaff_true); 3430 isl_pw_aff_free(pwaff_false); 3431 return isl_pw_aff_nan_on_domain(ls); 3432 } 3433 3434 pwaff_true = isl_pw_aff_align_params(pwaff_true, 3435 isl_pw_aff_get_space(pwaff_false)); 3436 pwaff_false = isl_pw_aff_align_params(pwaff_false, 3437 isl_pw_aff_get_space(pwaff_true)); 3438 equal = isl_pw_aff_plain_is_equal(pwaff_true, pwaff_false); 3439 if (equal < 0) 3440 goto error; 3441 if (equal) { 3442 isl_set *dom; 3443 3444 dom = isl_set_coalesce(isl_pw_aff_domain(cond)); 3445 isl_pw_aff_free(pwaff_false); 3446 return isl_pw_aff_intersect_domain(pwaff_true, dom); 3447 } 3448 3449 cond_true = isl_pw_aff_non_zero_set(isl_pw_aff_copy(cond)); 3450 cond_false = isl_pw_aff_zero_set(cond); 3451 return isl_pw_aff_select(cond_true, pwaff_true, 3452 cond_false, pwaff_false); 3453error: 3454 isl_pw_aff_free(cond); 3455 isl_pw_aff_free(pwaff_true); 3456 isl_pw_aff_free(pwaff_false); 3457 return NULL; 3458} 3459 3460isl_bool isl_aff_is_cst(__isl_keep isl_aff *aff) 3461{ 3462 int pos; 3463 3464 if (!aff) 3465 return isl_bool_error; 3466 3467 pos = isl_seq_first_non_zero(aff->v->el + 2, aff->v->size - 2); 3468 return isl_bool_ok(pos == -1); 3469} 3470 3471/* Check whether pwaff is a piecewise constant. 3472 */ 3473isl_bool isl_pw_aff_is_cst(__isl_keep isl_pw_aff *pwaff) 3474{ 3475 int i; 3476 3477 if (!pwaff) 3478 return isl_bool_error; 3479 3480 for (i = 0; i < pwaff->n; ++i) { 3481 isl_bool is_cst = isl_aff_is_cst(pwaff->p[i].aff); 3482 if (is_cst < 0 || !is_cst) 3483 return is_cst; 3484 } 3485 3486 return isl_bool_true; 3487} 3488 3489/* Return the product of "aff1" and "aff2". 3490 * 3491 * If either of the two is NaN, then the result is NaN. 3492 * 3493 * Otherwise, at least one of "aff1" or "aff2" needs to be a constant. 3494 */ 3495__isl_give isl_aff *isl_aff_mul(__isl_take isl_aff *aff1, 3496 __isl_take isl_aff *aff2) 3497{ 3498 if (!aff1 || !aff2) 3499 goto error; 3500 3501 if (isl_aff_is_nan(aff1)) { 3502 isl_aff_free(aff2); 3503 return aff1; 3504 } 3505 if (isl_aff_is_nan(aff2)) { 3506 isl_aff_free(aff1); 3507 return aff2; 3508 } 3509 3510 if (!isl_aff_is_cst(aff2) && isl_aff_is_cst(aff1)) 3511 return isl_aff_mul(aff2, aff1); 3512 3513 if (!isl_aff_is_cst(aff2)) 3514 isl_die(isl_aff_get_ctx(aff1), isl_error_invalid, 3515 "at least one affine expression should be constant", 3516 goto error); 3517 3518 aff1 = isl_aff_cow(aff1); 3519 if (!aff1 || !aff2) 3520 goto error; 3521 3522 aff1 = isl_aff_scale(aff1, aff2->v->el[1]); 3523 aff1 = isl_aff_scale_down(aff1, aff2->v->el[0]); 3524 3525 isl_aff_free(aff2); 3526 return aff1; 3527error: 3528 isl_aff_free(aff1); 3529 isl_aff_free(aff2); 3530 return NULL; 3531} 3532 3533/* Divide "aff1" by "aff2", assuming "aff2" is a constant. 3534 * 3535 * If either of the two is NaN, then the result is NaN. 3536 * A division by zero also results in NaN. 3537 */ 3538__isl_give isl_aff *isl_aff_div(__isl_take isl_aff *aff1, 3539 __isl_take isl_aff *aff2) 3540{ 3541 isl_bool is_cst, is_zero; 3542 int neg; 3543 3544 if (!aff1 || !aff2) 3545 goto error; 3546 3547 if (isl_aff_is_nan(aff1)) { 3548 isl_aff_free(aff2); 3549 return aff1; 3550 } 3551 if (isl_aff_is_nan(aff2)) { 3552 isl_aff_free(aff1); 3553 return aff2; 3554 } 3555 3556 is_cst = isl_aff_is_cst(aff2); 3557 if (is_cst < 0) 3558 goto error; 3559 if (!is_cst) 3560 isl_die(isl_aff_get_ctx(aff2), isl_error_invalid, 3561 "second argument should be a constant", goto error); 3562 is_zero = isl_aff_plain_is_zero(aff2); 3563 if (is_zero < 0) 3564 goto error; 3565 if (is_zero) 3566 return set_nan_free(aff1, aff2); 3567 3568 neg = isl_int_is_neg(aff2->v->el[1]); 3569 if (neg) { 3570 isl_int_neg(aff2->v->el[0], aff2->v->el[0]); 3571 isl_int_neg(aff2->v->el[1], aff2->v->el[1]); 3572 } 3573 3574 aff1 = isl_aff_scale(aff1, aff2->v->el[0]); 3575 aff1 = isl_aff_scale_down(aff1, aff2->v->el[1]); 3576 3577 if (neg) { 3578 isl_int_neg(aff2->v->el[0], aff2->v->el[0]); 3579 isl_int_neg(aff2->v->el[1], aff2->v->el[1]); 3580 } 3581 3582 isl_aff_free(aff2); 3583 return aff1; 3584error: 3585 isl_aff_free(aff1); 3586 isl_aff_free(aff2); 3587 return NULL; 3588} 3589 3590__isl_give isl_pw_aff *isl_pw_aff_add(__isl_take isl_pw_aff *pwaff1, 3591 __isl_take isl_pw_aff *pwaff2) 3592{ 3593 isl_pw_aff_align_params_bin(&pwaff1, &pwaff2); 3594 return isl_pw_aff_on_shared_domain(pwaff1, pwaff2, &isl_aff_add); 3595} 3596 3597__isl_give isl_pw_aff *isl_pw_aff_mul(__isl_take isl_pw_aff *pwaff1, 3598 __isl_take isl_pw_aff *pwaff2) 3599{ 3600 isl_pw_aff_align_params_bin(&pwaff1, &pwaff2); 3601 return isl_pw_aff_on_shared_domain(pwaff1, pwaff2, &isl_aff_mul); 3602} 3603 3604/* Divide "pa1" by "pa2", assuming "pa2" is a piecewise constant. 3605 */ 3606__isl_give isl_pw_aff *isl_pw_aff_div(__isl_take isl_pw_aff *pa1, 3607 __isl_take isl_pw_aff *pa2) 3608{ 3609 int is_cst; 3610 3611 is_cst = isl_pw_aff_is_cst(pa2); 3612 if (is_cst < 0) 3613 goto error; 3614 if (!is_cst) 3615 isl_die(isl_pw_aff_get_ctx(pa2), isl_error_invalid, 3616 "second argument should be a piecewise constant", 3617 goto error); 3618 isl_pw_aff_align_params_bin(&pa1, &pa2); 3619 return isl_pw_aff_on_shared_domain(pa1, pa2, &isl_aff_div); 3620error: 3621 isl_pw_aff_free(pa1); 3622 isl_pw_aff_free(pa2); 3623 return NULL; 3624} 3625 3626/* Compute the quotient of the integer division of "pa1" by "pa2" 3627 * with rounding towards zero. 3628 * "pa2" is assumed to be a piecewise constant. 3629 * 3630 * In particular, return 3631 * 3632 * pa1 >= 0 ? floor(pa1/pa2) : ceil(pa1/pa2) 3633 * 3634 */ 3635__isl_give isl_pw_aff *isl_pw_aff_tdiv_q(__isl_take isl_pw_aff *pa1, 3636 __isl_take isl_pw_aff *pa2) 3637{ 3638 int is_cst; 3639 isl_set *cond; 3640 isl_pw_aff *f, *c; 3641 3642 is_cst = isl_pw_aff_is_cst(pa2); 3643 if (is_cst < 0) 3644 goto error; 3645 if (!is_cst) 3646 isl_die(isl_pw_aff_get_ctx(pa2), isl_error_invalid, 3647 "second argument should be a piecewise constant", 3648 goto error); 3649 3650 pa1 = isl_pw_aff_div(pa1, pa2); 3651 3652 cond = isl_pw_aff_nonneg_set(isl_pw_aff_copy(pa1)); 3653 f = isl_pw_aff_floor(isl_pw_aff_copy(pa1)); 3654 c = isl_pw_aff_ceil(pa1); 3655 return isl_pw_aff_cond(isl_set_indicator_function(cond), f, c); 3656error: 3657 isl_pw_aff_free(pa1); 3658 isl_pw_aff_free(pa2); 3659 return NULL; 3660} 3661 3662/* Compute the remainder of the integer division of "pa1" by "pa2" 3663 * with rounding towards zero. 3664 * "pa2" is assumed to be a piecewise constant. 3665 * 3666 * In particular, return 3667 * 3668 * pa1 - pa2 * (pa1 >= 0 ? floor(pa1/pa2) : ceil(pa1/pa2)) 3669 * 3670 */ 3671__isl_give isl_pw_aff *isl_pw_aff_tdiv_r(__isl_take isl_pw_aff *pa1, 3672 __isl_take isl_pw_aff *pa2) 3673{ 3674 int is_cst; 3675 isl_pw_aff *res; 3676 3677 is_cst = isl_pw_aff_is_cst(pa2); 3678 if (is_cst < 0) 3679 goto error; 3680 if (!is_cst) 3681 isl_die(isl_pw_aff_get_ctx(pa2), isl_error_invalid, 3682 "second argument should be a piecewise constant", 3683 goto error); 3684 res = isl_pw_aff_tdiv_q(isl_pw_aff_copy(pa1), isl_pw_aff_copy(pa2)); 3685 res = isl_pw_aff_mul(pa2, res); 3686 res = isl_pw_aff_sub(pa1, res); 3687 return res; 3688error: 3689 isl_pw_aff_free(pa1); 3690 isl_pw_aff_free(pa2); 3691 return NULL; 3692} 3693 3694/* Does either of "pa1" or "pa2" involve any NaN? 3695 */ 3696static isl_bool either_involves_nan(__isl_keep isl_pw_aff *pa1, 3697 __isl_keep isl_pw_aff *pa2) 3698{ 3699 isl_bool has_nan; 3700 3701 has_nan = isl_pw_aff_involves_nan(pa1); 3702 if (has_nan < 0 || has_nan) 3703 return has_nan; 3704 return isl_pw_aff_involves_nan(pa2); 3705} 3706 3707/* Return a piecewise affine expression defined on the specified domain 3708 * that represents NaN. 3709 */ 3710static __isl_give isl_pw_aff *nan_on_domain_set(__isl_take isl_set *dom) 3711{ 3712 isl_local_space *ls; 3713 isl_pw_aff *pa; 3714 3715 ls = isl_local_space_from_space(isl_set_get_space(dom)); 3716 pa = isl_pw_aff_nan_on_domain(ls); 3717 pa = isl_pw_aff_intersect_domain(pa, dom); 3718 3719 return pa; 3720} 3721 3722/* Replace "pa1" and "pa2" (at least one of which involves a NaN) 3723 * by a NaN on their shared domain. 3724 * 3725 * In principle, the result could be refined to only being NaN 3726 * on the parts of this domain where at least one of "pa1" or "pa2" is NaN. 3727 */ 3728static __isl_give isl_pw_aff *replace_by_nan(__isl_take isl_pw_aff *pa1, 3729 __isl_take isl_pw_aff *pa2) 3730{ 3731 isl_set *dom; 3732 3733 dom = isl_set_intersect(isl_pw_aff_domain(pa1), isl_pw_aff_domain(pa2)); 3734 return nan_on_domain_set(dom); 3735} 3736 3737static __isl_give isl_pw_aff *pw_aff_min(__isl_take isl_pw_aff *pwaff1, 3738 __isl_take isl_pw_aff *pwaff2) 3739{ 3740 isl_set *le; 3741 isl_set *dom; 3742 3743 dom = isl_set_intersect(isl_pw_aff_domain(isl_pw_aff_copy(pwaff1)), 3744 isl_pw_aff_domain(isl_pw_aff_copy(pwaff2))); 3745 le = isl_pw_aff_le_set(isl_pw_aff_copy(pwaff1), 3746 isl_pw_aff_copy(pwaff2)); 3747 dom = isl_set_subtract(dom, isl_set_copy(le)); 3748 return isl_pw_aff_select(le, pwaff1, dom, pwaff2); 3749} 3750 3751static __isl_give isl_pw_aff *pw_aff_max(__isl_take isl_pw_aff *pwaff1, 3752 __isl_take isl_pw_aff *pwaff2) 3753{ 3754 isl_set *ge; 3755 isl_set *dom; 3756 3757 dom = isl_set_intersect(isl_pw_aff_domain(isl_pw_aff_copy(pwaff1)), 3758 isl_pw_aff_domain(isl_pw_aff_copy(pwaff2))); 3759 ge = isl_pw_aff_ge_set(isl_pw_aff_copy(pwaff1), 3760 isl_pw_aff_copy(pwaff2)); 3761 dom = isl_set_subtract(dom, isl_set_copy(ge)); 3762 return isl_pw_aff_select(ge, pwaff1, dom, pwaff2); 3763} 3764 3765/* Return an expression for the minimum (if "max" is not set) or 3766 * the maximum (if "max" is set) of "pa1" and "pa2". 3767 * If either expression involves any NaN, then return a NaN 3768 * on the shared domain as result. 3769 */ 3770static __isl_give isl_pw_aff *pw_aff_min_max(__isl_take isl_pw_aff *pa1, 3771 __isl_take isl_pw_aff *pa2, int max) 3772{ 3773 isl_bool has_nan; 3774 3775 has_nan = either_involves_nan(pa1, pa2); 3776 if (has_nan < 0) 3777 pa1 = isl_pw_aff_free(pa1); 3778 else if (has_nan) 3779 return replace_by_nan(pa1, pa2); 3780 3781 isl_pw_aff_align_params_bin(&pa1, &pa2); 3782 if (max) 3783 return pw_aff_max(pa1, pa2); 3784 else 3785 return pw_aff_min(pa1, pa2); 3786} 3787 3788/* Return an expression for the minimum of "pwaff1" and "pwaff2". 3789 */ 3790__isl_give isl_pw_aff *isl_pw_aff_min(__isl_take isl_pw_aff *pwaff1, 3791 __isl_take isl_pw_aff *pwaff2) 3792{ 3793 return pw_aff_min_max(pwaff1, pwaff2, 0); 3794} 3795 3796/* Return an expression for the maximum of "pwaff1" and "pwaff2". 3797 */ 3798__isl_give isl_pw_aff *isl_pw_aff_max(__isl_take isl_pw_aff *pwaff1, 3799 __isl_take isl_pw_aff *pwaff2) 3800{ 3801 return pw_aff_min_max(pwaff1, pwaff2, 1); 3802} 3803 3804/* Does "pa" not involve any NaN? 3805 */ 3806static isl_bool pw_aff_no_nan(__isl_keep isl_pw_aff *pa, void *user) 3807{ 3808 return isl_bool_not(isl_pw_aff_involves_nan(pa)); 3809} 3810 3811/* Does any element of "list" involve any NaN? 3812 * 3813 * That is, is it not the case that every element does not involve any NaN? 3814 */ 3815static isl_bool isl_pw_aff_list_involves_nan(__isl_keep isl_pw_aff_list *list) 3816{ 3817 return isl_bool_not(isl_pw_aff_list_every(list, &pw_aff_no_nan, NULL)); 3818} 3819 3820/* Replace "list" (consisting of "n" elements, of which 3821 * at least one element involves a NaN) 3822 * by a NaN on the shared domain of the elements. 3823 * 3824 * In principle, the result could be refined to only being NaN 3825 * on the parts of this domain where at least one of the elements is NaN. 3826 */ 3827static __isl_give isl_pw_aff *replace_list_by_nan( 3828 __isl_take isl_pw_aff_list *list, int n) 3829{ 3830 int i; 3831 isl_set *dom; 3832 3833 dom = isl_pw_aff_domain(isl_pw_aff_list_get_at(list, 0)); 3834 for (i = 1; i < n; ++i) { 3835 isl_set *dom_i; 3836 3837 dom_i = isl_pw_aff_domain(isl_pw_aff_list_get_at(list, i)); 3838 dom = isl_set_intersect(dom, dom_i); 3839 } 3840 3841 isl_pw_aff_list_free(list); 3842 return nan_on_domain_set(dom); 3843} 3844 3845/* Return the set where the element at "pos1" of "list" is less than or 3846 * equal to the element at "pos2". 3847 * Equality is only allowed if "pos1" is smaller than "pos2". 3848 */ 3849static __isl_give isl_set *less(__isl_keep isl_pw_aff_list *list, 3850 int pos1, int pos2) 3851{ 3852 isl_pw_aff *pa1, *pa2; 3853 3854 pa1 = isl_pw_aff_list_get_at(list, pos1); 3855 pa2 = isl_pw_aff_list_get_at(list, pos2); 3856 3857 if (pos1 < pos2) 3858 return isl_pw_aff_le_set(pa1, pa2); 3859 else 3860 return isl_pw_aff_lt_set(pa1, pa2); 3861} 3862 3863/* Return an isl_pw_aff that maps each element in the intersection of the 3864 * domains of the piecewise affine expressions in "list" 3865 * to the maximal (if "max" is set) or minimal (if "max" is not set) 3866 * expression in "list" at that element. 3867 * If any expression involves any NaN, then return a NaN 3868 * on the shared domain as result. 3869 * 3870 * If "list" has n elements, then the result consists of n pieces, 3871 * where, in the case of a minimum, each piece has as value expression 3872 * the value expression of one of the elements and as domain 3873 * the set of elements where that value expression 3874 * is less than (or equal) to the other value expressions. 3875 * In the case of a maximum, the condition is 3876 * that all the other value expressions are less than (or equal) 3877 * to the given value expression. 3878 * 3879 * In order to produce disjoint pieces, a pair of elements 3880 * in the original domain is only allowed to be equal to each other 3881 * on exactly one of the two pieces corresponding to the two elements. 3882 * The position in the list is used to break ties. 3883 * In particular, in the case of a minimum, 3884 * in the piece corresponding to a given element, 3885 * this element is allowed to be equal to any later element in the list, 3886 * but not to any earlier element in the list. 3887 */ 3888static __isl_give isl_pw_aff *isl_pw_aff_list_opt( 3889 __isl_take isl_pw_aff_list *list, int max) 3890{ 3891 int i, j; 3892 isl_bool has_nan; 3893 isl_size n; 3894 isl_space *space; 3895 isl_pw_aff *pa, *res; 3896 3897 n = isl_pw_aff_list_size(list); 3898 if (n < 0) 3899 goto error; 3900 if (n < 1) 3901 isl_die(isl_pw_aff_list_get_ctx(list), isl_error_invalid, 3902 "list should contain at least one element", goto error); 3903 3904 has_nan = isl_pw_aff_list_involves_nan(list); 3905 if (has_nan < 0) 3906 goto error; 3907 if (has_nan) 3908 return replace_list_by_nan(list, n); 3909 3910 pa = isl_pw_aff_list_get_at(list, 0); 3911 space = isl_pw_aff_get_space(pa); 3912 isl_pw_aff_free(pa); 3913 res = isl_pw_aff_empty(space); 3914 3915 for (i = 0; i < n; ++i) { 3916 pa = isl_pw_aff_list_get_at(list, i); 3917 for (j = 0; j < n; ++j) { 3918 isl_set *dom; 3919 3920 if (j == i) 3921 continue; 3922 if (max) 3923 dom = less(list, j, i); 3924 else 3925 dom = less(list, i, j); 3926 3927 pa = isl_pw_aff_intersect_domain(pa, dom); 3928 } 3929 res = isl_pw_aff_add_disjoint(res, pa); 3930 } 3931 3932 isl_pw_aff_list_free(list); 3933 return res; 3934error: 3935 isl_pw_aff_list_free(list); 3936 return NULL; 3937} 3938 3939/* Return an isl_pw_aff that maps each element in the intersection of the 3940 * domains of the elements of list to the minimal corresponding affine 3941 * expression. 3942 */ 3943__isl_give isl_pw_aff *isl_pw_aff_list_min(__isl_take isl_pw_aff_list *list) 3944{ 3945 return isl_pw_aff_list_opt(list, 0); 3946} 3947 3948/* Return an isl_pw_aff that maps each element in the intersection of the 3949 * domains of the elements of list to the maximal corresponding affine 3950 * expression. 3951 */ 3952__isl_give isl_pw_aff *isl_pw_aff_list_max(__isl_take isl_pw_aff_list *list) 3953{ 3954 return isl_pw_aff_list_opt(list, 1); 3955} 3956 3957/* Mark the domains of "pwaff" as rational. 3958 */ 3959__isl_give isl_pw_aff *isl_pw_aff_set_rational(__isl_take isl_pw_aff *pwaff) 3960{ 3961 int i; 3962 3963 pwaff = isl_pw_aff_cow(pwaff); 3964 if (!pwaff) 3965 return NULL; 3966 if (pwaff->n == 0) 3967 return pwaff; 3968 3969 for (i = 0; i < pwaff->n; ++i) { 3970 pwaff->p[i].set = isl_set_set_rational(pwaff->p[i].set); 3971 if (!pwaff->p[i].set) 3972 return isl_pw_aff_free(pwaff); 3973 } 3974 3975 return pwaff; 3976} 3977 3978/* Mark the domains of the elements of "list" as rational. 3979 */ 3980__isl_give isl_pw_aff_list *isl_pw_aff_list_set_rational( 3981 __isl_take isl_pw_aff_list *list) 3982{ 3983 int i, n; 3984 3985 if (!list) 3986 return NULL; 3987 if (list->n == 0) 3988 return list; 3989 3990 n = list->n; 3991 for (i = 0; i < n; ++i) { 3992 isl_pw_aff *pa; 3993 3994 pa = isl_pw_aff_list_get_pw_aff(list, i); 3995 pa = isl_pw_aff_set_rational(pa); 3996 list = isl_pw_aff_list_set_pw_aff(list, i, pa); 3997 } 3998 3999 return list; 4000} 4001 4002/* Do the parameters of "aff" match those of "space"? 4003 */ 4004isl_bool isl_aff_matching_params(__isl_keep isl_aff *aff, 4005 __isl_keep isl_space *space) 4006{ 4007 isl_space *aff_space; 4008 isl_bool match; 4009 4010 if (!aff || !space) 4011 return isl_bool_error; 4012 4013 aff_space = isl_aff_get_domain_space(aff); 4014 4015 match = isl_space_has_equal_params(space, aff_space); 4016 4017 isl_space_free(aff_space); 4018 return match; 4019} 4020 4021/* Check that the domain space of "aff" matches "space". 4022 */ 4023isl_stat isl_aff_check_match_domain_space(__isl_keep isl_aff *aff, 4024 __isl_keep isl_space *space) 4025{ 4026 isl_space *aff_space; 4027 isl_bool match; 4028 4029 if (!aff || !space) 4030 return isl_stat_error; 4031 4032 aff_space = isl_aff_get_domain_space(aff); 4033 4034 match = isl_space_has_equal_params(space, aff_space); 4035 if (match < 0) 4036 goto error; 4037 if (!match) 4038 isl_die(isl_aff_get_ctx(aff), isl_error_invalid, 4039 "parameters don't match", goto error); 4040 match = isl_space_tuple_is_equal(space, isl_dim_in, 4041 aff_space, isl_dim_set); 4042 if (match < 0) 4043 goto error; 4044 if (!match) 4045 isl_die(isl_aff_get_ctx(aff), isl_error_invalid, 4046 "domains don't match", goto error); 4047 isl_space_free(aff_space); 4048 return isl_stat_ok; 4049error: 4050 isl_space_free(aff_space); 4051 return isl_stat_error; 4052} 4053 4054/* Return the shared (universe) domain of the elements of "ma". 4055 * 4056 * Since an isl_multi_aff (and an isl_aff) is always total, 4057 * the domain is always the universe set in its domain space. 4058 * This is a helper function for use in the generic isl_multi_*_bind. 4059 */ 4060static __isl_give isl_basic_set *isl_multi_aff_domain( 4061 __isl_take isl_multi_aff *ma) 4062{ 4063 isl_space *space; 4064 4065 space = isl_multi_aff_get_space(ma); 4066 isl_multi_aff_free(ma); 4067 4068 return isl_basic_set_universe(isl_space_domain(space)); 4069} 4070 4071#undef BASE 4072#define BASE aff 4073 4074#include <isl_multi_no_explicit_domain.c> 4075#include <isl_multi_templ.c> 4076#include <isl_multi_un_op_templ.c> 4077#include <isl_multi_bin_val_templ.c> 4078#include <isl_multi_add_constant_templ.c> 4079#include <isl_multi_align_set.c> 4080#include <isl_multi_arith_templ.c> 4081#include <isl_multi_bind_domain_templ.c> 4082#include <isl_multi_cmp.c> 4083#include <isl_multi_dim_id_templ.c> 4084#include <isl_multi_dims.c> 4085#include <isl_multi_domain_reverse_templ.c> 4086#include <isl_multi_floor.c> 4087#include <isl_multi_from_base_templ.c> 4088#include <isl_multi_identity_templ.c> 4089#include <isl_multi_insert_domain_templ.c> 4090#include <isl_multi_locals_templ.c> 4091#include <isl_multi_move_dims_templ.c> 4092#include <isl_multi_nan_templ.c> 4093#include <isl_multi_product_templ.c> 4094#include <isl_multi_splice_templ.c> 4095#include <isl_multi_tuple_id_templ.c> 4096#include <isl_multi_unbind_params_templ.c> 4097#include <isl_multi_zero_templ.c> 4098 4099#undef DOMBASE 4100#define DOMBASE set 4101#include <isl_multi_check_domain_templ.c> 4102#include <isl_multi_apply_set_no_explicit_domain_templ.c> 4103#include <isl_multi_gist.c> 4104 4105#undef DOMBASE 4106#define DOMBASE basic_set 4107#include <isl_multi_bind_templ.c> 4108 4109/* Construct an isl_multi_aff living in "space" that corresponds 4110 * to the affine transformation matrix "mat". 4111 */ 4112__isl_give isl_multi_aff *isl_multi_aff_from_aff_mat( 4113 __isl_take isl_space *space, __isl_take isl_mat *mat) 4114{ 4115 isl_ctx *ctx; 4116 isl_local_space *ls = NULL; 4117 isl_multi_aff *ma = NULL; 4118 isl_size n_row, n_col, n_out, total; 4119 int i; 4120 4121 if (!space || !mat) 4122 goto error; 4123 4124 ctx = isl_mat_get_ctx(mat); 4125 4126 n_row = isl_mat_rows(mat); 4127 n_col = isl_mat_cols(mat); 4128 n_out = isl_space_dim(space, isl_dim_out); 4129 total = isl_space_dim(space, isl_dim_all); 4130 if (n_row < 0 || n_col < 0 || n_out < 0 || total < 0) 4131 goto error; 4132 if (n_row < 1) 4133 isl_die(ctx, isl_error_invalid, 4134 "insufficient number of rows", goto error); 4135 if (n_col < 1) 4136 isl_die(ctx, isl_error_invalid, 4137 "insufficient number of columns", goto error); 4138 if (1 + n_out != n_row || 2 + total != n_row + n_col) 4139 isl_die(ctx, isl_error_invalid, 4140 "dimension mismatch", goto error); 4141 4142 ma = isl_multi_aff_zero(isl_space_copy(space)); 4143 space = isl_space_domain(space); 4144 ls = isl_local_space_from_space(isl_space_copy(space)); 4145 4146 for (i = 0; i < n_row - 1; ++i) { 4147 isl_vec *v; 4148 isl_aff *aff; 4149 4150 v = isl_vec_alloc(ctx, 1 + n_col); 4151 if (!v) 4152 goto error; 4153 isl_int_set(v->el[0], mat->row[0][0]); 4154 isl_seq_cpy(v->el + 1, mat->row[1 + i], n_col); 4155 v = isl_vec_normalize(v); 4156 aff = isl_aff_alloc_vec_validated(isl_local_space_copy(ls), v); 4157 ma = isl_multi_aff_set_aff(ma, i, aff); 4158 } 4159 4160 isl_space_free(space); 4161 isl_local_space_free(ls); 4162 isl_mat_free(mat); 4163 return ma; 4164error: 4165 isl_space_free(space); 4166 isl_local_space_free(ls); 4167 isl_mat_free(mat); 4168 isl_multi_aff_free(ma); 4169 return NULL; 4170} 4171 4172/* Return the constant terms of the affine expressions of "ma". 4173 */ 4174__isl_give isl_multi_val *isl_multi_aff_get_constant_multi_val( 4175 __isl_keep isl_multi_aff *ma) 4176{ 4177 int i; 4178 isl_size n; 4179 isl_space *space; 4180 isl_multi_val *mv; 4181 4182 n = isl_multi_aff_size(ma); 4183 if (n < 0) 4184 return NULL; 4185 space = isl_space_range(isl_multi_aff_get_space(ma)); 4186 space = isl_space_drop_all_params(space); 4187 mv = isl_multi_val_zero(space); 4188 4189 for (i = 0; i < n; ++i) { 4190 isl_aff *aff; 4191 isl_val *val; 4192 4193 aff = isl_multi_aff_get_at(ma, i); 4194 val = isl_aff_get_constant_val(aff); 4195 isl_aff_free(aff); 4196 mv = isl_multi_val_set_at(mv, i, val); 4197 } 4198 4199 return mv; 4200} 4201 4202/* Remove any internal structure of the domain of "ma". 4203 * If there is any such internal structure in the input, 4204 * then the name of the corresponding space is also removed. 4205 */ 4206__isl_give isl_multi_aff *isl_multi_aff_flatten_domain( 4207 __isl_take isl_multi_aff *ma) 4208{ 4209 isl_space *space; 4210 4211 if (!ma) 4212 return NULL; 4213 4214 if (!ma->space->nested[0]) 4215 return ma; 4216 4217 space = isl_multi_aff_get_space(ma); 4218 space = isl_space_flatten_domain(space); 4219 ma = isl_multi_aff_reset_space(ma, space); 4220 4221 return ma; 4222} 4223 4224/* Given a map space, return an isl_multi_aff that maps a wrapped copy 4225 * of the space to its domain. 4226 */ 4227__isl_give isl_multi_aff *isl_multi_aff_domain_map(__isl_take isl_space *space) 4228{ 4229 int i; 4230 isl_size n_in; 4231 isl_local_space *ls; 4232 isl_multi_aff *ma; 4233 4234 if (!space) 4235 return NULL; 4236 if (!isl_space_is_map(space)) 4237 isl_die(isl_space_get_ctx(space), isl_error_invalid, 4238 "not a map space", goto error); 4239 4240 n_in = isl_space_dim(space, isl_dim_in); 4241 if (n_in < 0) 4242 goto error; 4243 space = isl_space_domain_map(space); 4244 4245 ma = isl_multi_aff_alloc(isl_space_copy(space)); 4246 if (n_in == 0) { 4247 isl_space_free(space); 4248 return ma; 4249 } 4250 4251 space = isl_space_domain(space); 4252 ls = isl_local_space_from_space(space); 4253 for (i = 0; i < n_in; ++i) { 4254 isl_aff *aff; 4255 4256 aff = isl_aff_var_on_domain(isl_local_space_copy(ls), 4257 isl_dim_set, i); 4258 ma = isl_multi_aff_set_aff(ma, i, aff); 4259 } 4260 isl_local_space_free(ls); 4261 return ma; 4262error: 4263 isl_space_free(space); 4264 return NULL; 4265} 4266 4267/* This function performs the same operation as isl_multi_aff_domain_map, 4268 * but is considered as a function on an isl_space when exported. 4269 */ 4270__isl_give isl_multi_aff *isl_space_domain_map_multi_aff( 4271 __isl_take isl_space *space) 4272{ 4273 return isl_multi_aff_domain_map(space); 4274} 4275 4276/* Given a map space, return an isl_multi_aff that maps a wrapped copy 4277 * of the space to its range. 4278 */ 4279__isl_give isl_multi_aff *isl_multi_aff_range_map(__isl_take isl_space *space) 4280{ 4281 int i; 4282 isl_size n_in, n_out; 4283 isl_local_space *ls; 4284 isl_multi_aff *ma; 4285 4286 if (!space) 4287 return NULL; 4288 if (!isl_space_is_map(space)) 4289 isl_die(isl_space_get_ctx(space), isl_error_invalid, 4290 "not a map space", goto error); 4291 4292 n_in = isl_space_dim(space, isl_dim_in); 4293 n_out = isl_space_dim(space, isl_dim_out); 4294 if (n_in < 0 || n_out < 0) 4295 goto error; 4296 space = isl_space_range_map(space); 4297 4298 ma = isl_multi_aff_alloc(isl_space_copy(space)); 4299 if (n_out == 0) { 4300 isl_space_free(space); 4301 return ma; 4302 } 4303 4304 space = isl_space_domain(space); 4305 ls = isl_local_space_from_space(space); 4306 for (i = 0; i < n_out; ++i) { 4307 isl_aff *aff; 4308 4309 aff = isl_aff_var_on_domain(isl_local_space_copy(ls), 4310 isl_dim_set, n_in + i); 4311 ma = isl_multi_aff_set_aff(ma, i, aff); 4312 } 4313 isl_local_space_free(ls); 4314 return ma; 4315error: 4316 isl_space_free(space); 4317 return NULL; 4318} 4319 4320/* This function performs the same operation as isl_multi_aff_range_map, 4321 * but is considered as a function on an isl_space when exported. 4322 */ 4323__isl_give isl_multi_aff *isl_space_range_map_multi_aff( 4324 __isl_take isl_space *space) 4325{ 4326 return isl_multi_aff_range_map(space); 4327} 4328 4329/* Given a map space, return an isl_pw_multi_aff that maps a wrapped copy 4330 * of the space to its domain. 4331 */ 4332__isl_give isl_pw_multi_aff *isl_pw_multi_aff_domain_map( 4333 __isl_take isl_space *space) 4334{ 4335 return isl_pw_multi_aff_from_multi_aff(isl_multi_aff_domain_map(space)); 4336} 4337 4338/* This function performs the same operation as isl_pw_multi_aff_domain_map, 4339 * but is considered as a function on an isl_space when exported. 4340 */ 4341__isl_give isl_pw_multi_aff *isl_space_domain_map_pw_multi_aff( 4342 __isl_take isl_space *space) 4343{ 4344 return isl_pw_multi_aff_domain_map(space); 4345} 4346 4347/* Given a map space, return an isl_pw_multi_aff that maps a wrapped copy 4348 * of the space to its range. 4349 */ 4350__isl_give isl_pw_multi_aff *isl_pw_multi_aff_range_map( 4351 __isl_take isl_space *space) 4352{ 4353 return isl_pw_multi_aff_from_multi_aff(isl_multi_aff_range_map(space)); 4354} 4355 4356/* This function performs the same operation as isl_pw_multi_aff_range_map, 4357 * but is considered as a function on an isl_space when exported. 4358 */ 4359__isl_give isl_pw_multi_aff *isl_space_range_map_pw_multi_aff( 4360 __isl_take isl_space *space) 4361{ 4362 return isl_pw_multi_aff_range_map(space); 4363} 4364 4365/* Given the space of a set and a range of set dimensions, 4366 * construct an isl_multi_aff that projects out those dimensions. 4367 */ 4368__isl_give isl_multi_aff *isl_multi_aff_project_out_map( 4369 __isl_take isl_space *space, enum isl_dim_type type, 4370 unsigned first, unsigned n) 4371{ 4372 int i; 4373 isl_size dim; 4374 isl_local_space *ls; 4375 isl_multi_aff *ma; 4376 4377 if (!space) 4378 return NULL; 4379 if (!isl_space_is_set(space)) 4380 isl_die(isl_space_get_ctx(space), isl_error_unsupported, 4381 "expecting set space", goto error); 4382 if (type != isl_dim_set) 4383 isl_die(isl_space_get_ctx(space), isl_error_invalid, 4384 "only set dimensions can be projected out", goto error); 4385 if (isl_space_check_range(space, type, first, n) < 0) 4386 goto error; 4387 4388 dim = isl_space_dim(space, isl_dim_set); 4389 if (dim < 0) 4390 goto error; 4391 4392 space = isl_space_from_domain(space); 4393 space = isl_space_add_dims(space, isl_dim_out, dim - n); 4394 4395 if (dim == n) 4396 return isl_multi_aff_alloc(space); 4397 4398 ma = isl_multi_aff_alloc(isl_space_copy(space)); 4399 space = isl_space_domain(space); 4400 ls = isl_local_space_from_space(space); 4401 4402 for (i = 0; i < first; ++i) { 4403 isl_aff *aff; 4404 4405 aff = isl_aff_var_on_domain(isl_local_space_copy(ls), 4406 isl_dim_set, i); 4407 ma = isl_multi_aff_set_aff(ma, i, aff); 4408 } 4409 4410 for (i = 0; i < dim - (first + n); ++i) { 4411 isl_aff *aff; 4412 4413 aff = isl_aff_var_on_domain(isl_local_space_copy(ls), 4414 isl_dim_set, first + n + i); 4415 ma = isl_multi_aff_set_aff(ma, first + i, aff); 4416 } 4417 4418 isl_local_space_free(ls); 4419 return ma; 4420error: 4421 isl_space_free(space); 4422 return NULL; 4423} 4424 4425/* Given the space of a set and a range of set dimensions, 4426 * construct an isl_pw_multi_aff that projects out those dimensions. 4427 */ 4428__isl_give isl_pw_multi_aff *isl_pw_multi_aff_project_out_map( 4429 __isl_take isl_space *space, enum isl_dim_type type, 4430 unsigned first, unsigned n) 4431{ 4432 isl_multi_aff *ma; 4433 4434 ma = isl_multi_aff_project_out_map(space, type, first, n); 4435 return isl_pw_multi_aff_from_multi_aff(ma); 4436} 4437 4438/* This function performs the same operation as isl_pw_multi_aff_from_multi_aff, 4439 * but is considered as a function on an isl_multi_aff when exported. 4440 */ 4441__isl_give isl_pw_multi_aff *isl_multi_aff_to_pw_multi_aff( 4442 __isl_take isl_multi_aff *ma) 4443{ 4444 return isl_pw_multi_aff_from_multi_aff(ma); 4445} 4446 4447/* Create a piecewise multi-affine expression in the given space that maps each 4448 * input dimension to the corresponding output dimension. 4449 */ 4450__isl_give isl_pw_multi_aff *isl_pw_multi_aff_identity( 4451 __isl_take isl_space *space) 4452{ 4453 return isl_pw_multi_aff_from_multi_aff(isl_multi_aff_identity(space)); 4454} 4455 4456/* Create a piecewise multi expression that maps elements in the given space 4457 * to themselves. 4458 */ 4459__isl_give isl_pw_multi_aff *isl_pw_multi_aff_identity_on_domain_space( 4460 __isl_take isl_space *space) 4461{ 4462 isl_multi_aff *ma; 4463 4464 ma = isl_multi_aff_identity_on_domain_space(space); 4465 return isl_pw_multi_aff_from_multi_aff(ma); 4466} 4467 4468/* This function performs the same operation as 4469 * isl_pw_multi_aff_identity_on_domain_space, 4470 * but is considered as a function on an isl_space when exported. 4471 */ 4472__isl_give isl_pw_multi_aff *isl_space_identity_pw_multi_aff_on_domain( 4473 __isl_take isl_space *space) 4474{ 4475 return isl_pw_multi_aff_identity_on_domain_space(space); 4476} 4477 4478/* Exploit the equalities in "eq" to simplify the affine expressions. 4479 */ 4480static __isl_give isl_multi_aff *isl_multi_aff_substitute_equalities( 4481 __isl_take isl_multi_aff *maff, __isl_take isl_basic_set *eq) 4482{ 4483 isl_size n; 4484 int i; 4485 4486 n = isl_multi_aff_size(maff); 4487 if (n < 0 || !eq) 4488 goto error; 4489 4490 for (i = 0; i < n; ++i) { 4491 isl_aff *aff; 4492 4493 aff = isl_multi_aff_take_at(maff, i); 4494 aff = isl_aff_substitute_equalities(aff, 4495 isl_basic_set_copy(eq)); 4496 maff = isl_multi_aff_restore_at(maff, i, aff); 4497 } 4498 4499 isl_basic_set_free(eq); 4500 return maff; 4501error: 4502 isl_basic_set_free(eq); 4503 isl_multi_aff_free(maff); 4504 return NULL; 4505} 4506 4507__isl_give isl_multi_aff *isl_multi_aff_scale(__isl_take isl_multi_aff *maff, 4508 isl_int f) 4509{ 4510 isl_size n; 4511 int i; 4512 4513 n = isl_multi_aff_size(maff); 4514 if (n < 0) 4515 return isl_multi_aff_free(maff); 4516 4517 for (i = 0; i < n; ++i) { 4518 isl_aff *aff; 4519 4520 aff = isl_multi_aff_take_at(maff, i); 4521 aff = isl_aff_scale(aff, f); 4522 maff = isl_multi_aff_restore_at(maff, i, aff); 4523 } 4524 4525 return maff; 4526} 4527 4528__isl_give isl_multi_aff *isl_multi_aff_add_on_domain(__isl_keep isl_set *dom, 4529 __isl_take isl_multi_aff *maff1, __isl_take isl_multi_aff *maff2) 4530{ 4531 maff1 = isl_multi_aff_add(maff1, maff2); 4532 maff1 = isl_multi_aff_gist(maff1, isl_set_copy(dom)); 4533 return maff1; 4534} 4535 4536isl_bool isl_multi_aff_is_empty(__isl_keep isl_multi_aff *maff) 4537{ 4538 if (!maff) 4539 return isl_bool_error; 4540 4541 return isl_bool_false; 4542} 4543 4544/* Return the set of domain elements where "ma1" is lexicographically 4545 * smaller than or equal to "ma2". 4546 */ 4547__isl_give isl_set *isl_multi_aff_lex_le_set(__isl_take isl_multi_aff *ma1, 4548 __isl_take isl_multi_aff *ma2) 4549{ 4550 return isl_multi_aff_lex_ge_set(ma2, ma1); 4551} 4552 4553/* Return the set of domain elements where "ma1" is lexicographically 4554 * smaller than "ma2". 4555 */ 4556__isl_give isl_set *isl_multi_aff_lex_lt_set(__isl_take isl_multi_aff *ma1, 4557 __isl_take isl_multi_aff *ma2) 4558{ 4559 return isl_multi_aff_lex_gt_set(ma2, ma1); 4560} 4561 4562/* Return the set of domain elements where "ma1" is lexicographically 4563 * greater than to "ma2". If "equal" is set, then include the domain 4564 * elements where they are equal. 4565 * Do this for the case where there are no entries. 4566 * In this case, "ma1" cannot be greater than "ma2", 4567 * but it is (greater than or) equal to "ma2". 4568 */ 4569static __isl_give isl_set *isl_multi_aff_lex_gte_set_0d( 4570 __isl_take isl_multi_aff *ma1, __isl_take isl_multi_aff *ma2, int equal) 4571{ 4572 isl_space *space; 4573 4574 space = isl_multi_aff_get_domain_space(ma1); 4575 4576 isl_multi_aff_free(ma1); 4577 isl_multi_aff_free(ma2); 4578 4579 if (equal) 4580 return isl_set_universe(space); 4581 else 4582 return isl_set_empty(space); 4583} 4584 4585/* Return the set where entry "i" of "ma1" and "ma2" 4586 * satisfy the relation prescribed by "cmp". 4587 */ 4588static __isl_give isl_set *isl_multi_aff_order_at(__isl_keep isl_multi_aff *ma1, 4589 __isl_keep isl_multi_aff *ma2, int i, 4590 __isl_give isl_set *(*cmp)(__isl_take isl_aff *aff1, 4591 __isl_take isl_aff *aff2)) 4592{ 4593 isl_aff *aff1, *aff2; 4594 4595 aff1 = isl_multi_aff_get_at(ma1, i); 4596 aff2 = isl_multi_aff_get_at(ma2, i); 4597 return cmp(aff1, aff2); 4598} 4599 4600/* Return the set of domain elements where "ma1" is lexicographically 4601 * greater than to "ma2". If "equal" is set, then include the domain 4602 * elements where they are equal. 4603 * 4604 * In particular, for all but the final entry, 4605 * include the set of elements where this entry is strictly greater in "ma1" 4606 * and all previous entries are equal. 4607 * The final entry is also allowed to be equal in the two functions 4608 * if "equal" is set. 4609 * 4610 * The case where there are no entries is handled separately. 4611 */ 4612static __isl_give isl_set *isl_multi_aff_lex_gte_set( 4613 __isl_take isl_multi_aff *ma1, __isl_take isl_multi_aff *ma2, int equal) 4614{ 4615 int i; 4616 isl_size n; 4617 isl_space *space; 4618 isl_set *res; 4619 isl_set *equal_set; 4620 isl_set *gte; 4621 4622 if (isl_multi_aff_check_equal_space(ma1, ma2) < 0) 4623 goto error; 4624 n = isl_multi_aff_size(ma1); 4625 if (n < 0) 4626 goto error; 4627 if (n == 0) 4628 return isl_multi_aff_lex_gte_set_0d(ma1, ma2, equal); 4629 4630 space = isl_multi_aff_get_domain_space(ma1); 4631 res = isl_set_empty(isl_space_copy(space)); 4632 equal_set = isl_set_universe(space); 4633 4634 for (i = 0; i + 1 < n; ++i) { 4635 isl_bool empty; 4636 isl_set *gt, *eq; 4637 4638 gt = isl_multi_aff_order_at(ma1, ma2, i, &isl_aff_gt_set); 4639 gt = isl_set_intersect(gt, isl_set_copy(equal_set)); 4640 res = isl_set_union(res, gt); 4641 eq = isl_multi_aff_order_at(ma1, ma2, i, &isl_aff_eq_set); 4642 equal_set = isl_set_intersect(equal_set, eq); 4643 4644 empty = isl_set_is_empty(equal_set); 4645 if (empty >= 0 && empty) 4646 break; 4647 } 4648 4649 if (equal) 4650 gte = isl_multi_aff_order_at(ma1, ma2, n - 1, &isl_aff_ge_set); 4651 else 4652 gte = isl_multi_aff_order_at(ma1, ma2, n - 1, &isl_aff_gt_set); 4653 isl_multi_aff_free(ma1); 4654 isl_multi_aff_free(ma2); 4655 4656 gte = isl_set_intersect(gte, equal_set); 4657 return isl_set_union(res, gte); 4658error: 4659 isl_multi_aff_free(ma1); 4660 isl_multi_aff_free(ma2); 4661 return NULL; 4662} 4663 4664/* Return the set of domain elements where "ma1" is lexicographically 4665 * greater than or equal to "ma2". 4666 */ 4667__isl_give isl_set *isl_multi_aff_lex_ge_set(__isl_take isl_multi_aff *ma1, 4668 __isl_take isl_multi_aff *ma2) 4669{ 4670 return isl_multi_aff_lex_gte_set(ma1, ma2, 1); 4671} 4672 4673/* Return the set of domain elements where "ma1" is lexicographically 4674 * greater than "ma2". 4675 */ 4676__isl_give isl_set *isl_multi_aff_lex_gt_set(__isl_take isl_multi_aff *ma1, 4677 __isl_take isl_multi_aff *ma2) 4678{ 4679 return isl_multi_aff_lex_gte_set(ma1, ma2, 0); 4680} 4681 4682#define isl_multi_aff_zero_in_space isl_multi_aff_zero 4683 4684#undef PW 4685#define PW isl_pw_multi_aff 4686#undef BASE 4687#define BASE multi_aff 4688#undef EL_IS_ZERO 4689#define EL_IS_ZERO is_empty 4690#undef ZERO 4691#define ZERO empty 4692#undef IS_ZERO 4693#define IS_ZERO is_empty 4694#undef FIELD 4695#define FIELD maff 4696#undef DEFAULT_IS_ZERO 4697#define DEFAULT_IS_ZERO 0 4698 4699#include <isl_pw_templ.c> 4700#include <isl_pw_un_op_templ.c> 4701#include <isl_pw_add_constant_multi_val_templ.c> 4702#include <isl_pw_add_constant_val_templ.c> 4703#include <isl_pw_add_disjoint_templ.c> 4704#include <isl_pw_bind_domain_templ.c> 4705#include <isl_pw_domain_reverse_templ.c> 4706#include <isl_pw_fix_templ.c> 4707#include <isl_pw_from_range_templ.c> 4708#include <isl_pw_insert_dims_templ.c> 4709#include <isl_pw_insert_domain_templ.c> 4710#include <isl_pw_locals_templ.c> 4711#include <isl_pw_move_dims_templ.c> 4712#include <isl_pw_neg_templ.c> 4713#include <isl_pw_pullback_templ.c> 4714#include <isl_pw_range_tuple_id_templ.c> 4715#include <isl_pw_union_opt.c> 4716 4717#undef BASE 4718#define BASE pw_multi_aff 4719 4720#include <isl_union_multi.c> 4721#include "isl_union_locals_templ.c" 4722#include <isl_union_neg.c> 4723#include <isl_union_sub_templ.c> 4724 4725#undef BASE 4726#define BASE multi_aff 4727 4728#include <isl_union_pw_templ.c> 4729 4730/* Generic function for extracting a factor from a product "pma". 4731 * "check_space" checks that the space is that of the right kind of product. 4732 * "space_factor" extracts the factor from the space. 4733 * "multi_aff_factor" extracts the factor from the constituent functions. 4734 */ 4735static __isl_give isl_pw_multi_aff *pw_multi_aff_factor( 4736 __isl_take isl_pw_multi_aff *pma, 4737 isl_stat (*check_space)(__isl_keep isl_pw_multi_aff *pma), 4738 __isl_give isl_space *(*space_factor)(__isl_take isl_space *space), 4739 __isl_give isl_multi_aff *(*multi_aff_factor)( 4740 __isl_take isl_multi_aff *ma)) 4741{ 4742 int i; 4743 isl_space *space; 4744 4745 if (check_space(pma) < 0) 4746 return isl_pw_multi_aff_free(pma); 4747 4748 space = isl_pw_multi_aff_take_space(pma); 4749 space = space_factor(space); 4750 4751 for (i = 0; pma && i < pma->n; ++i) { 4752 isl_multi_aff *ma; 4753 4754 ma = isl_pw_multi_aff_take_base_at(pma, i); 4755 ma = multi_aff_factor(ma); 4756 pma = isl_pw_multi_aff_restore_base_at(pma, i, ma); 4757 } 4758 4759 pma = isl_pw_multi_aff_restore_space(pma, space); 4760 4761 return pma; 4762} 4763 4764/* Is the range of "pma" a wrapped relation? 4765 */ 4766static isl_bool isl_pw_multi_aff_range_is_wrapping( 4767 __isl_keep isl_pw_multi_aff *pma) 4768{ 4769 return isl_space_range_is_wrapping(isl_pw_multi_aff_peek_space(pma)); 4770} 4771 4772/* Check that the range of "pma" is a product. 4773 */ 4774static isl_stat pw_multi_aff_check_range_product( 4775 __isl_keep isl_pw_multi_aff *pma) 4776{ 4777 isl_bool wraps; 4778 4779 wraps = isl_pw_multi_aff_range_is_wrapping(pma); 4780 if (wraps < 0) 4781 return isl_stat_error; 4782 if (!wraps) 4783 isl_die(isl_pw_multi_aff_get_ctx(pma), isl_error_invalid, 4784 "range is not a product", return isl_stat_error); 4785 return isl_stat_ok; 4786} 4787 4788/* Given a function A -> [B -> C], extract the function A -> B. 4789 */ 4790__isl_give isl_pw_multi_aff *isl_pw_multi_aff_range_factor_domain( 4791 __isl_take isl_pw_multi_aff *pma) 4792{ 4793 return pw_multi_aff_factor(pma, &pw_multi_aff_check_range_product, 4794 &isl_space_range_factor_domain, 4795 &isl_multi_aff_range_factor_domain); 4796} 4797 4798/* Given a function A -> [B -> C], extract the function A -> C. 4799 */ 4800__isl_give isl_pw_multi_aff *isl_pw_multi_aff_range_factor_range( 4801 __isl_take isl_pw_multi_aff *pma) 4802{ 4803 return pw_multi_aff_factor(pma, &pw_multi_aff_check_range_product, 4804 &isl_space_range_factor_range, 4805 &isl_multi_aff_range_factor_range); 4806} 4807 4808/* Given two piecewise multi affine expressions, return a piecewise 4809 * multi-affine expression defined on the union of the definition domains 4810 * of the inputs that is equal to the lexicographic maximum of the two 4811 * inputs on each cell. If only one of the two inputs is defined on 4812 * a given cell, then it is considered to be the maximum. 4813 */ 4814__isl_give isl_pw_multi_aff *isl_pw_multi_aff_union_lexmax( 4815 __isl_take isl_pw_multi_aff *pma1, 4816 __isl_take isl_pw_multi_aff *pma2) 4817{ 4818 isl_pw_multi_aff_align_params_bin(&pma1, &pma2); 4819 return isl_pw_multi_aff_union_opt_cmp(pma1, pma2, 4820 &isl_multi_aff_lex_ge_set); 4821} 4822 4823/* Given two piecewise multi affine expressions, return a piecewise 4824 * multi-affine expression defined on the union of the definition domains 4825 * of the inputs that is equal to the lexicographic minimum of the two 4826 * inputs on each cell. If only one of the two inputs is defined on 4827 * a given cell, then it is considered to be the minimum. 4828 */ 4829__isl_give isl_pw_multi_aff *isl_pw_multi_aff_union_lexmin( 4830 __isl_take isl_pw_multi_aff *pma1, 4831 __isl_take isl_pw_multi_aff *pma2) 4832{ 4833 isl_pw_multi_aff_align_params_bin(&pma1, &pma2); 4834 return isl_pw_multi_aff_union_opt_cmp(pma1, pma2, 4835 &isl_multi_aff_lex_le_set); 4836} 4837 4838__isl_give isl_pw_multi_aff *isl_pw_multi_aff_add( 4839 __isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2) 4840{ 4841 isl_pw_multi_aff_align_params_bin(&pma1, &pma2); 4842 return isl_pw_multi_aff_on_shared_domain(pma1, pma2, 4843 &isl_multi_aff_add); 4844} 4845 4846/* Subtract "pma2" from "pma1" and return the result. 4847 */ 4848__isl_give isl_pw_multi_aff *isl_pw_multi_aff_sub( 4849 __isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2) 4850{ 4851 isl_pw_multi_aff_align_params_bin(&pma1, &pma2); 4852 return isl_pw_multi_aff_on_shared_domain(pma1, pma2, 4853 &isl_multi_aff_sub); 4854} 4855 4856/* Given two piecewise multi-affine expressions A -> B and C -> D, 4857 * construct a piecewise multi-affine expression [A -> C] -> [B -> D]. 4858 */ 4859__isl_give isl_pw_multi_aff *isl_pw_multi_aff_product( 4860 __isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2) 4861{ 4862 int i, j, n; 4863 isl_space *space; 4864 isl_pw_multi_aff *res; 4865 4866 if (isl_pw_multi_aff_align_params_bin(&pma1, &pma2) < 0) 4867 goto error; 4868 4869 n = pma1->n * pma2->n; 4870 space = isl_space_product(isl_space_copy(pma1->dim), 4871 isl_space_copy(pma2->dim)); 4872 res = isl_pw_multi_aff_alloc_size(space, n); 4873 4874 for (i = 0; i < pma1->n; ++i) { 4875 for (j = 0; j < pma2->n; ++j) { 4876 isl_set *domain; 4877 isl_multi_aff *ma; 4878 4879 domain = isl_set_product(isl_set_copy(pma1->p[i].set), 4880 isl_set_copy(pma2->p[j].set)); 4881 ma = isl_multi_aff_product( 4882 isl_multi_aff_copy(pma1->p[i].maff), 4883 isl_multi_aff_copy(pma2->p[j].maff)); 4884 res = isl_pw_multi_aff_add_piece(res, domain, ma); 4885 } 4886 } 4887 4888 isl_pw_multi_aff_free(pma1); 4889 isl_pw_multi_aff_free(pma2); 4890 return res; 4891error: 4892 isl_pw_multi_aff_free(pma1); 4893 isl_pw_multi_aff_free(pma2); 4894 return NULL; 4895} 4896 4897/* Subtract the initial "n" elements in "ma" with coefficients in "c" and 4898 * denominator "denom". 4899 * "denom" is allowed to be negative, in which case the actual denominator 4900 * is -denom and the expressions are added instead. 4901 */ 4902static __isl_give isl_aff *subtract_initial(__isl_take isl_aff *aff, 4903 __isl_keep isl_multi_aff *ma, int n, isl_int *c, isl_int denom) 4904{ 4905 int i, first; 4906 int sign; 4907 isl_int d; 4908 4909 first = isl_seq_first_non_zero(c, n); 4910 if (first == -1) 4911 return aff; 4912 4913 sign = isl_int_sgn(denom); 4914 isl_int_init(d); 4915 isl_int_abs(d, denom); 4916 for (i = first; i < n; ++i) { 4917 isl_aff *aff_i; 4918 4919 if (isl_int_is_zero(c[i])) 4920 continue; 4921 aff_i = isl_multi_aff_get_aff(ma, i); 4922 aff_i = isl_aff_scale(aff_i, c[i]); 4923 aff_i = isl_aff_scale_down(aff_i, d); 4924 if (sign >= 0) 4925 aff = isl_aff_sub(aff, aff_i); 4926 else 4927 aff = isl_aff_add(aff, aff_i); 4928 } 4929 isl_int_clear(d); 4930 4931 return aff; 4932} 4933 4934/* Extract an affine expression that expresses the output dimension "pos" 4935 * of "bmap" in terms of the parameters and input dimensions from 4936 * equality "eq". 4937 * Note that this expression may involve integer divisions defined 4938 * in terms of parameters and input dimensions. 4939 * The equality may also involve references to earlier (but not later) 4940 * output dimensions. These are replaced by the corresponding elements 4941 * in "ma". 4942 * 4943 * If the equality is of the form 4944 * 4945 * f(i) + h(j) + a x + g(i) = 0, 4946 * 4947 * with f(i) a linear combinations of the parameters and input dimensions, 4948 * g(i) a linear combination of integer divisions defined in terms of the same 4949 * and h(j) a linear combinations of earlier output dimensions, 4950 * then the affine expression is 4951 * 4952 * (-f(i) - g(i))/a - h(j)/a 4953 * 4954 * If the equality is of the form 4955 * 4956 * f(i) + h(j) - a x + g(i) = 0, 4957 * 4958 * then the affine expression is 4959 * 4960 * (f(i) + g(i))/a - h(j)/(-a) 4961 * 4962 * 4963 * If "div" refers to an integer division (i.e., it is smaller than 4964 * the number of integer divisions), then the equality constraint 4965 * does involve an integer division (the one at position "div") that 4966 * is defined in terms of output dimensions. However, this integer 4967 * division can be eliminated by exploiting a pair of constraints 4968 * x >= l and x <= l + n, with n smaller than the coefficient of "div" 4969 * in the equality constraint. "ineq" refers to inequality x >= l, i.e., 4970 * -l + x >= 0. 4971 * In particular, let 4972 * 4973 * x = e(i) + m floor(...) 4974 * 4975 * with e(i) the expression derived above and floor(...) the integer 4976 * division involving output dimensions. 4977 * From 4978 * 4979 * l <= x <= l + n, 4980 * 4981 * we have 4982 * 4983 * 0 <= x - l <= n 4984 * 4985 * This means 4986 * 4987 * e(i) + m floor(...) - l = (e(i) + m floor(...) - l) mod m 4988 * = (e(i) - l) mod m 4989 * 4990 * Therefore, 4991 * 4992 * x - l = (e(i) - l) mod m 4993 * 4994 * or 4995 * 4996 * x = ((e(i) - l) mod m) + l 4997 * 4998 * The variable "shift" below contains the expression -l, which may 4999 * also involve a linear combination of earlier output dimensions. 5000 */ 5001static __isl_give isl_aff *extract_aff_from_equality( 5002 __isl_keep isl_basic_map *bmap, int pos, int eq, int div, int ineq, 5003 __isl_keep isl_multi_aff *ma) 5004{ 5005 unsigned o_out; 5006 isl_size n_div, n_out; 5007 isl_ctx *ctx; 5008 isl_local_space *ls; 5009 isl_aff *aff, *shift; 5010 isl_val *mod; 5011 5012 ctx = isl_basic_map_get_ctx(bmap); 5013 ls = isl_basic_map_get_local_space(bmap); 5014 ls = isl_local_space_domain(ls); 5015 aff = isl_aff_alloc(isl_local_space_copy(ls)); 5016 if (!aff) 5017 goto error; 5018 o_out = isl_basic_map_offset(bmap, isl_dim_out); 5019 n_out = isl_basic_map_dim(bmap, isl_dim_out); 5020 n_div = isl_basic_map_dim(bmap, isl_dim_div); 5021 if (n_out < 0 || n_div < 0) 5022 goto error; 5023 if (isl_int_is_neg(bmap->eq[eq][o_out + pos])) { 5024 isl_seq_cpy(aff->v->el + 1, bmap->eq[eq], o_out); 5025 isl_seq_cpy(aff->v->el + 1 + o_out, 5026 bmap->eq[eq] + o_out + n_out, n_div); 5027 } else { 5028 isl_seq_neg(aff->v->el + 1, bmap->eq[eq], o_out); 5029 isl_seq_neg(aff->v->el + 1 + o_out, 5030 bmap->eq[eq] + o_out + n_out, n_div); 5031 } 5032 if (div < n_div) 5033 isl_int_set_si(aff->v->el[1 + o_out + div], 0); 5034 isl_int_abs(aff->v->el[0], bmap->eq[eq][o_out + pos]); 5035 aff = subtract_initial(aff, ma, pos, bmap->eq[eq] + o_out, 5036 bmap->eq[eq][o_out + pos]); 5037 if (div < n_div) { 5038 shift = isl_aff_alloc(isl_local_space_copy(ls)); 5039 if (!shift) 5040 goto error; 5041 isl_seq_cpy(shift->v->el + 1, bmap->ineq[ineq], o_out); 5042 isl_seq_cpy(shift->v->el + 1 + o_out, 5043 bmap->ineq[ineq] + o_out + n_out, n_div); 5044 isl_int_set_si(shift->v->el[0], 1); 5045 shift = subtract_initial(shift, ma, pos, 5046 bmap->ineq[ineq] + o_out, ctx->negone); 5047 aff = isl_aff_add(aff, isl_aff_copy(shift)); 5048 mod = isl_val_int_from_isl_int(ctx, 5049 bmap->eq[eq][o_out + n_out + div]); 5050 mod = isl_val_abs(mod); 5051 aff = isl_aff_mod_val(aff, mod); 5052 aff = isl_aff_sub(aff, shift); 5053 } 5054 5055 isl_local_space_free(ls); 5056 return aff; 5057error: 5058 isl_local_space_free(ls); 5059 isl_aff_free(aff); 5060 return NULL; 5061} 5062 5063/* Given a basic map with output dimensions defined 5064 * in terms of the parameters input dimensions and earlier 5065 * output dimensions using an equality (and possibly a pair on inequalities), 5066 * extract an isl_aff that expresses output dimension "pos" in terms 5067 * of the parameters and input dimensions. 5068 * Note that this expression may involve integer divisions defined 5069 * in terms of parameters and input dimensions. 5070 * "ma" contains the expressions corresponding to earlier output dimensions. 5071 * 5072 * This function shares some similarities with 5073 * isl_basic_map_has_defining_equality and isl_constraint_get_bound. 5074 */ 5075static __isl_give isl_aff *extract_isl_aff_from_basic_map( 5076 __isl_keep isl_basic_map *bmap, int pos, __isl_keep isl_multi_aff *ma) 5077{ 5078 int eq, div, ineq; 5079 isl_aff *aff; 5080 5081 if (!bmap) 5082 return NULL; 5083 eq = isl_basic_map_output_defining_equality(bmap, pos, &div, &ineq); 5084 if (eq >= bmap->n_eq) 5085 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid, 5086 "unable to find suitable equality", return NULL); 5087 aff = extract_aff_from_equality(bmap, pos, eq, div, ineq, ma); 5088 5089 aff = isl_aff_remove_unused_divs(aff); 5090 return aff; 5091} 5092 5093/* Given a basic map where each output dimension is defined 5094 * in terms of the parameters and input dimensions using an equality, 5095 * extract an isl_multi_aff that expresses the output dimensions in terms 5096 * of the parameters and input dimensions. 5097 */ 5098static __isl_give isl_multi_aff *extract_isl_multi_aff_from_basic_map( 5099 __isl_take isl_basic_map *bmap) 5100{ 5101 int i; 5102 isl_size n_out; 5103 isl_multi_aff *ma; 5104 5105 if (!bmap) 5106 return NULL; 5107 5108 ma = isl_multi_aff_alloc(isl_basic_map_get_space(bmap)); 5109 n_out = isl_basic_map_dim(bmap, isl_dim_out); 5110 if (n_out < 0) 5111 ma = isl_multi_aff_free(ma); 5112 5113 for (i = 0; i < n_out; ++i) { 5114 isl_aff *aff; 5115 5116 aff = extract_isl_aff_from_basic_map(bmap, i, ma); 5117 ma = isl_multi_aff_set_aff(ma, i, aff); 5118 } 5119 5120 isl_basic_map_free(bmap); 5121 5122 return ma; 5123} 5124 5125/* Given a basic set where each set dimension is defined 5126 * in terms of the parameters using an equality, 5127 * extract an isl_multi_aff that expresses the set dimensions in terms 5128 * of the parameters. 5129 */ 5130__isl_give isl_multi_aff *isl_multi_aff_from_basic_set_equalities( 5131 __isl_take isl_basic_set *bset) 5132{ 5133 return extract_isl_multi_aff_from_basic_map(bset); 5134} 5135 5136/* Create an isl_pw_multi_aff that is equivalent to 5137 * isl_map_intersect_domain(isl_map_from_basic_map(bmap), domain). 5138 * The given basic map is such that each output dimension is defined 5139 * in terms of the parameters and input dimensions using an equality. 5140 * 5141 * Since some applications expect the result of isl_pw_multi_aff_from_map 5142 * to only contain integer affine expressions, we compute the floor 5143 * of the expression before returning. 5144 * 5145 * Remove all constraints involving local variables without 5146 * an explicit representation (resulting in the removal of those 5147 * local variables) prior to the actual extraction to ensure 5148 * that the local spaces in which the resulting affine expressions 5149 * are created do not contain any unknown local variables. 5150 * Removing such constraints is safe because constraints involving 5151 * unknown local variables are not used to determine whether 5152 * a basic map is obviously single-valued. 5153 */ 5154static __isl_give isl_pw_multi_aff *plain_pw_multi_aff_from_map( 5155 __isl_take isl_set *domain, __isl_take isl_basic_map *bmap) 5156{ 5157 isl_multi_aff *ma; 5158 5159 bmap = isl_basic_map_drop_constraints_involving_unknown_divs(bmap); 5160 ma = extract_isl_multi_aff_from_basic_map(bmap); 5161 ma = isl_multi_aff_floor(ma); 5162 return isl_pw_multi_aff_alloc(domain, ma); 5163} 5164 5165/* Try and create an isl_pw_multi_aff that is equivalent to the given isl_map. 5166 * This obviously only works if the input "map" is single-valued. 5167 * If so, we compute the lexicographic minimum of the image in the form 5168 * of an isl_pw_multi_aff. Since the image is unique, it is equal 5169 * to its lexicographic minimum. 5170 * If the input is not single-valued, we produce an error. 5171 */ 5172static __isl_give isl_pw_multi_aff *pw_multi_aff_from_map_base( 5173 __isl_take isl_map *map) 5174{ 5175 int i; 5176 int sv; 5177 isl_pw_multi_aff *pma; 5178 5179 sv = isl_map_is_single_valued(map); 5180 if (sv < 0) 5181 goto error; 5182 if (!sv) 5183 isl_die(isl_map_get_ctx(map), isl_error_invalid, 5184 "map is not single-valued", goto error); 5185 map = isl_map_make_disjoint(map); 5186 if (!map) 5187 return NULL; 5188 5189 pma = isl_pw_multi_aff_empty(isl_map_get_space(map)); 5190 5191 for (i = 0; i < map->n; ++i) { 5192 isl_pw_multi_aff *pma_i; 5193 isl_basic_map *bmap; 5194 bmap = isl_basic_map_copy(map->p[i]); 5195 pma_i = isl_basic_map_lexmin_pw_multi_aff(bmap); 5196 pma = isl_pw_multi_aff_add_disjoint(pma, pma_i); 5197 } 5198 5199 isl_map_free(map); 5200 return pma; 5201error: 5202 isl_map_free(map); 5203 return NULL; 5204} 5205 5206/* Construct an isl_aff from the given domain local space "ls" and 5207 * coefficients "v", where the local space may involve 5208 * local variables without a known expression, as long as these 5209 * do not have a non-zero coefficient in "v". 5210 * These need to be pruned away first since an isl_aff cannot 5211 * reference any local variables without a known expression. 5212 * For simplicity, remove all local variables that have a zero coefficient and 5213 * that are not used in other local variables with a non-zero coefficient. 5214 */ 5215static __isl_give isl_aff *isl_aff_alloc_vec_prune( 5216 __isl_take isl_local_space *ls, __isl_take isl_vec *v) 5217{ 5218 int i; 5219 isl_size n_div, v_div; 5220 5221 n_div = isl_local_space_dim(ls, isl_dim_div); 5222 v_div = isl_local_space_var_offset(ls, isl_dim_div); 5223 if (n_div < 0 || v_div < 0 || !v) 5224 goto error; 5225 for (i = n_div - 1; i >= 0; --i) { 5226 isl_bool involves; 5227 5228 if (!isl_int_is_zero(v->el[1 + 1 + v_div + i])) 5229 continue; 5230 involves = isl_local_space_involves_dims(ls, isl_dim_div, i, 1); 5231 if (involves < 0) 5232 goto error; 5233 if (involves) 5234 continue; 5235 ls = isl_local_space_drop_dims(ls, isl_dim_div, i, 1); 5236 v = isl_vec_drop_els(v, 1 + 1 + v_div + i, 1); 5237 if (!v) 5238 goto error; 5239 } 5240 5241 return isl_aff_alloc_vec(ls, v); 5242error: 5243 isl_local_space_free(ls); 5244 isl_vec_free(v); 5245 return NULL; 5246} 5247 5248/* Try and create an isl_pw_multi_aff that is equivalent to the given isl_map, 5249 * taking into account that the output dimension at position "d" 5250 * can be represented as 5251 * 5252 * x = floor((e(...) + c1) / m) 5253 * 5254 * given that constraint "i" is of the form 5255 * 5256 * e(...) + c1 - m x >= 0 5257 * 5258 * with e(...) an expression that does not involve any other output dimensions. 5259 * 5260 * 5261 * Let "map" be of the form 5262 * 5263 * A -> B 5264 * 5265 * We construct a mapping 5266 * 5267 * A -> [A -> x = floor(...)] 5268 * 5269 * apply that to the map, obtaining 5270 * 5271 * [A -> x = floor(...)] -> B 5272 * 5273 * and equate dimension "d" to x. 5274 * We then compute a isl_pw_multi_aff representation of the resulting map 5275 * and plug in the mapping above. 5276 * 5277 * The constraint "i" is guaranteed by the caller not to involve 5278 * any local variables without a known expression, but such local variables 5279 * may appear in other constraints. They therefore need to be removed 5280 * during the construction of the affine expression. 5281 */ 5282static __isl_give isl_pw_multi_aff *pw_multi_aff_from_map_div( 5283 __isl_take isl_map *map, __isl_take isl_basic_map *hull, int d, int i) 5284{ 5285 isl_space *space = NULL; 5286 isl_local_space *ls; 5287 isl_multi_aff *ma; 5288 isl_aff *aff; 5289 isl_vec *v; 5290 isl_map *insert; 5291 isl_size n_in; 5292 isl_pw_multi_aff *pma; 5293 isl_bool is_set; 5294 5295 is_set = isl_map_is_set(map); 5296 if (is_set < 0) 5297 goto error; 5298 5299 space = isl_space_domain(isl_map_get_space(map)); 5300 n_in = isl_space_dim(space, isl_dim_set); 5301 if (n_in < 0) 5302 goto error; 5303 5304 ls = isl_basic_map_get_local_space(hull); 5305 if (!is_set) 5306 ls = isl_local_space_wrap(ls); 5307 v = isl_basic_map_inequality_extract_output_upper_bound(hull, i, d); 5308 isl_basic_map_free(hull); 5309 5310 aff = isl_aff_alloc_vec_prune(ls, v); 5311 aff = isl_aff_floor(aff); 5312 if (is_set) { 5313 aff = isl_aff_project_domain_on_params(aff); 5314 isl_space_free(space); 5315 ma = isl_multi_aff_from_aff(aff); 5316 } else { 5317 aff = isl_aff_domain_factor_domain(aff); 5318 ma = isl_multi_aff_identity(isl_space_map_from_set(space)); 5319 ma = isl_multi_aff_range_product(ma, 5320 isl_multi_aff_from_aff(aff)); 5321 } 5322 5323 insert = isl_map_from_multi_aff_internal(isl_multi_aff_copy(ma)); 5324 map = isl_map_apply_domain(map, insert); 5325 map = isl_map_equate(map, isl_dim_in, n_in, isl_dim_out, d); 5326 pma = isl_pw_multi_aff_from_map(map); 5327 pma = isl_pw_multi_aff_pullback_multi_aff(pma, ma); 5328 5329 return pma; 5330error: 5331 isl_space_free(space); 5332 isl_map_free(map); 5333 isl_basic_map_free(hull); 5334 return NULL; 5335} 5336 5337/* Try and create an isl_pw_multi_aff that is equivalent to the given isl_map. 5338 * 5339 * As a special case, we first check if there is any pair of constraints, 5340 * shared by all the basic maps in "map" that force a given dimension 5341 * to be equal to the floor of some affine combination of the input dimensions. 5342 * 5343 * In particular, if we can find two constraints 5344 * 5345 * e(...) + c1 - m x >= 0 i.e., m x <= e(...) + c1 5346 * 5347 * and 5348 * 5349 * -e(...) + c2 + m x >= 0 i.e., m x >= e(...) - c2 5350 * 5351 * where m > 1 and e only depends on parameters and input dimensions, 5352 * and such that 5353 * 5354 * c1 + c2 < m i.e., -c2 >= c1 - (m - 1) 5355 * 5356 * then we know that we can take 5357 * 5358 * x = floor((e(...) + c1) / m) 5359 * 5360 * without having to perform any computation. 5361 * 5362 * Note that we know that 5363 * 5364 * c1 + c2 >= 1 5365 * 5366 * If c1 + c2 were 0, then we would have detected an equality during 5367 * simplification. If c1 + c2 were negative, then we would have detected 5368 * a contradiction. 5369 */ 5370static __isl_give isl_pw_multi_aff *pw_multi_aff_from_map_check_div( 5371 __isl_take isl_map *map) 5372{ 5373 int d; 5374 isl_size dim; 5375 isl_size i; 5376 isl_size n_ineq; 5377 isl_basic_map *hull; 5378 5379 hull = isl_map_unshifted_simple_hull(isl_map_copy(map)); 5380 dim = isl_map_dim(map, isl_dim_out); 5381 n_ineq = isl_basic_map_n_inequality(hull); 5382 if (dim < 0 || n_ineq < 0) 5383 goto error; 5384 5385 dim = isl_map_dim(map, isl_dim_out); 5386 for (d = 0; d < dim; ++d) { 5387 i = isl_basic_map_find_output_upper_div_constraint(hull, d); 5388 if (i < 0) 5389 goto error; 5390 if (i >= n_ineq) 5391 continue; 5392 return pw_multi_aff_from_map_div(map, hull, d, i); 5393 } 5394 isl_basic_map_free(hull); 5395 return pw_multi_aff_from_map_base(map); 5396error: 5397 isl_map_free(map); 5398 isl_basic_map_free(hull); 5399 return NULL; 5400} 5401 5402/* Given an affine expression 5403 * 5404 * [A -> B] -> f(A,B) 5405 * 5406 * construct an isl_multi_aff 5407 * 5408 * [A -> B] -> B' 5409 * 5410 * such that dimension "d" in B' is set to "aff" and the remaining 5411 * dimensions are set equal to the corresponding dimensions in B. 5412 * "n_in" is the dimension of the space A. 5413 * "n_out" is the dimension of the space B. 5414 * 5415 * If "is_set" is set, then the affine expression is of the form 5416 * 5417 * [B] -> f(B) 5418 * 5419 * and we construct an isl_multi_aff 5420 * 5421 * B -> B' 5422 */ 5423static __isl_give isl_multi_aff *range_map(__isl_take isl_aff *aff, int d, 5424 unsigned n_in, unsigned n_out, int is_set) 5425{ 5426 int i; 5427 isl_multi_aff *ma; 5428 isl_space *space, *space2; 5429 isl_local_space *ls; 5430 5431 space = isl_aff_get_domain_space(aff); 5432 ls = isl_local_space_from_space(isl_space_copy(space)); 5433 space2 = isl_space_copy(space); 5434 if (!is_set) 5435 space2 = isl_space_range(isl_space_unwrap(space2)); 5436 space = isl_space_map_from_domain_and_range(space, space2); 5437 ma = isl_multi_aff_alloc(space); 5438 ma = isl_multi_aff_set_aff(ma, d, aff); 5439 5440 for (i = 0; i < n_out; ++i) { 5441 if (i == d) 5442 continue; 5443 aff = isl_aff_var_on_domain(isl_local_space_copy(ls), 5444 isl_dim_set, n_in + i); 5445 ma = isl_multi_aff_set_aff(ma, i, aff); 5446 } 5447 5448 isl_local_space_free(ls); 5449 5450 return ma; 5451} 5452 5453/* Try and create an isl_pw_multi_aff that is equivalent to the given isl_map, 5454 * taking into account that the dimension at position "d" can be written as 5455 * 5456 * x = m a + f(..) (1) 5457 * 5458 * where m is equal to "gcd". 5459 * "i" is the index of the equality in "hull" that defines f(..). 5460 * In particular, the equality is of the form 5461 * 5462 * f(..) - x + m g(existentials) = 0 5463 * 5464 * or 5465 * 5466 * -f(..) + x + m g(existentials) = 0 5467 * 5468 * We basically plug (1) into "map", resulting in a map with "a" 5469 * in the range instead of "x". The corresponding isl_pw_multi_aff 5470 * defining "a" is then plugged back into (1) to obtain a definition for "x". 5471 * 5472 * Specifically, given the input map 5473 * 5474 * A -> B 5475 * 5476 * We first wrap it into a set 5477 * 5478 * [A -> B] 5479 * 5480 * and define (1) on top of the corresponding space, resulting in "aff". 5481 * We use this to create an isl_multi_aff that maps the output position "d" 5482 * from "a" to "x", leaving all other (intput and output) dimensions unchanged. 5483 * We plug this into the wrapped map, unwrap the result and compute the 5484 * corresponding isl_pw_multi_aff. 5485 * The result is an expression 5486 * 5487 * A -> T(A) 5488 * 5489 * We adjust that to 5490 * 5491 * A -> [A -> T(A)] 5492 * 5493 * so that we can plug that into "aff", after extending the latter to 5494 * a mapping 5495 * 5496 * [A -> B] -> B' 5497 * 5498 * 5499 * If "map" is actually a set, then there is no "A" space, meaning 5500 * that we do not need to perform any wrapping, and that the result 5501 * of the recursive call is of the form 5502 * 5503 * [T] 5504 * 5505 * which is plugged into a mapping of the form 5506 * 5507 * B -> B' 5508 */ 5509static __isl_give isl_pw_multi_aff *pw_multi_aff_from_map_stride( 5510 __isl_take isl_map *map, __isl_take isl_basic_map *hull, int d, int i, 5511 isl_int gcd) 5512{ 5513 isl_set *set; 5514 isl_space *space; 5515 isl_local_space *ls; 5516 isl_aff *aff; 5517 isl_multi_aff *ma; 5518 isl_pw_multi_aff *pma, *id; 5519 isl_size n_in; 5520 unsigned o_out; 5521 isl_size n_out; 5522 isl_bool is_set; 5523 5524 is_set = isl_map_is_set(map); 5525 if (is_set < 0) 5526 goto error; 5527 5528 n_in = isl_basic_map_dim(hull, isl_dim_in); 5529 n_out = isl_basic_map_dim(hull, isl_dim_out); 5530 if (n_in < 0 || n_out < 0) 5531 goto error; 5532 o_out = isl_basic_map_offset(hull, isl_dim_out); 5533 5534 if (is_set) 5535 set = map; 5536 else 5537 set = isl_map_wrap(map); 5538 space = isl_space_map_from_set(isl_set_get_space(set)); 5539 ma = isl_multi_aff_identity(space); 5540 ls = isl_local_space_from_space(isl_set_get_space(set)); 5541 aff = isl_aff_alloc(ls); 5542 if (aff) { 5543 isl_int_set_si(aff->v->el[0], 1); 5544 if (isl_int_is_one(hull->eq[i][o_out + d])) 5545 isl_seq_neg(aff->v->el + 1, hull->eq[i], 5546 aff->v->size - 1); 5547 else 5548 isl_seq_cpy(aff->v->el + 1, hull->eq[i], 5549 aff->v->size - 1); 5550 isl_int_set(aff->v->el[1 + o_out + d], gcd); 5551 } 5552 ma = isl_multi_aff_set_aff(ma, n_in + d, isl_aff_copy(aff)); 5553 set = isl_set_preimage_multi_aff(set, ma); 5554 5555 ma = range_map(aff, d, n_in, n_out, is_set); 5556 5557 if (is_set) 5558 map = set; 5559 else 5560 map = isl_set_unwrap(set); 5561 pma = isl_pw_multi_aff_from_map(map); 5562 5563 if (!is_set) { 5564 space = isl_pw_multi_aff_get_domain_space(pma); 5565 space = isl_space_map_from_set(space); 5566 id = isl_pw_multi_aff_identity(space); 5567 pma = isl_pw_multi_aff_range_product(id, pma); 5568 } 5569 id = isl_pw_multi_aff_from_multi_aff(ma); 5570 pma = isl_pw_multi_aff_pullback_pw_multi_aff(id, pma); 5571 5572 isl_basic_map_free(hull); 5573 return pma; 5574error: 5575 isl_map_free(map); 5576 isl_basic_map_free(hull); 5577 return NULL; 5578} 5579 5580/* Try and create an isl_pw_multi_aff that is equivalent to the given isl_map. 5581 * "hull" contains the equalities valid for "map". 5582 * 5583 * Check if any of the output dimensions is "strided". 5584 * That is, we check if it can be written as 5585 * 5586 * x = m a + f(..) 5587 * 5588 * with m greater than 1, a some combination of existentially quantified 5589 * variables and f an expression in the parameters and input dimensions. 5590 * If so, we remove the stride in pw_multi_aff_from_map_stride. 5591 * 5592 * Otherwise, we continue with pw_multi_aff_from_map_check_div for a further 5593 * special case. 5594 */ 5595static __isl_give isl_pw_multi_aff *pw_multi_aff_from_map_check_strides( 5596 __isl_take isl_map *map, __isl_take isl_basic_map *hull) 5597{ 5598 int i, j; 5599 isl_size n_out; 5600 unsigned o_out; 5601 isl_size n_div; 5602 unsigned o_div; 5603 isl_int gcd; 5604 5605 n_div = isl_basic_map_dim(hull, isl_dim_div); 5606 n_out = isl_basic_map_dim(hull, isl_dim_out); 5607 if (n_div < 0 || n_out < 0) 5608 goto error; 5609 5610 if (n_div == 0) { 5611 isl_basic_map_free(hull); 5612 return pw_multi_aff_from_map_check_div(map); 5613 } 5614 5615 isl_int_init(gcd); 5616 5617 o_div = isl_basic_map_offset(hull, isl_dim_div); 5618 o_out = isl_basic_map_offset(hull, isl_dim_out); 5619 5620 for (i = 0; i < n_out; ++i) { 5621 for (j = 0; j < hull->n_eq; ++j) { 5622 isl_int *eq = hull->eq[j]; 5623 isl_pw_multi_aff *res; 5624 5625 if (!isl_int_is_one(eq[o_out + i]) && 5626 !isl_int_is_negone(eq[o_out + i])) 5627 continue; 5628 if (isl_seq_first_non_zero(eq + o_out, i) != -1) 5629 continue; 5630 if (isl_seq_first_non_zero(eq + o_out + i + 1, 5631 n_out - (i + 1)) != -1) 5632 continue; 5633 isl_seq_gcd(eq + o_div, n_div, &gcd); 5634 if (isl_int_is_zero(gcd)) 5635 continue; 5636 if (isl_int_is_one(gcd)) 5637 continue; 5638 5639 res = pw_multi_aff_from_map_stride(map, hull, 5640 i, j, gcd); 5641 isl_int_clear(gcd); 5642 return res; 5643 } 5644 } 5645 5646 isl_int_clear(gcd); 5647 isl_basic_map_free(hull); 5648 return pw_multi_aff_from_map_check_div(map); 5649error: 5650 isl_map_free(map); 5651 isl_basic_map_free(hull); 5652 return NULL; 5653} 5654 5655/* Try and create an isl_pw_multi_aff that is equivalent to the given isl_map. 5656 * 5657 * As a special case, we first check if all output dimensions are uniquely 5658 * defined in terms of the parameters and input dimensions over the entire 5659 * domain. If so, we extract the desired isl_pw_multi_aff directly 5660 * from the affine hull of "map" and its domain. 5661 * 5662 * Otherwise, continue with pw_multi_aff_from_map_check_strides for more 5663 * special cases. 5664 */ 5665__isl_give isl_pw_multi_aff *isl_pw_multi_aff_from_map(__isl_take isl_map *map) 5666{ 5667 isl_bool sv; 5668 isl_size n; 5669 isl_basic_map *hull; 5670 5671 n = isl_map_n_basic_map(map); 5672 if (n < 0) 5673 goto error; 5674 5675 if (n == 1) { 5676 hull = isl_map_unshifted_simple_hull(isl_map_copy(map)); 5677 hull = isl_basic_map_plain_affine_hull(hull); 5678 sv = isl_basic_map_plain_is_single_valued(hull); 5679 if (sv >= 0 && sv) 5680 return plain_pw_multi_aff_from_map(isl_map_domain(map), 5681 hull); 5682 isl_basic_map_free(hull); 5683 } 5684 map = isl_map_detect_equalities(map); 5685 hull = isl_map_unshifted_simple_hull(isl_map_copy(map)); 5686 sv = isl_basic_map_plain_is_single_valued(hull); 5687 if (sv >= 0 && sv) 5688 return plain_pw_multi_aff_from_map(isl_map_domain(map), hull); 5689 if (sv >= 0) 5690 return pw_multi_aff_from_map_check_strides(map, hull); 5691 isl_basic_map_free(hull); 5692error: 5693 isl_map_free(map); 5694 return NULL; 5695} 5696 5697/* This function performs the same operation as isl_pw_multi_aff_from_map, 5698 * but is considered as a function on an isl_map when exported. 5699 */ 5700__isl_give isl_pw_multi_aff *isl_map_as_pw_multi_aff(__isl_take isl_map *map) 5701{ 5702 return isl_pw_multi_aff_from_map(map); 5703} 5704 5705__isl_give isl_pw_multi_aff *isl_pw_multi_aff_from_set(__isl_take isl_set *set) 5706{ 5707 return isl_pw_multi_aff_from_map(set); 5708} 5709 5710/* This function performs the same operation as isl_pw_multi_aff_from_set, 5711 * but is considered as a function on an isl_set when exported. 5712 */ 5713__isl_give isl_pw_multi_aff *isl_set_as_pw_multi_aff(__isl_take isl_set *set) 5714{ 5715 return isl_pw_multi_aff_from_set(set); 5716} 5717 5718/* Convert "map" into an isl_pw_multi_aff (if possible) and 5719 * add it to *user. 5720 */ 5721static isl_stat pw_multi_aff_from_map(__isl_take isl_map *map, void *user) 5722{ 5723 isl_union_pw_multi_aff **upma = user; 5724 isl_pw_multi_aff *pma; 5725 5726 pma = isl_pw_multi_aff_from_map(map); 5727 *upma = isl_union_pw_multi_aff_add_pw_multi_aff(*upma, pma); 5728 5729 return *upma ? isl_stat_ok : isl_stat_error; 5730} 5731 5732/* Create an isl_union_pw_multi_aff with the given isl_aff on a universe 5733 * domain. 5734 */ 5735__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_from_aff( 5736 __isl_take isl_aff *aff) 5737{ 5738 isl_multi_aff *ma; 5739 isl_pw_multi_aff *pma; 5740 5741 ma = isl_multi_aff_from_aff(aff); 5742 pma = isl_pw_multi_aff_from_multi_aff(ma); 5743 return isl_union_pw_multi_aff_from_pw_multi_aff(pma); 5744} 5745 5746/* Try and create an isl_union_pw_multi_aff that is equivalent 5747 * to the given isl_union_map. 5748 * The isl_union_map is required to be single-valued in each space. 5749 * Otherwise, an error is produced. 5750 */ 5751__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_from_union_map( 5752 __isl_take isl_union_map *umap) 5753{ 5754 isl_space *space; 5755 isl_union_pw_multi_aff *upma; 5756 5757 space = isl_union_map_get_space(umap); 5758 upma = isl_union_pw_multi_aff_empty(space); 5759 if (isl_union_map_foreach_map(umap, &pw_multi_aff_from_map, &upma) < 0) 5760 upma = isl_union_pw_multi_aff_free(upma); 5761 isl_union_map_free(umap); 5762 5763 return upma; 5764} 5765 5766/* This function performs the same operation as 5767 * isl_union_pw_multi_aff_from_union_map, 5768 * but is considered as a function on an isl_union_map when exported. 5769 */ 5770__isl_give isl_union_pw_multi_aff *isl_union_map_as_union_pw_multi_aff( 5771 __isl_take isl_union_map *umap) 5772{ 5773 return isl_union_pw_multi_aff_from_union_map(umap); 5774} 5775 5776/* Try and create an isl_union_pw_multi_aff that is equivalent 5777 * to the given isl_union_set. 5778 * The isl_union_set is required to be a singleton in each space. 5779 * Otherwise, an error is produced. 5780 */ 5781__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_from_union_set( 5782 __isl_take isl_union_set *uset) 5783{ 5784 return isl_union_pw_multi_aff_from_union_map(uset); 5785} 5786 5787/* Return the piecewise affine expression "set ? 1 : 0". 5788 */ 5789__isl_give isl_pw_aff *isl_set_indicator_function(__isl_take isl_set *set) 5790{ 5791 isl_pw_aff *pa; 5792 isl_space *space = isl_set_get_space(set); 5793 isl_local_space *ls = isl_local_space_from_space(space); 5794 isl_aff *zero = isl_aff_zero_on_domain(isl_local_space_copy(ls)); 5795 isl_aff *one = isl_aff_zero_on_domain(ls); 5796 5797 one = isl_aff_add_constant_si(one, 1); 5798 pa = isl_pw_aff_alloc(isl_set_copy(set), one); 5799 set = isl_set_complement(set); 5800 pa = isl_pw_aff_add_disjoint(pa, isl_pw_aff_alloc(set, zero)); 5801 5802 return pa; 5803} 5804 5805/* Plug in "subs" for dimension "type", "pos" of "aff". 5806 * 5807 * Let i be the dimension to replace and let "subs" be of the form 5808 * 5809 * f/d 5810 * 5811 * and "aff" of the form 5812 * 5813 * (a i + g)/m 5814 * 5815 * The result is 5816 * 5817 * (a f + d g')/(m d) 5818 * 5819 * where g' is the result of plugging in "subs" in each of the integer 5820 * divisions in g. 5821 */ 5822__isl_give isl_aff *isl_aff_substitute(__isl_take isl_aff *aff, 5823 enum isl_dim_type type, unsigned pos, __isl_keep isl_aff *subs) 5824{ 5825 isl_ctx *ctx; 5826 isl_int v; 5827 isl_size n_div; 5828 5829 aff = isl_aff_cow(aff); 5830 if (!aff || !subs) 5831 return isl_aff_free(aff); 5832 5833 ctx = isl_aff_get_ctx(aff); 5834 if (!isl_space_is_equal(aff->ls->dim, subs->ls->dim)) 5835 isl_die(ctx, isl_error_invalid, 5836 "spaces don't match", return isl_aff_free(aff)); 5837 n_div = isl_aff_domain_dim(subs, isl_dim_div); 5838 if (n_div < 0) 5839 return isl_aff_free(aff); 5840 if (n_div != 0) 5841 isl_die(ctx, isl_error_unsupported, 5842 "cannot handle divs yet", return isl_aff_free(aff)); 5843 5844 aff->ls = isl_local_space_substitute(aff->ls, type, pos, subs); 5845 if (!aff->ls) 5846 return isl_aff_free(aff); 5847 5848 aff->v = isl_vec_cow(aff->v); 5849 if (!aff->v) 5850 return isl_aff_free(aff); 5851 5852 pos += isl_local_space_offset(aff->ls, type); 5853 5854 isl_int_init(v); 5855 isl_seq_substitute(aff->v->el, pos, subs->v->el, 5856 aff->v->size, subs->v->size, v); 5857 isl_int_clear(v); 5858 5859 return aff; 5860} 5861 5862/* Plug in "subs" for dimension "type", "pos" in each of the affine 5863 * expressions in "maff". 5864 */ 5865__isl_give isl_multi_aff *isl_multi_aff_substitute( 5866 __isl_take isl_multi_aff *maff, enum isl_dim_type type, unsigned pos, 5867 __isl_keep isl_aff *subs) 5868{ 5869 isl_size n; 5870 int i; 5871 5872 n = isl_multi_aff_size(maff); 5873 if (n < 0 || !subs) 5874 return isl_multi_aff_free(maff); 5875 5876 if (type == isl_dim_in) 5877 type = isl_dim_set; 5878 5879 for (i = 0; i < n; ++i) { 5880 isl_aff *aff; 5881 5882 aff = isl_multi_aff_take_at(maff, i); 5883 aff = isl_aff_substitute(aff, type, pos, subs); 5884 maff = isl_multi_aff_restore_at(maff, i, aff); 5885 } 5886 5887 return maff; 5888} 5889 5890/* Plug in "subs" for input dimension "pos" of "pma". 5891 * 5892 * pma is of the form 5893 * 5894 * A_i(v) -> M_i(v) 5895 * 5896 * while subs is of the form 5897 * 5898 * v' = B_j(v) -> S_j 5899 * 5900 * Each pair i,j such that C_ij = A_i \cap B_i is non-empty 5901 * has a contribution in the result, in particular 5902 * 5903 * C_ij(S_j) -> M_i(S_j) 5904 * 5905 * Note that plugging in S_j in C_ij may also result in an empty set 5906 * and this contribution should simply be discarded. 5907 */ 5908__isl_give isl_pw_multi_aff *isl_pw_multi_aff_substitute( 5909 __isl_take isl_pw_multi_aff *pma, unsigned pos, 5910 __isl_keep isl_pw_aff *subs) 5911{ 5912 int i, j, n; 5913 isl_pw_multi_aff *res; 5914 5915 if (!pma || !subs) 5916 return isl_pw_multi_aff_free(pma); 5917 5918 n = pma->n * subs->n; 5919 res = isl_pw_multi_aff_alloc_size(isl_space_copy(pma->dim), n); 5920 5921 for (i = 0; i < pma->n; ++i) { 5922 for (j = 0; j < subs->n; ++j) { 5923 isl_set *common; 5924 isl_multi_aff *res_ij; 5925 int empty; 5926 5927 common = isl_set_intersect( 5928 isl_set_copy(pma->p[i].set), 5929 isl_set_copy(subs->p[j].set)); 5930 common = isl_set_substitute(common, 5931 pos, subs->p[j].aff); 5932 empty = isl_set_plain_is_empty(common); 5933 if (empty < 0 || empty) { 5934 isl_set_free(common); 5935 if (empty < 0) 5936 goto error; 5937 continue; 5938 } 5939 5940 res_ij = isl_multi_aff_substitute( 5941 isl_multi_aff_copy(pma->p[i].maff), 5942 isl_dim_in, pos, subs->p[j].aff); 5943 5944 res = isl_pw_multi_aff_add_piece(res, common, res_ij); 5945 } 5946 } 5947 5948 isl_pw_multi_aff_free(pma); 5949 return res; 5950error: 5951 isl_pw_multi_aff_free(pma); 5952 isl_pw_multi_aff_free(res); 5953 return NULL; 5954} 5955 5956/* Compute the preimage of a range of dimensions in the affine expression "src" 5957 * under "ma" and put the result in "dst". The number of dimensions in "src" 5958 * that precede the range is given by "n_before". The number of dimensions 5959 * in the range is given by the number of output dimensions of "ma". 5960 * The number of dimensions that follow the range is given by "n_after". 5961 * If "has_denom" is set (to one), 5962 * then "src" and "dst" have an extra initial denominator. 5963 * "n_div_ma" is the number of existentials in "ma" 5964 * "n_div_bset" is the number of existentials in "src" 5965 * The resulting "dst" (which is assumed to have been allocated by 5966 * the caller) contains coefficients for both sets of existentials, 5967 * first those in "ma" and then those in "src". 5968 * f, c1, c2 and g are temporary objects that have been initialized 5969 * by the caller. 5970 * 5971 * Let src represent the expression 5972 * 5973 * (a(p) + f_u u + b v + f_w w + c(divs))/d 5974 * 5975 * and let ma represent the expressions 5976 * 5977 * v_i = (r_i(p) + s_i(y) + t_i(divs'))/m_i 5978 * 5979 * We start out with the following expression for dst: 5980 * 5981 * (a(p) + f_u u + 0 y + f_w w + 0 divs' + c(divs) + f \sum_i b_i v_i)/d 5982 * 5983 * with the multiplication factor f initially equal to 1 5984 * and f \sum_i b_i v_i kept separately. 5985 * For each x_i that we substitute, we multiply the numerator 5986 * (and denominator) of dst by c_1 = m_i and add the numerator 5987 * of the x_i expression multiplied by c_2 = f b_i, 5988 * after removing the common factors of c_1 and c_2. 5989 * The multiplication factor f also needs to be multiplied by c_1 5990 * for the next x_j, j > i. 5991 */ 5992isl_stat isl_seq_preimage(isl_int *dst, isl_int *src, 5993 __isl_keep isl_multi_aff *ma, int n_before, int n_after, 5994 int n_div_ma, int n_div_bmap, 5995 isl_int f, isl_int c1, isl_int c2, isl_int g, int has_denom) 5996{ 5997 int i; 5998 isl_size n_param, n_in, n_out; 5999 int o_dst, o_src; 6000 6001 n_param = isl_multi_aff_dim(ma, isl_dim_param); 6002 n_in = isl_multi_aff_dim(ma, isl_dim_in); 6003 n_out = isl_multi_aff_dim(ma, isl_dim_out); 6004 if (n_param < 0 || n_in < 0 || n_out < 0) 6005 return isl_stat_error; 6006 6007 isl_seq_cpy(dst, src, has_denom + 1 + n_param + n_before); 6008 o_dst = o_src = has_denom + 1 + n_param + n_before; 6009 isl_seq_clr(dst + o_dst, n_in); 6010 o_dst += n_in; 6011 o_src += n_out; 6012 isl_seq_cpy(dst + o_dst, src + o_src, n_after); 6013 o_dst += n_after; 6014 o_src += n_after; 6015 isl_seq_clr(dst + o_dst, n_div_ma); 6016 o_dst += n_div_ma; 6017 isl_seq_cpy(dst + o_dst, src + o_src, n_div_bmap); 6018 6019 isl_int_set_si(f, 1); 6020 6021 for (i = 0; i < n_out; ++i) { 6022 int offset = has_denom + 1 + n_param + n_before + i; 6023 6024 if (isl_int_is_zero(src[offset])) 6025 continue; 6026 isl_int_set(c1, ma->u.p[i]->v->el[0]); 6027 isl_int_mul(c2, f, src[offset]); 6028 isl_int_gcd(g, c1, c2); 6029 isl_int_divexact(c1, c1, g); 6030 isl_int_divexact(c2, c2, g); 6031 6032 isl_int_mul(f, f, c1); 6033 o_dst = has_denom; 6034 o_src = 1; 6035 isl_seq_combine(dst + o_dst, c1, dst + o_dst, 6036 c2, ma->u.p[i]->v->el + o_src, 1 + n_param); 6037 o_dst += 1 + n_param; 6038 o_src += 1 + n_param; 6039 isl_seq_scale(dst + o_dst, dst + o_dst, c1, n_before); 6040 o_dst += n_before; 6041 isl_seq_combine(dst + o_dst, c1, dst + o_dst, 6042 c2, ma->u.p[i]->v->el + o_src, n_in); 6043 o_dst += n_in; 6044 o_src += n_in; 6045 isl_seq_scale(dst + o_dst, dst + o_dst, c1, n_after); 6046 o_dst += n_after; 6047 isl_seq_combine(dst + o_dst, c1, dst + o_dst, 6048 c2, ma->u.p[i]->v->el + o_src, n_div_ma); 6049 o_dst += n_div_ma; 6050 o_src += n_div_ma; 6051 isl_seq_scale(dst + o_dst, dst + o_dst, c1, n_div_bmap); 6052 if (has_denom) 6053 isl_int_mul(dst[0], dst[0], c1); 6054 } 6055 6056 return isl_stat_ok; 6057} 6058 6059/* Compute the pullback of "aff" by the function represented by "ma". 6060 * In other words, plug in "ma" in "aff". The result is an affine expression 6061 * defined over the domain space of "ma". 6062 * 6063 * If "aff" is represented by 6064 * 6065 * (a(p) + b x + c(divs))/d 6066 * 6067 * and ma is represented by 6068 * 6069 * x = D(p) + F(y) + G(divs') 6070 * 6071 * then the result is 6072 * 6073 * (a(p) + b D(p) + b F(y) + b G(divs') + c(divs))/d 6074 * 6075 * The divs in the local space of the input are similarly adjusted 6076 * through a call to isl_local_space_preimage_multi_aff. 6077 */ 6078__isl_give isl_aff *isl_aff_pullback_multi_aff(__isl_take isl_aff *aff, 6079 __isl_take isl_multi_aff *ma) 6080{ 6081 isl_aff *res = NULL; 6082 isl_local_space *ls; 6083 isl_size n_div_aff, n_div_ma; 6084 isl_int f, c1, c2, g; 6085 6086 ma = isl_multi_aff_align_divs(ma); 6087 if (!aff || !ma) 6088 goto error; 6089 6090 n_div_aff = isl_aff_dim(aff, isl_dim_div); 6091 n_div_ma = ma->n ? isl_aff_dim(ma->u.p[0], isl_dim_div) : 0; 6092 if (n_div_aff < 0 || n_div_ma < 0) 6093 goto error; 6094 6095 ls = isl_aff_get_domain_local_space(aff); 6096 ls = isl_local_space_preimage_multi_aff(ls, isl_multi_aff_copy(ma)); 6097 res = isl_aff_alloc(ls); 6098 if (!res) 6099 goto error; 6100 6101 isl_int_init(f); 6102 isl_int_init(c1); 6103 isl_int_init(c2); 6104 isl_int_init(g); 6105 6106 if (isl_seq_preimage(res->v->el, aff->v->el, ma, 0, 0, 6107 n_div_ma, n_div_aff, f, c1, c2, g, 1) < 0) 6108 res = isl_aff_free(res); 6109 6110 isl_int_clear(f); 6111 isl_int_clear(c1); 6112 isl_int_clear(c2); 6113 isl_int_clear(g); 6114 6115 isl_aff_free(aff); 6116 isl_multi_aff_free(ma); 6117 res = isl_aff_normalize(res); 6118 return res; 6119error: 6120 isl_aff_free(aff); 6121 isl_multi_aff_free(ma); 6122 isl_aff_free(res); 6123 return NULL; 6124} 6125 6126/* Compute the pullback of "aff1" by the function represented by "aff2". 6127 * In other words, plug in "aff2" in "aff1". The result is an affine expression 6128 * defined over the domain space of "aff1". 6129 * 6130 * The domain of "aff1" should match the range of "aff2", which means 6131 * that it should be single-dimensional. 6132 */ 6133__isl_give isl_aff *isl_aff_pullback_aff(__isl_take isl_aff *aff1, 6134 __isl_take isl_aff *aff2) 6135{ 6136 isl_multi_aff *ma; 6137 6138 ma = isl_multi_aff_from_aff(aff2); 6139 return isl_aff_pullback_multi_aff(aff1, ma); 6140} 6141 6142/* Compute the pullback of "ma1" by the function represented by "ma2". 6143 * In other words, plug in "ma2" in "ma1". 6144 */ 6145__isl_give isl_multi_aff *isl_multi_aff_pullback_multi_aff( 6146 __isl_take isl_multi_aff *ma1, __isl_take isl_multi_aff *ma2) 6147{ 6148 int i; 6149 isl_size n; 6150 isl_space *space = NULL; 6151 6152 isl_multi_aff_align_params_bin(&ma1, &ma2); 6153 ma2 = isl_multi_aff_align_divs(ma2); 6154 n = isl_multi_aff_size(ma1); 6155 if (n < 0 || !ma2) 6156 goto error; 6157 6158 space = isl_space_join(isl_multi_aff_get_space(ma2), 6159 isl_multi_aff_get_space(ma1)); 6160 6161 for (i = 0; i < n; ++i) { 6162 isl_aff *aff; 6163 6164 aff = isl_multi_aff_take_at(ma1, i); 6165 aff = isl_aff_pullback_multi_aff(aff, isl_multi_aff_copy(ma2)); 6166 ma1 = isl_multi_aff_restore_at(ma1, i, aff); 6167 } 6168 6169 ma1 = isl_multi_aff_reset_space(ma1, space); 6170 isl_multi_aff_free(ma2); 6171 return ma1; 6172error: 6173 isl_space_free(space); 6174 isl_multi_aff_free(ma2); 6175 isl_multi_aff_free(ma1); 6176 return NULL; 6177} 6178 6179/* Extend the local space of "dst" to include the divs 6180 * in the local space of "src". 6181 * 6182 * If "src" does not have any divs or if the local spaces of "dst" and 6183 * "src" are the same, then no extension is required. 6184 */ 6185__isl_give isl_aff *isl_aff_align_divs(__isl_take isl_aff *dst, 6186 __isl_keep isl_aff *src) 6187{ 6188 isl_ctx *ctx; 6189 isl_size src_n_div, dst_n_div; 6190 int *exp1 = NULL; 6191 int *exp2 = NULL; 6192 isl_bool equal; 6193 isl_mat *div; 6194 6195 if (!src || !dst) 6196 return isl_aff_free(dst); 6197 6198 ctx = isl_aff_get_ctx(src); 6199 equal = isl_local_space_has_equal_space(src->ls, dst->ls); 6200 if (equal < 0) 6201 return isl_aff_free(dst); 6202 if (!equal) 6203 isl_die(ctx, isl_error_invalid, 6204 "spaces don't match", goto error); 6205 6206 src_n_div = isl_aff_domain_dim(src, isl_dim_div); 6207 dst_n_div = isl_aff_domain_dim(dst, isl_dim_div); 6208 if (src_n_div == 0) 6209 return dst; 6210 equal = isl_local_space_is_equal(src->ls, dst->ls); 6211 if (equal < 0 || src_n_div < 0 || dst_n_div < 0) 6212 return isl_aff_free(dst); 6213 if (equal) 6214 return dst; 6215 6216 exp1 = isl_alloc_array(ctx, int, src_n_div); 6217 exp2 = isl_alloc_array(ctx, int, dst_n_div); 6218 if (!exp1 || (dst_n_div && !exp2)) 6219 goto error; 6220 6221 div = isl_merge_divs(src->ls->div, dst->ls->div, exp1, exp2); 6222 dst = isl_aff_expand_divs(dst, div, exp2); 6223 free(exp1); 6224 free(exp2); 6225 6226 return dst; 6227error: 6228 free(exp1); 6229 free(exp2); 6230 return isl_aff_free(dst); 6231} 6232 6233/* Adjust the local spaces of the affine expressions in "maff" 6234 * such that they all have the save divs. 6235 */ 6236__isl_give isl_multi_aff *isl_multi_aff_align_divs( 6237 __isl_take isl_multi_aff *maff) 6238{ 6239 isl_aff *aff_0; 6240 isl_size n; 6241 int i; 6242 6243 n = isl_multi_aff_size(maff); 6244 if (n < 0) 6245 return isl_multi_aff_free(maff); 6246 if (n <= 1) 6247 return maff; 6248 6249 aff_0 = isl_multi_aff_take_at(maff, 0); 6250 for (i = 1; i < n; ++i) { 6251 isl_aff *aff_i; 6252 6253 aff_i = isl_multi_aff_peek_at(maff, i); 6254 aff_0 = isl_aff_align_divs(aff_0, aff_i); 6255 } 6256 maff = isl_multi_aff_restore_at(maff, 0, aff_0); 6257 6258 aff_0 = isl_multi_aff_peek_at(maff, 0); 6259 for (i = 1; i < n; ++i) { 6260 isl_aff *aff_i; 6261 6262 aff_i = isl_multi_aff_take_at(maff, i); 6263 aff_i = isl_aff_align_divs(aff_i, aff_0); 6264 maff = isl_multi_aff_restore_at(maff, i, aff_i); 6265 } 6266 6267 return maff; 6268} 6269 6270__isl_give isl_aff *isl_aff_lift(__isl_take isl_aff *aff) 6271{ 6272 aff = isl_aff_cow(aff); 6273 if (!aff) 6274 return NULL; 6275 6276 aff->ls = isl_local_space_lift(aff->ls); 6277 if (!aff->ls) 6278 return isl_aff_free(aff); 6279 6280 return aff; 6281} 6282 6283/* Lift "maff" to a space with extra dimensions such that the result 6284 * has no more existentially quantified variables. 6285 * If "ls" is not NULL, then *ls is assigned the local space that lies 6286 * at the basis of the lifting applied to "maff". 6287 */ 6288__isl_give isl_multi_aff *isl_multi_aff_lift(__isl_take isl_multi_aff *maff, 6289 __isl_give isl_local_space **ls) 6290{ 6291 int i; 6292 isl_space *space; 6293 isl_aff *aff; 6294 isl_size n, n_div; 6295 6296 if (ls) 6297 *ls = NULL; 6298 6299 n = isl_multi_aff_size(maff); 6300 if (n < 0) 6301 return isl_multi_aff_free(maff); 6302 6303 if (n == 0) { 6304 if (ls) { 6305 isl_space *space = isl_multi_aff_get_domain_space(maff); 6306 *ls = isl_local_space_from_space(space); 6307 if (!*ls) 6308 return isl_multi_aff_free(maff); 6309 } 6310 return maff; 6311 } 6312 6313 maff = isl_multi_aff_align_divs(maff); 6314 6315 aff = isl_multi_aff_peek_at(maff, 0); 6316 n_div = isl_aff_dim(aff, isl_dim_div); 6317 if (n_div < 0) 6318 return isl_multi_aff_free(maff); 6319 space = isl_multi_aff_get_space(maff); 6320 space = isl_space_lift(isl_space_domain(space), n_div); 6321 space = isl_space_extend_domain_with_range(space, 6322 isl_multi_aff_get_space(maff)); 6323 maff = isl_multi_aff_restore_space(maff, space); 6324 6325 if (ls) { 6326 aff = isl_multi_aff_peek_at(maff, 0); 6327 *ls = isl_aff_get_domain_local_space(aff); 6328 if (!*ls) 6329 return isl_multi_aff_free(maff); 6330 } 6331 6332 for (i = 0; i < n; ++i) { 6333 aff = isl_multi_aff_take_at(maff, i); 6334 aff = isl_aff_lift(aff); 6335 maff = isl_multi_aff_restore_at(maff, i, aff); 6336 } 6337 6338 return maff; 6339} 6340 6341#undef TYPE 6342#define TYPE isl_pw_multi_aff 6343static 6344#include "check_type_range_templ.c" 6345 6346/* Extract an isl_pw_aff corresponding to output dimension "pos" of "pma". 6347 */ 6348__isl_give isl_pw_aff *isl_pw_multi_aff_get_at( 6349 __isl_keep isl_pw_multi_aff *pma, int pos) 6350{ 6351 int i; 6352 isl_size n_out; 6353 isl_space *space; 6354 isl_pw_aff *pa; 6355 6356 if (isl_pw_multi_aff_check_range(pma, isl_dim_out, pos, 1) < 0) 6357 return NULL; 6358 6359 n_out = isl_pw_multi_aff_dim(pma, isl_dim_out); 6360 if (n_out < 0) 6361 return NULL; 6362 6363 space = isl_pw_multi_aff_get_space(pma); 6364 space = isl_space_drop_dims(space, isl_dim_out, 6365 pos + 1, n_out - pos - 1); 6366 space = isl_space_drop_dims(space, isl_dim_out, 0, pos); 6367 6368 pa = isl_pw_aff_alloc_size(space, pma->n); 6369 for (i = 0; i < pma->n; ++i) { 6370 isl_aff *aff; 6371 aff = isl_multi_aff_get_aff(pma->p[i].maff, pos); 6372 pa = isl_pw_aff_add_piece(pa, isl_set_copy(pma->p[i].set), aff); 6373 } 6374 6375 return pa; 6376} 6377 6378/* This is an alternative name for the function above. 6379 */ 6380__isl_give isl_pw_aff *isl_pw_multi_aff_get_pw_aff( 6381 __isl_keep isl_pw_multi_aff *pma, int pos) 6382{ 6383 return isl_pw_multi_aff_get_at(pma, pos); 6384} 6385 6386/* Return an isl_pw_multi_aff with the given "set" as domain and 6387 * an unnamed zero-dimensional range. 6388 */ 6389__isl_give isl_pw_multi_aff *isl_pw_multi_aff_from_domain( 6390 __isl_take isl_set *set) 6391{ 6392 isl_multi_aff *ma; 6393 isl_space *space; 6394 6395 space = isl_set_get_space(set); 6396 space = isl_space_from_domain(space); 6397 ma = isl_multi_aff_zero(space); 6398 return isl_pw_multi_aff_alloc(set, ma); 6399} 6400 6401/* Add an isl_pw_multi_aff with the given "set" as domain and 6402 * an unnamed zero-dimensional range to *user. 6403 */ 6404static isl_stat add_pw_multi_aff_from_domain(__isl_take isl_set *set, 6405 void *user) 6406{ 6407 isl_union_pw_multi_aff **upma = user; 6408 isl_pw_multi_aff *pma; 6409 6410 pma = isl_pw_multi_aff_from_domain(set); 6411 *upma = isl_union_pw_multi_aff_add_pw_multi_aff(*upma, pma); 6412 6413 return isl_stat_ok; 6414} 6415 6416/* Return an isl_union_pw_multi_aff with the given "uset" as domain and 6417 * an unnamed zero-dimensional range. 6418 */ 6419__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_from_domain( 6420 __isl_take isl_union_set *uset) 6421{ 6422 isl_space *space; 6423 isl_union_pw_multi_aff *upma; 6424 6425 if (!uset) 6426 return NULL; 6427 6428 space = isl_union_set_get_space(uset); 6429 upma = isl_union_pw_multi_aff_empty(space); 6430 6431 if (isl_union_set_foreach_set(uset, 6432 &add_pw_multi_aff_from_domain, &upma) < 0) 6433 goto error; 6434 6435 isl_union_set_free(uset); 6436 return upma; 6437error: 6438 isl_union_set_free(uset); 6439 isl_union_pw_multi_aff_free(upma); 6440 return NULL; 6441} 6442 6443/* Local data for bin_entry and the callback "fn". 6444 */ 6445struct isl_union_pw_multi_aff_bin_data { 6446 isl_union_pw_multi_aff *upma2; 6447 isl_union_pw_multi_aff *res; 6448 isl_pw_multi_aff *pma; 6449 isl_stat (*fn)(__isl_take isl_pw_multi_aff *pma, void *user); 6450}; 6451 6452/* Given an isl_pw_multi_aff from upma1, store it in data->pma 6453 * and call data->fn for each isl_pw_multi_aff in data->upma2. 6454 */ 6455static isl_stat bin_entry(__isl_take isl_pw_multi_aff *pma, void *user) 6456{ 6457 struct isl_union_pw_multi_aff_bin_data *data = user; 6458 isl_stat r; 6459 6460 data->pma = pma; 6461 r = isl_union_pw_multi_aff_foreach_pw_multi_aff(data->upma2, 6462 data->fn, data); 6463 isl_pw_multi_aff_free(pma); 6464 6465 return r; 6466} 6467 6468/* Call "fn" on each pair of isl_pw_multi_affs in "upma1" and "upma2". 6469 * The isl_pw_multi_aff from upma1 is stored in data->pma (where data is 6470 * passed as user field) and the isl_pw_multi_aff from upma2 is available 6471 * as *entry. The callback should adjust data->res if desired. 6472 */ 6473static __isl_give isl_union_pw_multi_aff *bin_op( 6474 __isl_take isl_union_pw_multi_aff *upma1, 6475 __isl_take isl_union_pw_multi_aff *upma2, 6476 isl_stat (*fn)(__isl_take isl_pw_multi_aff *pma, void *user)) 6477{ 6478 isl_space *space; 6479 struct isl_union_pw_multi_aff_bin_data data = { NULL, NULL, NULL, fn }; 6480 6481 space = isl_union_pw_multi_aff_get_space(upma2); 6482 upma1 = isl_union_pw_multi_aff_align_params(upma1, space); 6483 space = isl_union_pw_multi_aff_get_space(upma1); 6484 upma2 = isl_union_pw_multi_aff_align_params(upma2, space); 6485 6486 if (!upma1 || !upma2) 6487 goto error; 6488 6489 data.upma2 = upma2; 6490 data.res = isl_union_pw_multi_aff_alloc_same_size(upma1); 6491 if (isl_union_pw_multi_aff_foreach_pw_multi_aff(upma1, 6492 &bin_entry, &data) < 0) 6493 goto error; 6494 6495 isl_union_pw_multi_aff_free(upma1); 6496 isl_union_pw_multi_aff_free(upma2); 6497 return data.res; 6498error: 6499 isl_union_pw_multi_aff_free(upma1); 6500 isl_union_pw_multi_aff_free(upma2); 6501 isl_union_pw_multi_aff_free(data.res); 6502 return NULL; 6503} 6504 6505/* Given two isl_pw_multi_affs A -> B and C -> D, 6506 * construct an isl_pw_multi_aff (A * C) -> [B -> D]. 6507 */ 6508__isl_give isl_pw_multi_aff *isl_pw_multi_aff_range_product( 6509 __isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2) 6510{ 6511 isl_space *space; 6512 6513 isl_pw_multi_aff_align_params_bin(&pma1, &pma2); 6514 space = isl_space_range_product(isl_pw_multi_aff_get_space(pma1), 6515 isl_pw_multi_aff_get_space(pma2)); 6516 return isl_pw_multi_aff_on_shared_domain_in(pma1, pma2, space, 6517 &isl_multi_aff_range_product); 6518} 6519 6520/* Given two isl_pw_multi_affs A -> B and C -> D, 6521 * construct an isl_pw_multi_aff (A * C) -> (B, D). 6522 */ 6523__isl_give isl_pw_multi_aff *isl_pw_multi_aff_flat_range_product( 6524 __isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2) 6525{ 6526 isl_space *space; 6527 6528 isl_pw_multi_aff_align_params_bin(&pma1, &pma2); 6529 space = isl_space_range_product(isl_pw_multi_aff_get_space(pma1), 6530 isl_pw_multi_aff_get_space(pma2)); 6531 space = isl_space_flatten_range(space); 6532 return isl_pw_multi_aff_on_shared_domain_in(pma1, pma2, space, 6533 &isl_multi_aff_flat_range_product); 6534} 6535 6536/* If data->pma and "pma2" have the same domain space, then use "range_product" 6537 * to compute some form of range product and add the result to data->res. 6538 */ 6539static isl_stat gen_range_product_entry(__isl_take isl_pw_multi_aff *pma2, 6540 __isl_give isl_pw_multi_aff *(*range_product)( 6541 __isl_take isl_pw_multi_aff *pma1, 6542 __isl_take isl_pw_multi_aff *pma2), 6543 void *user) 6544{ 6545 struct isl_union_pw_multi_aff_bin_data *data = user; 6546 isl_bool match; 6547 isl_space *space1, *space2; 6548 6549 space1 = isl_pw_multi_aff_peek_space(data->pma); 6550 space2 = isl_pw_multi_aff_peek_space(pma2); 6551 match = isl_space_tuple_is_equal(space1, isl_dim_in, 6552 space2, isl_dim_in); 6553 if (match < 0 || !match) { 6554 isl_pw_multi_aff_free(pma2); 6555 return match < 0 ? isl_stat_error : isl_stat_ok; 6556 } 6557 6558 pma2 = range_product(isl_pw_multi_aff_copy(data->pma), pma2); 6559 6560 data->res = isl_union_pw_multi_aff_add_pw_multi_aff(data->res, pma2); 6561 6562 return isl_stat_ok; 6563} 6564 6565/* If data->pma and "pma2" have the same domain space, then compute 6566 * their flat range product and add the result to data->res. 6567 */ 6568static isl_stat flat_range_product_entry(__isl_take isl_pw_multi_aff *pma2, 6569 void *user) 6570{ 6571 return gen_range_product_entry(pma2, 6572 &isl_pw_multi_aff_flat_range_product, user); 6573} 6574 6575/* Given two isl_union_pw_multi_affs A -> B and C -> D, 6576 * construct an isl_union_pw_multi_aff (A * C) -> (B, D). 6577 */ 6578__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_flat_range_product( 6579 __isl_take isl_union_pw_multi_aff *upma1, 6580 __isl_take isl_union_pw_multi_aff *upma2) 6581{ 6582 return bin_op(upma1, upma2, &flat_range_product_entry); 6583} 6584 6585/* If data->pma and "pma2" have the same domain space, then compute 6586 * their range product and add the result to data->res. 6587 */ 6588static isl_stat range_product_entry(__isl_take isl_pw_multi_aff *pma2, 6589 void *user) 6590{ 6591 return gen_range_product_entry(pma2, 6592 &isl_pw_multi_aff_range_product, user); 6593} 6594 6595/* Given two isl_union_pw_multi_affs A -> B and C -> D, 6596 * construct an isl_union_pw_multi_aff (A * C) -> [B -> D]. 6597 */ 6598__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_range_product( 6599 __isl_take isl_union_pw_multi_aff *upma1, 6600 __isl_take isl_union_pw_multi_aff *upma2) 6601{ 6602 return bin_op(upma1, upma2, &range_product_entry); 6603} 6604 6605/* Replace the affine expressions at position "pos" in "pma" by "pa". 6606 * The parameters are assumed to have been aligned. 6607 * 6608 * The implementation essentially performs an isl_pw_*_on_shared_domain, 6609 * except that it works on two different isl_pw_* types. 6610 */ 6611static __isl_give isl_pw_multi_aff *pw_multi_aff_set_pw_aff( 6612 __isl_take isl_pw_multi_aff *pma, unsigned pos, 6613 __isl_take isl_pw_aff *pa) 6614{ 6615 int i, j, n; 6616 isl_pw_multi_aff *res = NULL; 6617 6618 if (!pma || !pa) 6619 goto error; 6620 6621 if (!isl_space_tuple_is_equal(pma->dim, isl_dim_in, 6622 pa->dim, isl_dim_in)) 6623 isl_die(isl_pw_multi_aff_get_ctx(pma), isl_error_invalid, 6624 "domains don't match", goto error); 6625 if (isl_pw_multi_aff_check_range(pma, isl_dim_out, pos, 1) < 0) 6626 goto error; 6627 6628 n = pma->n * pa->n; 6629 res = isl_pw_multi_aff_alloc_size(isl_pw_multi_aff_get_space(pma), n); 6630 6631 for (i = 0; i < pma->n; ++i) { 6632 for (j = 0; j < pa->n; ++j) { 6633 isl_set *common; 6634 isl_multi_aff *res_ij; 6635 int empty; 6636 6637 common = isl_set_intersect(isl_set_copy(pma->p[i].set), 6638 isl_set_copy(pa->p[j].set)); 6639 empty = isl_set_plain_is_empty(common); 6640 if (empty < 0 || empty) { 6641 isl_set_free(common); 6642 if (empty < 0) 6643 goto error; 6644 continue; 6645 } 6646 6647 res_ij = isl_multi_aff_set_aff( 6648 isl_multi_aff_copy(pma->p[i].maff), pos, 6649 isl_aff_copy(pa->p[j].aff)); 6650 res_ij = isl_multi_aff_gist(res_ij, 6651 isl_set_copy(common)); 6652 6653 res = isl_pw_multi_aff_add_piece(res, common, res_ij); 6654 } 6655 } 6656 6657 isl_pw_multi_aff_free(pma); 6658 isl_pw_aff_free(pa); 6659 return res; 6660error: 6661 isl_pw_multi_aff_free(pma); 6662 isl_pw_aff_free(pa); 6663 return isl_pw_multi_aff_free(res); 6664} 6665 6666/* Replace the affine expressions at position "pos" in "pma" by "pa". 6667 */ 6668__isl_give isl_pw_multi_aff *isl_pw_multi_aff_set_pw_aff( 6669 __isl_take isl_pw_multi_aff *pma, unsigned pos, 6670 __isl_take isl_pw_aff *pa) 6671{ 6672 isl_bool equal_params; 6673 6674 if (!pma || !pa) 6675 goto error; 6676 equal_params = isl_space_has_equal_params(pma->dim, pa->dim); 6677 if (equal_params < 0) 6678 goto error; 6679 if (equal_params) 6680 return pw_multi_aff_set_pw_aff(pma, pos, pa); 6681 if (isl_pw_multi_aff_check_named_params(pma) < 0 || 6682 isl_pw_aff_check_named_params(pa) < 0) 6683 goto error; 6684 pma = isl_pw_multi_aff_align_params(pma, isl_pw_aff_get_space(pa)); 6685 pa = isl_pw_aff_align_params(pa, isl_pw_multi_aff_get_space(pma)); 6686 return pw_multi_aff_set_pw_aff(pma, pos, pa); 6687error: 6688 isl_pw_multi_aff_free(pma); 6689 isl_pw_aff_free(pa); 6690 return NULL; 6691} 6692 6693/* Do the parameters of "pa" match those of "space"? 6694 */ 6695isl_bool isl_pw_aff_matching_params(__isl_keep isl_pw_aff *pa, 6696 __isl_keep isl_space *space) 6697{ 6698 isl_space *pa_space; 6699 isl_bool match; 6700 6701 if (!pa || !space) 6702 return isl_bool_error; 6703 6704 pa_space = isl_pw_aff_get_space(pa); 6705 6706 match = isl_space_has_equal_params(space, pa_space); 6707 6708 isl_space_free(pa_space); 6709 return match; 6710} 6711 6712/* Check that the domain space of "pa" matches "space". 6713 */ 6714isl_stat isl_pw_aff_check_match_domain_space(__isl_keep isl_pw_aff *pa, 6715 __isl_keep isl_space *space) 6716{ 6717 isl_space *pa_space; 6718 isl_bool match; 6719 6720 if (!pa || !space) 6721 return isl_stat_error; 6722 6723 pa_space = isl_pw_aff_get_space(pa); 6724 6725 match = isl_space_has_equal_params(space, pa_space); 6726 if (match < 0) 6727 goto error; 6728 if (!match) 6729 isl_die(isl_pw_aff_get_ctx(pa), isl_error_invalid, 6730 "parameters don't match", goto error); 6731 match = isl_space_tuple_is_equal(space, isl_dim_in, 6732 pa_space, isl_dim_in); 6733 if (match < 0) 6734 goto error; 6735 if (!match) 6736 isl_die(isl_pw_aff_get_ctx(pa), isl_error_invalid, 6737 "domains don't match", goto error); 6738 isl_space_free(pa_space); 6739 return isl_stat_ok; 6740error: 6741 isl_space_free(pa_space); 6742 return isl_stat_error; 6743} 6744 6745#undef BASE 6746#define BASE pw_aff 6747#undef DOMBASE 6748#define DOMBASE set 6749 6750#include <isl_multi_explicit_domain.c> 6751#include <isl_multi_pw_aff_explicit_domain.c> 6752#include <isl_multi_templ.c> 6753#include <isl_multi_un_op_templ.c> 6754#include <isl_multi_bin_val_templ.c> 6755#include <isl_multi_add_constant_templ.c> 6756#include <isl_multi_align_set.c> 6757#include <isl_multi_apply_set_explicit_domain_templ.c> 6758#include <isl_multi_arith_templ.c> 6759#include <isl_multi_bind_templ.c> 6760#include <isl_multi_bind_domain_templ.c> 6761#include <isl_multi_coalesce.c> 6762#include <isl_multi_domain_templ.c> 6763#include <isl_multi_domain_reverse_templ.c> 6764#include <isl_multi_dim_id_templ.c> 6765#include <isl_multi_dims.c> 6766#include <isl_multi_from_base_templ.c> 6767#include <isl_multi_check_domain_templ.c> 6768#include <isl_multi_gist.c> 6769#include <isl_multi_hash.c> 6770#include <isl_multi_identity_templ.c> 6771#include <isl_multi_insert_domain_templ.c> 6772#include <isl_multi_intersect.c> 6773#include <isl_multi_min_max_templ.c> 6774#include <isl_multi_move_dims_templ.c> 6775#include <isl_multi_nan_templ.c> 6776#include <isl_multi_param_templ.c> 6777#include <isl_multi_product_templ.c> 6778#include <isl_multi_splice_templ.c> 6779#include <isl_multi_tuple_id_templ.c> 6780#include <isl_multi_union_add_templ.c> 6781#include <isl_multi_zero_templ.c> 6782#include <isl_multi_unbind_params_templ.c> 6783 6784/* Is every element of "mpa" defined over a single universe domain? 6785 */ 6786isl_bool isl_multi_pw_aff_isa_multi_aff(__isl_keep isl_multi_pw_aff *mpa) 6787{ 6788 return isl_multi_pw_aff_every(mpa, &isl_pw_aff_isa_aff); 6789} 6790 6791/* Given that every element of "mpa" is defined over a single universe domain, 6792 * return the corresponding base expressions. 6793 */ 6794__isl_give isl_multi_aff *isl_multi_pw_aff_as_multi_aff( 6795 __isl_take isl_multi_pw_aff *mpa) 6796{ 6797 int i; 6798 isl_size n; 6799 isl_multi_aff *ma; 6800 6801 n = isl_multi_pw_aff_size(mpa); 6802 if (n < 0) 6803 mpa = isl_multi_pw_aff_free(mpa); 6804 ma = isl_multi_aff_alloc(isl_multi_pw_aff_get_space(mpa)); 6805 for (i = 0; i < n; ++i) { 6806 isl_aff *aff; 6807 6808 aff = isl_pw_aff_as_aff(isl_multi_pw_aff_get_at(mpa, i)); 6809 ma = isl_multi_aff_set_aff(ma, i, aff); 6810 } 6811 isl_multi_pw_aff_free(mpa); 6812 return ma; 6813} 6814 6815/* If "mpa" has an explicit domain, then intersect the domain of "map" 6816 * with this explicit domain. 6817 */ 6818__isl_give isl_map *isl_map_intersect_multi_pw_aff_explicit_domain( 6819 __isl_take isl_map *map, __isl_keep isl_multi_pw_aff *mpa) 6820{ 6821 isl_set *dom; 6822 6823 if (!isl_multi_pw_aff_has_explicit_domain(mpa)) 6824 return map; 6825 6826 dom = isl_multi_pw_aff_domain(isl_multi_pw_aff_copy(mpa)); 6827 map = isl_map_intersect_domain(map, dom); 6828 6829 return map; 6830} 6831 6832/* Are all elements of "mpa" piecewise constants? 6833 */ 6834isl_bool isl_multi_pw_aff_is_cst(__isl_keep isl_multi_pw_aff *mpa) 6835{ 6836 return isl_multi_pw_aff_every(mpa, &isl_pw_aff_is_cst); 6837} 6838 6839/* Does "mpa" have a non-trivial explicit domain? 6840 * 6841 * The explicit domain, if present, is trivial if it represents 6842 * an (obviously) universe set. 6843 */ 6844isl_bool isl_multi_pw_aff_has_non_trivial_domain( 6845 __isl_keep isl_multi_pw_aff *mpa) 6846{ 6847 if (!mpa) 6848 return isl_bool_error; 6849 if (!isl_multi_pw_aff_has_explicit_domain(mpa)) 6850 return isl_bool_false; 6851 return isl_bool_not(isl_set_plain_is_universe(mpa->u.dom)); 6852} 6853 6854#undef BASE 6855#define BASE set 6856 6857#include "isl_opt_mpa_templ.c" 6858 6859/* Compute the minima of the set dimensions as a function of the 6860 * parameters, but independently of the other set dimensions. 6861 */ 6862__isl_give isl_multi_pw_aff *isl_set_min_multi_pw_aff(__isl_take isl_set *set) 6863{ 6864 return set_opt_mpa(set, &isl_set_dim_min); 6865} 6866 6867/* Compute the maxima of the set dimensions as a function of the 6868 * parameters, but independently of the other set dimensions. 6869 */ 6870__isl_give isl_multi_pw_aff *isl_set_max_multi_pw_aff(__isl_take isl_set *set) 6871{ 6872 return set_opt_mpa(set, &isl_set_dim_max); 6873} 6874 6875#undef BASE 6876#define BASE map 6877 6878#include "isl_opt_mpa_templ.c" 6879 6880/* Compute the minima of the output dimensions as a function of the 6881 * parameters and input dimensions, but independently of 6882 * the other output dimensions. 6883 */ 6884__isl_give isl_multi_pw_aff *isl_map_min_multi_pw_aff(__isl_take isl_map *map) 6885{ 6886 return map_opt_mpa(map, &isl_map_dim_min); 6887} 6888 6889/* Compute the maxima of the output dimensions as a function of the 6890 * parameters and input dimensions, but independently of 6891 * the other output dimensions. 6892 */ 6893__isl_give isl_multi_pw_aff *isl_map_max_multi_pw_aff(__isl_take isl_map *map) 6894{ 6895 return map_opt_mpa(map, &isl_map_dim_max); 6896} 6897 6898#undef TYPE 6899#define TYPE isl_pw_multi_aff 6900#include "isl_type_check_match_range_multi_val.c" 6901 6902/* Apply "fn" to the base expressions of "pma" and "mv". 6903 */ 6904static __isl_give isl_pw_multi_aff *isl_pw_multi_aff_op_multi_val( 6905 __isl_take isl_pw_multi_aff *pma, __isl_take isl_multi_val *mv, 6906 __isl_give isl_multi_aff *(*fn)(__isl_take isl_multi_aff *ma, 6907 __isl_take isl_multi_val *mv)) 6908{ 6909 int i; 6910 isl_size n; 6911 6912 if (isl_pw_multi_aff_check_match_range_multi_val(pma, mv) < 0) 6913 goto error; 6914 6915 n = isl_pw_multi_aff_n_piece(pma); 6916 if (n < 0) 6917 goto error; 6918 6919 for (i = 0; i < n; ++i) { 6920 isl_multi_aff *ma; 6921 6922 ma = isl_pw_multi_aff_take_base_at(pma, i); 6923 ma = fn(ma, isl_multi_val_copy(mv)); 6924 pma = isl_pw_multi_aff_restore_base_at(pma, i, ma); 6925 } 6926 6927 isl_multi_val_free(mv); 6928 return pma; 6929error: 6930 isl_multi_val_free(mv); 6931 isl_pw_multi_aff_free(pma); 6932 return NULL; 6933} 6934 6935/* Scale the elements of "pma" by the corresponding elements of "mv". 6936 */ 6937__isl_give isl_pw_multi_aff *isl_pw_multi_aff_scale_multi_val( 6938 __isl_take isl_pw_multi_aff *pma, __isl_take isl_multi_val *mv) 6939{ 6940 return isl_pw_multi_aff_op_multi_val(pma, mv, 6941 &isl_multi_aff_scale_multi_val); 6942} 6943 6944/* Scale the elements of "pma" down by the corresponding elements of "mv". 6945 */ 6946__isl_give isl_pw_multi_aff *isl_pw_multi_aff_scale_down_multi_val( 6947 __isl_take isl_pw_multi_aff *pma, __isl_take isl_multi_val *mv) 6948{ 6949 return isl_pw_multi_aff_op_multi_val(pma, mv, 6950 &isl_multi_aff_scale_down_multi_val); 6951} 6952 6953/* This function is called for each entry of an isl_union_pw_multi_aff. 6954 * If the space of the entry matches that of data->mv, 6955 * then apply isl_pw_multi_aff_scale_multi_val and return the result. 6956 * Otherwise, return an empty isl_pw_multi_aff. 6957 */ 6958static __isl_give isl_pw_multi_aff *union_pw_multi_aff_scale_multi_val_entry( 6959 __isl_take isl_pw_multi_aff *pma, void *user) 6960{ 6961 isl_bool equal; 6962 isl_multi_val *mv = user; 6963 6964 equal = isl_pw_multi_aff_match_range_multi_val(pma, mv); 6965 if (equal < 0) 6966 return isl_pw_multi_aff_free(pma); 6967 if (!equal) { 6968 isl_space *space = isl_pw_multi_aff_get_space(pma); 6969 isl_pw_multi_aff_free(pma); 6970 return isl_pw_multi_aff_empty(space); 6971 } 6972 6973 return isl_pw_multi_aff_scale_multi_val(pma, isl_multi_val_copy(mv)); 6974} 6975 6976/* Scale the elements of "upma" by the corresponding elements of "mv", 6977 * for those entries that match the space of "mv". 6978 */ 6979__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_scale_multi_val( 6980 __isl_take isl_union_pw_multi_aff *upma, __isl_take isl_multi_val *mv) 6981{ 6982 struct isl_union_pw_multi_aff_transform_control control = { 6983 .fn = &union_pw_multi_aff_scale_multi_val_entry, 6984 .fn_user = mv, 6985 }; 6986 6987 upma = isl_union_pw_multi_aff_align_params(upma, 6988 isl_multi_val_get_space(mv)); 6989 mv = isl_multi_val_align_params(mv, 6990 isl_union_pw_multi_aff_get_space(upma)); 6991 if (!upma || !mv) 6992 goto error; 6993 6994 return isl_union_pw_multi_aff_transform(upma, &control); 6995 6996 isl_multi_val_free(mv); 6997 return upma; 6998error: 6999 isl_multi_val_free(mv); 7000 isl_union_pw_multi_aff_free(upma); 7001 return NULL; 7002} 7003 7004/* Construct and return a piecewise multi affine expression 7005 * in the given space with value zero in each of the output dimensions and 7006 * a universe domain. 7007 */ 7008__isl_give isl_pw_multi_aff *isl_pw_multi_aff_zero(__isl_take isl_space *space) 7009{ 7010 return isl_pw_multi_aff_from_multi_aff(isl_multi_aff_zero(space)); 7011} 7012 7013/* Construct and return a piecewise multi affine expression 7014 * that is equal to the given piecewise affine expression. 7015 */ 7016__isl_give isl_pw_multi_aff *isl_pw_multi_aff_from_pw_aff( 7017 __isl_take isl_pw_aff *pa) 7018{ 7019 int i; 7020 isl_space *space; 7021 isl_pw_multi_aff *pma; 7022 7023 if (!pa) 7024 return NULL; 7025 7026 space = isl_pw_aff_get_space(pa); 7027 pma = isl_pw_multi_aff_alloc_size(space, pa->n); 7028 7029 for (i = 0; i < pa->n; ++i) { 7030 isl_set *set; 7031 isl_multi_aff *ma; 7032 7033 set = isl_set_copy(pa->p[i].set); 7034 ma = isl_multi_aff_from_aff(isl_aff_copy(pa->p[i].aff)); 7035 pma = isl_pw_multi_aff_add_piece(pma, set, ma); 7036 } 7037 7038 isl_pw_aff_free(pa); 7039 return pma; 7040} 7041 7042/* Construct and return a piecewise multi affine expression 7043 * that is equal to the given multi piecewise affine expression 7044 * on the shared domain of the piecewise affine expressions, 7045 * in the special case of a 0D multi piecewise affine expression. 7046 * 7047 * Create a piecewise multi affine expression with the explicit domain of 7048 * the 0D multi piecewise affine expression as domain. 7049 */ 7050static __isl_give isl_pw_multi_aff *isl_pw_multi_aff_from_multi_pw_aff_0D( 7051 __isl_take isl_multi_pw_aff *mpa) 7052{ 7053 isl_space *space; 7054 isl_set *dom; 7055 isl_multi_aff *ma; 7056 7057 space = isl_multi_pw_aff_get_space(mpa); 7058 dom = isl_multi_pw_aff_get_explicit_domain(mpa); 7059 isl_multi_pw_aff_free(mpa); 7060 7061 ma = isl_multi_aff_zero(space); 7062 return isl_pw_multi_aff_alloc(dom, ma); 7063} 7064 7065/* Construct and return a piecewise multi affine expression 7066 * that is equal to the given multi piecewise affine expression 7067 * on the shared domain of the piecewise affine expressions. 7068 */ 7069__isl_give isl_pw_multi_aff *isl_pw_multi_aff_from_multi_pw_aff( 7070 __isl_take isl_multi_pw_aff *mpa) 7071{ 7072 int i; 7073 isl_space *space; 7074 isl_pw_aff *pa; 7075 isl_pw_multi_aff *pma; 7076 7077 if (!mpa) 7078 return NULL; 7079 7080 if (mpa->n == 0) 7081 return isl_pw_multi_aff_from_multi_pw_aff_0D(mpa); 7082 7083 space = isl_multi_pw_aff_get_space(mpa); 7084 pa = isl_multi_pw_aff_get_pw_aff(mpa, 0); 7085 pma = isl_pw_multi_aff_from_pw_aff(pa); 7086 7087 for (i = 1; i < mpa->n; ++i) { 7088 isl_pw_multi_aff *pma_i; 7089 7090 pa = isl_multi_pw_aff_get_pw_aff(mpa, i); 7091 pma_i = isl_pw_multi_aff_from_pw_aff(pa); 7092 pma = isl_pw_multi_aff_range_product(pma, pma_i); 7093 } 7094 7095 pma = isl_pw_multi_aff_reset_space(pma, space); 7096 7097 isl_multi_pw_aff_free(mpa); 7098 return pma; 7099} 7100 7101/* Convenience function that constructs an isl_multi_pw_aff 7102 * directly from an isl_aff. 7103 */ 7104__isl_give isl_multi_pw_aff *isl_multi_pw_aff_from_aff(__isl_take isl_aff *aff) 7105{ 7106 return isl_multi_pw_aff_from_pw_aff(isl_pw_aff_from_aff(aff)); 7107} 7108 7109/* Construct and return a multi piecewise affine expression 7110 * that is equal to the given multi affine expression. 7111 */ 7112__isl_give isl_multi_pw_aff *isl_multi_pw_aff_from_multi_aff( 7113 __isl_take isl_multi_aff *ma) 7114{ 7115 int i; 7116 isl_size n; 7117 isl_multi_pw_aff *mpa; 7118 7119 n = isl_multi_aff_dim(ma, isl_dim_out); 7120 if (n < 0) 7121 ma = isl_multi_aff_free(ma); 7122 if (!ma) 7123 return NULL; 7124 7125 mpa = isl_multi_pw_aff_alloc(isl_multi_aff_get_space(ma)); 7126 7127 for (i = 0; i < n; ++i) { 7128 isl_pw_aff *pa; 7129 7130 pa = isl_pw_aff_from_aff(isl_multi_aff_get_aff(ma, i)); 7131 mpa = isl_multi_pw_aff_set_pw_aff(mpa, i, pa); 7132 } 7133 7134 isl_multi_aff_free(ma); 7135 return mpa; 7136} 7137 7138/* This function performs the same operation as isl_multi_pw_aff_from_multi_aff, 7139 * but is considered as a function on an isl_multi_aff when exported. 7140 */ 7141__isl_give isl_multi_pw_aff *isl_multi_aff_to_multi_pw_aff( 7142 __isl_take isl_multi_aff *ma) 7143{ 7144 return isl_multi_pw_aff_from_multi_aff(ma); 7145} 7146 7147/* Construct and return a multi piecewise affine expression 7148 * that is equal to the given piecewise multi affine expression. 7149 * 7150 * If the resulting multi piecewise affine expression has 7151 * an explicit domain, then assign it the domain of the input. 7152 * In other cases, the domain is stored in the individual elements. 7153 */ 7154__isl_give isl_multi_pw_aff *isl_multi_pw_aff_from_pw_multi_aff( 7155 __isl_take isl_pw_multi_aff *pma) 7156{ 7157 int i; 7158 isl_size n; 7159 isl_space *space; 7160 isl_multi_pw_aff *mpa; 7161 7162 n = isl_pw_multi_aff_dim(pma, isl_dim_out); 7163 if (n < 0) 7164 pma = isl_pw_multi_aff_free(pma); 7165 space = isl_pw_multi_aff_get_space(pma); 7166 mpa = isl_multi_pw_aff_alloc(space); 7167 7168 for (i = 0; i < n; ++i) { 7169 isl_pw_aff *pa; 7170 7171 pa = isl_pw_multi_aff_get_pw_aff(pma, i); 7172 mpa = isl_multi_pw_aff_set_pw_aff(mpa, i, pa); 7173 } 7174 if (isl_multi_pw_aff_has_explicit_domain(mpa)) { 7175 isl_set *dom; 7176 7177 dom = isl_pw_multi_aff_domain(isl_pw_multi_aff_copy(pma)); 7178 mpa = isl_multi_pw_aff_intersect_domain(mpa, dom); 7179 } 7180 7181 isl_pw_multi_aff_free(pma); 7182 return mpa; 7183} 7184 7185/* This function performs the same operation as 7186 * isl_multi_pw_aff_from_pw_multi_aff, 7187 * but is considered as a function on an isl_pw_multi_aff when exported. 7188 */ 7189__isl_give isl_multi_pw_aff *isl_pw_multi_aff_to_multi_pw_aff( 7190 __isl_take isl_pw_multi_aff *pma) 7191{ 7192 return isl_multi_pw_aff_from_pw_multi_aff(pma); 7193} 7194 7195/* Do "pa1" and "pa2" represent the same function? 7196 * 7197 * We first check if they are obviously equal. 7198 * If not, we convert them to maps and check if those are equal. 7199 * 7200 * If "pa1" or "pa2" contain any NaNs, then they are considered 7201 * not to be the same. A NaN is not equal to anything, not even 7202 * to another NaN. 7203 */ 7204isl_bool isl_pw_aff_is_equal(__isl_keep isl_pw_aff *pa1, 7205 __isl_keep isl_pw_aff *pa2) 7206{ 7207 isl_bool equal; 7208 isl_bool has_nan; 7209 isl_map *map1, *map2; 7210 7211 if (!pa1 || !pa2) 7212 return isl_bool_error; 7213 7214 equal = isl_pw_aff_plain_is_equal(pa1, pa2); 7215 if (equal < 0 || equal) 7216 return equal; 7217 has_nan = either_involves_nan(pa1, pa2); 7218 if (has_nan < 0) 7219 return isl_bool_error; 7220 if (has_nan) 7221 return isl_bool_false; 7222 7223 map1 = isl_map_from_pw_aff_internal(isl_pw_aff_copy(pa1)); 7224 map2 = isl_map_from_pw_aff_internal(isl_pw_aff_copy(pa2)); 7225 equal = isl_map_is_equal(map1, map2); 7226 isl_map_free(map1); 7227 isl_map_free(map2); 7228 7229 return equal; 7230} 7231 7232/* Do "mpa1" and "mpa2" represent the same function? 7233 * 7234 * Note that we cannot convert the entire isl_multi_pw_aff 7235 * to a map because the domains of the piecewise affine expressions 7236 * may not be the same. 7237 */ 7238isl_bool isl_multi_pw_aff_is_equal(__isl_keep isl_multi_pw_aff *mpa1, 7239 __isl_keep isl_multi_pw_aff *mpa2) 7240{ 7241 int i; 7242 isl_bool equal, equal_params; 7243 7244 if (!mpa1 || !mpa2) 7245 return isl_bool_error; 7246 7247 equal_params = isl_space_has_equal_params(mpa1->space, mpa2->space); 7248 if (equal_params < 0) 7249 return isl_bool_error; 7250 if (!equal_params) { 7251 if (!isl_space_has_named_params(mpa1->space)) 7252 return isl_bool_false; 7253 if (!isl_space_has_named_params(mpa2->space)) 7254 return isl_bool_false; 7255 mpa1 = isl_multi_pw_aff_copy(mpa1); 7256 mpa2 = isl_multi_pw_aff_copy(mpa2); 7257 mpa1 = isl_multi_pw_aff_align_params(mpa1, 7258 isl_multi_pw_aff_get_space(mpa2)); 7259 mpa2 = isl_multi_pw_aff_align_params(mpa2, 7260 isl_multi_pw_aff_get_space(mpa1)); 7261 equal = isl_multi_pw_aff_is_equal(mpa1, mpa2); 7262 isl_multi_pw_aff_free(mpa1); 7263 isl_multi_pw_aff_free(mpa2); 7264 return equal; 7265 } 7266 7267 equal = isl_space_is_equal(mpa1->space, mpa2->space); 7268 if (equal < 0 || !equal) 7269 return equal; 7270 7271 for (i = 0; i < mpa1->n; ++i) { 7272 equal = isl_pw_aff_is_equal(mpa1->u.p[i], mpa2->u.p[i]); 7273 if (equal < 0 || !equal) 7274 return equal; 7275 } 7276 7277 return isl_bool_true; 7278} 7279 7280/* Do "pma1" and "pma2" represent the same function? 7281 * 7282 * First check if they are obviously equal. 7283 * If not, then convert them to maps and check if those are equal. 7284 * 7285 * If "pa1" or "pa2" contain any NaNs, then they are considered 7286 * not to be the same. A NaN is not equal to anything, not even 7287 * to another NaN. 7288 */ 7289isl_bool isl_pw_multi_aff_is_equal(__isl_keep isl_pw_multi_aff *pma1, 7290 __isl_keep isl_pw_multi_aff *pma2) 7291{ 7292 isl_bool equal; 7293 isl_bool has_nan; 7294 isl_map *map1, *map2; 7295 7296 if (!pma1 || !pma2) 7297 return isl_bool_error; 7298 7299 equal = isl_pw_multi_aff_plain_is_equal(pma1, pma2); 7300 if (equal < 0 || equal) 7301 return equal; 7302 has_nan = isl_pw_multi_aff_involves_nan(pma1); 7303 if (has_nan >= 0 && !has_nan) 7304 has_nan = isl_pw_multi_aff_involves_nan(pma2); 7305 if (has_nan < 0 || has_nan) 7306 return isl_bool_not(has_nan); 7307 7308 map1 = isl_map_from_pw_multi_aff_internal(isl_pw_multi_aff_copy(pma1)); 7309 map2 = isl_map_from_pw_multi_aff_internal(isl_pw_multi_aff_copy(pma2)); 7310 equal = isl_map_is_equal(map1, map2); 7311 isl_map_free(map1); 7312 isl_map_free(map2); 7313 7314 return equal; 7315} 7316 7317#undef BASE 7318#define BASE multi_aff 7319 7320#include "isl_multi_pw_aff_pullback_templ.c" 7321 7322#undef BASE 7323#define BASE pw_multi_aff 7324 7325#include "isl_multi_pw_aff_pullback_templ.c" 7326 7327/* Apply "aff" to "mpa". The range of "mpa" needs to be compatible 7328 * with the domain of "aff". The domain of the result is the same 7329 * as that of "mpa". 7330 * "mpa" and "aff" are assumed to have been aligned. 7331 * 7332 * We first extract the parametric constant from "aff", defined 7333 * over the correct domain. 7334 * Then we add the appropriate combinations of the members of "mpa". 7335 * Finally, we add the integer divisions through recursive calls. 7336 */ 7337static __isl_give isl_pw_aff *isl_multi_pw_aff_apply_aff_aligned( 7338 __isl_take isl_multi_pw_aff *mpa, __isl_take isl_aff *aff) 7339{ 7340 int i; 7341 isl_size n_in, n_div, n_mpa_in; 7342 isl_space *space; 7343 isl_val *v; 7344 isl_pw_aff *pa; 7345 isl_aff *tmp; 7346 7347 n_in = isl_aff_dim(aff, isl_dim_in); 7348 n_div = isl_aff_dim(aff, isl_dim_div); 7349 n_mpa_in = isl_multi_pw_aff_dim(mpa, isl_dim_in); 7350 if (n_in < 0 || n_div < 0 || n_mpa_in < 0) 7351 goto error; 7352 7353 space = isl_space_domain(isl_multi_pw_aff_get_space(mpa)); 7354 tmp = isl_aff_copy(aff); 7355 tmp = isl_aff_drop_dims(tmp, isl_dim_div, 0, n_div); 7356 tmp = isl_aff_drop_dims(tmp, isl_dim_in, 0, n_in); 7357 tmp = isl_aff_add_dims(tmp, isl_dim_in, n_mpa_in); 7358 tmp = isl_aff_reset_domain_space(tmp, space); 7359 pa = isl_pw_aff_from_aff(tmp); 7360 7361 for (i = 0; i < n_in; ++i) { 7362 isl_pw_aff *pa_i; 7363 7364 if (!isl_aff_involves_dims(aff, isl_dim_in, i, 1)) 7365 continue; 7366 v = isl_aff_get_coefficient_val(aff, isl_dim_in, i); 7367 pa_i = isl_multi_pw_aff_get_pw_aff(mpa, i); 7368 pa_i = isl_pw_aff_scale_val(pa_i, v); 7369 pa = isl_pw_aff_add(pa, pa_i); 7370 } 7371 7372 for (i = 0; i < n_div; ++i) { 7373 isl_aff *div; 7374 isl_pw_aff *pa_i; 7375 7376 if (!isl_aff_involves_dims(aff, isl_dim_div, i, 1)) 7377 continue; 7378 div = isl_aff_get_div(aff, i); 7379 pa_i = isl_multi_pw_aff_apply_aff_aligned( 7380 isl_multi_pw_aff_copy(mpa), div); 7381 pa_i = isl_pw_aff_floor(pa_i); 7382 v = isl_aff_get_coefficient_val(aff, isl_dim_div, i); 7383 pa_i = isl_pw_aff_scale_val(pa_i, v); 7384 pa = isl_pw_aff_add(pa, pa_i); 7385 } 7386 7387 isl_multi_pw_aff_free(mpa); 7388 isl_aff_free(aff); 7389 7390 return pa; 7391error: 7392 isl_multi_pw_aff_free(mpa); 7393 isl_aff_free(aff); 7394 return NULL; 7395} 7396 7397/* Apply "aff" to "mpa". The range of "mpa" needs to be compatible 7398 * with the domain of "aff". The domain of the result is the same 7399 * as that of "mpa". 7400 */ 7401__isl_give isl_pw_aff *isl_multi_pw_aff_apply_aff( 7402 __isl_take isl_multi_pw_aff *mpa, __isl_take isl_aff *aff) 7403{ 7404 isl_bool equal_params; 7405 7406 if (!aff || !mpa) 7407 goto error; 7408 equal_params = isl_space_has_equal_params(aff->ls->dim, mpa->space); 7409 if (equal_params < 0) 7410 goto error; 7411 if (equal_params) 7412 return isl_multi_pw_aff_apply_aff_aligned(mpa, aff); 7413 7414 aff = isl_aff_align_params(aff, isl_multi_pw_aff_get_space(mpa)); 7415 mpa = isl_multi_pw_aff_align_params(mpa, isl_aff_get_space(aff)); 7416 7417 return isl_multi_pw_aff_apply_aff_aligned(mpa, aff); 7418error: 7419 isl_aff_free(aff); 7420 isl_multi_pw_aff_free(mpa); 7421 return NULL; 7422} 7423 7424/* Apply "pa" to "mpa". The range of "mpa" needs to be compatible 7425 * with the domain of "pa". The domain of the result is the same 7426 * as that of "mpa". 7427 * "mpa" and "pa" are assumed to have been aligned. 7428 * 7429 * We consider each piece in turn. Note that the domains of the 7430 * pieces are assumed to be disjoint and they remain disjoint 7431 * after taking the preimage (over the same function). 7432 */ 7433static __isl_give isl_pw_aff *isl_multi_pw_aff_apply_pw_aff_aligned( 7434 __isl_take isl_multi_pw_aff *mpa, __isl_take isl_pw_aff *pa) 7435{ 7436 isl_space *space; 7437 isl_pw_aff *res; 7438 int i; 7439 7440 if (!mpa || !pa) 7441 goto error; 7442 7443 space = isl_space_join(isl_multi_pw_aff_get_space(mpa), 7444 isl_pw_aff_get_space(pa)); 7445 res = isl_pw_aff_empty(space); 7446 7447 for (i = 0; i < pa->n; ++i) { 7448 isl_pw_aff *pa_i; 7449 isl_set *domain; 7450 7451 pa_i = isl_multi_pw_aff_apply_aff_aligned( 7452 isl_multi_pw_aff_copy(mpa), 7453 isl_aff_copy(pa->p[i].aff)); 7454 domain = isl_set_copy(pa->p[i].set); 7455 domain = isl_set_preimage_multi_pw_aff(domain, 7456 isl_multi_pw_aff_copy(mpa)); 7457 pa_i = isl_pw_aff_intersect_domain(pa_i, domain); 7458 res = isl_pw_aff_add_disjoint(res, pa_i); 7459 } 7460 7461 isl_pw_aff_free(pa); 7462 isl_multi_pw_aff_free(mpa); 7463 return res; 7464error: 7465 isl_pw_aff_free(pa); 7466 isl_multi_pw_aff_free(mpa); 7467 return NULL; 7468} 7469 7470/* Apply "pa" to "mpa". The range of "mpa" needs to be compatible 7471 * with the domain of "pa". The domain of the result is the same 7472 * as that of "mpa". 7473 */ 7474__isl_give isl_pw_aff *isl_multi_pw_aff_apply_pw_aff( 7475 __isl_take isl_multi_pw_aff *mpa, __isl_take isl_pw_aff *pa) 7476{ 7477 isl_bool equal_params; 7478 7479 if (!pa || !mpa) 7480 goto error; 7481 equal_params = isl_space_has_equal_params(pa->dim, mpa->space); 7482 if (equal_params < 0) 7483 goto error; 7484 if (equal_params) 7485 return isl_multi_pw_aff_apply_pw_aff_aligned(mpa, pa); 7486 7487 pa = isl_pw_aff_align_params(pa, isl_multi_pw_aff_get_space(mpa)); 7488 mpa = isl_multi_pw_aff_align_params(mpa, isl_pw_aff_get_space(pa)); 7489 7490 return isl_multi_pw_aff_apply_pw_aff_aligned(mpa, pa); 7491error: 7492 isl_pw_aff_free(pa); 7493 isl_multi_pw_aff_free(mpa); 7494 return NULL; 7495} 7496 7497/* Compute the pullback of "pa" by the function represented by "mpa". 7498 * In other words, plug in "mpa" in "pa". 7499 * 7500 * The pullback is computed by applying "pa" to "mpa". 7501 */ 7502__isl_give isl_pw_aff *isl_pw_aff_pullback_multi_pw_aff( 7503 __isl_take isl_pw_aff *pa, __isl_take isl_multi_pw_aff *mpa) 7504{ 7505 return isl_multi_pw_aff_apply_pw_aff(mpa, pa); 7506} 7507 7508#undef BASE 7509#define BASE multi_pw_aff 7510 7511#include "isl_multi_pw_aff_pullback_templ.c" 7512 7513/* Align the parameters of "mpa1" and "mpa2", check that the ranges 7514 * of "mpa1" and "mpa2" live in the same space, construct map space 7515 * between the domain spaces of "mpa1" and "mpa2" and call "order" 7516 * with this map space as extract argument. 7517 */ 7518static __isl_give isl_map *isl_multi_pw_aff_order_map( 7519 __isl_take isl_multi_pw_aff *mpa1, __isl_take isl_multi_pw_aff *mpa2, 7520 __isl_give isl_map *(*order)(__isl_keep isl_multi_pw_aff *mpa1, 7521 __isl_keep isl_multi_pw_aff *mpa2, __isl_take isl_space *space)) 7522{ 7523 int match; 7524 isl_space *space1, *space2; 7525 isl_map *res; 7526 7527 mpa1 = isl_multi_pw_aff_align_params(mpa1, 7528 isl_multi_pw_aff_get_space(mpa2)); 7529 mpa2 = isl_multi_pw_aff_align_params(mpa2, 7530 isl_multi_pw_aff_get_space(mpa1)); 7531 if (!mpa1 || !mpa2) 7532 goto error; 7533 match = isl_space_tuple_is_equal(mpa1->space, isl_dim_out, 7534 mpa2->space, isl_dim_out); 7535 if (match < 0) 7536 goto error; 7537 if (!match) 7538 isl_die(isl_multi_pw_aff_get_ctx(mpa1), isl_error_invalid, 7539 "range spaces don't match", goto error); 7540 space1 = isl_space_domain(isl_multi_pw_aff_get_space(mpa1)); 7541 space2 = isl_space_domain(isl_multi_pw_aff_get_space(mpa2)); 7542 space1 = isl_space_map_from_domain_and_range(space1, space2); 7543 7544 res = order(mpa1, mpa2, space1); 7545 isl_multi_pw_aff_free(mpa1); 7546 isl_multi_pw_aff_free(mpa2); 7547 return res; 7548error: 7549 isl_multi_pw_aff_free(mpa1); 7550 isl_multi_pw_aff_free(mpa2); 7551 return NULL; 7552} 7553 7554/* Return a map containing pairs of elements in the domains of "mpa1" and "mpa2" 7555 * where the function values are equal. "space" is the space of the result. 7556 * The parameters of "mpa1" and "mpa2" are assumed to have been aligned. 7557 * 7558 * "mpa1" and "mpa2" are equal when each of the pairs of elements 7559 * in the sequences are equal. 7560 */ 7561static __isl_give isl_map *isl_multi_pw_aff_eq_map_on_space( 7562 __isl_keep isl_multi_pw_aff *mpa1, __isl_keep isl_multi_pw_aff *mpa2, 7563 __isl_take isl_space *space) 7564{ 7565 int i; 7566 isl_size n; 7567 isl_map *res; 7568 7569 n = isl_multi_pw_aff_dim(mpa1, isl_dim_out); 7570 if (n < 0) 7571 space = isl_space_free(space); 7572 res = isl_map_universe(space); 7573 7574 for (i = 0; i < n; ++i) { 7575 isl_pw_aff *pa1, *pa2; 7576 isl_map *map; 7577 7578 pa1 = isl_multi_pw_aff_get_pw_aff(mpa1, i); 7579 pa2 = isl_multi_pw_aff_get_pw_aff(mpa2, i); 7580 map = isl_pw_aff_eq_map(pa1, pa2); 7581 res = isl_map_intersect(res, map); 7582 } 7583 7584 return res; 7585} 7586 7587/* Return a map containing pairs of elements in the domains of "mpa1" and "mpa2" 7588 * where the function values are equal. 7589 */ 7590__isl_give isl_map *isl_multi_pw_aff_eq_map(__isl_take isl_multi_pw_aff *mpa1, 7591 __isl_take isl_multi_pw_aff *mpa2) 7592{ 7593 return isl_multi_pw_aff_order_map(mpa1, mpa2, 7594 &isl_multi_pw_aff_eq_map_on_space); 7595} 7596 7597/* Intersect "map" with the result of applying "order" 7598 * on two copies of "mpa". 7599 */ 7600static __isl_give isl_map *isl_map_order_at_multi_pw_aff( 7601 __isl_take isl_map *map, __isl_take isl_multi_pw_aff *mpa, 7602 __isl_give isl_map *(*order)(__isl_take isl_multi_pw_aff *mpa1, 7603 __isl_take isl_multi_pw_aff *mpa2)) 7604{ 7605 return isl_map_intersect(map, order(mpa, isl_multi_pw_aff_copy(mpa))); 7606} 7607 7608/* Return the subset of "map" where the domain and the range 7609 * have equal "mpa" values. 7610 */ 7611__isl_give isl_map *isl_map_eq_at_multi_pw_aff(__isl_take isl_map *map, 7612 __isl_take isl_multi_pw_aff *mpa) 7613{ 7614 return isl_map_order_at_multi_pw_aff(map, mpa, 7615 &isl_multi_pw_aff_eq_map); 7616} 7617 7618/* Return a map containing pairs of elements in the domains of "mpa1" and "mpa2" 7619 * where the function values of "mpa1" lexicographically satisfies 7620 * "strict_base"/"base" compared to that of "mpa2". 7621 * "space" is the space of the result. 7622 * The parameters of "mpa1" and "mpa2" are assumed to have been aligned. 7623 * 7624 * "mpa1" lexicographically satisfies "strict_base"/"base" compared to "mpa2" 7625 * if, for some i, the i-th element of "mpa1" satisfies "strict_base"/"base" 7626 * when compared to the i-th element of "mpa2" while all previous elements are 7627 * pairwise equal. 7628 * In particular, if i corresponds to the final elements 7629 * then they need to satisfy "base", while "strict_base" needs to be satisfied 7630 * for other values of i. 7631 * If "base" is a strict order, then "base" and "strict_base" are the same. 7632 */ 7633static __isl_give isl_map *isl_multi_pw_aff_lex_map_on_space( 7634 __isl_keep isl_multi_pw_aff *mpa1, __isl_keep isl_multi_pw_aff *mpa2, 7635 __isl_give isl_map *(*strict_base)(__isl_take isl_pw_aff *pa1, 7636 __isl_take isl_pw_aff *pa2), 7637 __isl_give isl_map *(*base)(__isl_take isl_pw_aff *pa1, 7638 __isl_take isl_pw_aff *pa2), 7639 __isl_take isl_space *space) 7640{ 7641 int i; 7642 isl_size n; 7643 isl_map *res, *rest; 7644 7645 n = isl_multi_pw_aff_dim(mpa1, isl_dim_out); 7646 if (n < 0) 7647 space = isl_space_free(space); 7648 res = isl_map_empty(isl_space_copy(space)); 7649 rest = isl_map_universe(space); 7650 7651 for (i = 0; i < n; ++i) { 7652 int last; 7653 isl_pw_aff *pa1, *pa2; 7654 isl_map *map; 7655 7656 last = i == n - 1; 7657 7658 pa1 = isl_multi_pw_aff_get_pw_aff(mpa1, i); 7659 pa2 = isl_multi_pw_aff_get_pw_aff(mpa2, i); 7660 map = last ? base(pa1, pa2) : strict_base(pa1, pa2); 7661 map = isl_map_intersect(map, isl_map_copy(rest)); 7662 res = isl_map_union(res, map); 7663 7664 if (last) 7665 continue; 7666 7667 pa1 = isl_multi_pw_aff_get_pw_aff(mpa1, i); 7668 pa2 = isl_multi_pw_aff_get_pw_aff(mpa2, i); 7669 map = isl_pw_aff_eq_map(pa1, pa2); 7670 rest = isl_map_intersect(rest, map); 7671 } 7672 7673 isl_map_free(rest); 7674 return res; 7675} 7676 7677#undef ORDER 7678#define ORDER le 7679#undef STRICT_ORDER 7680#define STRICT_ORDER lt 7681#include "isl_aff_lex_templ.c" 7682 7683#undef ORDER 7684#define ORDER lt 7685#undef STRICT_ORDER 7686#define STRICT_ORDER lt 7687#include "isl_aff_lex_templ.c" 7688 7689#undef ORDER 7690#define ORDER ge 7691#undef STRICT_ORDER 7692#define STRICT_ORDER gt 7693#include "isl_aff_lex_templ.c" 7694 7695#undef ORDER 7696#define ORDER gt 7697#undef STRICT_ORDER 7698#define STRICT_ORDER gt 7699#include "isl_aff_lex_templ.c" 7700 7701/* Compare two isl_affs. 7702 * 7703 * Return -1 if "aff1" is "smaller" than "aff2", 1 if "aff1" is "greater" 7704 * than "aff2" and 0 if they are equal. 7705 * 7706 * The order is fairly arbitrary. We do consider expressions that only involve 7707 * earlier dimensions as "smaller". 7708 */ 7709int isl_aff_plain_cmp(__isl_keep isl_aff *aff1, __isl_keep isl_aff *aff2) 7710{ 7711 int cmp; 7712 int last1, last2; 7713 7714 if (aff1 == aff2) 7715 return 0; 7716 7717 if (!aff1) 7718 return -1; 7719 if (!aff2) 7720 return 1; 7721 7722 cmp = isl_local_space_cmp(aff1->ls, aff2->ls); 7723 if (cmp != 0) 7724 return cmp; 7725 7726 last1 = isl_seq_last_non_zero(aff1->v->el + 1, aff1->v->size - 1); 7727 last2 = isl_seq_last_non_zero(aff2->v->el + 1, aff1->v->size - 1); 7728 if (last1 != last2) 7729 return last1 - last2; 7730 7731 return isl_seq_cmp(aff1->v->el, aff2->v->el, aff1->v->size); 7732} 7733 7734/* Compare two isl_pw_affs. 7735 * 7736 * Return -1 if "pa1" is "smaller" than "pa2", 1 if "pa1" is "greater" 7737 * than "pa2" and 0 if they are equal. 7738 * 7739 * The order is fairly arbitrary. We do consider expressions that only involve 7740 * earlier dimensions as "smaller". 7741 */ 7742int isl_pw_aff_plain_cmp(__isl_keep isl_pw_aff *pa1, 7743 __isl_keep isl_pw_aff *pa2) 7744{ 7745 int i; 7746 int cmp; 7747 7748 if (pa1 == pa2) 7749 return 0; 7750 7751 if (!pa1) 7752 return -1; 7753 if (!pa2) 7754 return 1; 7755 7756 cmp = isl_space_cmp(pa1->dim, pa2->dim); 7757 if (cmp != 0) 7758 return cmp; 7759 7760 if (pa1->n != pa2->n) 7761 return pa1->n - pa2->n; 7762 7763 for (i = 0; i < pa1->n; ++i) { 7764 cmp = isl_set_plain_cmp(pa1->p[i].set, pa2->p[i].set); 7765 if (cmp != 0) 7766 return cmp; 7767 cmp = isl_aff_plain_cmp(pa1->p[i].aff, pa2->p[i].aff); 7768 if (cmp != 0) 7769 return cmp; 7770 } 7771 7772 return 0; 7773} 7774 7775/* Return a piecewise affine expression that is equal to "v" on "domain". 7776 */ 7777__isl_give isl_pw_aff *isl_pw_aff_val_on_domain(__isl_take isl_set *domain, 7778 __isl_take isl_val *v) 7779{ 7780 isl_space *space; 7781 isl_local_space *ls; 7782 isl_aff *aff; 7783 7784 space = isl_set_get_space(domain); 7785 ls = isl_local_space_from_space(space); 7786 aff = isl_aff_val_on_domain(ls, v); 7787 7788 return isl_pw_aff_alloc(domain, aff); 7789} 7790 7791/* This function performs the same operation as isl_pw_aff_val_on_domain, 7792 * but is considered as a function on an isl_set when exported. 7793 */ 7794__isl_give isl_pw_aff *isl_set_pw_aff_on_domain_val(__isl_take isl_set *domain, 7795 __isl_take isl_val *v) 7796{ 7797 return isl_pw_aff_val_on_domain(domain, v); 7798} 7799 7800/* Return a piecewise affine expression that is equal to the parameter 7801 * with identifier "id" on "domain". 7802 */ 7803__isl_give isl_pw_aff *isl_pw_aff_param_on_domain_id( 7804 __isl_take isl_set *domain, __isl_take isl_id *id) 7805{ 7806 isl_space *space; 7807 isl_aff *aff; 7808 7809 space = isl_set_get_space(domain); 7810 space = isl_space_add_param_id(space, isl_id_copy(id)); 7811 domain = isl_set_align_params(domain, isl_space_copy(space)); 7812 aff = isl_aff_param_on_domain_space_id(space, id); 7813 7814 return isl_pw_aff_alloc(domain, aff); 7815} 7816 7817/* This function performs the same operation as 7818 * isl_pw_aff_param_on_domain_id, 7819 * but is considered as a function on an isl_set when exported. 7820 */ 7821__isl_give isl_pw_aff *isl_set_param_pw_aff_on_domain_id( 7822 __isl_take isl_set *domain, __isl_take isl_id *id) 7823{ 7824 return isl_pw_aff_param_on_domain_id(domain, id); 7825} 7826 7827/* Return a multi affine expression that is equal to "mv" on domain 7828 * space "space". 7829 */ 7830__isl_give isl_multi_aff *isl_multi_aff_multi_val_on_domain_space( 7831 __isl_take isl_space *space, __isl_take isl_multi_val *mv) 7832{ 7833 int i; 7834 isl_size n; 7835 isl_space *space2; 7836 isl_local_space *ls; 7837 isl_multi_aff *ma; 7838 7839 n = isl_multi_val_dim(mv, isl_dim_set); 7840 if (!space || n < 0) 7841 goto error; 7842 7843 space2 = isl_multi_val_get_space(mv); 7844 space2 = isl_space_align_params(space2, isl_space_copy(space)); 7845 space = isl_space_align_params(space, isl_space_copy(space2)); 7846 space = isl_space_map_from_domain_and_range(space, space2); 7847 ma = isl_multi_aff_alloc(isl_space_copy(space)); 7848 ls = isl_local_space_from_space(isl_space_domain(space)); 7849 for (i = 0; i < n; ++i) { 7850 isl_val *v; 7851 isl_aff *aff; 7852 7853 v = isl_multi_val_get_val(mv, i); 7854 aff = isl_aff_val_on_domain(isl_local_space_copy(ls), v); 7855 ma = isl_multi_aff_set_aff(ma, i, aff); 7856 } 7857 isl_local_space_free(ls); 7858 7859 isl_multi_val_free(mv); 7860 return ma; 7861error: 7862 isl_space_free(space); 7863 isl_multi_val_free(mv); 7864 return NULL; 7865} 7866 7867/* This is an alternative name for the function above. 7868 */ 7869__isl_give isl_multi_aff *isl_multi_aff_multi_val_on_space( 7870 __isl_take isl_space *space, __isl_take isl_multi_val *mv) 7871{ 7872 return isl_multi_aff_multi_val_on_domain_space(space, mv); 7873} 7874 7875/* This function performs the same operation as 7876 * isl_multi_aff_multi_val_on_domain_space, 7877 * but is considered as a function on an isl_space when exported. 7878 */ 7879__isl_give isl_multi_aff *isl_space_multi_aff_on_domain_multi_val( 7880 __isl_take isl_space *space, __isl_take isl_multi_val *mv) 7881{ 7882 return isl_multi_aff_multi_val_on_domain_space(space, mv); 7883} 7884 7885/* Return a piecewise multi-affine expression 7886 * that is equal to "mv" on "domain". 7887 */ 7888__isl_give isl_pw_multi_aff *isl_pw_multi_aff_multi_val_on_domain( 7889 __isl_take isl_set *domain, __isl_take isl_multi_val *mv) 7890{ 7891 isl_space *space; 7892 isl_multi_aff *ma; 7893 7894 space = isl_set_get_space(domain); 7895 ma = isl_multi_aff_multi_val_on_space(space, mv); 7896 7897 return isl_pw_multi_aff_alloc(domain, ma); 7898} 7899 7900/* This function performs the same operation as 7901 * isl_pw_multi_aff_multi_val_on_domain, 7902 * but is considered as a function on an isl_set when exported. 7903 */ 7904__isl_give isl_pw_multi_aff *isl_set_pw_multi_aff_on_domain_multi_val( 7905 __isl_take isl_set *domain, __isl_take isl_multi_val *mv) 7906{ 7907 return isl_pw_multi_aff_multi_val_on_domain(domain, mv); 7908} 7909 7910/* Internal data structure for isl_union_pw_multi_aff_multi_val_on_domain. 7911 * mv is the value that should be attained on each domain set 7912 * res collects the results 7913 */ 7914struct isl_union_pw_multi_aff_multi_val_on_domain_data { 7915 isl_multi_val *mv; 7916 isl_union_pw_multi_aff *res; 7917}; 7918 7919/* Create an isl_pw_multi_aff equal to data->mv on "domain" 7920 * and add it to data->res. 7921 */ 7922static isl_stat pw_multi_aff_multi_val_on_domain(__isl_take isl_set *domain, 7923 void *user) 7924{ 7925 struct isl_union_pw_multi_aff_multi_val_on_domain_data *data = user; 7926 isl_pw_multi_aff *pma; 7927 isl_multi_val *mv; 7928 7929 mv = isl_multi_val_copy(data->mv); 7930 pma = isl_pw_multi_aff_multi_val_on_domain(domain, mv); 7931 data->res = isl_union_pw_multi_aff_add_pw_multi_aff(data->res, pma); 7932 7933 return data->res ? isl_stat_ok : isl_stat_error; 7934} 7935 7936/* Return a union piecewise multi-affine expression 7937 * that is equal to "mv" on "domain". 7938 */ 7939__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_multi_val_on_domain( 7940 __isl_take isl_union_set *domain, __isl_take isl_multi_val *mv) 7941{ 7942 struct isl_union_pw_multi_aff_multi_val_on_domain_data data; 7943 isl_space *space; 7944 7945 space = isl_union_set_get_space(domain); 7946 data.res = isl_union_pw_multi_aff_empty(space); 7947 data.mv = mv; 7948 if (isl_union_set_foreach_set(domain, 7949 &pw_multi_aff_multi_val_on_domain, &data) < 0) 7950 data.res = isl_union_pw_multi_aff_free(data.res); 7951 isl_union_set_free(domain); 7952 isl_multi_val_free(mv); 7953 return data.res; 7954} 7955 7956/* Compute the pullback of data->pma by the function represented by "pma2", 7957 * provided the spaces match, and add the results to data->res. 7958 */ 7959static isl_stat pullback_entry(__isl_take isl_pw_multi_aff *pma2, void *user) 7960{ 7961 struct isl_union_pw_multi_aff_bin_data *data = user; 7962 7963 if (!isl_space_tuple_is_equal(data->pma->dim, isl_dim_in, 7964 pma2->dim, isl_dim_out)) { 7965 isl_pw_multi_aff_free(pma2); 7966 return isl_stat_ok; 7967 } 7968 7969 pma2 = isl_pw_multi_aff_pullback_pw_multi_aff( 7970 isl_pw_multi_aff_copy(data->pma), pma2); 7971 7972 data->res = isl_union_pw_multi_aff_add_pw_multi_aff(data->res, pma2); 7973 if (!data->res) 7974 return isl_stat_error; 7975 7976 return isl_stat_ok; 7977} 7978 7979/* Compute the pullback of "upma1" by the function represented by "upma2". 7980 */ 7981__isl_give isl_union_pw_multi_aff * 7982isl_union_pw_multi_aff_pullback_union_pw_multi_aff( 7983 __isl_take isl_union_pw_multi_aff *upma1, 7984 __isl_take isl_union_pw_multi_aff *upma2) 7985{ 7986 return bin_op(upma1, upma2, &pullback_entry); 7987} 7988 7989/* Apply "upma2" to "upma1". 7990 * 7991 * That is, compute the pullback of "upma2" by "upma1". 7992 */ 7993__isl_give isl_union_pw_multi_aff * 7994isl_union_pw_multi_aff_apply_union_pw_multi_aff( 7995 __isl_take isl_union_pw_multi_aff *upma1, 7996 __isl_take isl_union_pw_multi_aff *upma2) 7997{ 7998 return isl_union_pw_multi_aff_pullback_union_pw_multi_aff(upma2, upma1); 7999} 8000 8001#undef BASE 8002#define BASE pw_multi_aff 8003static 8004#include "isl_copy_tuple_id_templ.c" 8005 8006/* Given a function "pma1" of the form A[B -> C] -> D and 8007 * a function "pma2" of the form E -> B, 8008 * replace the domain of the wrapped relation inside the domain of "pma1" 8009 * by the preimage with respect to "pma2". 8010 * In other words, plug in "pma2" in this nested domain. 8011 * The result is of the form A[E -> C] -> D. 8012 * 8013 * In particular, extend E -> B to A[E -> C] -> A[B -> C] and 8014 * plug that into "pma1". 8015 */ 8016__isl_give isl_pw_multi_aff * 8017isl_pw_multi_aff_preimage_domain_wrapped_domain_pw_multi_aff( 8018 __isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2) 8019{ 8020 isl_space *pma1_space, *pma2_space; 8021 isl_space *space; 8022 isl_pw_multi_aff *id; 8023 8024 pma1_space = isl_pw_multi_aff_peek_space(pma1); 8025 pma2_space = isl_pw_multi_aff_peek_space(pma2); 8026 8027 if (isl_space_check_domain_is_wrapping(pma1_space) < 0) 8028 goto error; 8029 if (isl_space_check_wrapped_tuple_is_equal(pma1_space, 8030 isl_dim_in, isl_dim_in, pma2_space, isl_dim_out) < 0) 8031 goto error; 8032 8033 space = isl_space_domain(isl_space_copy(pma1_space)); 8034 space = isl_space_range(isl_space_unwrap(space)); 8035 id = isl_pw_multi_aff_identity_on_domain_space(space); 8036 pma2 = isl_pw_multi_aff_product(pma2, id); 8037 8038 pma2 = isl_pw_multi_aff_copy_tuple_id(pma2, isl_dim_in, 8039 pma1_space, isl_dim_in); 8040 pma2 = isl_pw_multi_aff_copy_tuple_id(pma2, isl_dim_out, 8041 pma1_space, isl_dim_in); 8042 8043 return isl_pw_multi_aff_pullback_pw_multi_aff(pma1, pma2); 8044error: 8045 isl_pw_multi_aff_free(pma1); 8046 isl_pw_multi_aff_free(pma2); 8047 return NULL; 8048} 8049 8050/* If data->pma and "pma2" are such that 8051 * data->pma is of the form A[B -> C] -> D and 8052 * "pma2" is of the form E -> B, 8053 * then replace the domain of the wrapped relation 8054 * inside the domain of data->pma by the preimage with respect to "pma2" and 8055 * add the result to data->res. 8056 */ 8057static isl_stat preimage_domain_wrapped_domain_entry( 8058 __isl_take isl_pw_multi_aff *pma2, void *user) 8059{ 8060 struct isl_union_pw_multi_aff_bin_data *data = user; 8061 isl_space *pma1_space, *pma2_space; 8062 isl_bool match; 8063 8064 pma1_space = isl_pw_multi_aff_peek_space(data->pma); 8065 pma2_space = isl_pw_multi_aff_peek_space(pma2); 8066 8067 match = isl_space_domain_is_wrapping(pma1_space); 8068 if (match >= 0 && match) 8069 match = isl_space_wrapped_tuple_is_equal(pma1_space, isl_dim_in, 8070 isl_dim_in, pma2_space, isl_dim_out); 8071 if (match < 0 || !match) { 8072 isl_pw_multi_aff_free(pma2); 8073 return match < 0 ? isl_stat_error : isl_stat_ok; 8074 } 8075 8076 pma2 = isl_pw_multi_aff_preimage_domain_wrapped_domain_pw_multi_aff( 8077 isl_pw_multi_aff_copy(data->pma), pma2); 8078 8079 data->res = isl_union_pw_multi_aff_add_pw_multi_aff(data->res, pma2); 8080 8081 return isl_stat_non_null(data->res); 8082} 8083 8084/* For each pair of functions A[B -> C] -> D in "upma1" and 8085 * E -> B in "upma2", 8086 * replace the domain of the wrapped relation inside the domain of the first 8087 * by the preimage with respect to the second and collect the results. 8088 * In other words, plug in the second function in this nested domain. 8089 * The results are of the form A[E -> C] -> D. 8090 */ 8091__isl_give isl_union_pw_multi_aff * 8092isl_union_pw_multi_aff_preimage_domain_wrapped_domain_union_pw_multi_aff( 8093 __isl_take isl_union_pw_multi_aff *upma1, 8094 __isl_take isl_union_pw_multi_aff *upma2) 8095{ 8096 return bin_op(upma1, upma2, &preimage_domain_wrapped_domain_entry); 8097} 8098 8099/* Check that the domain space of "upa" matches "space". 8100 * 8101 * This function is called from isl_multi_union_pw_aff_set_union_pw_aff and 8102 * can in principle never fail since the space "space" is that 8103 * of the isl_multi_union_pw_aff and is a set space such that 8104 * there is no domain space to match. 8105 * 8106 * We check the parameters and double-check that "space" is 8107 * indeed that of a set. 8108 */ 8109static isl_stat isl_union_pw_aff_check_match_domain_space( 8110 __isl_keep isl_union_pw_aff *upa, __isl_keep isl_space *space) 8111{ 8112 isl_space *upa_space; 8113 isl_bool match; 8114 8115 if (!upa || !space) 8116 return isl_stat_error; 8117 8118 match = isl_space_is_set(space); 8119 if (match < 0) 8120 return isl_stat_error; 8121 if (!match) 8122 isl_die(isl_space_get_ctx(space), isl_error_invalid, 8123 "expecting set space", return isl_stat_error); 8124 8125 upa_space = isl_union_pw_aff_get_space(upa); 8126 match = isl_space_has_equal_params(space, upa_space); 8127 if (match < 0) 8128 goto error; 8129 if (!match) 8130 isl_die(isl_space_get_ctx(space), isl_error_invalid, 8131 "parameters don't match", goto error); 8132 8133 isl_space_free(upa_space); 8134 return isl_stat_ok; 8135error: 8136 isl_space_free(upa_space); 8137 return isl_stat_error; 8138} 8139 8140/* Do the parameters of "upa" match those of "space"? 8141 */ 8142static isl_bool isl_union_pw_aff_matching_params( 8143 __isl_keep isl_union_pw_aff *upa, __isl_keep isl_space *space) 8144{ 8145 isl_space *upa_space; 8146 isl_bool match; 8147 8148 if (!upa || !space) 8149 return isl_bool_error; 8150 8151 upa_space = isl_union_pw_aff_get_space(upa); 8152 8153 match = isl_space_has_equal_params(space, upa_space); 8154 8155 isl_space_free(upa_space); 8156 return match; 8157} 8158 8159/* Internal data structure for isl_union_pw_aff_reset_domain_space. 8160 * space represents the new parameters. 8161 * res collects the results. 8162 */ 8163struct isl_union_pw_aff_reset_params_data { 8164 isl_space *space; 8165 isl_union_pw_aff *res; 8166}; 8167 8168/* Replace the parameters of "pa" by data->space and 8169 * add the result to data->res. 8170 */ 8171static isl_stat reset_params(__isl_take isl_pw_aff *pa, void *user) 8172{ 8173 struct isl_union_pw_aff_reset_params_data *data = user; 8174 isl_space *space; 8175 8176 space = isl_pw_aff_get_space(pa); 8177 space = isl_space_replace_params(space, data->space); 8178 pa = isl_pw_aff_reset_space(pa, space); 8179 data->res = isl_union_pw_aff_add_pw_aff(data->res, pa); 8180 8181 return data->res ? isl_stat_ok : isl_stat_error; 8182} 8183 8184/* Replace the domain space of "upa" by "space". 8185 * Since a union expression does not have a (single) domain space, 8186 * "space" is necessarily a parameter space. 8187 * 8188 * Since the order and the names of the parameters determine 8189 * the hash value, we need to create a new hash table. 8190 */ 8191static __isl_give isl_union_pw_aff *isl_union_pw_aff_reset_domain_space( 8192 __isl_take isl_union_pw_aff *upa, __isl_take isl_space *space) 8193{ 8194 struct isl_union_pw_aff_reset_params_data data = { space }; 8195 isl_bool match; 8196 8197 match = isl_union_pw_aff_matching_params(upa, space); 8198 if (match < 0) 8199 upa = isl_union_pw_aff_free(upa); 8200 else if (match) { 8201 isl_space_free(space); 8202 return upa; 8203 } 8204 8205 data.res = isl_union_pw_aff_empty(isl_space_copy(space)); 8206 if (isl_union_pw_aff_foreach_pw_aff(upa, &reset_params, &data) < 0) 8207 data.res = isl_union_pw_aff_free(data.res); 8208 8209 isl_union_pw_aff_free(upa); 8210 isl_space_free(space); 8211 return data.res; 8212} 8213 8214/* Return the floor of "pa". 8215 */ 8216static __isl_give isl_pw_aff *floor_entry(__isl_take isl_pw_aff *pa, void *user) 8217{ 8218 return isl_pw_aff_floor(pa); 8219} 8220 8221/* Given f, return floor(f). 8222 */ 8223__isl_give isl_union_pw_aff *isl_union_pw_aff_floor( 8224 __isl_take isl_union_pw_aff *upa) 8225{ 8226 return isl_union_pw_aff_transform_inplace(upa, &floor_entry, NULL); 8227} 8228 8229/* Compute 8230 * 8231 * upa mod m = upa - m * floor(upa/m) 8232 * 8233 * with m an integer value. 8234 */ 8235__isl_give isl_union_pw_aff *isl_union_pw_aff_mod_val( 8236 __isl_take isl_union_pw_aff *upa, __isl_take isl_val *m) 8237{ 8238 isl_union_pw_aff *res; 8239 8240 if (!upa || !m) 8241 goto error; 8242 8243 if (!isl_val_is_int(m)) 8244 isl_die(isl_val_get_ctx(m), isl_error_invalid, 8245 "expecting integer modulo", goto error); 8246 if (!isl_val_is_pos(m)) 8247 isl_die(isl_val_get_ctx(m), isl_error_invalid, 8248 "expecting positive modulo", goto error); 8249 8250 res = isl_union_pw_aff_copy(upa); 8251 upa = isl_union_pw_aff_scale_down_val(upa, isl_val_copy(m)); 8252 upa = isl_union_pw_aff_floor(upa); 8253 upa = isl_union_pw_aff_scale_val(upa, m); 8254 res = isl_union_pw_aff_sub(res, upa); 8255 8256 return res; 8257error: 8258 isl_val_free(m); 8259 isl_union_pw_aff_free(upa); 8260 return NULL; 8261} 8262 8263/* Internal data structure for isl_union_pw_multi_aff_get_union_pw_aff. 8264 * pos is the output position that needs to be extracted. 8265 * res collects the results. 8266 */ 8267struct isl_union_pw_multi_aff_get_union_pw_aff_data { 8268 int pos; 8269 isl_union_pw_aff *res; 8270}; 8271 8272/* Extract an isl_pw_aff corresponding to output dimension "pos" of "pma" 8273 * (assuming it has such a dimension) and add it to data->res. 8274 */ 8275static isl_stat get_union_pw_aff(__isl_take isl_pw_multi_aff *pma, void *user) 8276{ 8277 struct isl_union_pw_multi_aff_get_union_pw_aff_data *data = user; 8278 isl_size n_out; 8279 isl_pw_aff *pa; 8280 8281 n_out = isl_pw_multi_aff_dim(pma, isl_dim_out); 8282 if (n_out < 0) 8283 return isl_stat_error; 8284 if (data->pos >= n_out) { 8285 isl_pw_multi_aff_free(pma); 8286 return isl_stat_ok; 8287 } 8288 8289 pa = isl_pw_multi_aff_get_pw_aff(pma, data->pos); 8290 isl_pw_multi_aff_free(pma); 8291 8292 data->res = isl_union_pw_aff_add_pw_aff(data->res, pa); 8293 8294 return data->res ? isl_stat_ok : isl_stat_error; 8295} 8296 8297/* Extract an isl_union_pw_aff corresponding to 8298 * output dimension "pos" of "upma". 8299 */ 8300__isl_give isl_union_pw_aff *isl_union_pw_multi_aff_get_union_pw_aff( 8301 __isl_keep isl_union_pw_multi_aff *upma, int pos) 8302{ 8303 struct isl_union_pw_multi_aff_get_union_pw_aff_data data; 8304 isl_space *space; 8305 8306 if (!upma) 8307 return NULL; 8308 8309 if (pos < 0) 8310 isl_die(isl_union_pw_multi_aff_get_ctx(upma), isl_error_invalid, 8311 "cannot extract at negative position", return NULL); 8312 8313 space = isl_union_pw_multi_aff_get_space(upma); 8314 data.res = isl_union_pw_aff_empty(space); 8315 data.pos = pos; 8316 if (isl_union_pw_multi_aff_foreach_pw_multi_aff(upma, 8317 &get_union_pw_aff, &data) < 0) 8318 data.res = isl_union_pw_aff_free(data.res); 8319 8320 return data.res; 8321} 8322 8323/* Return a union piecewise affine expression 8324 * that is equal to "aff" on "domain". 8325 */ 8326__isl_give isl_union_pw_aff *isl_union_pw_aff_aff_on_domain( 8327 __isl_take isl_union_set *domain, __isl_take isl_aff *aff) 8328{ 8329 isl_pw_aff *pa; 8330 8331 pa = isl_pw_aff_from_aff(aff); 8332 return isl_union_pw_aff_pw_aff_on_domain(domain, pa); 8333} 8334 8335/* Return a union piecewise affine expression 8336 * that is equal to the parameter identified by "id" on "domain". 8337 * 8338 * Make sure the parameter appears in the space passed to 8339 * isl_aff_param_on_domain_space_id. 8340 */ 8341__isl_give isl_union_pw_aff *isl_union_pw_aff_param_on_domain_id( 8342 __isl_take isl_union_set *domain, __isl_take isl_id *id) 8343{ 8344 isl_space *space; 8345 isl_aff *aff; 8346 8347 space = isl_union_set_get_space(domain); 8348 space = isl_space_add_param_id(space, isl_id_copy(id)); 8349 aff = isl_aff_param_on_domain_space_id(space, id); 8350 return isl_union_pw_aff_aff_on_domain(domain, aff); 8351} 8352 8353/* Internal data structure for isl_union_pw_aff_pw_aff_on_domain. 8354 * "pa" is the piecewise symbolic value that the resulting isl_union_pw_aff 8355 * needs to attain. 8356 * "res" collects the results. 8357 */ 8358struct isl_union_pw_aff_pw_aff_on_domain_data { 8359 isl_pw_aff *pa; 8360 isl_union_pw_aff *res; 8361}; 8362 8363/* Construct a piecewise affine expression that is equal to data->pa 8364 * on "domain" and add the result to data->res. 8365 */ 8366static isl_stat pw_aff_on_domain(__isl_take isl_set *domain, void *user) 8367{ 8368 struct isl_union_pw_aff_pw_aff_on_domain_data *data = user; 8369 isl_pw_aff *pa; 8370 isl_size dim; 8371 8372 pa = isl_pw_aff_copy(data->pa); 8373 dim = isl_set_dim(domain, isl_dim_set); 8374 if (dim < 0) 8375 pa = isl_pw_aff_free(pa); 8376 pa = isl_pw_aff_from_range(pa); 8377 pa = isl_pw_aff_add_dims(pa, isl_dim_in, dim); 8378 pa = isl_pw_aff_reset_domain_space(pa, isl_set_get_space(domain)); 8379 pa = isl_pw_aff_intersect_domain(pa, domain); 8380 data->res = isl_union_pw_aff_add_pw_aff(data->res, pa); 8381 8382 return data->res ? isl_stat_ok : isl_stat_error; 8383} 8384 8385/* Return a union piecewise affine expression 8386 * that is equal to "pa" on "domain", assuming "domain" and "pa" 8387 * have been aligned. 8388 * 8389 * Construct an isl_pw_aff on each of the sets in "domain" and 8390 * collect the results. 8391 */ 8392static __isl_give isl_union_pw_aff *isl_union_pw_aff_pw_aff_on_domain_aligned( 8393 __isl_take isl_union_set *domain, __isl_take isl_pw_aff *pa) 8394{ 8395 struct isl_union_pw_aff_pw_aff_on_domain_data data; 8396 isl_space *space; 8397 8398 space = isl_union_set_get_space(domain); 8399 data.res = isl_union_pw_aff_empty(space); 8400 data.pa = pa; 8401 if (isl_union_set_foreach_set(domain, &pw_aff_on_domain, &data) < 0) 8402 data.res = isl_union_pw_aff_free(data.res); 8403 isl_union_set_free(domain); 8404 isl_pw_aff_free(pa); 8405 return data.res; 8406} 8407 8408/* Return a union piecewise affine expression 8409 * that is equal to "pa" on "domain". 8410 * 8411 * Check that "pa" is a parametric expression, 8412 * align the parameters if needed and call 8413 * isl_union_pw_aff_pw_aff_on_domain_aligned. 8414 */ 8415__isl_give isl_union_pw_aff *isl_union_pw_aff_pw_aff_on_domain( 8416 __isl_take isl_union_set *domain, __isl_take isl_pw_aff *pa) 8417{ 8418 isl_bool is_set; 8419 isl_bool equal_params; 8420 isl_space *domain_space, *pa_space; 8421 8422 pa_space = isl_pw_aff_peek_space(pa); 8423 is_set = isl_space_is_set(pa_space); 8424 if (is_set < 0) 8425 goto error; 8426 if (!is_set) 8427 isl_die(isl_pw_aff_get_ctx(pa), isl_error_invalid, 8428 "expecting parametric expression", goto error); 8429 8430 domain_space = isl_union_set_get_space(domain); 8431 pa_space = isl_pw_aff_get_space(pa); 8432 equal_params = isl_space_has_equal_params(domain_space, pa_space); 8433 if (equal_params >= 0 && !equal_params) { 8434 isl_space *space; 8435 8436 space = isl_space_align_params(domain_space, pa_space); 8437 pa = isl_pw_aff_align_params(pa, isl_space_copy(space)); 8438 domain = isl_union_set_align_params(domain, space); 8439 } else { 8440 isl_space_free(domain_space); 8441 isl_space_free(pa_space); 8442 } 8443 8444 if (equal_params < 0) 8445 goto error; 8446 return isl_union_pw_aff_pw_aff_on_domain_aligned(domain, pa); 8447error: 8448 isl_union_set_free(domain); 8449 isl_pw_aff_free(pa); 8450 return NULL; 8451} 8452 8453/* Internal data structure for isl_union_pw_aff_val_on_domain. 8454 * "v" is the value that the resulting isl_union_pw_aff needs to attain. 8455 * "res" collects the results. 8456 */ 8457struct isl_union_pw_aff_val_on_domain_data { 8458 isl_val *v; 8459 isl_union_pw_aff *res; 8460}; 8461 8462/* Construct a piecewise affine expression that is equal to data->v 8463 * on "domain" and add the result to data->res. 8464 */ 8465static isl_stat pw_aff_val_on_domain(__isl_take isl_set *domain, void *user) 8466{ 8467 struct isl_union_pw_aff_val_on_domain_data *data = user; 8468 isl_pw_aff *pa; 8469 isl_val *v; 8470 8471 v = isl_val_copy(data->v); 8472 pa = isl_pw_aff_val_on_domain(domain, v); 8473 data->res = isl_union_pw_aff_add_pw_aff(data->res, pa); 8474 8475 return data->res ? isl_stat_ok : isl_stat_error; 8476} 8477 8478/* Return a union piecewise affine expression 8479 * that is equal to "v" on "domain". 8480 * 8481 * Construct an isl_pw_aff on each of the sets in "domain" and 8482 * collect the results. 8483 */ 8484__isl_give isl_union_pw_aff *isl_union_pw_aff_val_on_domain( 8485 __isl_take isl_union_set *domain, __isl_take isl_val *v) 8486{ 8487 struct isl_union_pw_aff_val_on_domain_data data; 8488 isl_space *space; 8489 8490 space = isl_union_set_get_space(domain); 8491 data.res = isl_union_pw_aff_empty(space); 8492 data.v = v; 8493 if (isl_union_set_foreach_set(domain, &pw_aff_val_on_domain, &data) < 0) 8494 data.res = isl_union_pw_aff_free(data.res); 8495 isl_union_set_free(domain); 8496 isl_val_free(v); 8497 return data.res; 8498} 8499 8500/* Construct a piecewise multi affine expression 8501 * that is equal to "pa" and add it to upma. 8502 */ 8503static isl_stat pw_multi_aff_from_pw_aff_entry(__isl_take isl_pw_aff *pa, 8504 void *user) 8505{ 8506 isl_union_pw_multi_aff **upma = user; 8507 isl_pw_multi_aff *pma; 8508 8509 pma = isl_pw_multi_aff_from_pw_aff(pa); 8510 *upma = isl_union_pw_multi_aff_add_pw_multi_aff(*upma, pma); 8511 8512 return *upma ? isl_stat_ok : isl_stat_error; 8513} 8514 8515/* Construct and return a union piecewise multi affine expression 8516 * that is equal to the given union piecewise affine expression. 8517 */ 8518__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_from_union_pw_aff( 8519 __isl_take isl_union_pw_aff *upa) 8520{ 8521 isl_space *space; 8522 isl_union_pw_multi_aff *upma; 8523 8524 if (!upa) 8525 return NULL; 8526 8527 space = isl_union_pw_aff_get_space(upa); 8528 upma = isl_union_pw_multi_aff_empty(space); 8529 8530 if (isl_union_pw_aff_foreach_pw_aff(upa, 8531 &pw_multi_aff_from_pw_aff_entry, &upma) < 0) 8532 upma = isl_union_pw_multi_aff_free(upma); 8533 8534 isl_union_pw_aff_free(upa); 8535 return upma; 8536} 8537 8538/* Compute the set of elements in the domain of "pa" where it is zero and 8539 * add this set to "uset". 8540 */ 8541static isl_stat zero_union_set(__isl_take isl_pw_aff *pa, void *user) 8542{ 8543 isl_union_set **uset = (isl_union_set **)user; 8544 8545 *uset = isl_union_set_add_set(*uset, isl_pw_aff_zero_set(pa)); 8546 8547 return *uset ? isl_stat_ok : isl_stat_error; 8548} 8549 8550/* Return a union set containing those elements in the domain 8551 * of "upa" where it is zero. 8552 */ 8553__isl_give isl_union_set *isl_union_pw_aff_zero_union_set( 8554 __isl_take isl_union_pw_aff *upa) 8555{ 8556 isl_union_set *zero; 8557 8558 zero = isl_union_set_empty(isl_union_pw_aff_get_space(upa)); 8559 if (isl_union_pw_aff_foreach_pw_aff(upa, &zero_union_set, &zero) < 0) 8560 zero = isl_union_set_free(zero); 8561 8562 isl_union_pw_aff_free(upa); 8563 return zero; 8564} 8565 8566/* Internal data structure for isl_union_pw_aff_bind_id, 8567 * storing the parameter that needs to be bound and 8568 * the accumulated results. 8569 */ 8570struct isl_bind_id_data { 8571 isl_id *id; 8572 isl_union_set *bound; 8573}; 8574 8575/* Bind the piecewise affine function "pa" to the parameter data->id, 8576 * adding the resulting elements in the domain where the expression 8577 * is equal to the parameter to data->bound. 8578 */ 8579static isl_stat bind_id(__isl_take isl_pw_aff *pa, void *user) 8580{ 8581 struct isl_bind_id_data *data = user; 8582 isl_set *bound; 8583 8584 bound = isl_pw_aff_bind_id(pa, isl_id_copy(data->id)); 8585 data->bound = isl_union_set_add_set(data->bound, bound); 8586 8587 return data->bound ? isl_stat_ok : isl_stat_error; 8588} 8589 8590/* Bind the union piecewise affine function "upa" to the parameter "id", 8591 * returning the elements in the domain where the expression 8592 * is equal to the parameter. 8593 */ 8594__isl_give isl_union_set *isl_union_pw_aff_bind_id( 8595 __isl_take isl_union_pw_aff *upa, __isl_take isl_id *id) 8596{ 8597 struct isl_bind_id_data data = { id }; 8598 8599 data.bound = isl_union_set_empty(isl_union_pw_aff_get_space(upa)); 8600 if (isl_union_pw_aff_foreach_pw_aff(upa, &bind_id, &data) < 0) 8601 data.bound = isl_union_set_free(data.bound); 8602 8603 isl_union_pw_aff_free(upa); 8604 isl_id_free(id); 8605 return data.bound; 8606} 8607 8608/* Internal data structure for isl_union_pw_aff_pullback_union_pw_multi_aff. 8609 * upma is the function that is plugged in. 8610 * pa is the current part of the function in which upma is plugged in. 8611 * res collects the results. 8612 */ 8613struct isl_union_pw_aff_pullback_upma_data { 8614 isl_union_pw_multi_aff *upma; 8615 isl_pw_aff *pa; 8616 isl_union_pw_aff *res; 8617}; 8618 8619/* Check if "pma" can be plugged into data->pa. 8620 * If so, perform the pullback and add the result to data->res. 8621 */ 8622static isl_stat pa_pb_pma(__isl_take isl_pw_multi_aff *pma, void *user) 8623{ 8624 struct isl_union_pw_aff_pullback_upma_data *data = user; 8625 isl_pw_aff *pa; 8626 8627 if (!isl_space_tuple_is_equal(data->pa->dim, isl_dim_in, 8628 pma->dim, isl_dim_out)) { 8629 isl_pw_multi_aff_free(pma); 8630 return isl_stat_ok; 8631 } 8632 8633 pa = isl_pw_aff_copy(data->pa); 8634 pa = isl_pw_aff_pullback_pw_multi_aff(pa, pma); 8635 8636 data->res = isl_union_pw_aff_add_pw_aff(data->res, pa); 8637 8638 return data->res ? isl_stat_ok : isl_stat_error; 8639} 8640 8641/* Check if any of the elements of data->upma can be plugged into pa, 8642 * add if so add the result to data->res. 8643 */ 8644static isl_stat upa_pb_upma(__isl_take isl_pw_aff *pa, void *user) 8645{ 8646 struct isl_union_pw_aff_pullback_upma_data *data = user; 8647 isl_stat r; 8648 8649 data->pa = pa; 8650 r = isl_union_pw_multi_aff_foreach_pw_multi_aff(data->upma, 8651 &pa_pb_pma, data); 8652 isl_pw_aff_free(pa); 8653 8654 return r; 8655} 8656 8657/* Compute the pullback of "upa" by the function represented by "upma". 8658 * In other words, plug in "upma" in "upa". The result contains 8659 * expressions defined over the domain space of "upma". 8660 * 8661 * Run over all pairs of elements in "upa" and "upma", perform 8662 * the pullback when appropriate and collect the results. 8663 * If the hash value were based on the domain space rather than 8664 * the function space, then we could run through all elements 8665 * of "upma" and directly pick out the corresponding element of "upa". 8666 */ 8667__isl_give isl_union_pw_aff *isl_union_pw_aff_pullback_union_pw_multi_aff( 8668 __isl_take isl_union_pw_aff *upa, 8669 __isl_take isl_union_pw_multi_aff *upma) 8670{ 8671 struct isl_union_pw_aff_pullback_upma_data data = { NULL, NULL }; 8672 isl_space *space; 8673 8674 space = isl_union_pw_multi_aff_get_space(upma); 8675 upa = isl_union_pw_aff_align_params(upa, space); 8676 space = isl_union_pw_aff_get_space(upa); 8677 upma = isl_union_pw_multi_aff_align_params(upma, space); 8678 8679 if (!upa || !upma) 8680 goto error; 8681 8682 data.upma = upma; 8683 data.res = isl_union_pw_aff_alloc_same_size(upa); 8684 if (isl_union_pw_aff_foreach_pw_aff(upa, &upa_pb_upma, &data) < 0) 8685 data.res = isl_union_pw_aff_free(data.res); 8686 8687 isl_union_pw_aff_free(upa); 8688 isl_union_pw_multi_aff_free(upma); 8689 return data.res; 8690error: 8691 isl_union_pw_aff_free(upa); 8692 isl_union_pw_multi_aff_free(upma); 8693 return NULL; 8694} 8695 8696#undef BASE 8697#define BASE union_pw_aff 8698#undef DOMBASE 8699#define DOMBASE union_set 8700 8701#include <isl_multi_explicit_domain.c> 8702#include <isl_multi_union_pw_aff_explicit_domain.c> 8703#include <isl_multi_templ.c> 8704#include <isl_multi_un_op_templ.c> 8705#include <isl_multi_bin_val_templ.c> 8706#include <isl_multi_align_set.c> 8707#include <isl_multi_align_union_set.c> 8708#include <isl_multi_apply_set_explicit_domain_templ.c> 8709#include <isl_multi_apply_union_set_explicit_domain_templ.c> 8710#include <isl_multi_arith_templ.c> 8711#include <isl_multi_bind_templ.c> 8712#include <isl_multi_coalesce.c> 8713#include <isl_multi_dim_id_templ.c> 8714#include <isl_multi_floor.c> 8715#include <isl_multi_from_base_templ.c> 8716#include <isl_multi_check_domain_templ.c> 8717#include <isl_multi_gist.c> 8718#include <isl_multi_intersect.c> 8719#include <isl_multi_nan_templ.c> 8720#include <isl_multi_tuple_id_templ.c> 8721#include <isl_multi_union_add_templ.c> 8722#include <isl_multi_zero_space_templ.c> 8723 8724/* Does "mupa" have a non-trivial explicit domain? 8725 * 8726 * The explicit domain, if present, is trivial if it represents 8727 * an (obviously) universe parameter set. 8728 */ 8729isl_bool isl_multi_union_pw_aff_has_non_trivial_domain( 8730 __isl_keep isl_multi_union_pw_aff *mupa) 8731{ 8732 isl_bool is_params, trivial; 8733 isl_set *set; 8734 8735 if (!mupa) 8736 return isl_bool_error; 8737 if (!isl_multi_union_pw_aff_has_explicit_domain(mupa)) 8738 return isl_bool_false; 8739 is_params = isl_union_set_is_params(mupa->u.dom); 8740 if (is_params < 0 || !is_params) 8741 return isl_bool_not(is_params); 8742 set = isl_set_from_union_set(isl_union_set_copy(mupa->u.dom)); 8743 trivial = isl_set_plain_is_universe(set); 8744 isl_set_free(set); 8745 return isl_bool_not(trivial); 8746} 8747 8748/* Construct a multiple union piecewise affine expression 8749 * in the given space with value zero in each of the output dimensions. 8750 * 8751 * Since there is no canonical zero value for 8752 * a union piecewise affine expression, we can only construct 8753 * a zero-dimensional "zero" value. 8754 */ 8755__isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_zero( 8756 __isl_take isl_space *space) 8757{ 8758 isl_bool params; 8759 isl_size dim; 8760 8761 if (!space) 8762 return NULL; 8763 8764 params = isl_space_is_params(space); 8765 if (params < 0) 8766 goto error; 8767 if (params) 8768 isl_die(isl_space_get_ctx(space), isl_error_invalid, 8769 "expecting proper set space", goto error); 8770 if (!isl_space_is_set(space)) 8771 isl_die(isl_space_get_ctx(space), isl_error_invalid, 8772 "expecting set space", goto error); 8773 dim = isl_space_dim(space, isl_dim_out); 8774 if (dim < 0) 8775 goto error; 8776 if (dim != 0) 8777 isl_die(isl_space_get_ctx(space), isl_error_invalid, 8778 "expecting 0D space", goto error); 8779 8780 return isl_multi_union_pw_aff_alloc(space); 8781error: 8782 isl_space_free(space); 8783 return NULL; 8784} 8785 8786/* Construct and return a multi union piecewise affine expression 8787 * that is equal to the given multi affine expression. 8788 */ 8789__isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_from_multi_aff( 8790 __isl_take isl_multi_aff *ma) 8791{ 8792 isl_multi_pw_aff *mpa; 8793 8794 mpa = isl_multi_pw_aff_from_multi_aff(ma); 8795 return isl_multi_union_pw_aff_from_multi_pw_aff(mpa); 8796} 8797 8798/* This function performs the same operation as 8799 * isl_multi_union_pw_aff_from_multi_aff, but is considered as a function on an 8800 * isl_multi_aff when exported. 8801 */ 8802__isl_give isl_multi_union_pw_aff *isl_multi_aff_to_multi_union_pw_aff( 8803 __isl_take isl_multi_aff *ma) 8804{ 8805 return isl_multi_union_pw_aff_from_multi_aff(ma); 8806} 8807 8808/* Construct and return a multi union piecewise affine expression 8809 * that is equal to the given multi piecewise affine expression. 8810 * 8811 * If the resulting multi union piecewise affine expression has 8812 * an explicit domain, then assign it the domain of the input. 8813 * In other cases, the domain is stored in the individual elements. 8814 */ 8815__isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_from_multi_pw_aff( 8816 __isl_take isl_multi_pw_aff *mpa) 8817{ 8818 int i; 8819 isl_size n; 8820 isl_space *space; 8821 isl_multi_union_pw_aff *mupa; 8822 8823 n = isl_multi_pw_aff_dim(mpa, isl_dim_out); 8824 if (n < 0) 8825 mpa = isl_multi_pw_aff_free(mpa); 8826 if (!mpa) 8827 return NULL; 8828 8829 space = isl_multi_pw_aff_get_space(mpa); 8830 space = isl_space_range(space); 8831 mupa = isl_multi_union_pw_aff_alloc(space); 8832 8833 for (i = 0; i < n; ++i) { 8834 isl_pw_aff *pa; 8835 isl_union_pw_aff *upa; 8836 8837 pa = isl_multi_pw_aff_get_pw_aff(mpa, i); 8838 upa = isl_union_pw_aff_from_pw_aff(pa); 8839 mupa = isl_multi_union_pw_aff_restore_check_space(mupa, i, upa); 8840 } 8841 if (isl_multi_union_pw_aff_has_explicit_domain(mupa)) { 8842 isl_union_set *dom; 8843 isl_multi_pw_aff *copy; 8844 8845 copy = isl_multi_pw_aff_copy(mpa); 8846 dom = isl_union_set_from_set(isl_multi_pw_aff_domain(copy)); 8847 mupa = isl_multi_union_pw_aff_intersect_domain(mupa, dom); 8848 } 8849 8850 isl_multi_pw_aff_free(mpa); 8851 8852 return mupa; 8853} 8854 8855/* Extract the range space of "pma" and assign it to *space. 8856 * If *space has already been set (through a previous call to this function), 8857 * then check that the range space is the same. 8858 */ 8859static isl_stat extract_space(__isl_take isl_pw_multi_aff *pma, void *user) 8860{ 8861 isl_space **space = user; 8862 isl_space *pma_space; 8863 isl_bool equal; 8864 8865 pma_space = isl_space_range(isl_pw_multi_aff_get_space(pma)); 8866 isl_pw_multi_aff_free(pma); 8867 8868 if (!pma_space) 8869 return isl_stat_error; 8870 if (!*space) { 8871 *space = pma_space; 8872 return isl_stat_ok; 8873 } 8874 8875 equal = isl_space_is_equal(pma_space, *space); 8876 isl_space_free(pma_space); 8877 8878 if (equal < 0) 8879 return isl_stat_error; 8880 if (!equal) 8881 isl_die(isl_space_get_ctx(*space), isl_error_invalid, 8882 "range spaces not the same", return isl_stat_error); 8883 return isl_stat_ok; 8884} 8885 8886/* Construct and return a multi union piecewise affine expression 8887 * that is equal to the given union piecewise multi affine expression. 8888 * 8889 * In order to be able to perform the conversion, the input 8890 * needs to be non-empty and may only involve a single range space. 8891 * 8892 * If the resulting multi union piecewise affine expression has 8893 * an explicit domain, then assign it the domain of the input. 8894 * In other cases, the domain is stored in the individual elements. 8895 */ 8896__isl_give isl_multi_union_pw_aff * 8897isl_multi_union_pw_aff_from_union_pw_multi_aff( 8898 __isl_take isl_union_pw_multi_aff *upma) 8899{ 8900 isl_space *space = NULL; 8901 isl_multi_union_pw_aff *mupa; 8902 int i; 8903 isl_size n; 8904 8905 n = isl_union_pw_multi_aff_n_pw_multi_aff(upma); 8906 if (n < 0) 8907 goto error; 8908 if (n == 0) 8909 isl_die(isl_union_pw_multi_aff_get_ctx(upma), isl_error_invalid, 8910 "cannot extract range space from empty input", 8911 goto error); 8912 if (isl_union_pw_multi_aff_foreach_pw_multi_aff(upma, &extract_space, 8913 &space) < 0) 8914 goto error; 8915 8916 if (!space) 8917 goto error; 8918 8919 n = isl_space_dim(space, isl_dim_set); 8920 if (n < 0) 8921 space = isl_space_free(space); 8922 mupa = isl_multi_union_pw_aff_alloc(space); 8923 8924 for (i = 0; i < n; ++i) { 8925 isl_union_pw_aff *upa; 8926 8927 upa = isl_union_pw_multi_aff_get_union_pw_aff(upma, i); 8928 mupa = isl_multi_union_pw_aff_set_union_pw_aff(mupa, i, upa); 8929 } 8930 if (isl_multi_union_pw_aff_has_explicit_domain(mupa)) { 8931 isl_union_set *dom; 8932 isl_union_pw_multi_aff *copy; 8933 8934 copy = isl_union_pw_multi_aff_copy(upma); 8935 dom = isl_union_pw_multi_aff_domain(copy); 8936 mupa = isl_multi_union_pw_aff_intersect_domain(mupa, dom); 8937 } 8938 8939 isl_union_pw_multi_aff_free(upma); 8940 return mupa; 8941error: 8942 isl_space_free(space); 8943 isl_union_pw_multi_aff_free(upma); 8944 return NULL; 8945} 8946 8947/* This function performs the same operation as 8948 * isl_multi_union_pw_aff_from_union_pw_multi_aff, 8949 * but is considered as a function on an isl_union_pw_multi_aff when exported. 8950 */ 8951__isl_give isl_multi_union_pw_aff * 8952isl_union_pw_multi_aff_as_multi_union_pw_aff( 8953 __isl_take isl_union_pw_multi_aff *upma) 8954{ 8955 return isl_multi_union_pw_aff_from_union_pw_multi_aff(upma); 8956} 8957 8958/* Try and create an isl_multi_union_pw_aff that is equivalent 8959 * to the given isl_union_map. 8960 * The isl_union_map is required to be single-valued in each space. 8961 * Moreover, it cannot be empty and all range spaces need to be the same. 8962 * Otherwise, an error is produced. 8963 */ 8964__isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_from_union_map( 8965 __isl_take isl_union_map *umap) 8966{ 8967 isl_union_pw_multi_aff *upma; 8968 8969 upma = isl_union_pw_multi_aff_from_union_map(umap); 8970 return isl_multi_union_pw_aff_from_union_pw_multi_aff(upma); 8971} 8972 8973/* This function performs the same operation as 8974 * isl_multi_union_pw_aff_from_union_map, 8975 * but is considered as a function on an isl_union_map when exported. 8976 */ 8977__isl_give isl_multi_union_pw_aff *isl_union_map_as_multi_union_pw_aff( 8978 __isl_take isl_union_map *umap) 8979{ 8980 return isl_multi_union_pw_aff_from_union_map(umap); 8981} 8982 8983/* Return a multiple union piecewise affine expression 8984 * that is equal to "mv" on "domain", assuming "domain" and "mv" 8985 * have been aligned. 8986 * 8987 * If the resulting multi union piecewise affine expression has 8988 * an explicit domain, then assign it the input domain. 8989 * In other cases, the domain is stored in the individual elements. 8990 */ 8991static __isl_give isl_multi_union_pw_aff * 8992isl_multi_union_pw_aff_multi_val_on_domain_aligned( 8993 __isl_take isl_union_set *domain, __isl_take isl_multi_val *mv) 8994{ 8995 int i; 8996 isl_size n; 8997 isl_space *space; 8998 isl_multi_union_pw_aff *mupa; 8999 9000 n = isl_multi_val_dim(mv, isl_dim_set); 9001 if (!domain || n < 0) 9002 goto error; 9003 9004 space = isl_multi_val_get_space(mv); 9005 mupa = isl_multi_union_pw_aff_alloc(space); 9006 for (i = 0; i < n; ++i) { 9007 isl_val *v; 9008 isl_union_pw_aff *upa; 9009 9010 v = isl_multi_val_get_val(mv, i); 9011 upa = isl_union_pw_aff_val_on_domain(isl_union_set_copy(domain), 9012 v); 9013 mupa = isl_multi_union_pw_aff_set_union_pw_aff(mupa, i, upa); 9014 } 9015 if (isl_multi_union_pw_aff_has_explicit_domain(mupa)) 9016 mupa = isl_multi_union_pw_aff_intersect_domain(mupa, 9017 isl_union_set_copy(domain)); 9018 9019 isl_union_set_free(domain); 9020 isl_multi_val_free(mv); 9021 return mupa; 9022error: 9023 isl_union_set_free(domain); 9024 isl_multi_val_free(mv); 9025 return NULL; 9026} 9027 9028/* Return a multiple union piecewise affine expression 9029 * that is equal to "mv" on "domain". 9030 */ 9031__isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_multi_val_on_domain( 9032 __isl_take isl_union_set *domain, __isl_take isl_multi_val *mv) 9033{ 9034 isl_bool equal_params; 9035 9036 if (!domain || !mv) 9037 goto error; 9038 equal_params = isl_space_has_equal_params(domain->dim, mv->space); 9039 if (equal_params < 0) 9040 goto error; 9041 if (equal_params) 9042 return isl_multi_union_pw_aff_multi_val_on_domain_aligned( 9043 domain, mv); 9044 domain = isl_union_set_align_params(domain, 9045 isl_multi_val_get_space(mv)); 9046 mv = isl_multi_val_align_params(mv, isl_union_set_get_space(domain)); 9047 return isl_multi_union_pw_aff_multi_val_on_domain_aligned(domain, mv); 9048error: 9049 isl_union_set_free(domain); 9050 isl_multi_val_free(mv); 9051 return NULL; 9052} 9053 9054/* Return a multiple union piecewise affine expression 9055 * that is equal to "ma" on "domain". 9056 */ 9057__isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_multi_aff_on_domain( 9058 __isl_take isl_union_set *domain, __isl_take isl_multi_aff *ma) 9059{ 9060 isl_pw_multi_aff *pma; 9061 9062 pma = isl_pw_multi_aff_from_multi_aff(ma); 9063 return isl_multi_union_pw_aff_pw_multi_aff_on_domain(domain, pma); 9064} 9065 9066/* Return a multiple union piecewise affine expression 9067 * that is equal to "pma" on "domain", assuming "domain" and "pma" 9068 * have been aligned. 9069 * 9070 * If the resulting multi union piecewise affine expression has 9071 * an explicit domain, then assign it the input domain. 9072 * In other cases, the domain is stored in the individual elements. 9073 */ 9074static __isl_give isl_multi_union_pw_aff * 9075isl_multi_union_pw_aff_pw_multi_aff_on_domain_aligned( 9076 __isl_take isl_union_set *domain, __isl_take isl_pw_multi_aff *pma) 9077{ 9078 int i; 9079 isl_size n; 9080 isl_space *space; 9081 isl_multi_union_pw_aff *mupa; 9082 9083 n = isl_pw_multi_aff_dim(pma, isl_dim_set); 9084 if (!domain || n < 0) 9085 goto error; 9086 space = isl_pw_multi_aff_get_space(pma); 9087 mupa = isl_multi_union_pw_aff_alloc(space); 9088 for (i = 0; i < n; ++i) { 9089 isl_pw_aff *pa; 9090 isl_union_pw_aff *upa; 9091 9092 pa = isl_pw_multi_aff_get_pw_aff(pma, i); 9093 upa = isl_union_pw_aff_pw_aff_on_domain( 9094 isl_union_set_copy(domain), pa); 9095 mupa = isl_multi_union_pw_aff_set_union_pw_aff(mupa, i, upa); 9096 } 9097 if (isl_multi_union_pw_aff_has_explicit_domain(mupa)) 9098 mupa = isl_multi_union_pw_aff_intersect_domain(mupa, 9099 isl_union_set_copy(domain)); 9100 9101 isl_union_set_free(domain); 9102 isl_pw_multi_aff_free(pma); 9103 return mupa; 9104error: 9105 isl_union_set_free(domain); 9106 isl_pw_multi_aff_free(pma); 9107 return NULL; 9108} 9109 9110/* Return a multiple union piecewise affine expression 9111 * that is equal to "pma" on "domain". 9112 */ 9113__isl_give isl_multi_union_pw_aff * 9114isl_multi_union_pw_aff_pw_multi_aff_on_domain(__isl_take isl_union_set *domain, 9115 __isl_take isl_pw_multi_aff *pma) 9116{ 9117 isl_bool equal_params; 9118 isl_space *space; 9119 9120 space = isl_pw_multi_aff_peek_space(pma); 9121 equal_params = isl_union_set_space_has_equal_params(domain, space); 9122 if (equal_params < 0) 9123 goto error; 9124 if (equal_params) 9125 return isl_multi_union_pw_aff_pw_multi_aff_on_domain_aligned( 9126 domain, pma); 9127 domain = isl_union_set_align_params(domain, 9128 isl_pw_multi_aff_get_space(pma)); 9129 pma = isl_pw_multi_aff_align_params(pma, 9130 isl_union_set_get_space(domain)); 9131 return isl_multi_union_pw_aff_pw_multi_aff_on_domain_aligned(domain, 9132 pma); 9133error: 9134 isl_union_set_free(domain); 9135 isl_pw_multi_aff_free(pma); 9136 return NULL; 9137} 9138 9139/* Return a union set containing those elements in the domains 9140 * of the elements of "mupa" where they are all zero. 9141 * 9142 * If there are no elements, then simply return the entire domain. 9143 */ 9144__isl_give isl_union_set *isl_multi_union_pw_aff_zero_union_set( 9145 __isl_take isl_multi_union_pw_aff *mupa) 9146{ 9147 int i; 9148 isl_size n; 9149 isl_union_pw_aff *upa; 9150 isl_union_set *zero; 9151 9152 n = isl_multi_union_pw_aff_dim(mupa, isl_dim_set); 9153 if (n < 0) 9154 mupa = isl_multi_union_pw_aff_free(mupa); 9155 if (!mupa) 9156 return NULL; 9157 9158 if (n == 0) 9159 return isl_multi_union_pw_aff_domain(mupa); 9160 9161 upa = isl_multi_union_pw_aff_get_union_pw_aff(mupa, 0); 9162 zero = isl_union_pw_aff_zero_union_set(upa); 9163 9164 for (i = 1; i < n; ++i) { 9165 isl_union_set *zero_i; 9166 9167 upa = isl_multi_union_pw_aff_get_union_pw_aff(mupa, i); 9168 zero_i = isl_union_pw_aff_zero_union_set(upa); 9169 9170 zero = isl_union_set_intersect(zero, zero_i); 9171 } 9172 9173 isl_multi_union_pw_aff_free(mupa); 9174 return zero; 9175} 9176 9177/* Construct a union map mapping the shared domain 9178 * of the union piecewise affine expressions to the range of "mupa" 9179 * in the special case of a 0D multi union piecewise affine expression. 9180 * 9181 * Construct a map between the explicit domain of "mupa" and 9182 * the range space. 9183 * Note that this assumes that the domain consists of explicit elements. 9184 */ 9185static __isl_give isl_union_map *isl_union_map_from_multi_union_pw_aff_0D( 9186 __isl_take isl_multi_union_pw_aff *mupa) 9187{ 9188 isl_bool is_params; 9189 isl_space *space; 9190 isl_union_set *dom, *ran; 9191 9192 space = isl_multi_union_pw_aff_get_space(mupa); 9193 dom = isl_multi_union_pw_aff_domain(mupa); 9194 ran = isl_union_set_from_set(isl_set_universe(space)); 9195 9196 is_params = isl_union_set_is_params(dom); 9197 if (is_params < 0) 9198 dom = isl_union_set_free(dom); 9199 else if (is_params) 9200 isl_die(isl_union_set_get_ctx(dom), isl_error_invalid, 9201 "cannot create union map from expression without " 9202 "explicit domain elements", 9203 dom = isl_union_set_free(dom)); 9204 9205 return isl_union_map_from_domain_and_range(dom, ran); 9206} 9207 9208/* Construct a union map mapping the shared domain 9209 * of the union piecewise affine expressions to the range of "mupa" 9210 * with each dimension in the range equated to the 9211 * corresponding union piecewise affine expression. 9212 * 9213 * If the input is zero-dimensional, then construct a mapping 9214 * from its explicit domain. 9215 */ 9216__isl_give isl_union_map *isl_union_map_from_multi_union_pw_aff( 9217 __isl_take isl_multi_union_pw_aff *mupa) 9218{ 9219 int i; 9220 isl_size n; 9221 isl_space *space; 9222 isl_union_map *umap; 9223 isl_union_pw_aff *upa; 9224 9225 n = isl_multi_union_pw_aff_dim(mupa, isl_dim_set); 9226 if (n < 0) 9227 mupa = isl_multi_union_pw_aff_free(mupa); 9228 if (!mupa) 9229 return NULL; 9230 9231 if (n == 0) 9232 return isl_union_map_from_multi_union_pw_aff_0D(mupa); 9233 9234 upa = isl_multi_union_pw_aff_get_union_pw_aff(mupa, 0); 9235 umap = isl_union_map_from_union_pw_aff(upa); 9236 9237 for (i = 1; i < n; ++i) { 9238 isl_union_map *umap_i; 9239 9240 upa = isl_multi_union_pw_aff_get_union_pw_aff(mupa, i); 9241 umap_i = isl_union_map_from_union_pw_aff(upa); 9242 umap = isl_union_map_flat_range_product(umap, umap_i); 9243 } 9244 9245 space = isl_multi_union_pw_aff_get_space(mupa); 9246 umap = isl_union_map_reset_range_space(umap, space); 9247 9248 isl_multi_union_pw_aff_free(mupa); 9249 return umap; 9250} 9251 9252/* Internal data structure for isl_union_pw_multi_aff_reset_range_space. 9253 * "range" is the space from which to set the range space. 9254 * "res" collects the results. 9255 */ 9256struct isl_union_pw_multi_aff_reset_range_space_data { 9257 isl_space *range; 9258 isl_union_pw_multi_aff *res; 9259}; 9260 9261/* Replace the range space of "pma" by the range space of data->range and 9262 * add the result to data->res. 9263 */ 9264static isl_stat reset_range_space(__isl_take isl_pw_multi_aff *pma, void *user) 9265{ 9266 struct isl_union_pw_multi_aff_reset_range_space_data *data = user; 9267 isl_space *space; 9268 9269 space = isl_pw_multi_aff_get_space(pma); 9270 space = isl_space_domain(space); 9271 space = isl_space_extend_domain_with_range(space, 9272 isl_space_copy(data->range)); 9273 pma = isl_pw_multi_aff_reset_space(pma, space); 9274 data->res = isl_union_pw_multi_aff_add_pw_multi_aff(data->res, pma); 9275 9276 return data->res ? isl_stat_ok : isl_stat_error; 9277} 9278 9279/* Replace the range space of all the piecewise affine expressions in "upma" by 9280 * the range space of "space". 9281 * 9282 * This assumes that all these expressions have the same output dimension. 9283 * 9284 * Since the spaces of the expressions change, so do their hash values. 9285 * We therefore need to create a new isl_union_pw_multi_aff. 9286 * Note that the hash value is currently computed based on the entire 9287 * space even though there can only be a single expression with a given 9288 * domain space. 9289 */ 9290static __isl_give isl_union_pw_multi_aff * 9291isl_union_pw_multi_aff_reset_range_space( 9292 __isl_take isl_union_pw_multi_aff *upma, __isl_take isl_space *space) 9293{ 9294 struct isl_union_pw_multi_aff_reset_range_space_data data = { space }; 9295 isl_space *space_upma; 9296 9297 space_upma = isl_union_pw_multi_aff_get_space(upma); 9298 data.res = isl_union_pw_multi_aff_empty(space_upma); 9299 if (isl_union_pw_multi_aff_foreach_pw_multi_aff(upma, 9300 &reset_range_space, &data) < 0) 9301 data.res = isl_union_pw_multi_aff_free(data.res); 9302 9303 isl_space_free(space); 9304 isl_union_pw_multi_aff_free(upma); 9305 return data.res; 9306} 9307 9308/* Construct and return a union piecewise multi affine expression 9309 * that is equal to the given multi union piecewise affine expression, 9310 * in the special case of a 0D multi union piecewise affine expression. 9311 * 9312 * Construct a union piecewise multi affine expression 9313 * on top of the explicit domain of the input. 9314 */ 9315__isl_give isl_union_pw_multi_aff * 9316isl_union_pw_multi_aff_from_multi_union_pw_aff_0D( 9317 __isl_take isl_multi_union_pw_aff *mupa) 9318{ 9319 isl_space *space; 9320 isl_multi_val *mv; 9321 isl_union_set *domain; 9322 9323 space = isl_multi_union_pw_aff_get_space(mupa); 9324 mv = isl_multi_val_zero(space); 9325 domain = isl_multi_union_pw_aff_domain(mupa); 9326 return isl_union_pw_multi_aff_multi_val_on_domain(domain, mv); 9327} 9328 9329/* Construct and return a union piecewise multi affine expression 9330 * that is equal to the given multi union piecewise affine expression. 9331 * 9332 * If the input is zero-dimensional, then 9333 * construct a union piecewise multi affine expression 9334 * on top of the explicit domain of the input. 9335 */ 9336__isl_give isl_union_pw_multi_aff * 9337isl_union_pw_multi_aff_from_multi_union_pw_aff( 9338 __isl_take isl_multi_union_pw_aff *mupa) 9339{ 9340 int i; 9341 isl_size n; 9342 isl_space *space; 9343 isl_union_pw_multi_aff *upma; 9344 isl_union_pw_aff *upa; 9345 9346 n = isl_multi_union_pw_aff_dim(mupa, isl_dim_set); 9347 if (n < 0) 9348 mupa = isl_multi_union_pw_aff_free(mupa); 9349 if (!mupa) 9350 return NULL; 9351 9352 if (n == 0) 9353 return isl_union_pw_multi_aff_from_multi_union_pw_aff_0D(mupa); 9354 9355 space = isl_multi_union_pw_aff_get_space(mupa); 9356 upa = isl_multi_union_pw_aff_get_union_pw_aff(mupa, 0); 9357 upma = isl_union_pw_multi_aff_from_union_pw_aff(upa); 9358 9359 for (i = 1; i < n; ++i) { 9360 isl_union_pw_multi_aff *upma_i; 9361 9362 upa = isl_multi_union_pw_aff_get_union_pw_aff(mupa, i); 9363 upma_i = isl_union_pw_multi_aff_from_union_pw_aff(upa); 9364 upma = isl_union_pw_multi_aff_flat_range_product(upma, upma_i); 9365 } 9366 9367 upma = isl_union_pw_multi_aff_reset_range_space(upma, space); 9368 9369 isl_multi_union_pw_aff_free(mupa); 9370 return upma; 9371} 9372 9373/* Intersect the range of "mupa" with "range", 9374 * in the special case where "mupa" is 0D. 9375 * 9376 * Intersect the domain of "mupa" with the constraints on the parameters 9377 * of "range". 9378 */ 9379static __isl_give isl_multi_union_pw_aff *mupa_intersect_range_0D( 9380 __isl_take isl_multi_union_pw_aff *mupa, __isl_take isl_set *range) 9381{ 9382 range = isl_set_params(range); 9383 mupa = isl_multi_union_pw_aff_intersect_params(mupa, range); 9384 return mupa; 9385} 9386 9387/* Intersect the range of "mupa" with "range". 9388 * That is, keep only those domain elements that have a function value 9389 * in "range". 9390 */ 9391__isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_intersect_range( 9392 __isl_take isl_multi_union_pw_aff *mupa, __isl_take isl_set *range) 9393{ 9394 isl_union_pw_multi_aff *upma; 9395 isl_union_set *domain; 9396 isl_space *space; 9397 isl_size n; 9398 int match; 9399 9400 n = isl_multi_union_pw_aff_dim(mupa, isl_dim_set); 9401 if (n < 0 || !range) 9402 goto error; 9403 9404 space = isl_set_get_space(range); 9405 match = isl_space_tuple_is_equal(mupa->space, isl_dim_set, 9406 space, isl_dim_set); 9407 isl_space_free(space); 9408 if (match < 0) 9409 goto error; 9410 if (!match) 9411 isl_die(isl_multi_union_pw_aff_get_ctx(mupa), isl_error_invalid, 9412 "space don't match", goto error); 9413 if (n == 0) 9414 return mupa_intersect_range_0D(mupa, range); 9415 9416 upma = isl_union_pw_multi_aff_from_multi_union_pw_aff( 9417 isl_multi_union_pw_aff_copy(mupa)); 9418 domain = isl_union_set_from_set(range); 9419 domain = isl_union_set_preimage_union_pw_multi_aff(domain, upma); 9420 mupa = isl_multi_union_pw_aff_intersect_domain(mupa, domain); 9421 9422 return mupa; 9423error: 9424 isl_multi_union_pw_aff_free(mupa); 9425 isl_set_free(range); 9426 return NULL; 9427} 9428 9429/* Return the shared domain of the elements of "mupa", 9430 * in the special case where "mupa" is zero-dimensional. 9431 * 9432 * Return the explicit domain of "mupa". 9433 * Note that this domain may be a parameter set, either 9434 * because "mupa" is meant to live in a set space or 9435 * because no explicit domain has been set. 9436 */ 9437__isl_give isl_union_set *isl_multi_union_pw_aff_domain_0D( 9438 __isl_take isl_multi_union_pw_aff *mupa) 9439{ 9440 isl_union_set *dom; 9441 9442 dom = isl_multi_union_pw_aff_get_explicit_domain(mupa); 9443 isl_multi_union_pw_aff_free(mupa); 9444 9445 return dom; 9446} 9447 9448/* Return the shared domain of the elements of "mupa". 9449 * 9450 * If "mupa" is zero-dimensional, then return its explicit domain. 9451 */ 9452__isl_give isl_union_set *isl_multi_union_pw_aff_domain( 9453 __isl_take isl_multi_union_pw_aff *mupa) 9454{ 9455 int i; 9456 isl_size n; 9457 isl_union_pw_aff *upa; 9458 isl_union_set *dom; 9459 9460 n = isl_multi_union_pw_aff_dim(mupa, isl_dim_set); 9461 if (n < 0) 9462 mupa = isl_multi_union_pw_aff_free(mupa); 9463 if (!mupa) 9464 return NULL; 9465 9466 if (n == 0) 9467 return isl_multi_union_pw_aff_domain_0D(mupa); 9468 9469 upa = isl_multi_union_pw_aff_get_union_pw_aff(mupa, 0); 9470 dom = isl_union_pw_aff_domain(upa); 9471 for (i = 1; i < n; ++i) { 9472 isl_union_set *dom_i; 9473 9474 upa = isl_multi_union_pw_aff_get_union_pw_aff(mupa, i); 9475 dom_i = isl_union_pw_aff_domain(upa); 9476 dom = isl_union_set_intersect(dom, dom_i); 9477 } 9478 9479 isl_multi_union_pw_aff_free(mupa); 9480 return dom; 9481} 9482 9483/* Apply "aff" to "mupa". The space of "mupa" is equal to the domain of "aff". 9484 * In particular, the spaces have been aligned. 9485 * The result is defined over the shared domain of the elements of "mupa" 9486 * 9487 * We first extract the parametric constant part of "aff" and 9488 * define that over the shared domain. 9489 * Then we iterate over all input dimensions of "aff" and add the corresponding 9490 * multiples of the elements of "mupa". 9491 * Finally, we consider the integer divisions, calling the function 9492 * recursively to obtain an isl_union_pw_aff corresponding to the 9493 * integer division argument. 9494 */ 9495static __isl_give isl_union_pw_aff *multi_union_pw_aff_apply_aff( 9496 __isl_take isl_multi_union_pw_aff *mupa, __isl_take isl_aff *aff) 9497{ 9498 int i; 9499 isl_size n_in, n_div; 9500 isl_union_pw_aff *upa; 9501 isl_union_set *uset; 9502 isl_val *v; 9503 isl_aff *cst; 9504 9505 n_in = isl_aff_dim(aff, isl_dim_in); 9506 n_div = isl_aff_dim(aff, isl_dim_div); 9507 if (n_in < 0 || n_div < 0) 9508 goto error; 9509 9510 uset = isl_multi_union_pw_aff_domain(isl_multi_union_pw_aff_copy(mupa)); 9511 cst = isl_aff_copy(aff); 9512 cst = isl_aff_drop_dims(cst, isl_dim_div, 0, n_div); 9513 cst = isl_aff_drop_dims(cst, isl_dim_in, 0, n_in); 9514 cst = isl_aff_project_domain_on_params(cst); 9515 upa = isl_union_pw_aff_aff_on_domain(uset, cst); 9516 9517 for (i = 0; i < n_in; ++i) { 9518 isl_union_pw_aff *upa_i; 9519 9520 if (!isl_aff_involves_dims(aff, isl_dim_in, i, 1)) 9521 continue; 9522 v = isl_aff_get_coefficient_val(aff, isl_dim_in, i); 9523 upa_i = isl_multi_union_pw_aff_get_union_pw_aff(mupa, i); 9524 upa_i = isl_union_pw_aff_scale_val(upa_i, v); 9525 upa = isl_union_pw_aff_add(upa, upa_i); 9526 } 9527 9528 for (i = 0; i < n_div; ++i) { 9529 isl_aff *div; 9530 isl_union_pw_aff *upa_i; 9531 9532 if (!isl_aff_involves_dims(aff, isl_dim_div, i, 1)) 9533 continue; 9534 div = isl_aff_get_div(aff, i); 9535 upa_i = multi_union_pw_aff_apply_aff( 9536 isl_multi_union_pw_aff_copy(mupa), div); 9537 upa_i = isl_union_pw_aff_floor(upa_i); 9538 v = isl_aff_get_coefficient_val(aff, isl_dim_div, i); 9539 upa_i = isl_union_pw_aff_scale_val(upa_i, v); 9540 upa = isl_union_pw_aff_add(upa, upa_i); 9541 } 9542 9543 isl_multi_union_pw_aff_free(mupa); 9544 isl_aff_free(aff); 9545 9546 return upa; 9547error: 9548 isl_multi_union_pw_aff_free(mupa); 9549 isl_aff_free(aff); 9550 return NULL; 9551} 9552 9553/* Apply "aff" to "mupa". The space of "mupa" needs to be compatible 9554 * with the domain of "aff". 9555 * Furthermore, the dimension of this space needs to be greater than zero. 9556 * The result is defined over the shared domain of the elements of "mupa" 9557 * 9558 * We perform these checks and then hand over control to 9559 * multi_union_pw_aff_apply_aff. 9560 */ 9561__isl_give isl_union_pw_aff *isl_multi_union_pw_aff_apply_aff( 9562 __isl_take isl_multi_union_pw_aff *mupa, __isl_take isl_aff *aff) 9563{ 9564 isl_size dim; 9565 isl_space *space1, *space2; 9566 isl_bool equal; 9567 9568 mupa = isl_multi_union_pw_aff_align_params(mupa, 9569 isl_aff_get_space(aff)); 9570 aff = isl_aff_align_params(aff, isl_multi_union_pw_aff_get_space(mupa)); 9571 if (!mupa || !aff) 9572 goto error; 9573 9574 space1 = isl_multi_union_pw_aff_get_space(mupa); 9575 space2 = isl_aff_get_domain_space(aff); 9576 equal = isl_space_is_equal(space1, space2); 9577 isl_space_free(space1); 9578 isl_space_free(space2); 9579 if (equal < 0) 9580 goto error; 9581 if (!equal) 9582 isl_die(isl_aff_get_ctx(aff), isl_error_invalid, 9583 "spaces don't match", goto error); 9584 dim = isl_aff_dim(aff, isl_dim_in); 9585 if (dim < 0) 9586 goto error; 9587 if (dim == 0) 9588 isl_die(isl_aff_get_ctx(aff), isl_error_invalid, 9589 "cannot determine domains", goto error); 9590 9591 return multi_union_pw_aff_apply_aff(mupa, aff); 9592error: 9593 isl_multi_union_pw_aff_free(mupa); 9594 isl_aff_free(aff); 9595 return NULL; 9596} 9597 9598/* Apply "ma" to "mupa", in the special case where "mupa" is 0D. 9599 * The space of "mupa" is known to be compatible with the domain of "ma". 9600 * 9601 * Construct an isl_multi_union_pw_aff that is equal to "ma" 9602 * on the domain of "mupa". 9603 */ 9604static __isl_give isl_multi_union_pw_aff *mupa_apply_multi_aff_0D( 9605 __isl_take isl_multi_union_pw_aff *mupa, __isl_take isl_multi_aff *ma) 9606{ 9607 isl_union_set *dom; 9608 9609 dom = isl_multi_union_pw_aff_domain(mupa); 9610 ma = isl_multi_aff_project_domain_on_params(ma); 9611 9612 return isl_multi_union_pw_aff_multi_aff_on_domain(dom, ma); 9613} 9614 9615/* Apply "ma" to "mupa". The space of "mupa" needs to be compatible 9616 * with the domain of "ma". 9617 * The result is defined over the shared domain of the elements of "mupa" 9618 */ 9619__isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_apply_multi_aff( 9620 __isl_take isl_multi_union_pw_aff *mupa, __isl_take isl_multi_aff *ma) 9621{ 9622 isl_space *space1, *space2; 9623 isl_multi_union_pw_aff *res; 9624 isl_bool equal; 9625 int i; 9626 isl_size n_in, n_out; 9627 9628 mupa = isl_multi_union_pw_aff_align_params(mupa, 9629 isl_multi_aff_get_space(ma)); 9630 ma = isl_multi_aff_align_params(ma, 9631 isl_multi_union_pw_aff_get_space(mupa)); 9632 n_in = isl_multi_aff_dim(ma, isl_dim_in); 9633 n_out = isl_multi_aff_dim(ma, isl_dim_out); 9634 if (!mupa || n_in < 0 || n_out < 0) 9635 goto error; 9636 9637 space1 = isl_multi_union_pw_aff_get_space(mupa); 9638 space2 = isl_multi_aff_get_domain_space(ma); 9639 equal = isl_space_is_equal(space1, space2); 9640 isl_space_free(space1); 9641 isl_space_free(space2); 9642 if (equal < 0) 9643 goto error; 9644 if (!equal) 9645 isl_die(isl_multi_aff_get_ctx(ma), isl_error_invalid, 9646 "spaces don't match", goto error); 9647 if (n_in == 0) 9648 return mupa_apply_multi_aff_0D(mupa, ma); 9649 9650 space1 = isl_space_range(isl_multi_aff_get_space(ma)); 9651 res = isl_multi_union_pw_aff_alloc(space1); 9652 9653 for (i = 0; i < n_out; ++i) { 9654 isl_aff *aff; 9655 isl_union_pw_aff *upa; 9656 9657 aff = isl_multi_aff_get_aff(ma, i); 9658 upa = multi_union_pw_aff_apply_aff( 9659 isl_multi_union_pw_aff_copy(mupa), aff); 9660 res = isl_multi_union_pw_aff_set_union_pw_aff(res, i, upa); 9661 } 9662 9663 isl_multi_aff_free(ma); 9664 isl_multi_union_pw_aff_free(mupa); 9665 return res; 9666error: 9667 isl_multi_union_pw_aff_free(mupa); 9668 isl_multi_aff_free(ma); 9669 return NULL; 9670} 9671 9672/* Apply "pa" to "mupa", in the special case where "mupa" is 0D. 9673 * The space of "mupa" is known to be compatible with the domain of "pa". 9674 * 9675 * Construct an isl_multi_union_pw_aff that is equal to "pa" 9676 * on the domain of "mupa". 9677 */ 9678static __isl_give isl_union_pw_aff *isl_multi_union_pw_aff_apply_pw_aff_0D( 9679 __isl_take isl_multi_union_pw_aff *mupa, __isl_take isl_pw_aff *pa) 9680{ 9681 isl_union_set *dom; 9682 9683 dom = isl_multi_union_pw_aff_domain(mupa); 9684 pa = isl_pw_aff_project_domain_on_params(pa); 9685 9686 return isl_union_pw_aff_pw_aff_on_domain(dom, pa); 9687} 9688 9689/* Apply "pa" to "mupa". The space of "mupa" needs to be compatible 9690 * with the domain of "pa". 9691 * Furthermore, the dimension of this space needs to be greater than zero. 9692 * The result is defined over the shared domain of the elements of "mupa" 9693 */ 9694__isl_give isl_union_pw_aff *isl_multi_union_pw_aff_apply_pw_aff( 9695 __isl_take isl_multi_union_pw_aff *mupa, __isl_take isl_pw_aff *pa) 9696{ 9697 int i; 9698 isl_bool equal; 9699 isl_size n_in; 9700 isl_space *space, *space2; 9701 isl_union_pw_aff *upa; 9702 9703 mupa = isl_multi_union_pw_aff_align_params(mupa, 9704 isl_pw_aff_get_space(pa)); 9705 pa = isl_pw_aff_align_params(pa, 9706 isl_multi_union_pw_aff_get_space(mupa)); 9707 if (!mupa || !pa) 9708 goto error; 9709 9710 space = isl_multi_union_pw_aff_get_space(mupa); 9711 space2 = isl_pw_aff_get_domain_space(pa); 9712 equal = isl_space_is_equal(space, space2); 9713 isl_space_free(space); 9714 isl_space_free(space2); 9715 if (equal < 0) 9716 goto error; 9717 if (!equal) 9718 isl_die(isl_pw_aff_get_ctx(pa), isl_error_invalid, 9719 "spaces don't match", goto error); 9720 n_in = isl_pw_aff_dim(pa, isl_dim_in); 9721 if (n_in < 0) 9722 goto error; 9723 if (n_in == 0) 9724 return isl_multi_union_pw_aff_apply_pw_aff_0D(mupa, pa); 9725 9726 space = isl_space_params(isl_multi_union_pw_aff_get_space(mupa)); 9727 upa = isl_union_pw_aff_empty(space); 9728 9729 for (i = 0; i < pa->n; ++i) { 9730 isl_aff *aff; 9731 isl_set *domain; 9732 isl_multi_union_pw_aff *mupa_i; 9733 isl_union_pw_aff *upa_i; 9734 9735 mupa_i = isl_multi_union_pw_aff_copy(mupa); 9736 domain = isl_set_copy(pa->p[i].set); 9737 mupa_i = isl_multi_union_pw_aff_intersect_range(mupa_i, domain); 9738 aff = isl_aff_copy(pa->p[i].aff); 9739 upa_i = multi_union_pw_aff_apply_aff(mupa_i, aff); 9740 upa = isl_union_pw_aff_union_add(upa, upa_i); 9741 } 9742 9743 isl_multi_union_pw_aff_free(mupa); 9744 isl_pw_aff_free(pa); 9745 return upa; 9746error: 9747 isl_multi_union_pw_aff_free(mupa); 9748 isl_pw_aff_free(pa); 9749 return NULL; 9750} 9751 9752/* Apply "pma" to "mupa", in the special case where "mupa" is 0D. 9753 * The space of "mupa" is known to be compatible with the domain of "pma". 9754 * 9755 * Construct an isl_multi_union_pw_aff that is equal to "pma" 9756 * on the domain of "mupa". 9757 */ 9758static __isl_give isl_multi_union_pw_aff *mupa_apply_pw_multi_aff_0D( 9759 __isl_take isl_multi_union_pw_aff *mupa, 9760 __isl_take isl_pw_multi_aff *pma) 9761{ 9762 isl_union_set *dom; 9763 9764 dom = isl_multi_union_pw_aff_domain(mupa); 9765 pma = isl_pw_multi_aff_project_domain_on_params(pma); 9766 9767 return isl_multi_union_pw_aff_pw_multi_aff_on_domain(dom, pma); 9768} 9769 9770/* Apply "pma" to "mupa". The space of "mupa" needs to be compatible 9771 * with the domain of "pma". 9772 * The result is defined over the shared domain of the elements of "mupa" 9773 */ 9774__isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_apply_pw_multi_aff( 9775 __isl_take isl_multi_union_pw_aff *mupa, 9776 __isl_take isl_pw_multi_aff *pma) 9777{ 9778 isl_space *space1, *space2; 9779 isl_multi_union_pw_aff *res; 9780 isl_bool equal; 9781 int i; 9782 isl_size n_in, n_out; 9783 9784 mupa = isl_multi_union_pw_aff_align_params(mupa, 9785 isl_pw_multi_aff_get_space(pma)); 9786 pma = isl_pw_multi_aff_align_params(pma, 9787 isl_multi_union_pw_aff_get_space(mupa)); 9788 if (!mupa || !pma) 9789 goto error; 9790 9791 space1 = isl_multi_union_pw_aff_get_space(mupa); 9792 space2 = isl_pw_multi_aff_get_domain_space(pma); 9793 equal = isl_space_is_equal(space1, space2); 9794 isl_space_free(space1); 9795 isl_space_free(space2); 9796 if (equal < 0) 9797 goto error; 9798 if (!equal) 9799 isl_die(isl_pw_multi_aff_get_ctx(pma), isl_error_invalid, 9800 "spaces don't match", goto error); 9801 n_in = isl_pw_multi_aff_dim(pma, isl_dim_in); 9802 n_out = isl_pw_multi_aff_dim(pma, isl_dim_out); 9803 if (n_in < 0 || n_out < 0) 9804 goto error; 9805 if (n_in == 0) 9806 return mupa_apply_pw_multi_aff_0D(mupa, pma); 9807 9808 space1 = isl_space_range(isl_pw_multi_aff_get_space(pma)); 9809 res = isl_multi_union_pw_aff_alloc(space1); 9810 9811 for (i = 0; i < n_out; ++i) { 9812 isl_pw_aff *pa; 9813 isl_union_pw_aff *upa; 9814 9815 pa = isl_pw_multi_aff_get_pw_aff(pma, i); 9816 upa = isl_multi_union_pw_aff_apply_pw_aff( 9817 isl_multi_union_pw_aff_copy(mupa), pa); 9818 res = isl_multi_union_pw_aff_set_union_pw_aff(res, i, upa); 9819 } 9820 9821 isl_pw_multi_aff_free(pma); 9822 isl_multi_union_pw_aff_free(mupa); 9823 return res; 9824error: 9825 isl_multi_union_pw_aff_free(mupa); 9826 isl_pw_multi_aff_free(pma); 9827 return NULL; 9828} 9829 9830/* Replace the explicit domain of "mupa" by its preimage under "upma". 9831 * If the explicit domain only keeps track of constraints on the parameters, 9832 * then only update those constraints. 9833 */ 9834static __isl_give isl_multi_union_pw_aff *preimage_explicit_domain( 9835 __isl_take isl_multi_union_pw_aff *mupa, 9836 __isl_keep isl_union_pw_multi_aff *upma) 9837{ 9838 isl_bool is_params; 9839 9840 if (isl_multi_union_pw_aff_check_has_explicit_domain(mupa) < 0) 9841 return isl_multi_union_pw_aff_free(mupa); 9842 9843 mupa = isl_multi_union_pw_aff_cow(mupa); 9844 if (!mupa) 9845 return NULL; 9846 9847 is_params = isl_union_set_is_params(mupa->u.dom); 9848 if (is_params < 0) 9849 return isl_multi_union_pw_aff_free(mupa); 9850 9851 upma = isl_union_pw_multi_aff_copy(upma); 9852 if (is_params) 9853 mupa->u.dom = isl_union_set_intersect_params(mupa->u.dom, 9854 isl_union_set_params(isl_union_pw_multi_aff_domain(upma))); 9855 else 9856 mupa->u.dom = isl_union_set_preimage_union_pw_multi_aff( 9857 mupa->u.dom, upma); 9858 if (!mupa->u.dom) 9859 return isl_multi_union_pw_aff_free(mupa); 9860 return mupa; 9861} 9862 9863/* Compute the pullback of "mupa" by the function represented by "upma". 9864 * In other words, plug in "upma" in "mupa". The result contains 9865 * expressions defined over the domain space of "upma". 9866 * 9867 * Run over all elements of "mupa" and plug in "upma" in each of them. 9868 * 9869 * If "mupa" has an explicit domain, then it is this domain 9870 * that needs to undergo a pullback instead, i.e., a preimage. 9871 */ 9872__isl_give isl_multi_union_pw_aff * 9873isl_multi_union_pw_aff_pullback_union_pw_multi_aff( 9874 __isl_take isl_multi_union_pw_aff *mupa, 9875 __isl_take isl_union_pw_multi_aff *upma) 9876{ 9877 int i; 9878 isl_size n; 9879 9880 mupa = isl_multi_union_pw_aff_align_params(mupa, 9881 isl_union_pw_multi_aff_get_space(upma)); 9882 upma = isl_union_pw_multi_aff_align_params(upma, 9883 isl_multi_union_pw_aff_get_space(mupa)); 9884 mupa = isl_multi_union_pw_aff_cow(mupa); 9885 n = isl_multi_union_pw_aff_dim(mupa, isl_dim_set); 9886 if (n < 0 || !upma) 9887 goto error; 9888 9889 for (i = 0; i < n; ++i) { 9890 isl_union_pw_aff *upa; 9891 9892 upa = isl_multi_union_pw_aff_get_union_pw_aff(mupa, i); 9893 upa = isl_union_pw_aff_pullback_union_pw_multi_aff(upa, 9894 isl_union_pw_multi_aff_copy(upma)); 9895 mupa = isl_multi_union_pw_aff_set_union_pw_aff(mupa, i, upa); 9896 } 9897 9898 if (isl_multi_union_pw_aff_has_explicit_domain(mupa)) 9899 mupa = preimage_explicit_domain(mupa, upma); 9900 9901 isl_union_pw_multi_aff_free(upma); 9902 return mupa; 9903error: 9904 isl_multi_union_pw_aff_free(mupa); 9905 isl_union_pw_multi_aff_free(upma); 9906 return NULL; 9907} 9908 9909/* Extract the sequence of elements in "mupa" with domain space "space" 9910 * (ignoring parameters). 9911 * 9912 * For the elements of "mupa" that are not defined on the specified space, 9913 * the corresponding element in the result is empty. 9914 */ 9915__isl_give isl_multi_pw_aff *isl_multi_union_pw_aff_extract_multi_pw_aff( 9916 __isl_keep isl_multi_union_pw_aff *mupa, __isl_take isl_space *space) 9917{ 9918 int i; 9919 isl_size n; 9920 isl_space *space_mpa; 9921 isl_multi_pw_aff *mpa; 9922 9923 n = isl_multi_union_pw_aff_dim(mupa, isl_dim_set); 9924 if (n < 0 || !space) 9925 goto error; 9926 9927 space_mpa = isl_multi_union_pw_aff_get_space(mupa); 9928 space = isl_space_replace_params(space, space_mpa); 9929 space_mpa = isl_space_map_from_domain_and_range(isl_space_copy(space), 9930 space_mpa); 9931 mpa = isl_multi_pw_aff_alloc(space_mpa); 9932 9933 space = isl_space_from_domain(space); 9934 space = isl_space_add_dims(space, isl_dim_out, 1); 9935 for (i = 0; i < n; ++i) { 9936 isl_union_pw_aff *upa; 9937 isl_pw_aff *pa; 9938 9939 upa = isl_multi_union_pw_aff_get_union_pw_aff(mupa, i); 9940 pa = isl_union_pw_aff_extract_pw_aff(upa, 9941 isl_space_copy(space)); 9942 mpa = isl_multi_pw_aff_set_pw_aff(mpa, i, pa); 9943 isl_union_pw_aff_free(upa); 9944 } 9945 9946 isl_space_free(space); 9947 return mpa; 9948error: 9949 isl_space_free(space); 9950 return NULL; 9951} 9952 9953/* Data structure that specifies how isl_union_pw_multi_aff_un_op 9954 * should modify the base expressions in the input. 9955 * 9956 * If "filter" is not NULL, then only the base expressions that satisfy "filter" 9957 * are taken into account. 9958 * "fn" is applied to each entry in the input. 9959 */ 9960struct isl_union_pw_multi_aff_un_op_control { 9961 isl_bool (*filter)(__isl_keep isl_pw_multi_aff *part); 9962 __isl_give isl_pw_multi_aff *(*fn)(__isl_take isl_pw_multi_aff *pma); 9963}; 9964 9965/* Wrapper for isl_union_pw_multi_aff_un_op filter functions (which do not take 9966 * a second argument) for use as an isl_union_pw_multi_aff_transform 9967 * filter function (which does take a second argument). 9968 * Simply call control->filter without the second argument. 9969 */ 9970static isl_bool isl_union_pw_multi_aff_un_op_filter_drop_user( 9971 __isl_take isl_pw_multi_aff *pma, void *user) 9972{ 9973 struct isl_union_pw_multi_aff_un_op_control *control = user; 9974 9975 return control->filter(pma); 9976} 9977 9978/* Wrapper for isl_union_pw_multi_aff_un_op base functions (which do not take 9979 * a second argument) for use as an isl_union_pw_multi_aff_transform 9980 * base function (which does take a second argument). 9981 * Simply call control->fn without the second argument. 9982 */ 9983static __isl_give isl_pw_multi_aff *isl_union_pw_multi_aff_un_op_drop_user( 9984 __isl_take isl_pw_multi_aff *pma, void *user) 9985{ 9986 struct isl_union_pw_multi_aff_un_op_control *control = user; 9987 9988 return control->fn(pma); 9989} 9990 9991/* Construct an isl_union_pw_multi_aff that is obtained by 9992 * modifying "upma" according to "control". 9993 * 9994 * isl_union_pw_multi_aff_transform performs essentially 9995 * the same operation, but takes a filter and a callback function 9996 * of a different form (with an extra argument). 9997 * Call isl_union_pw_multi_aff_transform with wrappers 9998 * that remove this extra argument. 9999 */ 10000static __isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_un_op( 10001 __isl_take isl_union_pw_multi_aff *upma, 10002 struct isl_union_pw_multi_aff_un_op_control *control) 10003{ 10004 struct isl_union_pw_multi_aff_transform_control t_control = { 10005 .filter = &isl_union_pw_multi_aff_un_op_filter_drop_user, 10006 .filter_user = control, 10007 .fn = &isl_union_pw_multi_aff_un_op_drop_user, 10008 .fn_user = control, 10009 }; 10010 10011 return isl_union_pw_multi_aff_transform(upma, &t_control); 10012} 10013 10014/* For each function in "upma" of the form A -> [B -> C], 10015 * extract the function A -> B and collect the results. 10016 */ 10017__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_range_factor_domain( 10018 __isl_take isl_union_pw_multi_aff *upma) 10019{ 10020 struct isl_union_pw_multi_aff_un_op_control control = { 10021 .filter = &isl_pw_multi_aff_range_is_wrapping, 10022 .fn = &isl_pw_multi_aff_range_factor_domain, 10023 }; 10024 return isl_union_pw_multi_aff_un_op(upma, &control); 10025} 10026 10027/* For each function in "upma" of the form A -> [B -> C], 10028 * extract the function A -> C and collect the results. 10029 */ 10030__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_range_factor_range( 10031 __isl_take isl_union_pw_multi_aff *upma) 10032{ 10033 struct isl_union_pw_multi_aff_un_op_control control = { 10034 .filter = &isl_pw_multi_aff_range_is_wrapping, 10035 .fn = &isl_pw_multi_aff_range_factor_range, 10036 }; 10037 return isl_union_pw_multi_aff_un_op(upma, &control); 10038} 10039 10040/* Evaluate the affine function "aff" in the void point "pnt". 10041 * In particular, return the value NaN. 10042 */ 10043static __isl_give isl_val *eval_void(__isl_take isl_aff *aff, 10044 __isl_take isl_point *pnt) 10045{ 10046 isl_ctx *ctx; 10047 10048 ctx = isl_point_get_ctx(pnt); 10049 isl_aff_free(aff); 10050 isl_point_free(pnt); 10051 return isl_val_nan(ctx); 10052} 10053 10054/* Evaluate the affine expression "aff" 10055 * in the coordinates (with denominator) "pnt". 10056 */ 10057static __isl_give isl_val *eval(__isl_keep isl_vec *aff, 10058 __isl_keep isl_vec *pnt) 10059{ 10060 isl_int n, d; 10061 isl_ctx *ctx; 10062 isl_val *v; 10063 10064 if (!aff || !pnt) 10065 return NULL; 10066 10067 ctx = isl_vec_get_ctx(aff); 10068 isl_int_init(n); 10069 isl_int_init(d); 10070 isl_seq_inner_product(aff->el + 1, pnt->el, pnt->size, &n); 10071 isl_int_mul(d, aff->el[0], pnt->el[0]); 10072 v = isl_val_rat_from_isl_int(ctx, n, d); 10073 v = isl_val_normalize(v); 10074 isl_int_clear(n); 10075 isl_int_clear(d); 10076 10077 return v; 10078} 10079 10080/* Check that the domain space of "aff" is equal to "space". 10081 */ 10082static isl_stat isl_aff_check_has_domain_space(__isl_keep isl_aff *aff, 10083 __isl_keep isl_space *space) 10084{ 10085 isl_bool ok; 10086 10087 ok = isl_space_is_equal(isl_aff_peek_domain_space(aff), space); 10088 if (ok < 0) 10089 return isl_stat_error; 10090 if (!ok) 10091 isl_die(isl_aff_get_ctx(aff), isl_error_invalid, 10092 "incompatible spaces", return isl_stat_error); 10093 return isl_stat_ok; 10094} 10095 10096/* Evaluate the affine function "aff" in "pnt". 10097 */ 10098__isl_give isl_val *isl_aff_eval(__isl_take isl_aff *aff, 10099 __isl_take isl_point *pnt) 10100{ 10101 isl_bool is_void; 10102 isl_val *v; 10103 isl_local_space *ls; 10104 10105 if (isl_aff_check_has_domain_space(aff, isl_point_peek_space(pnt)) < 0) 10106 goto error; 10107 is_void = isl_point_is_void(pnt); 10108 if (is_void < 0) 10109 goto error; 10110 if (is_void) 10111 return eval_void(aff, pnt); 10112 10113 ls = isl_aff_get_domain_local_space(aff); 10114 pnt = isl_local_space_lift_point(ls, pnt); 10115 10116 v = eval(aff->v, isl_point_peek_vec(pnt)); 10117 10118 isl_aff_free(aff); 10119 isl_point_free(pnt); 10120 10121 return v; 10122error: 10123 isl_aff_free(aff); 10124 isl_point_free(pnt); 10125 return NULL; 10126} 10127