1 1.1 mrg /* 2 1.1 mrg * Copyright 2011 Sven Verdoolaege 3 1.1 mrg * Copyright 2012-2014 Ecole Normale Superieure 4 1.1 mrg * 5 1.1 mrg * Use of this software is governed by the MIT license 6 1.1 mrg * 7 1.1 mrg * Written by Sven Verdoolaege, 8 1.1 mrg * Ecole Normale Superieure, 45 rue dUlm, 75230 Paris, France 9 1.1 mrg */ 10 1.1 mrg 11 1.1 mrg #include <isl/id.h> 12 1.1 mrg #include <isl_space_private.h> 13 1.1 mrg #include <isl/set.h> 14 1.1 mrg #include <isl_reordering.h> 15 1.1 mrg 16 1.1 mrg #include <isl_multi_macro.h> 17 1.1 mrg 18 1.1 mrg #define MULTI_NAME(BASE) "isl_multi_" #BASE 19 1.1 mrg 20 1.1 mrg isl_ctx *FN(MULTI(BASE),get_ctx)(__isl_keep MULTI(BASE) *multi) 21 1.1 mrg { 22 1.1 mrg return multi ? isl_space_get_ctx(multi->space) : NULL; 23 1.1 mrg } 24 1.1 mrg 25 1.1 mrg /* Return the space of "multi". 26 1.1 mrg */ 27 1.1 mrg __isl_keep isl_space *FN(MULTI(BASE),peek_space)(__isl_keep MULTI(BASE) *multi) 28 1.1 mrg { 29 1.1 mrg return multi ? multi->space : NULL; 30 1.1 mrg } 31 1.1 mrg 32 1.1 mrg __isl_give isl_space *FN(MULTI(BASE),get_space)(__isl_keep MULTI(BASE) *multi) 33 1.1 mrg { 34 1.1 mrg return isl_space_copy(FN(MULTI(BASE),peek_space)(multi)); 35 1.1 mrg } 36 1.1 mrg 37 1.1 mrg __isl_give isl_space *FN(MULTI(BASE),get_domain_space)( 38 1.1 mrg __isl_keep MULTI(BASE) *multi) 39 1.1 mrg { 40 1.1 mrg return multi ? isl_space_domain(isl_space_copy(multi->space)) : NULL; 41 1.1 mrg } 42 1.1 mrg 43 1.1 mrg /* Allocate a multi expression living in "space". 44 1.1 mrg * 45 1.1 mrg * If the number of base expressions is zero, then make sure 46 1.1 mrg * there is enough room in the structure for the explicit domain, 47 1.1 mrg * in case the type supports such an explicit domain. 48 1.1 mrg */ 49 1.1 mrg __isl_give MULTI(BASE) *FN(MULTI(BASE),alloc)(__isl_take isl_space *space) 50 1.1 mrg { 51 1.1 mrg isl_ctx *ctx; 52 1.1 mrg isl_size n; 53 1.1 mrg MULTI(BASE) *multi; 54 1.1 mrg 55 1.1 mrg n = isl_space_dim(space, isl_dim_out); 56 1.1 mrg if (n < 0) 57 1.1 mrg goto error; 58 1.1 mrg 59 1.1 mrg ctx = isl_space_get_ctx(space); 60 1.1 mrg if (n > 0) 61 1.1 mrg multi = isl_calloc(ctx, MULTI(BASE), 62 1.1 mrg sizeof(MULTI(BASE)) + (n - 1) * sizeof(struct EL *)); 63 1.1 mrg else 64 1.1 mrg multi = isl_calloc(ctx, MULTI(BASE), sizeof(MULTI(BASE))); 65 1.1 mrg if (!multi) 66 1.1 mrg goto error; 67 1.1 mrg 68 1.1 mrg multi->space = space; 69 1.1 mrg multi->n = n; 70 1.1 mrg multi->ref = 1; 71 1.1 mrg if (FN(MULTI(BASE),has_explicit_domain)(multi)) 72 1.1 mrg multi = FN(MULTI(BASE),init_explicit_domain)(multi); 73 1.1 mrg return multi; 74 1.1 mrg error: 75 1.1 mrg isl_space_free(space); 76 1.1 mrg return NULL; 77 1.1 mrg } 78 1.1 mrg 79 1.1 mrg __isl_give MULTI(BASE) *FN(MULTI(BASE),dup)(__isl_keep MULTI(BASE) *multi) 80 1.1 mrg { 81 1.1 mrg int i; 82 1.1 mrg MULTI(BASE) *dup; 83 1.1 mrg 84 1.1 mrg if (!multi) 85 1.1 mrg return NULL; 86 1.1 mrg 87 1.1 mrg dup = FN(MULTI(BASE),alloc)(isl_space_copy(multi->space)); 88 1.1 mrg if (!dup) 89 1.1 mrg return NULL; 90 1.1 mrg 91 1.1 mrg for (i = 0; i < multi->n; ++i) 92 1.1 mrg dup = FN(FN(MULTI(BASE),set),BASE)(dup, i, 93 1.1 mrg FN(EL,copy)(multi->u.p[i])); 94 1.1 mrg if (FN(MULTI(BASE),has_explicit_domain)(multi)) 95 1.1 mrg dup = FN(MULTI(BASE),copy_explicit_domain)(dup, multi); 96 1.1 mrg 97 1.1 mrg return dup; 98 1.1 mrg } 99 1.1 mrg 100 1.1 mrg __isl_give MULTI(BASE) *FN(MULTI(BASE),cow)(__isl_take MULTI(BASE) *multi) 101 1.1 mrg { 102 1.1 mrg if (!multi) 103 1.1 mrg return NULL; 104 1.1 mrg 105 1.1 mrg if (multi->ref == 1) 106 1.1 mrg return multi; 107 1.1 mrg 108 1.1 mrg multi->ref--; 109 1.1 mrg return FN(MULTI(BASE),dup)(multi); 110 1.1 mrg } 111 1.1 mrg 112 1.1 mrg __isl_give MULTI(BASE) *FN(MULTI(BASE),copy)(__isl_keep MULTI(BASE) *multi) 113 1.1 mrg { 114 1.1 mrg if (!multi) 115 1.1 mrg return NULL; 116 1.1 mrg 117 1.1 mrg multi->ref++; 118 1.1 mrg return multi; 119 1.1 mrg } 120 1.1 mrg 121 1.1 mrg __isl_null MULTI(BASE) *FN(MULTI(BASE),free)(__isl_take MULTI(BASE) *multi) 122 1.1 mrg { 123 1.1 mrg int i; 124 1.1 mrg 125 1.1 mrg if (!multi) 126 1.1 mrg return NULL; 127 1.1 mrg 128 1.1 mrg if (--multi->ref > 0) 129 1.1 mrg return NULL; 130 1.1 mrg 131 1.1 mrg isl_space_free(multi->space); 132 1.1 mrg for (i = 0; i < multi->n; ++i) 133 1.1 mrg FN(EL,free)(multi->u.p[i]); 134 1.1 mrg if (FN(MULTI(BASE),has_explicit_domain)(multi)) 135 1.1 mrg FN(MULTI(BASE),free_explicit_domain)(multi); 136 1.1 mrg free(multi); 137 1.1 mrg 138 1.1 mrg return NULL; 139 1.1 mrg } 140 1.1 mrg 141 1.1 mrg /* Return the space of "multi". 142 1.1 mrg * The caller is not allowed to modify "multi" between this call 143 1.1 mrg * and the call to *_restore_space because the number 144 1.1 mrg * of references needs to stay the same. 145 1.1 mrg * The only exception is that isl_multi_*_free can be called instead. 146 1.1 mrg * No copy is taken of multi->space if "multi" has only one reference 147 1.1 mrg * such that it can be modified inplace if both have only a single reference. 148 1.1 mrg */ 149 1.1 mrg __isl_give isl_space *FN(MULTI(BASE),take_space)(__isl_keep MULTI(BASE) *multi) 150 1.1 mrg { 151 1.1 mrg isl_space *space; 152 1.1 mrg 153 1.1 mrg if (!multi) 154 1.1 mrg return NULL; 155 1.1 mrg if (multi->ref != 1) 156 1.1 mrg return FN(MULTI(BASE),get_space)(multi); 157 1.1 mrg space = multi->space; 158 1.1 mrg multi->space = NULL; 159 1.1 mrg return space; 160 1.1 mrg } 161 1.1 mrg 162 1.1 mrg /* Set the space of "multi" to "space", where the space of "multi" 163 1.1 mrg * may be missing due to a preceding call to isl_multi_*_take_space. 164 1.1 mrg * However, in this case, "multi" only has a single reference and 165 1.1 mrg * then the call to isl_multi_*_cow has no effect. 166 1.1 mrg */ 167 1.1 mrg __isl_give MULTI(BASE) *FN(MULTI(BASE),restore_space)( 168 1.1 mrg __isl_take MULTI(BASE) *multi, __isl_take isl_space *space) 169 1.1 mrg { 170 1.1 mrg if (!multi || !space) 171 1.1 mrg goto error; 172 1.1 mrg 173 1.1 mrg if (multi->space == space) { 174 1.1 mrg isl_space_free(space); 175 1.1 mrg return multi; 176 1.1 mrg } 177 1.1 mrg 178 1.1 mrg multi = FN(MULTI(BASE),cow)(multi); 179 1.1 mrg if (!multi) 180 1.1 mrg goto error; 181 1.1 mrg isl_space_free(multi->space); 182 1.1 mrg multi->space = space; 183 1.1 mrg 184 1.1 mrg return multi; 185 1.1 mrg error: 186 1.1 mrg FN(MULTI(BASE),free)(multi); 187 1.1 mrg isl_space_free(space); 188 1.1 mrg return NULL; 189 1.1 mrg } 190 1.1 mrg 191 1.1 mrg isl_size FN(MULTI(BASE),dim)(__isl_keep MULTI(BASE) *multi, 192 1.1 mrg enum isl_dim_type type) 193 1.1 mrg { 194 1.1 mrg return isl_space_dim(FN(MULTI(BASE),peek_space)(multi), type); 195 1.1 mrg } 196 1.1 mrg 197 1.1 mrg /* Return the number of base expressions in "multi". 198 1.1 mrg */ 199 1.1 mrg isl_size FN(MULTI(BASE),size)(__isl_keep MULTI(BASE) *multi) 200 1.1 mrg { 201 1.1 mrg return multi ? multi->n : isl_size_error; 202 1.1 mrg } 203 1.1 mrg 204 1.1 mrg #undef TYPE 205 1.1 mrg #define TYPE MULTI(BASE) 206 1.1 mrg static 207 1.1 mrg #include "check_type_range_templ.c" 208 1.1 mrg 209 1.1 mrg /* Return the base expression at position "pos" in "multi". 210 1.1 mrg */ 211 1.1 mrg static __isl_give EL *FN(MULTI(BASE),peek_at)(__isl_keep MULTI(BASE) *multi, 212 1.1 mrg int pos) 213 1.1 mrg { 214 1.1 mrg if (FN(MULTI(BASE),check_range)(multi, isl_dim_out, pos, 1) < 0) 215 1.1 mrg return NULL; 216 1.1 mrg return multi->u.p[pos]; 217 1.1 mrg } 218 1.1 mrg 219 1.1 mrg /* Return a copy of the base expression at position "pos" in "multi". 220 1.1 mrg */ 221 1.1 mrg __isl_give EL *FN(MULTI(BASE),get_at)(__isl_keep MULTI(BASE) *multi, int pos) 222 1.1 mrg { 223 1.1 mrg return FN(EL,copy)(FN(MULTI(BASE),peek_at)(multi, pos)); 224 1.1 mrg } 225 1.1 mrg 226 1.1 mrg /* This is an alternative name for the function above. 227 1.1 mrg */ 228 1.1 mrg __isl_give EL *FN(FN(MULTI(BASE),get),BASE)(__isl_keep MULTI(BASE) *multi, 229 1.1 mrg int pos) 230 1.1 mrg { 231 1.1 mrg return FN(MULTI(BASE),get_at)(multi, pos); 232 1.1 mrg } 233 1.1 mrg 234 1.1 mrg /* Return the base expression at position "pos" in "multi". 235 1.1 mrg * This may be either a copy or the base expression itself 236 1.1 mrg * if there is only one reference to "multi". 237 1.1 mrg * This allows the base expression to be modified inplace 238 1.1 mrg * if both the multi expression and this base expression 239 1.1 mrg * have only a single reference. 240 1.1 mrg * The caller is not allowed to modify "multi" between this call and 241 1.1 mrg * the subsequent call to isl_multi_*_restore_at_*. 242 1.1 mrg * The only exception is that isl_multi_*_free can be called instead. 243 1.1 mrg */ 244 1.1 mrg static __isl_give EL *FN(MULTI(BASE),take_at)(__isl_keep MULTI(BASE) *multi, 245 1.1 mrg int pos) 246 1.1 mrg { 247 1.1 mrg EL *el; 248 1.1 mrg 249 1.1 mrg if (!multi) 250 1.1 mrg return NULL; 251 1.1 mrg if (multi->ref != 1) 252 1.1 mrg return FN(MULTI(BASE),get_at)(multi, pos); 253 1.1 mrg if (FN(MULTI(BASE),check_range)(multi, isl_dim_out, pos, 1) < 0) 254 1.1 mrg return NULL; 255 1.1 mrg el = multi->u.p[pos]; 256 1.1 mrg multi->u.p[pos] = NULL; 257 1.1 mrg return el; 258 1.1 mrg } 259 1.1 mrg 260 1.1 mrg /* Set the element at position "pos" of "multi" to "el", 261 1.1 mrg * where the position may be empty if "multi" has only a single reference. 262 1.1 mrg */ 263 1.1 mrg static __isl_give MULTI(BASE) *FN(MULTI(BASE),restore_at)( 264 1.1 mrg __isl_take MULTI(BASE) *multi, int pos, __isl_take EL *el) 265 1.1 mrg { 266 1.1 mrg if (FN(MULTI(BASE),check_range)(multi, isl_dim_out, pos, 1) < 0 || !el) 267 1.1 mrg goto error; 268 1.1 mrg 269 1.1 mrg if (multi->u.p[pos] == el) { 270 1.1 mrg FN(EL,free)(el); 271 1.1 mrg return multi; 272 1.1 mrg } 273 1.1 mrg 274 1.1 mrg multi = FN(MULTI(BASE),cow)(multi); 275 1.1 mrg if (!multi) 276 1.1 mrg goto error; 277 1.1 mrg 278 1.1 mrg FN(EL,free)(multi->u.p[pos]); 279 1.1 mrg multi->u.p[pos] = el; 280 1.1 mrg 281 1.1 mrg return multi; 282 1.1 mrg error: 283 1.1 mrg FN(MULTI(BASE),free)(multi); 284 1.1 mrg FN(EL,free)(el); 285 1.1 mrg return NULL; 286 1.1 mrg } 287 1.1 mrg 288 1.1 mrg /* Set the element at position "pos" of "multi" to "el", 289 1.1 mrg * where the position may be empty if "multi" has only a single reference. 290 1.1 mrg * However, the space of "multi" is available and is checked 291 1.1 mrg * for compatibility with "el". 292 1.1 mrg */ 293 1.1 mrg static __isl_give MULTI(BASE) *FN(MULTI(BASE),restore_check_space)( 294 1.1 mrg __isl_take MULTI(BASE) *multi, int pos, __isl_take EL *el) 295 1.1 mrg { 296 1.1 mrg isl_space *space; 297 1.1 mrg 298 1.1 mrg space = FN(MULTI(BASE),peek_space)(multi); 299 1.1 mrg if (FN(EL,check_match_domain_space)(el, space) < 0) 300 1.1 mrg multi = FN(MULTI(BASE),free)(multi); 301 1.1 mrg return FN(MULTI(BASE),restore_at)(multi, pos, el); 302 1.1 mrg } 303 1.1 mrg 304 1.1 mrg /* Replace the base expression at position "pos" in "multi" with "el". 305 1.1 mrg */ 306 1.1 mrg __isl_give MULTI(BASE) *FN(MULTI(BASE),set_at)( 307 1.1 mrg __isl_take MULTI(BASE) *multi, int pos, __isl_take EL *el) 308 1.1 mrg { 309 1.1 mrg isl_space *multi_space = NULL; 310 1.1 mrg isl_space *el_space = NULL; 311 1.1 mrg isl_bool match; 312 1.1 mrg 313 1.1 mrg multi_space = FN(MULTI(BASE),get_space)(multi); 314 1.1 mrg match = FN(EL,matching_params)(el, multi_space); 315 1.1 mrg if (match < 0) 316 1.1 mrg goto error; 317 1.1 mrg if (!match) { 318 1.1 mrg multi = FN(MULTI(BASE),align_params)(multi, 319 1.1 mrg FN(EL,get_space)(el)); 320 1.1 mrg isl_space_free(multi_space); 321 1.1 mrg multi_space = FN(MULTI(BASE),get_space)(multi); 322 1.1 mrg el = FN(EL,align_params)(el, isl_space_copy(multi_space)); 323 1.1 mrg } 324 1.1 mrg 325 1.1 mrg multi = FN(MULTI(BASE),restore_check_space)(multi, pos, el); 326 1.1 mrg 327 1.1 mrg isl_space_free(multi_space); 328 1.1 mrg isl_space_free(el_space); 329 1.1 mrg 330 1.1 mrg return multi; 331 1.1 mrg error: 332 1.1 mrg FN(MULTI(BASE),free)(multi); 333 1.1 mrg FN(EL,free)(el); 334 1.1 mrg isl_space_free(multi_space); 335 1.1 mrg isl_space_free(el_space); 336 1.1 mrg return NULL; 337 1.1 mrg } 338 1.1 mrg 339 1.1 mrg /* This is an alternative name for the function above. 340 1.1 mrg */ 341 1.1 mrg __isl_give MULTI(BASE) *FN(FN(MULTI(BASE),set),BASE)( 342 1.1 mrg __isl_take MULTI(BASE) *multi, int pos, __isl_take EL *el) 343 1.1 mrg { 344 1.1 mrg return FN(MULTI(BASE),set_at)(multi, pos, el); 345 1.1 mrg } 346 1.1 mrg 347 1.1 mrg /* Return the base expressions of "multi" as a list. 348 1.1 mrg */ 349 1.1 mrg __isl_give LIST(EL) *FN(MULTI(BASE),get_list)( 350 1.1 mrg __isl_keep MULTI(BASE) *multi) 351 1.1 mrg { 352 1.1 mrg isl_size n; 353 1.1 mrg int i; 354 1.1 mrg LIST(EL) *list; 355 1.1 mrg 356 1.1 mrg n = FN(MULTI(BASE),size)(multi); 357 1.1 mrg if (n < 0) 358 1.1 mrg return NULL; 359 1.1 mrg list = FN(LIST(EL),alloc)(FN(MULTI(BASE),get_ctx(multi)), n); 360 1.1 mrg for (i = 0; i < n; ++i) { 361 1.1 mrg EL *el = FN(MULTI(BASE),get_at)(multi, i); 362 1.1 mrg list = FN(LIST(EL),add)(list, el); 363 1.1 mrg } 364 1.1 mrg 365 1.1 mrg return list; 366 1.1 mrg } 367 1.1 mrg 368 1.1 mrg /* Reset the space of "multi". This function is called from isl_pw_templ.c 369 1.1 mrg * and doesn't know if the space of an element object is represented 370 1.1 mrg * directly or through its domain. It therefore passes along both, 371 1.1 mrg * which we pass along to the element function since we don't know how 372 1.1 mrg * that is represented either. 373 1.1 mrg * 374 1.1 mrg * If "multi" has an explicit domain, then the caller is expected 375 1.1 mrg * to make sure that any modification that would change the dimensions 376 1.1 mrg * of the explicit domain has bee applied before this function is called. 377 1.1 mrg */ 378 1.1 mrg __isl_give MULTI(BASE) *FN(MULTI(BASE),reset_space_and_domain)( 379 1.1 mrg __isl_take MULTI(BASE) *multi, __isl_take isl_space *space, 380 1.1 mrg __isl_take isl_space *domain) 381 1.1 mrg { 382 1.1 mrg isl_size n; 383 1.1 mrg int i; 384 1.1 mrg 385 1.1 mrg n = FN(MULTI(BASE),size)(multi); 386 1.1 mrg if (n < 0 || !space || !domain) 387 1.1 mrg goto error; 388 1.1 mrg 389 1.1 mrg for (i = 0; i < n; ++i) { 390 1.1 mrg EL *el; 391 1.1 mrg 392 1.1 mrg el = FN(MULTI(BASE),take_at)(multi, i); 393 1.1 mrg el = FN(EL,reset_domain_space)(el, isl_space_copy(domain)); 394 1.1 mrg multi = FN(MULTI(BASE),restore_at)(multi, i, el); 395 1.1 mrg } 396 1.1 mrg if (FN(MULTI(BASE),has_explicit_domain)(multi)) 397 1.1 mrg multi = FN(MULTI(BASE),reset_explicit_domain_space)(multi, 398 1.1 mrg isl_space_copy(domain)); 399 1.1 mrg isl_space_free(domain); 400 1.1 mrg 401 1.1 mrg multi = FN(MULTI(BASE),restore_space)(multi, space); 402 1.1 mrg 403 1.1 mrg return multi; 404 1.1 mrg error: 405 1.1 mrg isl_space_free(domain); 406 1.1 mrg isl_space_free(space); 407 1.1 mrg FN(MULTI(BASE),free)(multi); 408 1.1 mrg return NULL; 409 1.1 mrg } 410 1.1 mrg 411 1.1 mrg __isl_give MULTI(BASE) *FN(MULTI(BASE),reset_domain_space)( 412 1.1 mrg __isl_take MULTI(BASE) *multi, __isl_take isl_space *domain) 413 1.1 mrg { 414 1.1 mrg isl_space *space, *multi_space; 415 1.1 mrg 416 1.1 mrg multi_space = FN(MULTI(BASE),get_space)(multi); 417 1.1 mrg space = isl_space_extend_domain_with_range(isl_space_copy(domain), 418 1.1 mrg multi_space); 419 1.1 mrg return FN(MULTI(BASE),reset_space_and_domain)(multi, space, domain); 420 1.1 mrg } 421 1.1 mrg 422 1.1 mrg __isl_give MULTI(BASE) *FN(MULTI(BASE),reset_space)( 423 1.1 mrg __isl_take MULTI(BASE) *multi, __isl_take isl_space *space) 424 1.1 mrg { 425 1.1 mrg isl_space *domain; 426 1.1 mrg 427 1.1 mrg domain = isl_space_domain(isl_space_copy(space)); 428 1.1 mrg return FN(MULTI(BASE),reset_space_and_domain)(multi, space, domain); 429 1.1 mrg } 430 1.1 mrg 431 1.1 mrg /* Reset the user pointer on all identifiers of parameters and tuples 432 1.1 mrg * of the space of "multi". 433 1.1 mrg */ 434 1.1 mrg __isl_give MULTI(BASE) *FN(MULTI(BASE),reset_user)( 435 1.1 mrg __isl_take MULTI(BASE) *multi) 436 1.1 mrg { 437 1.1 mrg isl_space *space; 438 1.1 mrg 439 1.1 mrg space = FN(MULTI(BASE),get_space)(multi); 440 1.1 mrg space = isl_space_reset_user(space); 441 1.1 mrg 442 1.1 mrg return FN(MULTI(BASE),reset_space)(multi, space); 443 1.1 mrg } 444 1.1 mrg 445 1.1 mrg __isl_give MULTI(BASE) *FN(MULTI(BASE),realign_domain)( 446 1.1 mrg __isl_take MULTI(BASE) *multi, __isl_take isl_reordering *exp) 447 1.1 mrg { 448 1.1 mrg int i; 449 1.1 mrg isl_size n; 450 1.1 mrg isl_space *space; 451 1.1 mrg 452 1.1 mrg n = FN(MULTI(BASE),size)(multi); 453 1.1 mrg if (n < 0 || !exp) 454 1.1 mrg goto error; 455 1.1 mrg 456 1.1 mrg for (i = 0; i < n; ++i) { 457 1.1 mrg EL *el; 458 1.1 mrg 459 1.1 mrg el = FN(MULTI(BASE),take_at)(multi, i); 460 1.1 mrg el = FN(EL,realign_domain)(el, isl_reordering_copy(exp)); 461 1.1 mrg multi = FN(MULTI(BASE),restore_at)(multi, i, el); 462 1.1 mrg } 463 1.1 mrg 464 1.1 mrg space = isl_reordering_get_space(exp); 465 1.1 mrg multi = FN(MULTI(BASE),reset_domain_space)(multi, space); 466 1.1 mrg 467 1.1 mrg isl_reordering_free(exp); 468 1.1 mrg return multi; 469 1.1 mrg error: 470 1.1 mrg isl_reordering_free(exp); 471 1.1 mrg FN(MULTI(BASE),free)(multi); 472 1.1 mrg return NULL; 473 1.1 mrg } 474 1.1 mrg 475 1.1 mrg /* Align the parameters of "multi" to those of "model". 476 1.1 mrg * 477 1.1 mrg * If "multi" has an explicit domain, then align the parameters 478 1.1 mrg * of the domain first. 479 1.1 mrg */ 480 1.1 mrg __isl_give MULTI(BASE) *FN(MULTI(BASE),align_params)( 481 1.1 mrg __isl_take MULTI(BASE) *multi, __isl_take isl_space *model) 482 1.1 mrg { 483 1.1 mrg isl_ctx *ctx; 484 1.1 mrg isl_bool equal_params; 485 1.1 mrg isl_space *domain_space; 486 1.1 mrg isl_reordering *exp; 487 1.1 mrg 488 1.1 mrg if (!multi || !model) 489 1.1 mrg goto error; 490 1.1 mrg 491 1.1 mrg equal_params = isl_space_has_equal_params(multi->space, model); 492 1.1 mrg if (equal_params < 0) 493 1.1 mrg goto error; 494 1.1 mrg if (equal_params) { 495 1.1 mrg isl_space_free(model); 496 1.1 mrg return multi; 497 1.1 mrg } 498 1.1 mrg 499 1.1 mrg ctx = isl_space_get_ctx(model); 500 1.1 mrg if (!isl_space_has_named_params(model)) 501 1.1 mrg isl_die(ctx, isl_error_invalid, 502 1.1 mrg "model has unnamed parameters", goto error); 503 1.1 mrg if (!isl_space_has_named_params(multi->space)) 504 1.1 mrg isl_die(ctx, isl_error_invalid, 505 1.1 mrg "input has unnamed parameters", goto error); 506 1.1 mrg 507 1.1 mrg if (FN(MULTI(BASE),has_explicit_domain)(multi)) { 508 1.1 mrg multi = FN(MULTI(BASE),align_explicit_domain_params)(multi, 509 1.1 mrg isl_space_copy(model)); 510 1.1 mrg if (!multi) 511 1.1 mrg goto error; 512 1.1 mrg } 513 1.1 mrg domain_space = FN(MULTI(BASE),get_domain_space)(multi); 514 1.1 mrg exp = isl_parameter_alignment_reordering(domain_space, model); 515 1.1 mrg isl_space_free(domain_space); 516 1.1 mrg multi = FN(MULTI(BASE),realign_domain)(multi, exp); 517 1.1 mrg 518 1.1 mrg isl_space_free(model); 519 1.1 mrg return multi; 520 1.1 mrg error: 521 1.1 mrg isl_space_free(model); 522 1.1 mrg FN(MULTI(BASE),free)(multi); 523 1.1 mrg return NULL; 524 1.1 mrg } 525 1.1 mrg 526 1.1 mrg /* Create a multi expression in the given space with the elements of "list" 527 1.1 mrg * as base expressions. 528 1.1 mrg * 529 1.1 mrg * Since isl_multi_*_restore_* assumes that the element and 530 1.1 mrg * the multi expression have matching spaces, the alignment 531 1.1 mrg * (if any) needs to be performed beforehand. 532 1.1 mrg */ 533 1.1 mrg __isl_give MULTI(BASE) *FN(FN(MULTI(BASE),from),LIST(BASE))( 534 1.1 mrg __isl_take isl_space *space, __isl_take LIST(EL) *list) 535 1.1 mrg { 536 1.1 mrg int i; 537 1.1 mrg isl_size n, dim; 538 1.1 mrg isl_ctx *ctx; 539 1.1 mrg MULTI(BASE) *multi; 540 1.1 mrg 541 1.1 mrg dim = isl_space_dim(space, isl_dim_out); 542 1.1 mrg n = FN(FN(LIST(EL),n),BASE)(list); 543 1.1 mrg if (dim < 0 || n < 0) 544 1.1 mrg goto error; 545 1.1 mrg 546 1.1 mrg ctx = isl_space_get_ctx(space); 547 1.1 mrg if (n != dim) 548 1.1 mrg isl_die(ctx, isl_error_invalid, 549 1.1 mrg "invalid number of elements in list", goto error); 550 1.1 mrg 551 1.1 mrg for (i = 0; i < n; ++i) { 552 1.1 mrg EL *el = FN(LIST(EL),peek)(list, i); 553 1.1 mrg space = isl_space_align_params(space, FN(EL,get_space)(el)); 554 1.1 mrg } 555 1.1 mrg multi = FN(MULTI(BASE),alloc)(isl_space_copy(space)); 556 1.1 mrg for (i = 0; i < n; ++i) { 557 1.1 mrg EL *el = FN(FN(LIST(EL),get),BASE)(list, i); 558 1.1 mrg el = FN(EL,align_params)(el, isl_space_copy(space)); 559 1.1 mrg multi = FN(MULTI(BASE),restore_check_space)(multi, i, el); 560 1.1 mrg } 561 1.1 mrg 562 1.1 mrg isl_space_free(space); 563 1.1 mrg FN(LIST(EL),free)(list); 564 1.1 mrg return multi; 565 1.1 mrg error: 566 1.1 mrg isl_space_free(space); 567 1.1 mrg FN(LIST(EL),free)(list); 568 1.1 mrg return NULL; 569 1.1 mrg } 570 1.1 mrg 571 1.1 mrg /* This function performs the same operation as isl_multi_*_from_*_list, 572 1.1 mrg * but is considered as a function on an isl_space when exported. 573 1.1 mrg */ 574 1.1 mrg __isl_give MULTI(BASE) *FN(isl_space_multi,BASE)(__isl_take isl_space *space, 575 1.1 mrg __isl_take LIST(EL) *list) 576 1.1 mrg { 577 1.1 mrg return FN(FN(MULTI(BASE),from),LIST(BASE))(space, list); 578 1.1 mrg } 579 1.1 mrg 580 1.1 mrg /* Drop the "n" output dimensions of "multi" starting at "first", 581 1.1 mrg * where the space is assumed to have been adjusted already. 582 1.1 mrg */ 583 1.1 mrg static __isl_give MULTI(BASE) *FN(MULTI(BASE),drop_output_dims)( 584 1.1 mrg __isl_take MULTI(BASE) *multi, unsigned first, unsigned n) 585 1.1 mrg { 586 1.1 mrg int i; 587 1.1 mrg 588 1.1 mrg multi = FN(MULTI(BASE),cow)(multi); 589 1.1 mrg if (!multi) 590 1.1 mrg return NULL; 591 1.1 mrg 592 1.1 mrg for (i = 0; i < n; ++i) 593 1.1 mrg FN(EL,free)(multi->u.p[first + i]); 594 1.1 mrg for (i = first; i + n < multi->n; ++i) 595 1.1 mrg multi->u.p[i] = multi->u.p[i + n]; 596 1.1 mrg multi->n -= n; 597 1.1 mrg if (n > 0 && FN(MULTI(BASE),has_explicit_domain)(multi)) 598 1.1 mrg multi = FN(MULTI(BASE),init_explicit_domain)(multi); 599 1.1 mrg 600 1.1 mrg return multi; 601 1.1 mrg } 602 1.1 mrg 603 1.1 mrg __isl_give MULTI(BASE) *FN(MULTI(BASE),drop_dims)( 604 1.1 mrg __isl_take MULTI(BASE) *multi, 605 1.1 mrg enum isl_dim_type type, unsigned first, unsigned n) 606 1.1 mrg { 607 1.1 mrg isl_space *space; 608 1.1 mrg isl_size size; 609 1.1 mrg int i; 610 1.1 mrg 611 1.1 mrg if (FN(MULTI(BASE),check_range)(multi, type, first, n) < 0) 612 1.1 mrg return FN(MULTI(BASE),free)(multi); 613 1.1 mrg 614 1.1 mrg space = FN(MULTI(BASE),take_space)(multi); 615 1.1 mrg space = isl_space_drop_dims(space, type, first, n); 616 1.1 mrg multi = FN(MULTI(BASE),restore_space)(multi, space); 617 1.1 mrg 618 1.1 mrg if (type == isl_dim_out) 619 1.1 mrg return FN(MULTI(BASE),drop_output_dims)(multi, first, n); 620 1.1 mrg 621 1.1 mrg if (FN(MULTI(BASE),has_explicit_domain)(multi)) 622 1.1 mrg multi = FN(MULTI(BASE),drop_explicit_domain_dims)(multi, 623 1.1 mrg type, first, n); 624 1.1 mrg 625 1.1 mrg size = FN(MULTI(BASE),size)(multi); 626 1.1 mrg if (size < 0) 627 1.1 mrg return FN(MULTI(BASE),free)(multi); 628 1.1 mrg for (i = 0; i < size; ++i) { 629 1.1 mrg EL *el; 630 1.1 mrg 631 1.1 mrg el = FN(MULTI(BASE),take_at)(multi, i); 632 1.1 mrg el = FN(EL,drop_dims)(el, type, first, n); 633 1.1 mrg multi = FN(MULTI(BASE),restore_at)(multi, i, el); 634 1.1 mrg } 635 1.1 mrg 636 1.1 mrg return multi; 637 1.1 mrg } 638 1.1 mrg 639 1.1 mrg #undef TYPE 640 1.1 mrg #define TYPE MULTI(BASE) 641 1.1 mrg 642 1.1 mrg #include "isl_check_named_params_templ.c" 643 1.1 mrg static 644 1.1 mrg #include "isl_align_params_bin_templ.c" 645 1.1 mrg 646 1.1 mrg /* Given two MULTI(BASE)s A -> B and C -> D, 647 1.1 mrg * construct a MULTI(BASE) (A * C) -> [B -> D]. 648 1.1 mrg * 649 1.1 mrg * If "multi1" and/or "multi2" has an explicit domain, then 650 1.1 mrg * intersect the domain of the result with these explicit domains. 651 1.1 mrg */ 652 1.1 mrg __isl_give MULTI(BASE) *FN(MULTI(BASE),range_product)( 653 1.1 mrg __isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2) 654 1.1 mrg { 655 1.1 mrg int i; 656 1.1 mrg isl_size n1, n2; 657 1.1 mrg EL *el; 658 1.1 mrg isl_space *space; 659 1.1 mrg MULTI(BASE) *res; 660 1.1 mrg 661 1.1 mrg FN(MULTI(BASE),align_params_bin)(&multi1, &multi2); 662 1.1 mrg n1 = FN(MULTI(BASE),size)(multi1); 663 1.1 mrg n2 = FN(MULTI(BASE),size)(multi2); 664 1.1 mrg if (n1 < 0 || n2 < 0) 665 1.1 mrg goto error; 666 1.1 mrg 667 1.1 mrg space = isl_space_range_product(FN(MULTI(BASE),get_space)(multi1), 668 1.1 mrg FN(MULTI(BASE),get_space)(multi2)); 669 1.1 mrg res = FN(MULTI(BASE),alloc)(space); 670 1.1 mrg 671 1.1 mrg for (i = 0; i < n1; ++i) { 672 1.1 mrg el = FN(FN(MULTI(BASE),get),BASE)(multi1, i); 673 1.1 mrg res = FN(FN(MULTI(BASE),set),BASE)(res, i, el); 674 1.1 mrg } 675 1.1 mrg 676 1.1 mrg for (i = 0; i < n2; ++i) { 677 1.1 mrg el = FN(FN(MULTI(BASE),get),BASE)(multi2, i); 678 1.1 mrg res = FN(FN(MULTI(BASE),set),BASE)(res, n1 + i, el); 679 1.1 mrg } 680 1.1 mrg 681 1.1 mrg if (FN(MULTI(BASE),has_explicit_domain)(multi1)) 682 1.1 mrg res = FN(MULTI(BASE),intersect_explicit_domain)(res, multi1); 683 1.1 mrg if (FN(MULTI(BASE),has_explicit_domain)(multi2)) 684 1.1 mrg res = FN(MULTI(BASE),intersect_explicit_domain)(res, multi2); 685 1.1 mrg 686 1.1 mrg FN(MULTI(BASE),free)(multi1); 687 1.1 mrg FN(MULTI(BASE),free)(multi2); 688 1.1 mrg return res; 689 1.1 mrg error: 690 1.1 mrg FN(MULTI(BASE),free)(multi1); 691 1.1 mrg FN(MULTI(BASE),free)(multi2); 692 1.1 mrg return NULL; 693 1.1 mrg } 694 1.1 mrg 695 1.1 mrg /* Is the range of "multi" a wrapped relation? 696 1.1 mrg */ 697 1.1 mrg isl_bool FN(MULTI(BASE),range_is_wrapping)(__isl_keep MULTI(BASE) *multi) 698 1.1 mrg { 699 1.1 mrg if (!multi) 700 1.1 mrg return isl_bool_error; 701 1.1 mrg return isl_space_range_is_wrapping(multi->space); 702 1.1 mrg } 703 1.1 mrg 704 1.1 mrg /* Given a function A -> [B -> C], extract the function A -> B. 705 1.1 mrg */ 706 1.1 mrg __isl_give MULTI(BASE) *FN(MULTI(BASE),range_factor_domain)( 707 1.1 mrg __isl_take MULTI(BASE) *multi) 708 1.1 mrg { 709 1.1 mrg isl_space *space; 710 1.1 mrg isl_size total, keep; 711 1.1 mrg 712 1.1 mrg total = FN(MULTI(BASE),dim)(multi, isl_dim_out); 713 1.1 mrg if (total < 0) 714 1.1 mrg return FN(MULTI(BASE),free)(multi); 715 1.1 mrg if (!isl_space_range_is_wrapping(multi->space)) 716 1.1 mrg isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_invalid, 717 1.1 mrg "range is not a product", 718 1.1 mrg return FN(MULTI(BASE),free)(multi)); 719 1.1 mrg 720 1.1 mrg space = FN(MULTI(BASE),get_space)(multi); 721 1.1 mrg space = isl_space_range_factor_domain(space); 722 1.1 mrg keep = isl_space_dim(space, isl_dim_out); 723 1.1 mrg if (keep < 0) 724 1.1 mrg multi = FN(MULTI(BASE),free)(multi); 725 1.1 mrg multi = FN(MULTI(BASE),drop_dims)(multi, 726 1.1 mrg isl_dim_out, keep, total - keep); 727 1.1 mrg multi = FN(MULTI(BASE),reset_space)(multi, space); 728 1.1 mrg 729 1.1 mrg return multi; 730 1.1 mrg } 731 1.1 mrg 732 1.1 mrg /* Given a function A -> [B -> C], extract the function A -> C. 733 1.1 mrg */ 734 1.1 mrg __isl_give MULTI(BASE) *FN(MULTI(BASE),range_factor_range)( 735 1.1 mrg __isl_take MULTI(BASE) *multi) 736 1.1 mrg { 737 1.1 mrg isl_space *space; 738 1.1 mrg isl_size total, keep; 739 1.1 mrg 740 1.1 mrg total = FN(MULTI(BASE),dim)(multi, isl_dim_out); 741 1.1 mrg if (total < 0) 742 1.1 mrg return FN(MULTI(BASE),free)(multi); 743 1.1 mrg if (!isl_space_range_is_wrapping(multi->space)) 744 1.1 mrg isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_invalid, 745 1.1 mrg "range is not a product", 746 1.1 mrg return FN(MULTI(BASE),free)(multi)); 747 1.1 mrg 748 1.1 mrg space = FN(MULTI(BASE),get_space)(multi); 749 1.1 mrg space = isl_space_range_factor_range(space); 750 1.1 mrg keep = isl_space_dim(space, isl_dim_out); 751 1.1 mrg if (keep < 0) 752 1.1 mrg multi = FN(MULTI(BASE),free)(multi); 753 1.1 mrg multi = FN(MULTI(BASE),drop_dims)(multi, isl_dim_out, 0, total - keep); 754 1.1 mrg multi = FN(MULTI(BASE),reset_space)(multi, space); 755 1.1 mrg 756 1.1 mrg return multi; 757 1.1 mrg } 758 1.1 mrg 759 1.1 mrg /* Given a function [B -> C], extract the function C. 760 1.1 mrg */ 761 1.1 mrg __isl_give MULTI(BASE) *FN(MULTI(BASE),factor_range)( 762 1.1 mrg __isl_take MULTI(BASE) *multi) 763 1.1 mrg { 764 1.1 mrg isl_space *space; 765 1.1 mrg isl_size total, keep; 766 1.1 mrg 767 1.1 mrg total = FN(MULTI(BASE),dim)(multi, isl_dim_set); 768 1.1 mrg if (total < 0) 769 1.1 mrg return FN(MULTI(BASE),free)(multi); 770 1.1 mrg if (!isl_space_is_wrapping(multi->space)) 771 1.1 mrg isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_invalid, 772 1.1 mrg "not a product", return FN(MULTI(BASE),free)(multi)); 773 1.1 mrg 774 1.1 mrg space = FN(MULTI(BASE),get_space)(multi); 775 1.1 mrg space = isl_space_factor_range(space); 776 1.1 mrg keep = isl_space_dim(space, isl_dim_set); 777 1.1 mrg if (keep < 0) 778 1.1 mrg multi = FN(MULTI(BASE),free)(multi); 779 1.1 mrg multi = FN(MULTI(BASE),drop_dims)(multi, isl_dim_set, 0, total - keep); 780 1.1 mrg multi = FN(MULTI(BASE),reset_space)(multi, space); 781 1.1 mrg 782 1.1 mrg return multi; 783 1.1 mrg } 784 1.1 mrg 785 1.1 mrg __isl_give MULTI(BASE) *FN(MULTI(BASE),flatten_range)( 786 1.1 mrg __isl_take MULTI(BASE) *multi) 787 1.1 mrg { 788 1.1 mrg isl_space *space; 789 1.1 mrg 790 1.1 mrg space = FN(MULTI(BASE),take_space)(multi); 791 1.1 mrg space = isl_space_flatten_range(space); 792 1.1 mrg multi = FN(MULTI(BASE),restore_space)(multi, space); 793 1.1 mrg 794 1.1 mrg return multi; 795 1.1 mrg } 796 1.1 mrg 797 1.1 mrg /* Given two MULTI(BASE)s A -> B and C -> D, 798 1.1 mrg * construct a MULTI(BASE) (A * C) -> (B, D). 799 1.1 mrg */ 800 1.1 mrg __isl_give MULTI(BASE) *FN(MULTI(BASE),flat_range_product)( 801 1.1 mrg __isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2) 802 1.1 mrg { 803 1.1 mrg MULTI(BASE) *multi; 804 1.1 mrg 805 1.1 mrg multi = FN(MULTI(BASE),range_product)(multi1, multi2); 806 1.1 mrg multi = FN(MULTI(BASE),flatten_range)(multi); 807 1.1 mrg return multi; 808 1.1 mrg } 809 1.1 mrg 810 1.1 mrg /* Given two multi expressions, "multi1" 811 1.1 mrg * 812 1.1 mrg * [A] -> [B1 B2] 813 1.1 mrg * 814 1.1 mrg * where B2 starts at position "pos", and "multi2" 815 1.1 mrg * 816 1.1 mrg * [A] -> [D] 817 1.1 mrg * 818 1.1 mrg * return the multi expression 819 1.1 mrg * 820 1.1 mrg * [A] -> [B1 D B2] 821 1.1 mrg */ 822 1.1 mrg __isl_give MULTI(BASE) *FN(MULTI(BASE),range_splice)( 823 1.1 mrg __isl_take MULTI(BASE) *multi1, unsigned pos, 824 1.1 mrg __isl_take MULTI(BASE) *multi2) 825 1.1 mrg { 826 1.1 mrg MULTI(BASE) *res; 827 1.1 mrg isl_size dim; 828 1.1 mrg 829 1.1 mrg dim = FN(MULTI(BASE),size)(multi1); 830 1.1 mrg if (dim < 0 || !multi2) 831 1.1 mrg goto error; 832 1.1 mrg 833 1.1 mrg if (FN(MULTI(BASE),check_range)(multi1, isl_dim_out, pos, 0) < 0) 834 1.1 mrg goto error; 835 1.1 mrg 836 1.1 mrg res = FN(MULTI(BASE),copy)(multi1); 837 1.1 mrg res = FN(MULTI(BASE),drop_dims)(res, isl_dim_out, pos, dim - pos); 838 1.1 mrg multi1 = FN(MULTI(BASE),drop_dims)(multi1, isl_dim_out, 0, pos); 839 1.1 mrg 840 1.1 mrg res = FN(MULTI(BASE),flat_range_product)(res, multi2); 841 1.1 mrg res = FN(MULTI(BASE),flat_range_product)(res, multi1); 842 1.1 mrg 843 1.1 mrg return res; 844 1.1 mrg error: 845 1.1 mrg FN(MULTI(BASE),free)(multi1); 846 1.1 mrg FN(MULTI(BASE),free)(multi2); 847 1.1 mrg return NULL; 848 1.1 mrg } 849 1.1 mrg 850 1.1 mrg #undef TYPE 851 1.1 mrg #define TYPE MULTI(BASE) 852 1.1 mrg 853 1.1 mrg static 854 1.1 mrg #include "isl_type_has_equal_space_bin_templ.c" 855 1.1 mrg static 856 1.1 mrg #include "isl_type_check_equal_space_templ.c" 857 1.1 mrg 858 1.1 mrg /* This function is currently only used from isl_aff.c 859 1.1 mrg */ 860 1.1 mrg static __isl_give MULTI(BASE) *FN(MULTI(BASE),bin_op)( 861 1.1 mrg __isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2, 862 1.1 mrg __isl_give EL *(*fn)(__isl_take EL *, __isl_take EL *)) 863 1.1 mrg __attribute__ ((unused)); 864 1.1 mrg 865 1.1 mrg /* Pairwise perform "fn" to the elements of "multi1" and "multi2" and 866 1.1 mrg * return the result. 867 1.1 mrg * 868 1.1 mrg * If "multi2" has an explicit domain, then 869 1.1 mrg * intersect the domain of the result with this explicit domain. 870 1.1 mrg */ 871 1.1 mrg static __isl_give MULTI(BASE) *FN(MULTI(BASE),bin_op)( 872 1.1 mrg __isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2, 873 1.1 mrg __isl_give EL *(*fn)(__isl_take EL *, __isl_take EL *)) 874 1.1 mrg { 875 1.1 mrg isl_size n; 876 1.1 mrg int i; 877 1.1 mrg 878 1.1 mrg FN(MULTI(BASE),align_params_bin)(&multi1, &multi2); 879 1.1 mrg n = FN(MULTI(BASE),size)(multi1); 880 1.1 mrg if (n < 0 || FN(MULTI(BASE),check_equal_space)(multi1, multi2) < 0) 881 1.1 mrg goto error; 882 1.1 mrg 883 1.1 mrg for (i = 0; i < n; ++i) { 884 1.1 mrg EL *el1, *el2; 885 1.1 mrg 886 1.1 mrg el2 = FN(MULTI(BASE),get_at)(multi2, i); 887 1.1 mrg el1 = FN(MULTI(BASE),take_at)(multi1, i); 888 1.1 mrg el1 = fn(el1, el2); 889 1.1 mrg multi1 = FN(MULTI(BASE),restore_at)(multi1, i, el1); 890 1.1 mrg } 891 1.1 mrg 892 1.1 mrg if (FN(MULTI(BASE),has_explicit_domain)(multi2)) 893 1.1 mrg multi1 = FN(MULTI(BASE),intersect_explicit_domain)(multi1, 894 1.1 mrg multi2); 895 1.1 mrg 896 1.1 mrg FN(MULTI(BASE),free)(multi2); 897 1.1 mrg return multi1; 898 1.1 mrg error: 899 1.1 mrg FN(MULTI(BASE),free)(multi1); 900 1.1 mrg FN(MULTI(BASE),free)(multi2); 901 1.1 mrg return NULL; 902 1.1 mrg } 903 1.1 mrg 904 1.1 mrg /* Only used on some multi-expressions. 905 1.1 mrg */ 906 1.1 mrg static isl_bool FN(MULTI(BASE),any)(__isl_keep MULTI(BASE) *multi, 907 1.1 mrg isl_bool (*test)(__isl_keep EL *)) __attribute__ ((unused)); 908 1.1 mrg 909 1.1 mrg /* Does "test" succeed on any base expression of "multi"? 910 1.1 mrg */ 911 1.1 mrg static isl_bool FN(MULTI(BASE),any)(__isl_keep MULTI(BASE) *multi, 912 1.1 mrg isl_bool (*test)(__isl_keep EL *)) 913 1.1 mrg { 914 1.1 mrg isl_size n; 915 1.1 mrg int i; 916 1.1 mrg 917 1.1 mrg n = FN(MULTI(BASE),size)(multi); 918 1.1 mrg if (n < 0) 919 1.1 mrg return isl_bool_error; 920 1.1 mrg 921 1.1 mrg for (i = 0; i < n; ++i) { 922 1.1 mrg isl_bool any = test(multi->u.p[i]); 923 1.1 mrg if (any < 0 || any) 924 1.1 mrg return any; 925 1.1 mrg } 926 1.1 mrg 927 1.1 mrg return isl_bool_false; 928 1.1 mrg } 929 1.1 mrg 930 1.1 mrg /* Only used on some multi-expressions. 931 1.1 mrg */ 932 1.1 mrg static isl_bool FN(MULTI(BASE),every)(__isl_keep MULTI(BASE) *multi, 933 1.1 mrg isl_bool (*test)(__isl_keep EL *)) __attribute__ ((unused)); 934 1.1 mrg 935 1.1 mrg /* Does "test" succeed on every base expression of "multi"? 936 1.1 mrg */ 937 1.1 mrg static isl_bool FN(MULTI(BASE),every)(__isl_keep MULTI(BASE) *multi, 938 1.1 mrg isl_bool (*test)(__isl_keep EL *)) 939 1.1 mrg { 940 1.1 mrg isl_size n; 941 1.1 mrg int i; 942 1.1 mrg 943 1.1 mrg n = FN(MULTI(BASE),size)(multi); 944 1.1 mrg if (n < 0) 945 1.1 mrg return isl_bool_error; 946 1.1 mrg 947 1.1 mrg for (i = 0; i < n; ++i) { 948 1.1 mrg isl_bool every = test(multi->u.p[i]); 949 1.1 mrg if (every < 0 || !every) 950 1.1 mrg return every; 951 1.1 mrg } 952 1.1 mrg 953 1.1 mrg return isl_bool_true; 954 1.1 mrg } 955 1.1 mrg 956 1.1 mrg #undef TYPE 957 1.1 mrg #define TYPE MULTI(BASE) 958 1.1 mrg #include "isl_from_range_templ.c" 959 1.1 mrg 960 1.1 mrg /* Are "multi1" and "multi2" obviously equal? 961 1.1 mrg */ 962 1.1 mrg isl_bool FN(MULTI(BASE),plain_is_equal)(__isl_keep MULTI(BASE) *multi1, 963 1.1 mrg __isl_keep MULTI(BASE) *multi2) 964 1.1 mrg { 965 1.1 mrg int i; 966 1.1 mrg isl_bool equal; 967 1.1 mrg 968 1.1 mrg if (!multi1 || !multi2) 969 1.1 mrg return isl_bool_error; 970 1.1 mrg if (multi1->n != multi2->n) 971 1.1 mrg return isl_bool_false; 972 1.1 mrg equal = isl_space_is_equal(multi1->space, multi2->space); 973 1.1 mrg if (equal < 0 || !equal) 974 1.1 mrg return equal; 975 1.1 mrg 976 1.1 mrg for (i = 0; i < multi1->n; ++i) { 977 1.1 mrg equal = FN(EL,plain_is_equal)(multi1->u.p[i], multi2->u.p[i]); 978 1.1 mrg if (equal < 0 || !equal) 979 1.1 mrg return equal; 980 1.1 mrg } 981 1.1 mrg 982 1.1 mrg if (FN(MULTI(BASE),has_explicit_domain)(multi1) || 983 1.1 mrg FN(MULTI(BASE),has_explicit_domain)(multi2)) { 984 1.1 mrg equal = FN(MULTI(BASE),equal_explicit_domain)(multi1, multi2); 985 1.1 mrg if (equal < 0 || !equal) 986 1.1 mrg return equal; 987 1.1 mrg } 988 1.1 mrg 989 1.1 mrg return isl_bool_true; 990 1.1 mrg } 991