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