1 1.1 mrg /* 2 1.1 mrg * Copyright 2010-2011 INRIA Saclay 3 1.1 mrg * Copyright 2013-2014 Ecole Normale Superieure 4 1.1 mrg * Copyright 2014 INRIA Rocquencourt 5 1.1 mrg * Copyright 2016-2017 Sven Verdoolaege 6 1.1 mrg * Copyright 2022 Cerebras Systems 7 1.1 mrg * 8 1.1 mrg * Use of this software is governed by the MIT license 9 1.1 mrg * 10 1.1 mrg * Written by Sven Verdoolaege, INRIA Saclay - Ile-de-France, 11 1.1 mrg * Parc Club Orsay Universite, ZAC des vignes, 4 rue Jacques Monod, 12 1.1 mrg * 91893 Orsay, France 13 1.1 mrg * and Inria Paris - Rocquencourt, Domaine de Voluceau - Rocquencourt, 14 1.1 mrg * B.P. 105 - 78153 Le Chesnay, France 15 1.1 mrg * and Cerebras Systems, 1237 E Arques Ave, Sunnyvale, CA, USA 16 1.1 mrg */ 17 1.1 mrg 18 1.1 mrg #include <isl_map_private.h> 19 1.1 mrg #include <isl_union_map_private.h> 20 1.1 mrg #include <isl/ctx.h> 21 1.1 mrg #include <isl/hash.h> 22 1.1 mrg #include <isl_aff_private.h> 23 1.1 mrg #include <isl/map.h> 24 1.1 mrg #include <isl/set.h> 25 1.1 mrg #include <isl_space_private.h> 26 1.1 mrg #include <isl/union_set.h> 27 1.1 mrg #include <isl_maybe_map.h> 28 1.1 mrg #include <isl_id_private.h> 29 1.1 mrg 30 1.1 mrg #include <bset_from_bmap.c> 31 1.1 mrg #include <set_to_map.c> 32 1.1 mrg #include <set_from_map.c> 33 1.1 mrg #include <uset_to_umap.c> 34 1.1 mrg #include <uset_from_umap.c> 35 1.1 mrg #include <set_list_from_map_list_inl.c> 36 1.1 mrg 37 1.1 mrg #undef TYPE 38 1.1 mrg #define TYPE isl_union_map 39 1.1 mrg static 40 1.1 mrg #include "has_single_reference_templ.c" 41 1.1 mrg static 42 1.1 mrg #include "check_single_reference_templ.c" 43 1.1 mrg 44 1.1 mrg /* Return the number of parameters of "umap", where "type" 45 1.1 mrg * is required to be set to isl_dim_param. 46 1.1 mrg */ 47 1.1 mrg isl_size isl_union_map_dim(__isl_keep isl_union_map *umap, 48 1.1 mrg enum isl_dim_type type) 49 1.1 mrg { 50 1.1 mrg if (!umap) 51 1.1 mrg return isl_size_error; 52 1.1 mrg 53 1.1 mrg if (type != isl_dim_param) 54 1.1 mrg isl_die(isl_union_map_get_ctx(umap), isl_error_invalid, 55 1.1 mrg "can only reference parameters", return isl_size_error); 56 1.1 mrg 57 1.1 mrg return isl_space_dim(umap->dim, type); 58 1.1 mrg } 59 1.1 mrg 60 1.1 mrg /* Return the number of parameters of "uset", where "type" 61 1.1 mrg * is required to be set to isl_dim_param. 62 1.1 mrg */ 63 1.1 mrg isl_size isl_union_set_dim(__isl_keep isl_union_set *uset, 64 1.1 mrg enum isl_dim_type type) 65 1.1 mrg { 66 1.1 mrg return isl_union_map_dim(uset, type); 67 1.1 mrg } 68 1.1 mrg 69 1.1 mrg /* Return the id of the specified dimension. 70 1.1 mrg */ 71 1.1 mrg __isl_give isl_id *isl_union_map_get_dim_id(__isl_keep isl_union_map *umap, 72 1.1 mrg enum isl_dim_type type, unsigned pos) 73 1.1 mrg { 74 1.1 mrg if (!umap) 75 1.1 mrg return NULL; 76 1.1 mrg 77 1.1 mrg if (type != isl_dim_param) 78 1.1 mrg isl_die(isl_union_map_get_ctx(umap), isl_error_invalid, 79 1.1 mrg "can only reference parameters", return NULL); 80 1.1 mrg 81 1.1 mrg return isl_space_get_dim_id(umap->dim, type, pos); 82 1.1 mrg } 83 1.1 mrg 84 1.1 mrg /* Is this union set a parameter domain? 85 1.1 mrg */ 86 1.1 mrg isl_bool isl_union_set_is_params(__isl_keep isl_union_set *uset) 87 1.1 mrg { 88 1.1 mrg isl_set *set; 89 1.1 mrg isl_bool params; 90 1.1 mrg 91 1.1 mrg if (!uset) 92 1.1 mrg return isl_bool_error; 93 1.1 mrg if (uset->table.n != 1) 94 1.1 mrg return isl_bool_false; 95 1.1 mrg 96 1.1 mrg set = isl_set_from_union_set(isl_union_set_copy(uset)); 97 1.1 mrg params = isl_set_is_params(set); 98 1.1 mrg isl_set_free(set); 99 1.1 mrg return params; 100 1.1 mrg } 101 1.1 mrg 102 1.1 mrg /* Is this union map actually a parameter domain? 103 1.1 mrg * Users should never call this function. Outside of isl, 104 1.1 mrg * a union map can never be a parameter domain. 105 1.1 mrg */ 106 1.1 mrg isl_bool isl_union_map_is_params(__isl_keep isl_union_map *umap) 107 1.1 mrg { 108 1.1 mrg return isl_union_set_is_params(uset_from_umap(umap)); 109 1.1 mrg } 110 1.1 mrg 111 1.1 mrg static __isl_give isl_union_map *isl_union_map_alloc( 112 1.1 mrg __isl_take isl_space *space, int size) 113 1.1 mrg { 114 1.1 mrg isl_union_map *umap; 115 1.1 mrg 116 1.1 mrg space = isl_space_params(space); 117 1.1 mrg if (!space) 118 1.1 mrg return NULL; 119 1.1 mrg 120 1.1 mrg umap = isl_calloc_type(space->ctx, isl_union_map); 121 1.1 mrg if (!umap) { 122 1.1 mrg isl_space_free(space); 123 1.1 mrg return NULL; 124 1.1 mrg } 125 1.1 mrg 126 1.1 mrg umap->ref = 1; 127 1.1 mrg umap->dim = space; 128 1.1 mrg if (isl_hash_table_init(space->ctx, &umap->table, size) < 0) 129 1.1 mrg return isl_union_map_free(umap); 130 1.1 mrg 131 1.1 mrg return umap; 132 1.1 mrg } 133 1.1 mrg 134 1.1 mrg /* Create an empty union map without specifying any parameters. 135 1.1 mrg */ 136 1.1 mrg __isl_give isl_union_map *isl_union_map_empty_ctx(isl_ctx *ctx) 137 1.1 mrg { 138 1.1 mrg return isl_union_map_empty_space(isl_space_unit(ctx)); 139 1.1 mrg } 140 1.1 mrg 141 1.1 mrg __isl_give isl_union_map *isl_union_map_empty_space(__isl_take isl_space *space) 142 1.1 mrg { 143 1.1 mrg return isl_union_map_alloc(space, 16); 144 1.1 mrg } 145 1.1 mrg 146 1.1 mrg /* This is an alternative name for the function above. 147 1.1 mrg */ 148 1.1 mrg __isl_give isl_union_map *isl_union_map_empty(__isl_take isl_space *space) 149 1.1 mrg { 150 1.1 mrg return isl_union_map_empty_space(space); 151 1.1 mrg } 152 1.1 mrg 153 1.1 mrg /* Create an empty union set without specifying any parameters. 154 1.1 mrg */ 155 1.1 mrg __isl_give isl_union_set *isl_union_set_empty_ctx(isl_ctx *ctx) 156 1.1 mrg { 157 1.1 mrg return uset_from_umap(isl_union_map_empty_ctx(ctx)); 158 1.1 mrg } 159 1.1 mrg 160 1.1 mrg __isl_give isl_union_set *isl_union_set_empty_space(__isl_take isl_space *space) 161 1.1 mrg { 162 1.1 mrg return uset_from_umap(isl_union_map_empty_space(space)); 163 1.1 mrg } 164 1.1 mrg 165 1.1 mrg /* This is an alternative name for the function above. 166 1.1 mrg */ 167 1.1 mrg __isl_give isl_union_set *isl_union_set_empty(__isl_take isl_space *space) 168 1.1 mrg { 169 1.1 mrg return isl_union_set_empty_space(space); 170 1.1 mrg } 171 1.1 mrg 172 1.1 mrg isl_ctx *isl_union_map_get_ctx(__isl_keep isl_union_map *umap) 173 1.1 mrg { 174 1.1 mrg return umap ? umap->dim->ctx : NULL; 175 1.1 mrg } 176 1.1 mrg 177 1.1 mrg isl_ctx *isl_union_set_get_ctx(__isl_keep isl_union_set *uset) 178 1.1 mrg { 179 1.1 mrg return uset ? uset->dim->ctx : NULL; 180 1.1 mrg } 181 1.1 mrg 182 1.1 mrg /* Return the space of "umap". 183 1.1 mrg */ 184 1.1 mrg __isl_keep isl_space *isl_union_map_peek_space(__isl_keep isl_union_map *umap) 185 1.1 mrg { 186 1.1 mrg return umap ? umap->dim : NULL; 187 1.1 mrg } 188 1.1 mrg 189 1.1 mrg /* Return the space of "uset". 190 1.1 mrg */ 191 1.1 mrg __isl_keep isl_space *isl_union_set_peek_space(__isl_keep isl_union_set *uset) 192 1.1 mrg { 193 1.1 mrg return isl_union_map_peek_space(uset_to_umap(uset)); 194 1.1 mrg } 195 1.1 mrg 196 1.1 mrg __isl_give isl_space *isl_union_map_get_space(__isl_keep isl_union_map *umap) 197 1.1 mrg { 198 1.1 mrg return isl_space_copy(isl_union_map_peek_space(umap)); 199 1.1 mrg } 200 1.1 mrg 201 1.1 mrg /* Return the position of the parameter with the given name 202 1.1 mrg * in "umap". 203 1.1 mrg * Return -1 if no such dimension can be found. 204 1.1 mrg */ 205 1.1 mrg int isl_union_map_find_dim_by_name(__isl_keep isl_union_map *umap, 206 1.1 mrg enum isl_dim_type type, const char *name) 207 1.1 mrg { 208 1.1 mrg if (!umap) 209 1.1 mrg return -1; 210 1.1 mrg return isl_space_find_dim_by_name(umap->dim, type, name); 211 1.1 mrg } 212 1.1 mrg 213 1.1 mrg /* Return the position of the parameter with id "id" in "umap". 214 1.1 mrg * Return -1 if no such dimension can be found. 215 1.1 mrg */ 216 1.1 mrg static int isl_union_map_find_dim_by_id(__isl_keep isl_union_map *umap, 217 1.1 mrg enum isl_dim_type type, __isl_keep isl_id *id) 218 1.1 mrg { 219 1.1 mrg isl_space *space; 220 1.1 mrg 221 1.1 mrg space = isl_union_map_peek_space(umap); 222 1.1 mrg return isl_space_find_dim_by_id(space, type, id); 223 1.1 mrg } 224 1.1 mrg 225 1.1 mrg __isl_give isl_space *isl_union_set_get_space(__isl_keep isl_union_set *uset) 226 1.1 mrg { 227 1.1 mrg return isl_union_map_get_space(uset); 228 1.1 mrg } 229 1.1 mrg 230 1.1 mrg static isl_stat free_umap_entry(void **entry, void *user) 231 1.1 mrg { 232 1.1 mrg isl_map *map = *entry; 233 1.1 mrg isl_map_free(map); 234 1.1 mrg return isl_stat_ok; 235 1.1 mrg } 236 1.1 mrg 237 1.1 mrg static isl_stat add_map(__isl_take isl_map *map, void *user) 238 1.1 mrg { 239 1.1 mrg isl_union_map **umap = (isl_union_map **)user; 240 1.1 mrg 241 1.1 mrg *umap = isl_union_map_add_map(*umap, map); 242 1.1 mrg 243 1.1 mrg return isl_stat_ok; 244 1.1 mrg } 245 1.1 mrg 246 1.1 mrg __isl_give isl_union_map *isl_union_map_dup(__isl_keep isl_union_map *umap) 247 1.1 mrg { 248 1.1 mrg isl_union_map *dup; 249 1.1 mrg 250 1.1 mrg if (!umap) 251 1.1 mrg return NULL; 252 1.1 mrg 253 1.1 mrg dup = isl_union_map_empty(isl_space_copy(umap->dim)); 254 1.1 mrg if (isl_union_map_foreach_map(umap, &add_map, &dup) < 0) 255 1.1 mrg goto error; 256 1.1 mrg return dup; 257 1.1 mrg error: 258 1.1 mrg isl_union_map_free(dup); 259 1.1 mrg return NULL; 260 1.1 mrg } 261 1.1 mrg 262 1.1 mrg __isl_give isl_union_map *isl_union_map_cow(__isl_take isl_union_map *umap) 263 1.1 mrg { 264 1.1 mrg if (!umap) 265 1.1 mrg return NULL; 266 1.1 mrg 267 1.1 mrg if (umap->ref == 1) 268 1.1 mrg return umap; 269 1.1 mrg umap->ref--; 270 1.1 mrg return isl_union_map_dup(umap); 271 1.1 mrg } 272 1.1 mrg 273 1.1 mrg struct isl_union_align { 274 1.1 mrg isl_reordering *exp; 275 1.1 mrg isl_union_map *res; 276 1.1 mrg }; 277 1.1 mrg 278 1.1 mrg static isl_stat align_entry(void **entry, void *user) 279 1.1 mrg { 280 1.1 mrg isl_map *map = *entry; 281 1.1 mrg isl_reordering *exp; 282 1.1 mrg struct isl_union_align *data = user; 283 1.1 mrg 284 1.1 mrg exp = isl_reordering_extend_space(isl_reordering_copy(data->exp), 285 1.1 mrg isl_map_get_space(map)); 286 1.1 mrg 287 1.1 mrg data->res = isl_union_map_add_map(data->res, 288 1.1 mrg isl_map_realign(isl_map_copy(map), exp)); 289 1.1 mrg 290 1.1 mrg return isl_stat_ok; 291 1.1 mrg } 292 1.1 mrg 293 1.1 mrg /* Align the parameters of umap along those of model. 294 1.1 mrg * The result has the parameters of model first, in the same order 295 1.1 mrg * as they appear in model, followed by any remaining parameters of 296 1.1 mrg * umap that do not appear in model. 297 1.1 mrg */ 298 1.1 mrg __isl_give isl_union_map *isl_union_map_align_params( 299 1.1 mrg __isl_take isl_union_map *umap, __isl_take isl_space *model) 300 1.1 mrg { 301 1.1 mrg struct isl_union_align data = { NULL, NULL }; 302 1.1 mrg isl_space *space; 303 1.1 mrg isl_bool equal_params; 304 1.1 mrg 305 1.1 mrg space = isl_union_map_peek_space(umap); 306 1.1 mrg equal_params = isl_space_has_equal_params(space, model); 307 1.1 mrg if (equal_params < 0) 308 1.1 mrg goto error; 309 1.1 mrg if (equal_params) { 310 1.1 mrg isl_space_free(model); 311 1.1 mrg return umap; 312 1.1 mrg } 313 1.1 mrg 314 1.1 mrg data.exp = isl_parameter_alignment_reordering(space, model); 315 1.1 mrg if (!data.exp) 316 1.1 mrg goto error; 317 1.1 mrg 318 1.1 mrg data.res = isl_union_map_alloc(isl_reordering_get_space(data.exp), 319 1.1 mrg umap->table.n); 320 1.1 mrg if (isl_hash_table_foreach(isl_union_map_get_ctx(umap), &umap->table, 321 1.1 mrg &align_entry, &data) < 0) 322 1.1 mrg goto error; 323 1.1 mrg 324 1.1 mrg isl_reordering_free(data.exp); 325 1.1 mrg isl_union_map_free(umap); 326 1.1 mrg isl_space_free(model); 327 1.1 mrg return data.res; 328 1.1 mrg error: 329 1.1 mrg isl_reordering_free(data.exp); 330 1.1 mrg isl_union_map_free(umap); 331 1.1 mrg isl_union_map_free(data.res); 332 1.1 mrg isl_space_free(model); 333 1.1 mrg return NULL; 334 1.1 mrg } 335 1.1 mrg 336 1.1 mrg __isl_give isl_union_set *isl_union_set_align_params( 337 1.1 mrg __isl_take isl_union_set *uset, __isl_take isl_space *model) 338 1.1 mrg { 339 1.1 mrg return isl_union_map_align_params(uset, model); 340 1.1 mrg } 341 1.1 mrg 342 1.1 mrg /* This is a wrapper around isl_union_map_project_out for use 343 1.1 mrg * by isl_union_map_drop_unused_params. 344 1.1 mrg * 345 1.1 mrg * In particular, this function is only called on parameters 346 1.1 mrg * that are not involved in the description of "umap". 347 1.1 mrg * Dropping those parameters is therefore equivalent 348 1.1 mrg * to projecting them out. 349 1.1 mrg */ 350 1.1 mrg static __isl_give isl_union_map *isl_union_map_drop_dims( 351 1.1 mrg __isl_take isl_union_map *umap, 352 1.1 mrg enum isl_dim_type type, unsigned first, unsigned n) 353 1.1 mrg { 354 1.1 mrg return isl_union_map_project_out(umap, type, first, n); 355 1.1 mrg } 356 1.1 mrg 357 1.1 mrg #undef TYPE 358 1.1 mrg #define TYPE isl_union_map 359 1.1 mrg #include "isl_check_named_params_templ.c" 360 1.1 mrg #include "isl_drop_unused_params_templ.c" 361 1.1 mrg 362 1.1 mrg /* Drop all parameters not referenced by "uset". 363 1.1 mrg */ 364 1.1 mrg __isl_give isl_union_set *isl_union_set_drop_unused_params( 365 1.1 mrg __isl_take isl_union_set *uset) 366 1.1 mrg { 367 1.1 mrg isl_union_map *umap; 368 1.1 mrg 369 1.1 mrg umap = isl_union_map_drop_unused_params(uset_to_umap(uset)); 370 1.1 mrg return uset_from_umap(umap); 371 1.1 mrg } 372 1.1 mrg 373 1.1 mrg __isl_give isl_union_map *isl_union_map_union(__isl_take isl_union_map *umap1, 374 1.1 mrg __isl_take isl_union_map *umap2) 375 1.1 mrg { 376 1.1 mrg umap1 = isl_union_map_align_params(umap1, isl_union_map_get_space(umap2)); 377 1.1 mrg umap2 = isl_union_map_align_params(umap2, isl_union_map_get_space(umap1)); 378 1.1 mrg 379 1.1 mrg umap1 = isl_union_map_cow(umap1); 380 1.1 mrg 381 1.1 mrg if (!umap1 || !umap2) 382 1.1 mrg goto error; 383 1.1 mrg 384 1.1 mrg if (isl_union_map_foreach_map(umap2, &add_map, &umap1) < 0) 385 1.1 mrg goto error; 386 1.1 mrg 387 1.1 mrg isl_union_map_free(umap2); 388 1.1 mrg 389 1.1 mrg return umap1; 390 1.1 mrg error: 391 1.1 mrg isl_union_map_free(umap1); 392 1.1 mrg isl_union_map_free(umap2); 393 1.1 mrg return NULL; 394 1.1 mrg } 395 1.1 mrg 396 1.1 mrg __isl_give isl_union_set *isl_union_set_union(__isl_take isl_union_set *uset1, 397 1.1 mrg __isl_take isl_union_set *uset2) 398 1.1 mrg { 399 1.1 mrg return isl_union_map_union(uset1, uset2); 400 1.1 mrg } 401 1.1 mrg 402 1.1 mrg __isl_give isl_union_map *isl_union_map_copy(__isl_keep isl_union_map *umap) 403 1.1 mrg { 404 1.1 mrg if (!umap) 405 1.1 mrg return NULL; 406 1.1 mrg 407 1.1 mrg umap->ref++; 408 1.1 mrg return umap; 409 1.1 mrg } 410 1.1 mrg 411 1.1 mrg __isl_give isl_union_set *isl_union_set_copy(__isl_keep isl_union_set *uset) 412 1.1 mrg { 413 1.1 mrg return isl_union_map_copy(uset); 414 1.1 mrg } 415 1.1 mrg 416 1.1 mrg __isl_null isl_union_map *isl_union_map_free(__isl_take isl_union_map *umap) 417 1.1 mrg { 418 1.1 mrg if (!umap) 419 1.1 mrg return NULL; 420 1.1 mrg 421 1.1 mrg if (--umap->ref > 0) 422 1.1 mrg return NULL; 423 1.1 mrg 424 1.1 mrg isl_hash_table_foreach(umap->dim->ctx, &umap->table, 425 1.1 mrg &free_umap_entry, NULL); 426 1.1 mrg isl_hash_table_clear(&umap->table); 427 1.1 mrg isl_space_free(umap->dim); 428 1.1 mrg free(umap); 429 1.1 mrg return NULL; 430 1.1 mrg } 431 1.1 mrg 432 1.1 mrg __isl_null isl_union_set *isl_union_set_free(__isl_take isl_union_set *uset) 433 1.1 mrg { 434 1.1 mrg return isl_union_map_free(uset); 435 1.1 mrg } 436 1.1 mrg 437 1.1 mrg /* Do "umap" and "space" have the same parameters? 438 1.1 mrg */ 439 1.1 mrg isl_bool isl_union_map_space_has_equal_params(__isl_keep isl_union_map *umap, 440 1.1 mrg __isl_keep isl_space *space) 441 1.1 mrg { 442 1.1 mrg isl_space *umap_space; 443 1.1 mrg 444 1.1 mrg umap_space = isl_union_map_peek_space(umap); 445 1.1 mrg return isl_space_has_equal_params(umap_space, space); 446 1.1 mrg } 447 1.1 mrg 448 1.1 mrg /* Do "uset" and "space" have the same parameters? 449 1.1 mrg */ 450 1.1 mrg isl_bool isl_union_set_space_has_equal_params(__isl_keep isl_union_set *uset, 451 1.1 mrg __isl_keep isl_space *space) 452 1.1 mrg { 453 1.1 mrg return isl_union_map_space_has_equal_params(uset_to_umap(uset), space); 454 1.1 mrg } 455 1.1 mrg 456 1.1 mrg /* Is the space of the map at "entry" equal to "space", ignoring parameters? 457 1.1 mrg */ 458 1.1 mrg static isl_bool has_space_tuples(const void *entry, const void *val) 459 1.1 mrg { 460 1.1 mrg isl_map *map = (isl_map *)entry; 461 1.1 mrg isl_space *space = (isl_space *) val; 462 1.1 mrg 463 1.1 mrg return isl_map_has_space_tuples(map, space); 464 1.1 mrg } 465 1.1 mrg 466 1.1 mrg /* Find the entry in "umap" with space "space" (ignoring parameters), 467 1.1 mrg * returning isl_hash_table_entry_none if no such entry appears in "umap" and 468 1.1 mrg * NULL on error. 469 1.1 mrg * If "reserve" is set, then an entry is created if it does 470 1.1 mrg * not exist already. Since this modifies the hash table in-place, 471 1.1 mrg * this means "umap" must have a single reference when "reserve" is set. 472 1.1 mrg */ 473 1.1 mrg static struct isl_hash_table_entry *isl_union_map_find_entry( 474 1.1 mrg __isl_keep isl_union_map *umap, __isl_keep isl_space *space, 475 1.1 mrg int reserve) 476 1.1 mrg { 477 1.1 mrg uint32_t hash; 478 1.1 mrg 479 1.1 mrg if (!umap || !space) 480 1.1 mrg return NULL; 481 1.1 mrg if (reserve && isl_union_map_check_single_reference(umap) < 0) 482 1.1 mrg return NULL; 483 1.1 mrg 484 1.1 mrg hash = isl_space_get_tuple_hash(space); 485 1.1 mrg return isl_hash_table_find(isl_union_map_get_ctx(umap), &umap->table, 486 1.1 mrg hash, &has_space_tuples, space, reserve); 487 1.1 mrg } 488 1.1 mrg 489 1.1 mrg /* Find the entry in "uset" with space "space" (ignoring parameters), 490 1.1 mrg * returning isl_hash_table_entry_none if no such entry appears in "uset" and 491 1.1 mrg * NULL on error. 492 1.1 mrg * If "reserve" is set, then an entry is created if it does 493 1.1 mrg * not exist already. In this case, a NULL return indicates an error. 494 1.1 mrg */ 495 1.1 mrg struct isl_hash_table_entry *isl_union_set_find_entry( 496 1.1 mrg __isl_keep isl_union_set *uset, __isl_keep isl_space *space, 497 1.1 mrg int reserve) 498 1.1 mrg { 499 1.1 mrg return isl_union_map_find_entry(uset_to_umap(uset), space, reserve); 500 1.1 mrg } 501 1.1 mrg 502 1.1 mrg __isl_give isl_union_map *isl_union_map_add_map(__isl_take isl_union_map *umap, 503 1.1 mrg __isl_take isl_map *map) 504 1.1 mrg { 505 1.1 mrg struct isl_hash_table_entry *entry; 506 1.1 mrg isl_bool aligned; 507 1.1 mrg isl_space *space; 508 1.1 mrg 509 1.1 mrg if (!map || !umap) 510 1.1 mrg goto error; 511 1.1 mrg 512 1.1 mrg if (isl_map_plain_is_empty(map)) { 513 1.1 mrg isl_map_free(map); 514 1.1 mrg return umap; 515 1.1 mrg } 516 1.1 mrg 517 1.1 mrg aligned = isl_map_space_has_equal_params(map, umap->dim); 518 1.1 mrg if (aligned < 0) 519 1.1 mrg goto error; 520 1.1 mrg if (!aligned) { 521 1.1 mrg umap = isl_union_map_align_params(umap, isl_map_get_space(map)); 522 1.1 mrg map = isl_map_align_params(map, isl_union_map_get_space(umap)); 523 1.1 mrg } 524 1.1 mrg 525 1.1 mrg umap = isl_union_map_cow(umap); 526 1.1 mrg 527 1.1 mrg space = isl_map_peek_space(map); 528 1.1 mrg entry = isl_union_map_find_entry(umap, space, 1); 529 1.1 mrg if (!entry) 530 1.1 mrg goto error; 531 1.1 mrg 532 1.1 mrg if (!entry->data) 533 1.1 mrg entry->data = map; 534 1.1 mrg else { 535 1.1 mrg entry->data = isl_map_union(entry->data, isl_map_copy(map)); 536 1.1 mrg if (!entry->data) 537 1.1 mrg goto error; 538 1.1 mrg isl_map_free(map); 539 1.1 mrg } 540 1.1 mrg 541 1.1 mrg return umap; 542 1.1 mrg error: 543 1.1 mrg isl_map_free(map); 544 1.1 mrg isl_union_map_free(umap); 545 1.1 mrg return NULL; 546 1.1 mrg } 547 1.1 mrg 548 1.1 mrg __isl_give isl_union_set *isl_union_set_add_set(__isl_take isl_union_set *uset, 549 1.1 mrg __isl_take isl_set *set) 550 1.1 mrg { 551 1.1 mrg return isl_union_map_add_map(uset, set_to_map(set)); 552 1.1 mrg } 553 1.1 mrg 554 1.1 mrg __isl_give isl_union_map *isl_union_map_from_map(__isl_take isl_map *map) 555 1.1 mrg { 556 1.1 mrg isl_space *space; 557 1.1 mrg isl_union_map *umap; 558 1.1 mrg 559 1.1 mrg if (!map) 560 1.1 mrg return NULL; 561 1.1 mrg 562 1.1 mrg space = isl_map_get_space(map); 563 1.1 mrg space = isl_space_params(space); 564 1.1 mrg umap = isl_union_map_empty(space); 565 1.1 mrg umap = isl_union_map_add_map(umap, map); 566 1.1 mrg 567 1.1 mrg return umap; 568 1.1 mrg } 569 1.1 mrg 570 1.1 mrg /* This function performs the same operation as isl_union_map_from_map, 571 1.1 mrg * but is considered as a function on an isl_map when exported. 572 1.1 mrg */ 573 1.1 mrg __isl_give isl_union_map *isl_map_to_union_map(__isl_take isl_map *map) 574 1.1 mrg { 575 1.1 mrg return isl_union_map_from_map(map); 576 1.1 mrg } 577 1.1 mrg 578 1.1 mrg __isl_give isl_union_set *isl_union_set_from_set(__isl_take isl_set *set) 579 1.1 mrg { 580 1.1 mrg return isl_union_map_from_map(set_to_map(set)); 581 1.1 mrg } 582 1.1 mrg 583 1.1 mrg /* This function performs the same operation as isl_union_set_from_set, 584 1.1 mrg * but is considered as a function on an isl_set when exported. 585 1.1 mrg */ 586 1.1 mrg __isl_give isl_union_set *isl_set_to_union_set(__isl_take isl_set *set) 587 1.1 mrg { 588 1.1 mrg return isl_union_set_from_set(set); 589 1.1 mrg } 590 1.1 mrg 591 1.1 mrg __isl_give isl_union_map *isl_union_map_from_basic_map( 592 1.1 mrg __isl_take isl_basic_map *bmap) 593 1.1 mrg { 594 1.1 mrg return isl_union_map_from_map(isl_map_from_basic_map(bmap)); 595 1.1 mrg } 596 1.1 mrg 597 1.1 mrg __isl_give isl_union_set *isl_union_set_from_basic_set( 598 1.1 mrg __isl_take isl_basic_set *bset) 599 1.1 mrg { 600 1.1 mrg return isl_union_map_from_basic_map(bset); 601 1.1 mrg } 602 1.1 mrg 603 1.1 mrg struct isl_union_map_foreach_data 604 1.1 mrg { 605 1.1 mrg isl_stat (*fn)(__isl_take isl_map *map, void *user); 606 1.1 mrg void *user; 607 1.1 mrg }; 608 1.1 mrg 609 1.1 mrg static isl_stat call_on_copy(void **entry, void *user) 610 1.1 mrg { 611 1.1 mrg isl_map *map = *entry; 612 1.1 mrg struct isl_union_map_foreach_data *data; 613 1.1 mrg data = (struct isl_union_map_foreach_data *)user; 614 1.1 mrg 615 1.1 mrg return data->fn(isl_map_copy(map), data->user); 616 1.1 mrg } 617 1.1 mrg 618 1.1 mrg isl_size isl_union_map_n_map(__isl_keep isl_union_map *umap) 619 1.1 mrg { 620 1.1 mrg return umap ? umap->table.n : isl_size_error; 621 1.1 mrg } 622 1.1 mrg 623 1.1 mrg isl_size isl_union_set_n_set(__isl_keep isl_union_set *uset) 624 1.1 mrg { 625 1.1 mrg return uset ? uset->table.n : isl_size_error; 626 1.1 mrg } 627 1.1 mrg 628 1.1 mrg isl_stat isl_union_map_foreach_map(__isl_keep isl_union_map *umap, 629 1.1 mrg isl_stat (*fn)(__isl_take isl_map *map, void *user), void *user) 630 1.1 mrg { 631 1.1 mrg struct isl_union_map_foreach_data data = { fn, user }; 632 1.1 mrg 633 1.1 mrg if (!umap) 634 1.1 mrg return isl_stat_error; 635 1.1 mrg 636 1.1 mrg return isl_hash_table_foreach(umap->dim->ctx, &umap->table, 637 1.1 mrg &call_on_copy, &data); 638 1.1 mrg } 639 1.1 mrg 640 1.1 mrg /* Internal data structure for isl_union_map_every_map. 641 1.1 mrg * 642 1.1 mrg * "test" is the user-specified callback function. 643 1.1 mrg * "user" is the user-specified callback function argument. 644 1.1 mrg * 645 1.1 mrg * "failed" is initialized to 0 and set to 1 if "test" fails 646 1.1 mrg * on any map. 647 1.1 mrg */ 648 1.1 mrg struct isl_union_map_every_data { 649 1.1 mrg isl_bool (*test)(__isl_keep isl_map *map, void *user); 650 1.1 mrg void *user; 651 1.1 mrg int failed; 652 1.1 mrg }; 653 1.1 mrg 654 1.1 mrg /* Call data->test on "map". 655 1.1 mrg * If this fails, then set data->failed and abort. 656 1.1 mrg */ 657 1.1 mrg static isl_stat call_every(void **entry, void *user) 658 1.1 mrg { 659 1.1 mrg isl_map *map = *entry; 660 1.1 mrg struct isl_union_map_every_data *data = user; 661 1.1 mrg isl_bool r; 662 1.1 mrg 663 1.1 mrg r = data->test(map, data->user); 664 1.1 mrg if (r < 0) 665 1.1 mrg return isl_stat_error; 666 1.1 mrg if (r) 667 1.1 mrg return isl_stat_ok; 668 1.1 mrg data->failed = 1; 669 1.1 mrg return isl_stat_error; 670 1.1 mrg } 671 1.1 mrg 672 1.1 mrg /* Does "test" succeed on every map in "umap"? 673 1.1 mrg */ 674 1.1 mrg isl_bool isl_union_map_every_map(__isl_keep isl_union_map *umap, 675 1.1 mrg isl_bool (*test)(__isl_keep isl_map *map, void *user), void *user) 676 1.1 mrg { 677 1.1 mrg struct isl_union_map_every_data data = { test, user, 0 }; 678 1.1 mrg isl_stat r; 679 1.1 mrg 680 1.1 mrg if (!umap) 681 1.1 mrg return isl_bool_error; 682 1.1 mrg 683 1.1 mrg r = isl_hash_table_foreach(isl_union_map_get_ctx(umap), &umap->table, 684 1.1 mrg &call_every, &data); 685 1.1 mrg if (r >= 0) 686 1.1 mrg return isl_bool_true; 687 1.1 mrg if (data.failed) 688 1.1 mrg return isl_bool_false; 689 1.1 mrg return isl_bool_error; 690 1.1 mrg } 691 1.1 mrg 692 1.1 mrg /* Add "map" to "list". 693 1.1 mrg */ 694 1.1 mrg static isl_stat add_list_map(__isl_take isl_map *map, void *user) 695 1.1 mrg { 696 1.1 mrg isl_map_list **list = user; 697 1.1 mrg 698 1.1 mrg *list = isl_map_list_add(*list, map); 699 1.1 mrg 700 1.1 mrg if (!*list) 701 1.1 mrg return isl_stat_error; 702 1.1 mrg return isl_stat_ok; 703 1.1 mrg } 704 1.1 mrg 705 1.1 mrg /* Return the maps in "umap" as a list. 706 1.1 mrg * 707 1.1 mrg * First construct a list of the appropriate size and then add all the 708 1.1 mrg * elements. 709 1.1 mrg */ 710 1.1 mrg __isl_give isl_map_list *isl_union_map_get_map_list( 711 1.1 mrg __isl_keep isl_union_map *umap) 712 1.1 mrg { 713 1.1 mrg isl_size n_maps; 714 1.1 mrg isl_ctx *ctx; 715 1.1 mrg isl_map_list *list; 716 1.1 mrg 717 1.1 mrg n_maps = isl_union_map_n_map(umap); 718 1.1 mrg if (n_maps < 0) 719 1.1 mrg return NULL; 720 1.1 mrg ctx = isl_union_map_get_ctx(umap); 721 1.1 mrg list = isl_map_list_alloc(ctx, n_maps); 722 1.1 mrg 723 1.1 mrg if (isl_union_map_foreach_map(umap, &add_list_map, &list) < 0) 724 1.1 mrg list = isl_map_list_free(list); 725 1.1 mrg 726 1.1 mrg return list; 727 1.1 mrg } 728 1.1 mrg 729 1.1 mrg /* Return the sets in "uset" as a list. 730 1.1 mrg */ 731 1.1 mrg __isl_give isl_set_list *isl_union_set_get_set_list( 732 1.1 mrg __isl_keep isl_union_set *uset) 733 1.1 mrg { 734 1.1 mrg return set_list_from_map_list( 735 1.1 mrg isl_union_map_get_map_list(uset_to_umap(uset))); 736 1.1 mrg } 737 1.1 mrg 738 1.1 mrg /* Can "umap" be converted to an isl_map? 739 1.1 mrg * That is, does it contain elements in exactly one space? 740 1.1 mrg */ 741 1.1 mrg isl_bool isl_union_map_isa_map(__isl_keep isl_union_map *umap) 742 1.1 mrg { 743 1.1 mrg isl_size n; 744 1.1 mrg 745 1.1 mrg n = isl_union_map_n_map(umap); 746 1.1 mrg if (n < 0) 747 1.1 mrg return isl_bool_error; 748 1.1 mrg return isl_bool_ok(n == 1); 749 1.1 mrg } 750 1.1 mrg 751 1.1 mrg /* Can "uset" be converted to an isl_set? 752 1.1 mrg * That is, does it contain elements in exactly one space? 753 1.1 mrg */ 754 1.1 mrg isl_bool isl_union_set_isa_set(__isl_keep isl_union_set *uset) 755 1.1 mrg { 756 1.1 mrg return isl_union_map_isa_map(uset_to_umap(uset)); 757 1.1 mrg } 758 1.1 mrg 759 1.1 mrg static isl_stat copy_map(void **entry, void *user) 760 1.1 mrg { 761 1.1 mrg isl_map *map = *entry; 762 1.1 mrg isl_map **map_p = user; 763 1.1 mrg 764 1.1 mrg *map_p = isl_map_copy(map); 765 1.1 mrg 766 1.1 mrg return isl_stat_error; 767 1.1 mrg } 768 1.1 mrg 769 1.1 mrg __isl_give isl_map *isl_map_from_union_map(__isl_take isl_union_map *umap) 770 1.1 mrg { 771 1.1 mrg isl_bool is_map; 772 1.1 mrg isl_ctx *ctx; 773 1.1 mrg isl_map *map = NULL; 774 1.1 mrg 775 1.1 mrg is_map = isl_union_map_isa_map(umap); 776 1.1 mrg if (is_map < 0) 777 1.1 mrg goto error; 778 1.1 mrg ctx = isl_union_map_get_ctx(umap); 779 1.1 mrg if (!is_map) 780 1.1 mrg isl_die(ctx, isl_error_invalid, 781 1.1 mrg "union map needs to contain elements in exactly " 782 1.1 mrg "one space", goto error); 783 1.1 mrg 784 1.1 mrg isl_hash_table_foreach(ctx, &umap->table, ©_map, &map); 785 1.1 mrg 786 1.1 mrg isl_union_map_free(umap); 787 1.1 mrg 788 1.1 mrg return map; 789 1.1 mrg error: 790 1.1 mrg isl_union_map_free(umap); 791 1.1 mrg return NULL; 792 1.1 mrg } 793 1.1 mrg 794 1.1 mrg /* This function performs the same operation as isl_map_from_union_map, 795 1.1 mrg * but is considered as a function on an isl_union_map when exported. 796 1.1 mrg */ 797 1.1 mrg __isl_give isl_map *isl_union_map_as_map(__isl_take isl_union_map *umap) 798 1.1 mrg { 799 1.1 mrg return isl_map_from_union_map(umap); 800 1.1 mrg } 801 1.1 mrg 802 1.1 mrg __isl_give isl_set *isl_set_from_union_set(__isl_take isl_union_set *uset) 803 1.1 mrg { 804 1.1 mrg return isl_map_from_union_map(uset); 805 1.1 mrg } 806 1.1 mrg 807 1.1 mrg /* This function performs the same operation as isl_set_from_union_set, 808 1.1 mrg * but is considered as a function on an isl_union_set when exported. 809 1.1 mrg */ 810 1.1 mrg __isl_give isl_set *isl_union_set_as_set(__isl_take isl_union_set *uset) 811 1.1 mrg { 812 1.1 mrg return isl_set_from_union_set(uset); 813 1.1 mrg } 814 1.1 mrg 815 1.1 mrg /* Extract the map in "umap" that lives in the given space (ignoring 816 1.1 mrg * parameters). 817 1.1 mrg */ 818 1.1 mrg __isl_give isl_map *isl_union_map_extract_map(__isl_keep isl_union_map *umap, 819 1.1 mrg __isl_take isl_space *space) 820 1.1 mrg { 821 1.1 mrg struct isl_hash_table_entry *entry; 822 1.1 mrg 823 1.1 mrg entry = isl_union_map_find_entry(umap, space, 0); 824 1.1 mrg if (!entry) 825 1.1 mrg goto error; 826 1.1 mrg if (entry == isl_hash_table_entry_none) 827 1.1 mrg return isl_map_empty(space); 828 1.1 mrg isl_space_free(space); 829 1.1 mrg return isl_map_copy(entry->data); 830 1.1 mrg error: 831 1.1 mrg isl_space_free(space); 832 1.1 mrg return NULL; 833 1.1 mrg } 834 1.1 mrg 835 1.1 mrg __isl_give isl_set *isl_union_set_extract_set(__isl_keep isl_union_set *uset, 836 1.1 mrg __isl_take isl_space *space) 837 1.1 mrg { 838 1.1 mrg return set_from_map(isl_union_map_extract_map(uset, space)); 839 1.1 mrg } 840 1.1 mrg 841 1.1 mrg /* Check if umap contains a map in the given space (ignoring parameters). 842 1.1 mrg */ 843 1.1 mrg isl_bool isl_union_map_contains(__isl_keep isl_union_map *umap, 844 1.1 mrg __isl_keep isl_space *space) 845 1.1 mrg { 846 1.1 mrg struct isl_hash_table_entry *entry; 847 1.1 mrg 848 1.1 mrg space = isl_space_drop_all_params(isl_space_copy(space)); 849 1.1 mrg space = isl_space_align_params(space, isl_union_map_get_space(umap)); 850 1.1 mrg entry = isl_union_map_find_entry(umap, space, 0); 851 1.1 mrg isl_space_free(space); 852 1.1 mrg if (!entry) 853 1.1 mrg return isl_bool_error; 854 1.1 mrg return isl_bool_ok(entry != isl_hash_table_entry_none); 855 1.1 mrg } 856 1.1 mrg 857 1.1 mrg isl_bool isl_union_set_contains(__isl_keep isl_union_set *uset, 858 1.1 mrg __isl_keep isl_space *space) 859 1.1 mrg { 860 1.1 mrg return isl_union_map_contains(uset, space); 861 1.1 mrg } 862 1.1 mrg 863 1.1 mrg isl_stat isl_union_set_foreach_set(__isl_keep isl_union_set *uset, 864 1.1 mrg isl_stat (*fn)(__isl_take isl_set *set, void *user), void *user) 865 1.1 mrg { 866 1.1 mrg return isl_union_map_foreach_map(uset, 867 1.1 mrg (isl_stat(*)(__isl_take isl_map *, void*))fn, user); 868 1.1 mrg } 869 1.1 mrg 870 1.1 mrg /* Internal data structure for isl_union_set_every_set. 871 1.1 mrg * 872 1.1 mrg * "test" is the user-specified callback function. 873 1.1 mrg * "user" is the user-specified callback function argument. 874 1.1 mrg */ 875 1.1 mrg struct isl_test_set_from_map_data { 876 1.1 mrg isl_bool (*test)(__isl_keep isl_set *set, void *user); 877 1.1 mrg void *user; 878 1.1 mrg }; 879 1.1 mrg 880 1.1 mrg /* Call data->test on "map", which is part of an isl_union_set and 881 1.1 mrg * therefore known to be an isl_set. 882 1.1 mrg */ 883 1.1 mrg static isl_bool test_set_from_map(__isl_keep isl_map *map, void *user) 884 1.1 mrg { 885 1.1 mrg struct isl_test_set_from_map_data *data = user; 886 1.1 mrg 887 1.1 mrg return data->test(set_from_map(map), data->user); 888 1.1 mrg } 889 1.1 mrg 890 1.1 mrg /* Does "test" succeed on every set in "uset"? 891 1.1 mrg */ 892 1.1 mrg isl_bool isl_union_set_every_set(__isl_keep isl_union_set *uset, 893 1.1 mrg isl_bool (*test)(__isl_keep isl_set *set, void *user), void *user) 894 1.1 mrg { 895 1.1 mrg struct isl_test_set_from_map_data data = { test, user }; 896 1.1 mrg 897 1.1 mrg return isl_union_map_every_map(uset_to_umap(uset), 898 1.1 mrg &test_set_from_map, &data); 899 1.1 mrg } 900 1.1 mrg 901 1.1 mrg struct isl_union_set_foreach_point_data { 902 1.1 mrg isl_stat (*fn)(__isl_take isl_point *pnt, void *user); 903 1.1 mrg void *user; 904 1.1 mrg }; 905 1.1 mrg 906 1.1 mrg static isl_stat foreach_point(__isl_take isl_set *set, void *user) 907 1.1 mrg { 908 1.1 mrg struct isl_union_set_foreach_point_data *data = user; 909 1.1 mrg isl_stat r; 910 1.1 mrg 911 1.1 mrg r = isl_set_foreach_point(set, data->fn, data->user); 912 1.1 mrg isl_set_free(set); 913 1.1 mrg 914 1.1 mrg return r; 915 1.1 mrg } 916 1.1 mrg 917 1.1 mrg isl_stat isl_union_set_foreach_point(__isl_keep isl_union_set *uset, 918 1.1 mrg isl_stat (*fn)(__isl_take isl_point *pnt, void *user), void *user) 919 1.1 mrg { 920 1.1 mrg struct isl_union_set_foreach_point_data data = { fn, user }; 921 1.1 mrg return isl_union_set_foreach_set(uset, &foreach_point, &data); 922 1.1 mrg } 923 1.1 mrg 924 1.1 mrg /* Data structure that specifies how gen_bin_op should 925 1.1 mrg * construct results from the inputs. 926 1.1 mrg * 927 1.1 mrg * If "subtract" is set, then a map in the first input is copied to the result 928 1.1 mrg * if there is no corresponding map in the second input. 929 1.1 mrg * Otherwise, a map in the first input with no corresponding map 930 1.1 mrg * in the second input is ignored. 931 1.1 mrg * If "filter" is not NULL, then it specifies which maps in the first 932 1.1 mrg * input may have a matching map in the second input. 933 1.1 mrg * In particular, it makes sure that "match_space" can be called 934 1.1 mrg * on the space of the map. 935 1.1 mrg * "match_space" specifies how to transform the space of a map 936 1.1 mrg * in the first input to the space of the corresponding map 937 1.1 mrg * in the second input. 938 1.1 mrg * "fn_map" specifies how the matching maps, one from each input, 939 1.1 mrg * should be combined to form a map in the result. 940 1.1 mrg */ 941 1.1 mrg struct isl_bin_op_control { 942 1.1 mrg int subtract; 943 1.1 mrg isl_bool (*filter)(__isl_keep isl_map *map); 944 1.1 mrg __isl_give isl_space *(*match_space)(__isl_take isl_space *space); 945 1.1 mrg __isl_give isl_map *(*fn_map)(__isl_take isl_map *map1, 946 1.1 mrg __isl_take isl_map *map2); 947 1.1 mrg }; 948 1.1 mrg 949 1.1 mrg /* Internal data structure for gen_bin_op. 950 1.1 mrg * "control" specifies how the maps in the result should be constructed. 951 1.1 mrg * "umap2" is a pointer to the second argument. 952 1.1 mrg * "res" collects the results. 953 1.1 mrg */ 954 1.1 mrg struct isl_union_map_gen_bin_data { 955 1.1 mrg struct isl_bin_op_control *control; 956 1.1 mrg isl_union_map *umap2; 957 1.1 mrg isl_union_map *res; 958 1.1 mrg }; 959 1.1 mrg 960 1.1 mrg /* Add a copy of "map" to "res" and return the result. 961 1.1 mrg */ 962 1.1 mrg static __isl_give isl_union_map *bin_add_map(__isl_take isl_union_map *res, 963 1.1 mrg __isl_keep isl_map *map) 964 1.1 mrg { 965 1.1 mrg return isl_union_map_add_map(res, isl_map_copy(map)); 966 1.1 mrg } 967 1.1 mrg 968 1.1 mrg /* Combine "map1" and "map2", add the result to "res" and return the result. 969 1.1 mrg * Check whether the result is empty before adding it to "res". 970 1.1 mrg */ 971 1.1 mrg static __isl_give isl_union_map *bin_add_pair(__isl_take isl_union_map *res, 972 1.1 mrg __isl_keep isl_map *map1, __isl_keep isl_map *map2, 973 1.1 mrg struct isl_union_map_gen_bin_data *data) 974 1.1 mrg { 975 1.1 mrg isl_bool empty; 976 1.1 mrg isl_map *map; 977 1.1 mrg 978 1.1 mrg map = data->control->fn_map(isl_map_copy(map1), isl_map_copy(map2)); 979 1.1 mrg empty = isl_map_is_empty(map); 980 1.1 mrg if (empty < 0 || empty) { 981 1.1 mrg isl_map_free(map); 982 1.1 mrg if (empty < 0) 983 1.1 mrg return isl_union_map_free(res); 984 1.1 mrg return res; 985 1.1 mrg } 986 1.1 mrg return isl_union_map_add_map(res, map); 987 1.1 mrg } 988 1.1 mrg 989 1.1 mrg /* Dummy match_space function that simply returns the input space. 990 1.1 mrg */ 991 1.1 mrg static __isl_give isl_space *identity(__isl_take isl_space *space) 992 1.1 mrg { 993 1.1 mrg return space; 994 1.1 mrg } 995 1.1 mrg 996 1.1 mrg /* Look for the map in data->umap2 that corresponds to "map", if any. 997 1.1 mrg * Return (isl_bool_true, matching map) if there is one, 998 1.1 mrg * (isl_bool_false, NULL) if there is no matching map and 999 1.1 mrg * (isl_bool_error, NULL) on error. 1000 1.1 mrg * 1001 1.1 mrg * If not NULL, then data->control->filter specifies whether "map" 1002 1.1 mrg * can have any matching map. If so, 1003 1.1 mrg * data->control->match_space specifies which map in data->umap2 1004 1.1 mrg * corresponds to "map". 1005 1.1 mrg */ 1006 1.1 mrg static __isl_keep isl_maybe_isl_map bin_try_get_match( 1007 1.1 mrg struct isl_union_map_gen_bin_data *data, __isl_keep isl_map *map) 1008 1.1 mrg { 1009 1.1 mrg struct isl_hash_table_entry *entry2; 1010 1.1 mrg isl_space *space; 1011 1.1 mrg isl_maybe_isl_map res = { isl_bool_error, NULL }; 1012 1.1 mrg 1013 1.1 mrg if (data->control->filter) { 1014 1.1 mrg res.valid = data->control->filter(map); 1015 1.1 mrg if (res.valid < 0 || !res.valid) 1016 1.1 mrg return res; 1017 1.1 mrg res.valid = isl_bool_error; 1018 1.1 mrg } 1019 1.1 mrg 1020 1.1 mrg space = isl_map_get_space(map); 1021 1.1 mrg if (data->control->match_space != &identity) 1022 1.1 mrg space = data->control->match_space(space); 1023 1.1 mrg entry2 = isl_union_map_find_entry(data->umap2, space, 0); 1024 1.1 mrg isl_space_free(space); 1025 1.1 mrg if (entry2) 1026 1.1 mrg res.valid = isl_bool_ok(entry2 != isl_hash_table_entry_none); 1027 1.1 mrg if (res.valid >= 0 && res.valid) 1028 1.1 mrg res.value = entry2->data; 1029 1.1 mrg 1030 1.1 mrg return res; 1031 1.1 mrg } 1032 1.1 mrg 1033 1.1 mrg /* isl_hash_table_foreach callback for gen_bin_op. 1034 1.1 mrg * Look for the map in data->umap2 that corresponds 1035 1.1 mrg * to the map that "entry" points to, apply the binary operation and 1036 1.1 mrg * add the result to data->res. 1037 1.1 mrg * 1038 1.1 mrg * If no corresponding map can be found, then the effect depends 1039 1.1 mrg * on data->control->subtract. If it is set, then the current map 1040 1.1 mrg * is added directly to the result. Otherwise, it is ignored. 1041 1.1 mrg */ 1042 1.1 mrg static isl_stat gen_bin_entry(void **entry, void *user) 1043 1.1 mrg { 1044 1.1 mrg struct isl_union_map_gen_bin_data *data = user; 1045 1.1 mrg isl_map *map = *entry; 1046 1.1 mrg isl_maybe_isl_map m; 1047 1.1 mrg 1048 1.1 mrg m = bin_try_get_match(data, map); 1049 1.1 mrg if (m.valid < 0) 1050 1.1 mrg return isl_stat_error; 1051 1.1 mrg if (!m.valid && !data->control->subtract) 1052 1.1 mrg return isl_stat_ok; 1053 1.1 mrg 1054 1.1 mrg if (!m.valid) 1055 1.1 mrg data->res = bin_add_map(data->res, map); 1056 1.1 mrg else 1057 1.1 mrg data->res = bin_add_pair(data->res, map, m.value, data); 1058 1.1 mrg if (!data->res) 1059 1.1 mrg return isl_stat_error; 1060 1.1 mrg 1061 1.1 mrg return isl_stat_ok; 1062 1.1 mrg } 1063 1.1 mrg 1064 1.1 mrg /* Apply a binary operation to "umap1" and "umap2" based on "control". 1065 1.1 mrg * Run over all maps in "umap1" and look for the corresponding map in "umap2" 1066 1.1 mrg * in gen_bin_entry. 1067 1.1 mrg */ 1068 1.1 mrg static __isl_give isl_union_map *gen_bin_op(__isl_take isl_union_map *umap1, 1069 1.1 mrg __isl_take isl_union_map *umap2, struct isl_bin_op_control *control) 1070 1.1 mrg { 1071 1.1 mrg struct isl_union_map_gen_bin_data data = { control, NULL, NULL }; 1072 1.1 mrg 1073 1.1 mrg umap1 = isl_union_map_align_params(umap1, isl_union_map_get_space(umap2)); 1074 1.1 mrg umap2 = isl_union_map_align_params(umap2, isl_union_map_get_space(umap1)); 1075 1.1 mrg 1076 1.1 mrg if (!umap1 || !umap2) 1077 1.1 mrg goto error; 1078 1.1 mrg 1079 1.1 mrg data.umap2 = umap2; 1080 1.1 mrg data.res = isl_union_map_alloc(isl_space_copy(umap1->dim), 1081 1.1 mrg umap1->table.n); 1082 1.1 mrg if (isl_hash_table_foreach(umap1->dim->ctx, &umap1->table, 1083 1.1 mrg &gen_bin_entry, &data) < 0) 1084 1.1 mrg goto error; 1085 1.1 mrg 1086 1.1 mrg isl_union_map_free(umap1); 1087 1.1 mrg isl_union_map_free(umap2); 1088 1.1 mrg return data.res; 1089 1.1 mrg error: 1090 1.1 mrg isl_union_map_free(umap1); 1091 1.1 mrg isl_union_map_free(umap2); 1092 1.1 mrg isl_union_map_free(data.res); 1093 1.1 mrg return NULL; 1094 1.1 mrg } 1095 1.1 mrg 1096 1.1 mrg __isl_give isl_union_map *isl_union_map_subtract( 1097 1.1 mrg __isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2) 1098 1.1 mrg { 1099 1.1 mrg struct isl_bin_op_control control = { 1100 1.1 mrg .subtract = 1, 1101 1.1 mrg .match_space = &identity, 1102 1.1 mrg .fn_map = &isl_map_subtract, 1103 1.1 mrg }; 1104 1.1 mrg 1105 1.1 mrg return gen_bin_op(umap1, umap2, &control); 1106 1.1 mrg } 1107 1.1 mrg 1108 1.1 mrg __isl_give isl_union_set *isl_union_set_subtract( 1109 1.1 mrg __isl_take isl_union_set *uset1, __isl_take isl_union_set *uset2) 1110 1.1 mrg { 1111 1.1 mrg return isl_union_map_subtract(uset1, uset2); 1112 1.1 mrg } 1113 1.1 mrg 1114 1.1 mrg struct isl_union_map_gen_bin_set_data { 1115 1.1 mrg isl_set *set; 1116 1.1 mrg isl_union_map *res; 1117 1.1 mrg }; 1118 1.1 mrg 1119 1.1 mrg static isl_stat intersect_params_entry(void **entry, void *user) 1120 1.1 mrg { 1121 1.1 mrg struct isl_union_map_gen_bin_set_data *data = user; 1122 1.1 mrg isl_map *map = *entry; 1123 1.1 mrg int empty; 1124 1.1 mrg 1125 1.1 mrg map = isl_map_copy(map); 1126 1.1 mrg map = isl_map_intersect_params(map, isl_set_copy(data->set)); 1127 1.1 mrg 1128 1.1 mrg empty = isl_map_is_empty(map); 1129 1.1 mrg if (empty < 0) { 1130 1.1 mrg isl_map_free(map); 1131 1.1 mrg return isl_stat_error; 1132 1.1 mrg } 1133 1.1 mrg 1134 1.1 mrg data->res = isl_union_map_add_map(data->res, map); 1135 1.1 mrg 1136 1.1 mrg return isl_stat_ok; 1137 1.1 mrg } 1138 1.1 mrg 1139 1.1 mrg static __isl_give isl_union_map *gen_bin_set_op(__isl_take isl_union_map *umap, 1140 1.1 mrg __isl_take isl_set *set, isl_stat (*fn)(void **, void *)) 1141 1.1 mrg { 1142 1.1 mrg struct isl_union_map_gen_bin_set_data data = { NULL, NULL }; 1143 1.1 mrg 1144 1.1 mrg umap = isl_union_map_align_params(umap, isl_set_get_space(set)); 1145 1.1 mrg set = isl_set_align_params(set, isl_union_map_get_space(umap)); 1146 1.1 mrg 1147 1.1 mrg if (!umap || !set) 1148 1.1 mrg goto error; 1149 1.1 mrg 1150 1.1 mrg data.set = set; 1151 1.1 mrg data.res = isl_union_map_alloc(isl_space_copy(umap->dim), 1152 1.1 mrg umap->table.n); 1153 1.1 mrg if (isl_hash_table_foreach(umap->dim->ctx, &umap->table, 1154 1.1 mrg fn, &data) < 0) 1155 1.1 mrg goto error; 1156 1.1 mrg 1157 1.1 mrg isl_union_map_free(umap); 1158 1.1 mrg isl_set_free(set); 1159 1.1 mrg return data.res; 1160 1.1 mrg error: 1161 1.1 mrg isl_union_map_free(umap); 1162 1.1 mrg isl_set_free(set); 1163 1.1 mrg isl_union_map_free(data.res); 1164 1.1 mrg return NULL; 1165 1.1 mrg } 1166 1.1 mrg 1167 1.1 mrg /* Intersect "umap" with the parameter domain "set". 1168 1.1 mrg * 1169 1.1 mrg * If "set" does not have any constraints, then we can return immediately. 1170 1.1 mrg */ 1171 1.1 mrg __isl_give isl_union_map *isl_union_map_intersect_params( 1172 1.1 mrg __isl_take isl_union_map *umap, __isl_take isl_set *set) 1173 1.1 mrg { 1174 1.1 mrg int is_universe; 1175 1.1 mrg 1176 1.1 mrg is_universe = isl_set_plain_is_universe(set); 1177 1.1 mrg if (is_universe < 0) 1178 1.1 mrg goto error; 1179 1.1 mrg if (is_universe) { 1180 1.1 mrg isl_set_free(set); 1181 1.1 mrg return umap; 1182 1.1 mrg } 1183 1.1 mrg 1184 1.1 mrg return gen_bin_set_op(umap, set, &intersect_params_entry); 1185 1.1 mrg error: 1186 1.1 mrg isl_union_map_free(umap); 1187 1.1 mrg isl_set_free(set); 1188 1.1 mrg return NULL; 1189 1.1 mrg } 1190 1.1 mrg 1191 1.1 mrg __isl_give isl_union_set *isl_union_set_intersect_params( 1192 1.1 mrg __isl_take isl_union_set *uset, __isl_take isl_set *set) 1193 1.1 mrg { 1194 1.1 mrg return isl_union_map_intersect_params(uset, set); 1195 1.1 mrg } 1196 1.1 mrg 1197 1.1 mrg static __isl_give isl_union_map *union_map_intersect_params( 1198 1.1 mrg __isl_take isl_union_map *umap, __isl_take isl_union_set *uset) 1199 1.1 mrg { 1200 1.1 mrg return isl_union_map_intersect_params(umap, 1201 1.1 mrg isl_set_from_union_set(uset)); 1202 1.1 mrg } 1203 1.1 mrg 1204 1.1 mrg static __isl_give isl_union_map *union_map_gist_params( 1205 1.1 mrg __isl_take isl_union_map *umap, __isl_take isl_union_set *uset) 1206 1.1 mrg { 1207 1.1 mrg return isl_union_map_gist_params(umap, isl_set_from_union_set(uset)); 1208 1.1 mrg } 1209 1.1 mrg 1210 1.1 mrg struct isl_union_map_match_bin_data { 1211 1.1 mrg isl_union_map *umap2; 1212 1.1 mrg isl_union_map *res; 1213 1.1 mrg __isl_give isl_map *(*fn)(__isl_take isl_map*, __isl_take isl_map*); 1214 1.1 mrg }; 1215 1.1 mrg 1216 1.1 mrg static isl_stat match_bin_entry(void **entry, void *user) 1217 1.1 mrg { 1218 1.1 mrg struct isl_union_map_match_bin_data *data = user; 1219 1.1 mrg struct isl_hash_table_entry *entry2; 1220 1.1 mrg isl_space *space; 1221 1.1 mrg isl_map *map = *entry; 1222 1.1 mrg int empty; 1223 1.1 mrg 1224 1.1 mrg space = isl_map_peek_space(map); 1225 1.1 mrg entry2 = isl_union_map_find_entry(data->umap2, space, 0); 1226 1.1 mrg if (!entry2) 1227 1.1 mrg return isl_stat_error; 1228 1.1 mrg if (entry2 == isl_hash_table_entry_none) 1229 1.1 mrg return isl_stat_ok; 1230 1.1 mrg 1231 1.1 mrg map = isl_map_copy(map); 1232 1.1 mrg map = data->fn(map, isl_map_copy(entry2->data)); 1233 1.1 mrg 1234 1.1 mrg empty = isl_map_is_empty(map); 1235 1.1 mrg if (empty < 0) { 1236 1.1 mrg isl_map_free(map); 1237 1.1 mrg return isl_stat_error; 1238 1.1 mrg } 1239 1.1 mrg if (empty) { 1240 1.1 mrg isl_map_free(map); 1241 1.1 mrg return isl_stat_ok; 1242 1.1 mrg } 1243 1.1 mrg 1244 1.1 mrg data->res = isl_union_map_add_map(data->res, map); 1245 1.1 mrg 1246 1.1 mrg return isl_stat_ok; 1247 1.1 mrg } 1248 1.1 mrg 1249 1.1 mrg static __isl_give isl_union_map *match_bin_op(__isl_take isl_union_map *umap1, 1250 1.1 mrg __isl_take isl_union_map *umap2, 1251 1.1 mrg __isl_give isl_map *(*fn)(__isl_take isl_map*, __isl_take isl_map*)) 1252 1.1 mrg { 1253 1.1 mrg struct isl_union_map_match_bin_data data = { NULL, NULL, fn }; 1254 1.1 mrg 1255 1.1 mrg umap1 = isl_union_map_align_params(umap1, isl_union_map_get_space(umap2)); 1256 1.1 mrg umap2 = isl_union_map_align_params(umap2, isl_union_map_get_space(umap1)); 1257 1.1 mrg 1258 1.1 mrg if (!umap1 || !umap2) 1259 1.1 mrg goto error; 1260 1.1 mrg 1261 1.1 mrg data.umap2 = umap2; 1262 1.1 mrg data.res = isl_union_map_alloc(isl_space_copy(umap1->dim), 1263 1.1 mrg umap1->table.n); 1264 1.1 mrg if (isl_hash_table_foreach(umap1->dim->ctx, &umap1->table, 1265 1.1 mrg &match_bin_entry, &data) < 0) 1266 1.1 mrg goto error; 1267 1.1 mrg 1268 1.1 mrg isl_union_map_free(umap1); 1269 1.1 mrg isl_union_map_free(umap2); 1270 1.1 mrg return data.res; 1271 1.1 mrg error: 1272 1.1 mrg isl_union_map_free(umap1); 1273 1.1 mrg isl_union_map_free(umap2); 1274 1.1 mrg isl_union_map_free(data.res); 1275 1.1 mrg return NULL; 1276 1.1 mrg } 1277 1.1 mrg 1278 1.1 mrg __isl_give isl_union_map *isl_union_map_intersect( 1279 1.1 mrg __isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2) 1280 1.1 mrg { 1281 1.1 mrg return match_bin_op(umap1, umap2, &isl_map_intersect); 1282 1.1 mrg } 1283 1.1 mrg 1284 1.1 mrg /* Compute the intersection of the two union_sets. 1285 1.1 mrg * As a special case, if exactly one of the two union_sets 1286 1.1 mrg * is a parameter domain, then intersect the parameter domain 1287 1.1 mrg * of the other one with this set. 1288 1.1 mrg */ 1289 1.1 mrg __isl_give isl_union_set *isl_union_set_intersect( 1290 1.1 mrg __isl_take isl_union_set *uset1, __isl_take isl_union_set *uset2) 1291 1.1 mrg { 1292 1.1 mrg int p1, p2; 1293 1.1 mrg 1294 1.1 mrg p1 = isl_union_set_is_params(uset1); 1295 1.1 mrg p2 = isl_union_set_is_params(uset2); 1296 1.1 mrg if (p1 < 0 || p2 < 0) 1297 1.1 mrg goto error; 1298 1.1 mrg if (!p1 && p2) 1299 1.1 mrg return union_map_intersect_params(uset1, uset2); 1300 1.1 mrg if (p1 && !p2) 1301 1.1 mrg return union_map_intersect_params(uset2, uset1); 1302 1.1 mrg return isl_union_map_intersect(uset1, uset2); 1303 1.1 mrg error: 1304 1.1 mrg isl_union_set_free(uset1); 1305 1.1 mrg isl_union_set_free(uset2); 1306 1.1 mrg return NULL; 1307 1.1 mrg } 1308 1.1 mrg 1309 1.1 mrg static isl_stat gist_params_entry(void **entry, void *user) 1310 1.1 mrg { 1311 1.1 mrg struct isl_union_map_gen_bin_set_data *data = user; 1312 1.1 mrg isl_map *map = *entry; 1313 1.1 mrg int empty; 1314 1.1 mrg 1315 1.1 mrg map = isl_map_copy(map); 1316 1.1 mrg map = isl_map_gist_params(map, isl_set_copy(data->set)); 1317 1.1 mrg 1318 1.1 mrg empty = isl_map_is_empty(map); 1319 1.1 mrg if (empty < 0) { 1320 1.1 mrg isl_map_free(map); 1321 1.1 mrg return isl_stat_error; 1322 1.1 mrg } 1323 1.1 mrg 1324 1.1 mrg data->res = isl_union_map_add_map(data->res, map); 1325 1.1 mrg 1326 1.1 mrg return isl_stat_ok; 1327 1.1 mrg } 1328 1.1 mrg 1329 1.1 mrg __isl_give isl_union_map *isl_union_map_gist_params( 1330 1.1 mrg __isl_take isl_union_map *umap, __isl_take isl_set *set) 1331 1.1 mrg { 1332 1.1 mrg return gen_bin_set_op(umap, set, &gist_params_entry); 1333 1.1 mrg } 1334 1.1 mrg 1335 1.1 mrg __isl_give isl_union_set *isl_union_set_gist_params( 1336 1.1 mrg __isl_take isl_union_set *uset, __isl_take isl_set *set) 1337 1.1 mrg { 1338 1.1 mrg return isl_union_map_gist_params(uset, set); 1339 1.1 mrg } 1340 1.1 mrg 1341 1.1 mrg __isl_give isl_union_map *isl_union_map_gist(__isl_take isl_union_map *umap, 1342 1.1 mrg __isl_take isl_union_map *context) 1343 1.1 mrg { 1344 1.1 mrg return match_bin_op(umap, context, &isl_map_gist); 1345 1.1 mrg } 1346 1.1 mrg 1347 1.1 mrg __isl_give isl_union_set *isl_union_set_gist(__isl_take isl_union_set *uset, 1348 1.1 mrg __isl_take isl_union_set *context) 1349 1.1 mrg { 1350 1.1 mrg if (isl_union_set_is_params(context)) 1351 1.1 mrg return union_map_gist_params(uset, context); 1352 1.1 mrg return isl_union_map_gist(uset, context); 1353 1.1 mrg } 1354 1.1 mrg 1355 1.1 mrg /* For each map in "umap", remove the constraints in the corresponding map 1356 1.1 mrg * of "context". 1357 1.1 mrg * Each map in "context" is assumed to consist of a single disjunct and 1358 1.1 mrg * to have explicit representations for all local variables. 1359 1.1 mrg */ 1360 1.1 mrg __isl_give isl_union_map *isl_union_map_plain_gist( 1361 1.1 mrg __isl_take isl_union_map *umap, __isl_take isl_union_map *context) 1362 1.1 mrg { 1363 1.1 mrg return match_bin_op(umap, context, &isl_map_plain_gist); 1364 1.1 mrg } 1365 1.1 mrg 1366 1.1 mrg /* For each set in "uset", remove the constraints in the corresponding set 1367 1.1 mrg * of "context". 1368 1.1 mrg * Each set in "context" is assumed to consist of a single disjunct and 1369 1.1 mrg * to have explicit representations for all local variables. 1370 1.1 mrg */ 1371 1.1 mrg __isl_give isl_union_set *isl_union_set_plain_gist( 1372 1.1 mrg __isl_take isl_union_set *uset, __isl_take isl_union_set *context) 1373 1.1 mrg { 1374 1.1 mrg return isl_union_map_plain_gist(uset, context); 1375 1.1 mrg } 1376 1.1 mrg 1377 1.1 mrg static __isl_give isl_map *lex_le_set(__isl_take isl_map *set1, 1378 1.1 mrg __isl_take isl_map *set2) 1379 1.1 mrg { 1380 1.1 mrg return isl_set_lex_le_set(set_from_map(set1), set_from_map(set2)); 1381 1.1 mrg } 1382 1.1 mrg 1383 1.1 mrg static __isl_give isl_map *lex_lt_set(__isl_take isl_map *set1, 1384 1.1 mrg __isl_take isl_map *set2) 1385 1.1 mrg { 1386 1.1 mrg return isl_set_lex_lt_set(set_from_map(set1), set_from_map(set2)); 1387 1.1 mrg } 1388 1.1 mrg 1389 1.1 mrg __isl_give isl_union_map *isl_union_set_lex_lt_union_set( 1390 1.1 mrg __isl_take isl_union_set *uset1, __isl_take isl_union_set *uset2) 1391 1.1 mrg { 1392 1.1 mrg return match_bin_op(uset1, uset2, &lex_lt_set); 1393 1.1 mrg } 1394 1.1 mrg 1395 1.1 mrg __isl_give isl_union_map *isl_union_set_lex_le_union_set( 1396 1.1 mrg __isl_take isl_union_set *uset1, __isl_take isl_union_set *uset2) 1397 1.1 mrg { 1398 1.1 mrg return match_bin_op(uset1, uset2, &lex_le_set); 1399 1.1 mrg } 1400 1.1 mrg 1401 1.1 mrg __isl_give isl_union_map *isl_union_set_lex_gt_union_set( 1402 1.1 mrg __isl_take isl_union_set *uset1, __isl_take isl_union_set *uset2) 1403 1.1 mrg { 1404 1.1 mrg return isl_union_map_reverse(isl_union_set_lex_lt_union_set(uset2, uset1)); 1405 1.1 mrg } 1406 1.1 mrg 1407 1.1 mrg __isl_give isl_union_map *isl_union_set_lex_ge_union_set( 1408 1.1 mrg __isl_take isl_union_set *uset1, __isl_take isl_union_set *uset2) 1409 1.1 mrg { 1410 1.1 mrg return isl_union_map_reverse(isl_union_set_lex_le_union_set(uset2, uset1)); 1411 1.1 mrg } 1412 1.1 mrg 1413 1.1 mrg __isl_give isl_union_map *isl_union_map_lex_gt_union_map( 1414 1.1 mrg __isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2) 1415 1.1 mrg { 1416 1.1 mrg return isl_union_map_reverse(isl_union_map_lex_lt_union_map(umap2, umap1)); 1417 1.1 mrg } 1418 1.1 mrg 1419 1.1 mrg __isl_give isl_union_map *isl_union_map_lex_ge_union_map( 1420 1.1 mrg __isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2) 1421 1.1 mrg { 1422 1.1 mrg return isl_union_map_reverse(isl_union_map_lex_le_union_map(umap2, umap1)); 1423 1.1 mrg } 1424 1.1 mrg 1425 1.1 mrg /* Intersect the domain of "umap" with "uset". 1426 1.1 mrg */ 1427 1.1 mrg static __isl_give isl_union_map *union_map_intersect_domain( 1428 1.1 mrg __isl_take isl_union_map *umap, __isl_take isl_union_set *uset) 1429 1.1 mrg { 1430 1.1 mrg struct isl_bin_op_control control = { 1431 1.1 mrg .match_space = &isl_space_domain, 1432 1.1 mrg .fn_map = &isl_map_intersect_domain, 1433 1.1 mrg }; 1434 1.1 mrg 1435 1.1 mrg return gen_bin_op(umap, uset, &control); 1436 1.1 mrg } 1437 1.1 mrg 1438 1.1 mrg /* Intersect the domain of "umap" with "uset". 1439 1.1 mrg * If "uset" is a parameters domain, then intersect the parameter 1440 1.1 mrg * domain of "umap" with this set. 1441 1.1 mrg */ 1442 1.1 mrg __isl_give isl_union_map *isl_union_map_intersect_domain_union_set( 1443 1.1 mrg __isl_take isl_union_map *umap, __isl_take isl_union_set *uset) 1444 1.1 mrg { 1445 1.1 mrg if (isl_union_set_is_params(uset)) 1446 1.1 mrg return union_map_intersect_params(umap, uset); 1447 1.1 mrg else 1448 1.1 mrg return union_map_intersect_domain(umap, uset); 1449 1.1 mrg } 1450 1.1 mrg 1451 1.1 mrg /* This is an alternative name for the function above. 1452 1.1 mrg */ 1453 1.1 mrg __isl_give isl_union_map *isl_union_map_intersect_domain( 1454 1.1 mrg __isl_take isl_union_map *umap, __isl_take isl_union_set *uset) 1455 1.1 mrg { 1456 1.1 mrg return isl_union_map_intersect_domain_union_set(umap, uset); 1457 1.1 mrg } 1458 1.1 mrg 1459 1.1 mrg /* Remove the elements of "uset" from the domain of "umap". 1460 1.1 mrg */ 1461 1.1 mrg __isl_give isl_union_map *isl_union_map_subtract_domain( 1462 1.1 mrg __isl_take isl_union_map *umap, __isl_take isl_union_set *dom) 1463 1.1 mrg { 1464 1.1 mrg struct isl_bin_op_control control = { 1465 1.1 mrg .subtract = 1, 1466 1.1 mrg .match_space = &isl_space_domain, 1467 1.1 mrg .fn_map = &isl_map_subtract_domain, 1468 1.1 mrg }; 1469 1.1 mrg 1470 1.1 mrg return gen_bin_op(umap, dom, &control); 1471 1.1 mrg } 1472 1.1 mrg 1473 1.1 mrg /* Remove the elements of "uset" from the range of "umap". 1474 1.1 mrg */ 1475 1.1 mrg __isl_give isl_union_map *isl_union_map_subtract_range( 1476 1.1 mrg __isl_take isl_union_map *umap, __isl_take isl_union_set *dom) 1477 1.1 mrg { 1478 1.1 mrg struct isl_bin_op_control control = { 1479 1.1 mrg .subtract = 1, 1480 1.1 mrg .match_space = &isl_space_range, 1481 1.1 mrg .fn_map = &isl_map_subtract_range, 1482 1.1 mrg }; 1483 1.1 mrg 1484 1.1 mrg return gen_bin_op(umap, dom, &control); 1485 1.1 mrg } 1486 1.1 mrg 1487 1.1 mrg /* Compute the gist of "umap" with respect to the domain "uset". 1488 1.1 mrg */ 1489 1.1 mrg static __isl_give isl_union_map *union_map_gist_domain( 1490 1.1 mrg __isl_take isl_union_map *umap, __isl_take isl_union_set *uset) 1491 1.1 mrg { 1492 1.1 mrg struct isl_bin_op_control control = { 1493 1.1 mrg .match_space = &isl_space_domain, 1494 1.1 mrg .fn_map = &isl_map_gist_domain, 1495 1.1 mrg }; 1496 1.1 mrg 1497 1.1 mrg return gen_bin_op(umap, uset, &control); 1498 1.1 mrg } 1499 1.1 mrg 1500 1.1 mrg /* Compute the gist of "umap" with respect to the domain "uset". 1501 1.1 mrg * If "uset" is a parameters domain, then compute the gist 1502 1.1 mrg * with respect to this parameter domain. 1503 1.1 mrg */ 1504 1.1 mrg __isl_give isl_union_map *isl_union_map_gist_domain( 1505 1.1 mrg __isl_take isl_union_map *umap, __isl_take isl_union_set *uset) 1506 1.1 mrg { 1507 1.1 mrg if (isl_union_set_is_params(uset)) 1508 1.1 mrg return union_map_gist_params(umap, uset); 1509 1.1 mrg else 1510 1.1 mrg return union_map_gist_domain(umap, uset); 1511 1.1 mrg } 1512 1.1 mrg 1513 1.1 mrg /* Compute the gist of "umap" with respect to the range "uset". 1514 1.1 mrg */ 1515 1.1 mrg __isl_give isl_union_map *isl_union_map_gist_range( 1516 1.1 mrg __isl_take isl_union_map *umap, __isl_take isl_union_set *uset) 1517 1.1 mrg { 1518 1.1 mrg struct isl_bin_op_control control = { 1519 1.1 mrg .match_space = &isl_space_range, 1520 1.1 mrg .fn_map = &isl_map_gist_range, 1521 1.1 mrg }; 1522 1.1 mrg 1523 1.1 mrg return gen_bin_op(umap, uset, &control); 1524 1.1 mrg } 1525 1.1 mrg 1526 1.1 mrg __isl_give isl_union_map *isl_union_map_intersect_range_union_set( 1527 1.1 mrg __isl_take isl_union_map *umap, __isl_take isl_union_set *uset) 1528 1.1 mrg { 1529 1.1 mrg struct isl_bin_op_control control = { 1530 1.1 mrg .match_space = &isl_space_range, 1531 1.1 mrg .fn_map = &isl_map_intersect_range, 1532 1.1 mrg }; 1533 1.1 mrg 1534 1.1 mrg return gen_bin_op(umap, uset, &control); 1535 1.1 mrg } 1536 1.1 mrg 1537 1.1 mrg /* This is an alternative name for the function above. 1538 1.1 mrg */ 1539 1.1 mrg __isl_give isl_union_map *isl_union_map_intersect_range( 1540 1.1 mrg __isl_take isl_union_map *umap, __isl_take isl_union_set *uset) 1541 1.1 mrg { 1542 1.1 mrg return isl_union_map_intersect_range_union_set(umap, uset); 1543 1.1 mrg } 1544 1.1 mrg 1545 1.1 mrg /* Intersect each map in "umap" in a space [A -> B] -> C 1546 1.1 mrg * with the corresponding map in "factor" in the space A -> C and 1547 1.1 mrg * collect the results. 1548 1.1 mrg */ 1549 1.1 mrg __isl_give isl_union_map *isl_union_map_intersect_domain_factor_domain( 1550 1.1 mrg __isl_take isl_union_map *umap, __isl_take isl_union_map *factor) 1551 1.1 mrg { 1552 1.1 mrg struct isl_bin_op_control control = { 1553 1.1 mrg .filter = &isl_map_domain_is_wrapping, 1554 1.1 mrg .match_space = &isl_space_domain_factor_domain, 1555 1.1 mrg .fn_map = &isl_map_intersect_domain_factor_domain, 1556 1.1 mrg }; 1557 1.1 mrg 1558 1.1 mrg return gen_bin_op(umap, factor, &control); 1559 1.1 mrg } 1560 1.1 mrg 1561 1.1 mrg /* Intersect each map in "umap" in a space [A -> B] -> C 1562 1.1 mrg * with the corresponding map in "factor" in the space B -> C and 1563 1.1 mrg * collect the results. 1564 1.1 mrg */ 1565 1.1 mrg __isl_give isl_union_map *isl_union_map_intersect_domain_factor_range( 1566 1.1 mrg __isl_take isl_union_map *umap, __isl_take isl_union_map *factor) 1567 1.1 mrg { 1568 1.1 mrg struct isl_bin_op_control control = { 1569 1.1 mrg .filter = &isl_map_domain_is_wrapping, 1570 1.1 mrg .match_space = &isl_space_domain_factor_range, 1571 1.1 mrg .fn_map = &isl_map_intersect_domain_factor_range, 1572 1.1 mrg }; 1573 1.1 mrg 1574 1.1 mrg return gen_bin_op(umap, factor, &control); 1575 1.1 mrg } 1576 1.1 mrg 1577 1.1 mrg /* Intersect each map in "umap" in a space A -> [B -> C] 1578 1.1 mrg * with the corresponding map in "factor" in the space A -> B and 1579 1.1 mrg * collect the results. 1580 1.1 mrg */ 1581 1.1 mrg __isl_give isl_union_map *isl_union_map_intersect_range_factor_domain( 1582 1.1 mrg __isl_take isl_union_map *umap, __isl_take isl_union_map *factor) 1583 1.1 mrg { 1584 1.1 mrg struct isl_bin_op_control control = { 1585 1.1 mrg .filter = &isl_map_range_is_wrapping, 1586 1.1 mrg .match_space = &isl_space_range_factor_domain, 1587 1.1 mrg .fn_map = &isl_map_intersect_range_factor_domain, 1588 1.1 mrg }; 1589 1.1 mrg 1590 1.1 mrg return gen_bin_op(umap, factor, &control); 1591 1.1 mrg } 1592 1.1 mrg 1593 1.1 mrg /* Intersect each map in "umap" in a space A -> [B -> C] 1594 1.1 mrg * with the corresponding map in "factor" in the space A -> C and 1595 1.1 mrg * collect the results. 1596 1.1 mrg */ 1597 1.1 mrg __isl_give isl_union_map *isl_union_map_intersect_range_factor_range( 1598 1.1 mrg __isl_take isl_union_map *umap, __isl_take isl_union_map *factor) 1599 1.1 mrg { 1600 1.1 mrg struct isl_bin_op_control control = { 1601 1.1 mrg .filter = &isl_map_range_is_wrapping, 1602 1.1 mrg .match_space = &isl_space_range_factor_range, 1603 1.1 mrg .fn_map = &isl_map_intersect_range_factor_range, 1604 1.1 mrg }; 1605 1.1 mrg 1606 1.1 mrg return gen_bin_op(umap, factor, &control); 1607 1.1 mrg } 1608 1.1 mrg 1609 1.1 mrg struct isl_union_map_bin_data { 1610 1.1 mrg isl_union_map *umap2; 1611 1.1 mrg isl_union_map *res; 1612 1.1 mrg isl_map *map; 1613 1.1 mrg isl_stat (*fn)(void **entry, void *user); 1614 1.1 mrg }; 1615 1.1 mrg 1616 1.1 mrg static isl_stat apply_range_entry(void **entry, void *user) 1617 1.1 mrg { 1618 1.1 mrg struct isl_union_map_bin_data *data = user; 1619 1.1 mrg isl_map *map2 = *entry; 1620 1.1 mrg isl_bool empty, match; 1621 1.1 mrg 1622 1.1 mrg match = isl_map_tuple_is_equal(data->map, isl_dim_out, 1623 1.1 mrg map2, isl_dim_in); 1624 1.1 mrg if (match < 0) 1625 1.1 mrg return isl_stat_error; 1626 1.1 mrg if (!match) 1627 1.1 mrg return isl_stat_ok; 1628 1.1 mrg 1629 1.1 mrg map2 = isl_map_apply_range(isl_map_copy(data->map), isl_map_copy(map2)); 1630 1.1 mrg 1631 1.1 mrg empty = isl_map_is_empty(map2); 1632 1.1 mrg if (empty < 0) { 1633 1.1 mrg isl_map_free(map2); 1634 1.1 mrg return isl_stat_error; 1635 1.1 mrg } 1636 1.1 mrg if (empty) { 1637 1.1 mrg isl_map_free(map2); 1638 1.1 mrg return isl_stat_ok; 1639 1.1 mrg } 1640 1.1 mrg 1641 1.1 mrg data->res = isl_union_map_add_map(data->res, map2); 1642 1.1 mrg 1643 1.1 mrg return isl_stat_ok; 1644 1.1 mrg } 1645 1.1 mrg 1646 1.1 mrg static isl_stat bin_entry(void **entry, void *user) 1647 1.1 mrg { 1648 1.1 mrg struct isl_union_map_bin_data *data = user; 1649 1.1 mrg isl_map *map = *entry; 1650 1.1 mrg 1651 1.1 mrg data->map = map; 1652 1.1 mrg if (isl_hash_table_foreach(data->umap2->dim->ctx, &data->umap2->table, 1653 1.1 mrg data->fn, data) < 0) 1654 1.1 mrg return isl_stat_error; 1655 1.1 mrg 1656 1.1 mrg return isl_stat_ok; 1657 1.1 mrg } 1658 1.1 mrg 1659 1.1 mrg static __isl_give isl_union_map *bin_op(__isl_take isl_union_map *umap1, 1660 1.1 mrg __isl_take isl_union_map *umap2, 1661 1.1 mrg isl_stat (*fn)(void **entry, void *user)) 1662 1.1 mrg { 1663 1.1 mrg struct isl_union_map_bin_data data = { NULL, NULL, NULL, fn }; 1664 1.1 mrg 1665 1.1 mrg umap1 = isl_union_map_align_params(umap1, isl_union_map_get_space(umap2)); 1666 1.1 mrg umap2 = isl_union_map_align_params(umap2, isl_union_map_get_space(umap1)); 1667 1.1 mrg 1668 1.1 mrg if (!umap1 || !umap2) 1669 1.1 mrg goto error; 1670 1.1 mrg 1671 1.1 mrg data.umap2 = umap2; 1672 1.1 mrg data.res = isl_union_map_alloc(isl_space_copy(umap1->dim), 1673 1.1 mrg umap1->table.n); 1674 1.1 mrg if (isl_hash_table_foreach(umap1->dim->ctx, &umap1->table, 1675 1.1 mrg &bin_entry, &data) < 0) 1676 1.1 mrg goto error; 1677 1.1 mrg 1678 1.1 mrg isl_union_map_free(umap1); 1679 1.1 mrg isl_union_map_free(umap2); 1680 1.1 mrg return data.res; 1681 1.1 mrg error: 1682 1.1 mrg isl_union_map_free(umap1); 1683 1.1 mrg isl_union_map_free(umap2); 1684 1.1 mrg isl_union_map_free(data.res); 1685 1.1 mrg return NULL; 1686 1.1 mrg } 1687 1.1 mrg 1688 1.1 mrg /* Intersect each map in "umap" in a space [A -> B] -> C 1689 1.1 mrg * with the corresponding set in "domain" in the space A and 1690 1.1 mrg * collect the results. 1691 1.1 mrg */ 1692 1.1 mrg __isl_give isl_union_map * 1693 1.1 mrg isl_union_map_intersect_domain_wrapped_domain_union_set( 1694 1.1 mrg __isl_take isl_union_map *umap, __isl_take isl_union_set *domain) 1695 1.1 mrg { 1696 1.1 mrg struct isl_bin_op_control control = { 1697 1.1 mrg .filter = &isl_map_domain_is_wrapping, 1698 1.1 mrg .match_space = &isl_space_domain_wrapped_domain, 1699 1.1 mrg .fn_map = &isl_map_intersect_domain_wrapped_domain, 1700 1.1 mrg }; 1701 1.1 mrg 1702 1.1 mrg return gen_bin_op(umap, domain, &control); 1703 1.1 mrg } 1704 1.1 mrg 1705 1.1 mrg /* Intersect each map in "umap" in a space A -> [B -> C] 1706 1.1 mrg * with the corresponding set in "domain" in the space B and 1707 1.1 mrg * collect the results. 1708 1.1 mrg */ 1709 1.1 mrg __isl_give isl_union_map * 1710 1.1 mrg isl_union_map_intersect_range_wrapped_domain_union_set( 1711 1.1 mrg __isl_take isl_union_map *umap, __isl_take isl_union_set *domain) 1712 1.1 mrg { 1713 1.1 mrg struct isl_bin_op_control control = { 1714 1.1 mrg .filter = &isl_map_range_is_wrapping, 1715 1.1 mrg .match_space = &isl_space_range_wrapped_domain, 1716 1.1 mrg .fn_map = &isl_map_intersect_range_wrapped_domain, 1717 1.1 mrg }; 1718 1.1 mrg 1719 1.1 mrg return gen_bin_op(umap, domain, &control); 1720 1.1 mrg } 1721 1.1 mrg 1722 1.1 mrg __isl_give isl_union_map *isl_union_map_apply_range( 1723 1.1 mrg __isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2) 1724 1.1 mrg { 1725 1.1 mrg return bin_op(umap1, umap2, &apply_range_entry); 1726 1.1 mrg } 1727 1.1 mrg 1728 1.1 mrg __isl_give isl_union_map *isl_union_map_apply_domain( 1729 1.1 mrg __isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2) 1730 1.1 mrg { 1731 1.1 mrg umap1 = isl_union_map_reverse(umap1); 1732 1.1 mrg umap1 = isl_union_map_apply_range(umap1, umap2); 1733 1.1 mrg return isl_union_map_reverse(umap1); 1734 1.1 mrg } 1735 1.1 mrg 1736 1.1 mrg __isl_give isl_union_set *isl_union_set_apply( 1737 1.1 mrg __isl_take isl_union_set *uset, __isl_take isl_union_map *umap) 1738 1.1 mrg { 1739 1.1 mrg return isl_union_map_apply_range(uset, umap); 1740 1.1 mrg } 1741 1.1 mrg 1742 1.1 mrg static isl_stat map_lex_lt_entry(void **entry, void *user) 1743 1.1 mrg { 1744 1.1 mrg struct isl_union_map_bin_data *data = user; 1745 1.1 mrg isl_map *map2 = *entry; 1746 1.1 mrg isl_bool match; 1747 1.1 mrg 1748 1.1 mrg match = isl_map_tuple_is_equal(data->map, isl_dim_out, 1749 1.1 mrg map2, isl_dim_out); 1750 1.1 mrg if (match < 0) 1751 1.1 mrg return isl_stat_error; 1752 1.1 mrg if (!match) 1753 1.1 mrg return isl_stat_ok; 1754 1.1 mrg 1755 1.1 mrg map2 = isl_map_lex_lt_map(isl_map_copy(data->map), isl_map_copy(map2)); 1756 1.1 mrg 1757 1.1 mrg data->res = isl_union_map_add_map(data->res, map2); 1758 1.1 mrg 1759 1.1 mrg return isl_stat_ok; 1760 1.1 mrg } 1761 1.1 mrg 1762 1.1 mrg __isl_give isl_union_map *isl_union_map_lex_lt_union_map( 1763 1.1 mrg __isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2) 1764 1.1 mrg { 1765 1.1 mrg return bin_op(umap1, umap2, &map_lex_lt_entry); 1766 1.1 mrg } 1767 1.1 mrg 1768 1.1 mrg static isl_stat map_lex_le_entry(void **entry, void *user) 1769 1.1 mrg { 1770 1.1 mrg struct isl_union_map_bin_data *data = user; 1771 1.1 mrg isl_map *map2 = *entry; 1772 1.1 mrg isl_bool match; 1773 1.1 mrg 1774 1.1 mrg match = isl_map_tuple_is_equal(data->map, isl_dim_out, 1775 1.1 mrg map2, isl_dim_out); 1776 1.1 mrg if (match < 0) 1777 1.1 mrg return isl_stat_error; 1778 1.1 mrg if (!match) 1779 1.1 mrg return isl_stat_ok; 1780 1.1 mrg 1781 1.1 mrg map2 = isl_map_lex_le_map(isl_map_copy(data->map), isl_map_copy(map2)); 1782 1.1 mrg 1783 1.1 mrg data->res = isl_union_map_add_map(data->res, map2); 1784 1.1 mrg 1785 1.1 mrg return isl_stat_ok; 1786 1.1 mrg } 1787 1.1 mrg 1788 1.1 mrg __isl_give isl_union_map *isl_union_map_lex_le_union_map( 1789 1.1 mrg __isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2) 1790 1.1 mrg { 1791 1.1 mrg return bin_op(umap1, umap2, &map_lex_le_entry); 1792 1.1 mrg } 1793 1.1 mrg 1794 1.1 mrg static isl_stat product_entry(void **entry, void *user) 1795 1.1 mrg { 1796 1.1 mrg struct isl_union_map_bin_data *data = user; 1797 1.1 mrg isl_map *map2 = *entry; 1798 1.1 mrg 1799 1.1 mrg map2 = isl_map_product(isl_map_copy(data->map), isl_map_copy(map2)); 1800 1.1 mrg 1801 1.1 mrg data->res = isl_union_map_add_map(data->res, map2); 1802 1.1 mrg 1803 1.1 mrg return isl_stat_ok; 1804 1.1 mrg } 1805 1.1 mrg 1806 1.1 mrg __isl_give isl_union_map *isl_union_map_product(__isl_take isl_union_map *umap1, 1807 1.1 mrg __isl_take isl_union_map *umap2) 1808 1.1 mrg { 1809 1.1 mrg return bin_op(umap1, umap2, &product_entry); 1810 1.1 mrg } 1811 1.1 mrg 1812 1.1 mrg static isl_stat set_product_entry(void **entry, void *user) 1813 1.1 mrg { 1814 1.1 mrg struct isl_union_map_bin_data *data = user; 1815 1.1 mrg isl_set *set2 = *entry; 1816 1.1 mrg 1817 1.1 mrg set2 = isl_set_product(isl_set_copy(data->map), isl_set_copy(set2)); 1818 1.1 mrg 1819 1.1 mrg data->res = isl_union_set_add_set(data->res, set2); 1820 1.1 mrg 1821 1.1 mrg return isl_stat_ok; 1822 1.1 mrg } 1823 1.1 mrg 1824 1.1 mrg __isl_give isl_union_set *isl_union_set_product(__isl_take isl_union_set *uset1, 1825 1.1 mrg __isl_take isl_union_set *uset2) 1826 1.1 mrg { 1827 1.1 mrg return bin_op(uset1, uset2, &set_product_entry); 1828 1.1 mrg } 1829 1.1 mrg 1830 1.1 mrg static isl_stat domain_product_entry(void **entry, void *user) 1831 1.1 mrg { 1832 1.1 mrg struct isl_union_map_bin_data *data = user; 1833 1.1 mrg isl_map *map2 = *entry; 1834 1.1 mrg isl_bool match; 1835 1.1 mrg 1836 1.1 mrg match = isl_map_tuple_is_equal(data->map, isl_dim_out, 1837 1.1 mrg map2, isl_dim_out); 1838 1.1 mrg if (match < 0) 1839 1.1 mrg return isl_stat_error; 1840 1.1 mrg if (!match) 1841 1.1 mrg return isl_stat_ok; 1842 1.1 mrg 1843 1.1 mrg map2 = isl_map_domain_product(isl_map_copy(data->map), 1844 1.1 mrg isl_map_copy(map2)); 1845 1.1 mrg 1846 1.1 mrg data->res = isl_union_map_add_map(data->res, map2); 1847 1.1 mrg 1848 1.1 mrg return isl_stat_ok; 1849 1.1 mrg } 1850 1.1 mrg 1851 1.1 mrg /* Given two maps A -> B and C -> D, construct a map [A -> C] -> (B * D) 1852 1.1 mrg */ 1853 1.1 mrg __isl_give isl_union_map *isl_union_map_domain_product( 1854 1.1 mrg __isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2) 1855 1.1 mrg { 1856 1.1 mrg return bin_op(umap1, umap2, &domain_product_entry); 1857 1.1 mrg } 1858 1.1 mrg 1859 1.1 mrg static isl_stat range_product_entry(void **entry, void *user) 1860 1.1 mrg { 1861 1.1 mrg struct isl_union_map_bin_data *data = user; 1862 1.1 mrg isl_map *map2 = *entry; 1863 1.1 mrg isl_bool match; 1864 1.1 mrg 1865 1.1 mrg match = isl_map_tuple_is_equal(data->map, isl_dim_in, map2, isl_dim_in); 1866 1.1 mrg if (match < 0) 1867 1.1 mrg return isl_stat_error; 1868 1.1 mrg if (!match) 1869 1.1 mrg return isl_stat_ok; 1870 1.1 mrg 1871 1.1 mrg map2 = isl_map_range_product(isl_map_copy(data->map), 1872 1.1 mrg isl_map_copy(map2)); 1873 1.1 mrg 1874 1.1 mrg data->res = isl_union_map_add_map(data->res, map2); 1875 1.1 mrg 1876 1.1 mrg return isl_stat_ok; 1877 1.1 mrg } 1878 1.1 mrg 1879 1.1 mrg __isl_give isl_union_map *isl_union_map_range_product( 1880 1.1 mrg __isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2) 1881 1.1 mrg { 1882 1.1 mrg return bin_op(umap1, umap2, &range_product_entry); 1883 1.1 mrg } 1884 1.1 mrg 1885 1.1 mrg /* If data->map A -> B and "map2" C -> D have the same range space, 1886 1.1 mrg * then add (A, C) -> (B * D) to data->res. 1887 1.1 mrg */ 1888 1.1 mrg static isl_stat flat_domain_product_entry(void **entry, void *user) 1889 1.1 mrg { 1890 1.1 mrg struct isl_union_map_bin_data *data = user; 1891 1.1 mrg isl_map *map2 = *entry; 1892 1.1 mrg isl_bool match; 1893 1.1 mrg 1894 1.1 mrg match = isl_map_tuple_is_equal(data->map, isl_dim_out, 1895 1.1 mrg map2, isl_dim_out); 1896 1.1 mrg if (match < 0) 1897 1.1 mrg return isl_stat_error; 1898 1.1 mrg if (!match) 1899 1.1 mrg return isl_stat_ok; 1900 1.1 mrg 1901 1.1 mrg map2 = isl_map_flat_domain_product(isl_map_copy(data->map), 1902 1.1 mrg isl_map_copy(map2)); 1903 1.1 mrg 1904 1.1 mrg data->res = isl_union_map_add_map(data->res, map2); 1905 1.1 mrg 1906 1.1 mrg return isl_stat_ok; 1907 1.1 mrg } 1908 1.1 mrg 1909 1.1 mrg /* Given two maps A -> B and C -> D, construct a map (A, C) -> (B * D). 1910 1.1 mrg */ 1911 1.1 mrg __isl_give isl_union_map *isl_union_map_flat_domain_product( 1912 1.1 mrg __isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2) 1913 1.1 mrg { 1914 1.1 mrg return bin_op(umap1, umap2, &flat_domain_product_entry); 1915 1.1 mrg } 1916 1.1 mrg 1917 1.1 mrg static isl_stat flat_range_product_entry(void **entry, void *user) 1918 1.1 mrg { 1919 1.1 mrg struct isl_union_map_bin_data *data = user; 1920 1.1 mrg isl_map *map2 = *entry; 1921 1.1 mrg isl_bool match; 1922 1.1 mrg 1923 1.1 mrg match = isl_map_tuple_is_equal(data->map, isl_dim_in, map2, isl_dim_in); 1924 1.1 mrg if (match < 0) 1925 1.1 mrg return isl_stat_error; 1926 1.1 mrg if (!match) 1927 1.1 mrg return isl_stat_ok; 1928 1.1 mrg 1929 1.1 mrg map2 = isl_map_flat_range_product(isl_map_copy(data->map), 1930 1.1 mrg isl_map_copy(map2)); 1931 1.1 mrg 1932 1.1 mrg data->res = isl_union_map_add_map(data->res, map2); 1933 1.1 mrg 1934 1.1 mrg return isl_stat_ok; 1935 1.1 mrg } 1936 1.1 mrg 1937 1.1 mrg __isl_give isl_union_map *isl_union_map_flat_range_product( 1938 1.1 mrg __isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2) 1939 1.1 mrg { 1940 1.1 mrg return bin_op(umap1, umap2, &flat_range_product_entry); 1941 1.1 mrg } 1942 1.1 mrg 1943 1.1 mrg /* Data structure that specifies how un_op should modify 1944 1.1 mrg * the maps in the union map. 1945 1.1 mrg * 1946 1.1 mrg * If "inplace" is set, then the maps in the input union map 1947 1.1 mrg * are modified in place. This means that "fn_map" should not 1948 1.1 mrg * change the meaning of the map or that the union map only 1949 1.1 mrg * has a single reference. 1950 1.1 mrg * If "total" is set, then all maps need to be modified and 1951 1.1 mrg * the results need to live in the same space. 1952 1.1 mrg * Otherwise, a new union map is constructed to store the results. 1953 1.1 mrg * If "filter" is not NULL, then only the input maps that satisfy "filter" 1954 1.1 mrg * are taken into account. "filter_user" is passed as the second argument 1955 1.1 mrg * to "filter". No filter can be set if "inplace" or 1956 1.1 mrg * "total" is set. 1957 1.1 mrg * At most one of "fn_map" or "fn_map2" can be set, specifying 1958 1.1 mrg * how the maps (selected by "filter") should be transformed. 1959 1.1 mrg * If "fn_map2" is set, then "fn_map2_user" is passed as the second argument. 1960 1.1 mrg */ 1961 1.1 mrg struct isl_un_op_control { 1962 1.1 mrg int inplace; 1963 1.1 mrg int total; 1964 1.1 mrg isl_bool (*filter)(__isl_keep isl_map *map, void *user); 1965 1.1 mrg void *filter_user; 1966 1.1 mrg __isl_give isl_map *(*fn_map)(__isl_take isl_map *map); 1967 1.1 mrg __isl_give isl_map *(*fn_map2)(__isl_take isl_map *map, void *user); 1968 1.1 mrg void *fn_map2_user; 1969 1.1 mrg }; 1970 1.1 mrg 1971 1.1 mrg /* Data structure for wrapping the data for un_op_filter_drop_user. 1972 1.1 mrg * "filter" is the function that is being wrapped. 1973 1.1 mrg */ 1974 1.1 mrg struct isl_un_op_drop_user_data { 1975 1.1 mrg isl_bool (*filter)(__isl_keep isl_map *map); 1976 1.1 mrg }; 1977 1.1 mrg 1978 1.1 mrg /* Wrapper for isl_un_op_control filters that do not require 1979 1.1 mrg * a second argument. 1980 1.1 mrg * Simply call data->filter without the second argument. 1981 1.1 mrg */ 1982 1.1 mrg static isl_bool un_op_filter_drop_user(__isl_keep isl_map *map, void *user) 1983 1.1 mrg { 1984 1.1 mrg struct isl_un_op_drop_user_data *data = user; 1985 1.1 mrg return data->filter(map); 1986 1.1 mrg } 1987 1.1 mrg 1988 1.1 mrg /* Internal data structure for "un_op". 1989 1.1 mrg * "control" specifies how the maps in the union map should be modified. 1990 1.1 mrg * "res" collects the results. 1991 1.1 mrg */ 1992 1.1 mrg struct isl_union_map_un_data { 1993 1.1 mrg struct isl_un_op_control *control; 1994 1.1 mrg isl_union_map *res; 1995 1.1 mrg }; 1996 1.1 mrg 1997 1.1 mrg /* isl_hash_table_foreach callback for un_op. 1998 1.1 mrg * Handle the map that "entry" points to. 1999 1.1 mrg * 2000 1.1 mrg * If control->filter is set, then check if this map satisfies the filter. 2001 1.1 mrg * If so (or if control->filter is not set), modify the map 2002 1.1 mrg * by calling control->fn_map or control->fn_map2 (if set) and 2003 1.1 mrg * either add the result to data->res or 2004 1.1 mrg * replace the original entry by the result (if control->inplace is set). 2005 1.1 mrg */ 2006 1.1 mrg static isl_stat un_entry(void **entry, void *user) 2007 1.1 mrg { 2008 1.1 mrg struct isl_union_map_un_data *data = user; 2009 1.1 mrg struct isl_un_op_control *control = data->control; 2010 1.1 mrg isl_map *map = *entry; 2011 1.1 mrg 2012 1.1 mrg if (control->filter) { 2013 1.1 mrg isl_bool ok; 2014 1.1 mrg 2015 1.1 mrg ok = control->filter(map, control->filter_user); 2016 1.1 mrg if (ok < 0) 2017 1.1 mrg return isl_stat_error; 2018 1.1 mrg if (!ok) 2019 1.1 mrg return isl_stat_ok; 2020 1.1 mrg } 2021 1.1 mrg 2022 1.1 mrg map = isl_map_copy(map); 2023 1.1 mrg if (control->fn_map2 != NULL) 2024 1.1 mrg map = control->fn_map2(map, control->fn_map2_user); 2025 1.1 mrg else if (control->fn_map != NULL) 2026 1.1 mrg map = control->fn_map(map); 2027 1.1 mrg if (!map) 2028 1.1 mrg return isl_stat_error; 2029 1.1 mrg if (control->inplace) { 2030 1.1 mrg isl_map_free(*entry); 2031 1.1 mrg *entry = map; 2032 1.1 mrg } else { 2033 1.1 mrg data->res = isl_union_map_add_map(data->res, map); 2034 1.1 mrg if (!data->res) 2035 1.1 mrg return isl_stat_error; 2036 1.1 mrg } 2037 1.1 mrg 2038 1.1 mrg return isl_stat_ok; 2039 1.1 mrg } 2040 1.1 mrg 2041 1.1 mrg /* Modify the maps in "umap" based on "control". 2042 1.1 mrg * If control->inplace is set, then modify the maps in "umap" in-place. 2043 1.1 mrg * Otherwise, create a new union map to hold the results. 2044 1.1 mrg * If control->total is set, then perform an inplace computation 2045 1.1 mrg * if "umap" is only referenced once. Otherwise, create a new union map 2046 1.1 mrg * to store the results. 2047 1.1 mrg */ 2048 1.1 mrg static __isl_give isl_union_map *un_op(__isl_take isl_union_map *umap, 2049 1.1 mrg struct isl_un_op_control *control) 2050 1.1 mrg { 2051 1.1 mrg struct isl_union_map_un_data data = { control }; 2052 1.1 mrg 2053 1.1 mrg if (!umap) 2054 1.1 mrg return NULL; 2055 1.1 mrg if (!!control->fn_map && !!control->fn_map2) 2056 1.1 mrg isl_die(isl_union_map_get_ctx(umap), isl_error_internal, 2057 1.1 mrg "at most one mapping function can be specified", 2058 1.1 mrg return isl_union_map_free(umap)); 2059 1.1 mrg if ((control->inplace || control->total) && control->filter) 2060 1.1 mrg isl_die(isl_union_map_get_ctx(umap), isl_error_invalid, 2061 1.1 mrg "inplace/total modification cannot be filtered", 2062 1.1 mrg return isl_union_map_free(umap)); 2063 1.1 mrg 2064 1.1 mrg if (control->total && umap->ref == 1) 2065 1.1 mrg control->inplace = 1; 2066 1.1 mrg if (control->inplace) { 2067 1.1 mrg data.res = umap; 2068 1.1 mrg } else { 2069 1.1 mrg isl_space *space; 2070 1.1 mrg 2071 1.1 mrg space = isl_union_map_get_space(umap); 2072 1.1 mrg data.res = isl_union_map_alloc(space, umap->table.n); 2073 1.1 mrg } 2074 1.1 mrg if (isl_hash_table_foreach(isl_union_map_get_ctx(umap), 2075 1.1 mrg &umap->table, &un_entry, &data) < 0) 2076 1.1 mrg data.res = isl_union_map_free(data.res); 2077 1.1 mrg 2078 1.1 mrg if (control->inplace) 2079 1.1 mrg return data.res; 2080 1.1 mrg isl_union_map_free(umap); 2081 1.1 mrg return data.res; 2082 1.1 mrg } 2083 1.1 mrg 2084 1.1 mrg __isl_give isl_union_map *isl_union_map_from_range( 2085 1.1 mrg __isl_take isl_union_set *uset) 2086 1.1 mrg { 2087 1.1 mrg struct isl_un_op_control control = { 2088 1.1 mrg .fn_map = &isl_map_from_range, 2089 1.1 mrg }; 2090 1.1 mrg return un_op(uset, &control); 2091 1.1 mrg } 2092 1.1 mrg 2093 1.1 mrg __isl_give isl_union_map *isl_union_map_from_domain( 2094 1.1 mrg __isl_take isl_union_set *uset) 2095 1.1 mrg { 2096 1.1 mrg return isl_union_map_reverse(isl_union_map_from_range(uset)); 2097 1.1 mrg } 2098 1.1 mrg 2099 1.1 mrg __isl_give isl_union_map *isl_union_map_from_domain_and_range( 2100 1.1 mrg __isl_take isl_union_set *domain, __isl_take isl_union_set *range) 2101 1.1 mrg { 2102 1.1 mrg return isl_union_map_apply_range(isl_union_map_from_domain(domain), 2103 1.1 mrg isl_union_map_from_range(range)); 2104 1.1 mrg } 2105 1.1 mrg 2106 1.1 mrg /* Modify the maps in "umap" by applying "fn" on them. 2107 1.1 mrg * "fn" should apply to all maps in "umap" and should not modify the space. 2108 1.1 mrg */ 2109 1.1 mrg static __isl_give isl_union_map *total(__isl_take isl_union_map *umap, 2110 1.1 mrg __isl_give isl_map *(*fn)(__isl_take isl_map *)) 2111 1.1 mrg { 2112 1.1 mrg struct isl_un_op_control control = { 2113 1.1 mrg .total = 1, 2114 1.1 mrg .fn_map = fn, 2115 1.1 mrg }; 2116 1.1 mrg 2117 1.1 mrg return un_op(umap, &control); 2118 1.1 mrg } 2119 1.1 mrg 2120 1.1 mrg /* Compute the affine hull of "map" and return the result as an isl_map. 2121 1.1 mrg */ 2122 1.1 mrg static __isl_give isl_map *isl_map_affine_hull_map(__isl_take isl_map *map) 2123 1.1 mrg { 2124 1.1 mrg return isl_map_from_basic_map(isl_map_affine_hull(map)); 2125 1.1 mrg } 2126 1.1 mrg 2127 1.1 mrg __isl_give isl_union_map *isl_union_map_affine_hull( 2128 1.1 mrg __isl_take isl_union_map *umap) 2129 1.1 mrg { 2130 1.1 mrg return total(umap, &isl_map_affine_hull_map); 2131 1.1 mrg } 2132 1.1 mrg 2133 1.1 mrg __isl_give isl_union_set *isl_union_set_affine_hull( 2134 1.1 mrg __isl_take isl_union_set *uset) 2135 1.1 mrg { 2136 1.1 mrg return isl_union_map_affine_hull(uset); 2137 1.1 mrg } 2138 1.1 mrg 2139 1.1 mrg /* Wrapper around isl_set_combined_lineality_space 2140 1.1 mrg * that returns the combined lineality space in the form of an isl_set 2141 1.1 mrg * instead of an isl_basic_set. 2142 1.1 mrg */ 2143 1.1 mrg static __isl_give isl_set *combined_lineality_space(__isl_take isl_set *set) 2144 1.1 mrg { 2145 1.1 mrg return isl_set_from_basic_set(isl_set_combined_lineality_space(set)); 2146 1.1 mrg } 2147 1.1 mrg 2148 1.1 mrg /* For each set in "uset", compute the (linear) hull 2149 1.1 mrg * of the lineality spaces of its basic sets and 2150 1.1 mrg * collect and return the results. 2151 1.1 mrg */ 2152 1.1 mrg __isl_give isl_union_set *isl_union_set_combined_lineality_space( 2153 1.1 mrg __isl_take isl_union_set *uset) 2154 1.1 mrg { 2155 1.1 mrg struct isl_un_op_control control = { 2156 1.1 mrg .fn_map = &combined_lineality_space, 2157 1.1 mrg }; 2158 1.1 mrg return un_op(uset, &control); 2159 1.1 mrg } 2160 1.1 mrg 2161 1.1 mrg /* Compute the polyhedral hull of "map" and return the result as an isl_map. 2162 1.1 mrg */ 2163 1.1 mrg static __isl_give isl_map *isl_map_polyhedral_hull_map(__isl_take isl_map *map) 2164 1.1 mrg { 2165 1.1 mrg return isl_map_from_basic_map(isl_map_polyhedral_hull(map)); 2166 1.1 mrg } 2167 1.1 mrg 2168 1.1 mrg __isl_give isl_union_map *isl_union_map_polyhedral_hull( 2169 1.1 mrg __isl_take isl_union_map *umap) 2170 1.1 mrg { 2171 1.1 mrg return total(umap, &isl_map_polyhedral_hull_map); 2172 1.1 mrg } 2173 1.1 mrg 2174 1.1 mrg __isl_give isl_union_set *isl_union_set_polyhedral_hull( 2175 1.1 mrg __isl_take isl_union_set *uset) 2176 1.1 mrg { 2177 1.1 mrg return isl_union_map_polyhedral_hull(uset); 2178 1.1 mrg } 2179 1.1 mrg 2180 1.1 mrg /* Compute a superset of the convex hull of "map" that is described 2181 1.1 mrg * by only translates of the constraints in the constituents of "map" and 2182 1.1 mrg * return the result as an isl_map. 2183 1.1 mrg */ 2184 1.1 mrg static __isl_give isl_map *isl_map_simple_hull_map(__isl_take isl_map *map) 2185 1.1 mrg { 2186 1.1 mrg return isl_map_from_basic_map(isl_map_simple_hull(map)); 2187 1.1 mrg } 2188 1.1 mrg 2189 1.1 mrg __isl_give isl_union_map *isl_union_map_simple_hull( 2190 1.1 mrg __isl_take isl_union_map *umap) 2191 1.1 mrg { 2192 1.1 mrg return total(umap, &isl_map_simple_hull_map); 2193 1.1 mrg } 2194 1.1 mrg 2195 1.1 mrg __isl_give isl_union_set *isl_union_set_simple_hull( 2196 1.1 mrg __isl_take isl_union_set *uset) 2197 1.1 mrg { 2198 1.1 mrg return isl_union_map_simple_hull(uset); 2199 1.1 mrg } 2200 1.1 mrg 2201 1.1 mrg static __isl_give isl_union_map *inplace(__isl_take isl_union_map *umap, 2202 1.1 mrg __isl_give isl_map *(*fn)(__isl_take isl_map *)) 2203 1.1 mrg { 2204 1.1 mrg struct isl_un_op_control control = { 2205 1.1 mrg .inplace = 1, 2206 1.1 mrg .fn_map = fn, 2207 1.1 mrg }; 2208 1.1 mrg 2209 1.1 mrg return un_op(umap, &control); 2210 1.1 mrg } 2211 1.1 mrg 2212 1.1 mrg /* Remove redundant constraints in each of the basic maps of "umap". 2213 1.1 mrg * Since removing redundant constraints does not change the meaning 2214 1.1 mrg * or the space, the operation can be performed in-place. 2215 1.1 mrg */ 2216 1.1 mrg __isl_give isl_union_map *isl_union_map_remove_redundancies( 2217 1.1 mrg __isl_take isl_union_map *umap) 2218 1.1 mrg { 2219 1.1 mrg return inplace(umap, &isl_map_remove_redundancies); 2220 1.1 mrg } 2221 1.1 mrg 2222 1.1 mrg /* Remove redundant constraints in each of the basic sets of "uset". 2223 1.1 mrg */ 2224 1.1 mrg __isl_give isl_union_set *isl_union_set_remove_redundancies( 2225 1.1 mrg __isl_take isl_union_set *uset) 2226 1.1 mrg { 2227 1.1 mrg return isl_union_map_remove_redundancies(uset); 2228 1.1 mrg } 2229 1.1 mrg 2230 1.1 mrg __isl_give isl_union_map *isl_union_map_coalesce( 2231 1.1 mrg __isl_take isl_union_map *umap) 2232 1.1 mrg { 2233 1.1 mrg return inplace(umap, &isl_map_coalesce); 2234 1.1 mrg } 2235 1.1 mrg 2236 1.1 mrg __isl_give isl_union_set *isl_union_set_coalesce( 2237 1.1 mrg __isl_take isl_union_set *uset) 2238 1.1 mrg { 2239 1.1 mrg return isl_union_map_coalesce(uset); 2240 1.1 mrg } 2241 1.1 mrg 2242 1.1 mrg __isl_give isl_union_map *isl_union_map_detect_equalities( 2243 1.1 mrg __isl_take isl_union_map *umap) 2244 1.1 mrg { 2245 1.1 mrg return inplace(umap, &isl_map_detect_equalities); 2246 1.1 mrg } 2247 1.1 mrg 2248 1.1 mrg __isl_give isl_union_set *isl_union_set_detect_equalities( 2249 1.1 mrg __isl_take isl_union_set *uset) 2250 1.1 mrg { 2251 1.1 mrg return isl_union_map_detect_equalities(uset); 2252 1.1 mrg } 2253 1.1 mrg 2254 1.1 mrg __isl_give isl_union_map *isl_union_map_compute_divs( 2255 1.1 mrg __isl_take isl_union_map *umap) 2256 1.1 mrg { 2257 1.1 mrg return inplace(umap, &isl_map_compute_divs); 2258 1.1 mrg } 2259 1.1 mrg 2260 1.1 mrg __isl_give isl_union_set *isl_union_set_compute_divs( 2261 1.1 mrg __isl_take isl_union_set *uset) 2262 1.1 mrg { 2263 1.1 mrg return isl_union_map_compute_divs(uset); 2264 1.1 mrg } 2265 1.1 mrg 2266 1.1 mrg __isl_give isl_union_map *isl_union_map_lexmin( 2267 1.1 mrg __isl_take isl_union_map *umap) 2268 1.1 mrg { 2269 1.1 mrg return total(umap, &isl_map_lexmin); 2270 1.1 mrg } 2271 1.1 mrg 2272 1.1 mrg __isl_give isl_union_set *isl_union_set_lexmin( 2273 1.1 mrg __isl_take isl_union_set *uset) 2274 1.1 mrg { 2275 1.1 mrg return isl_union_map_lexmin(uset); 2276 1.1 mrg } 2277 1.1 mrg 2278 1.1 mrg __isl_give isl_union_map *isl_union_map_lexmax( 2279 1.1 mrg __isl_take isl_union_map *umap) 2280 1.1 mrg { 2281 1.1 mrg return total(umap, &isl_map_lexmax); 2282 1.1 mrg } 2283 1.1 mrg 2284 1.1 mrg __isl_give isl_union_set *isl_union_set_lexmax( 2285 1.1 mrg __isl_take isl_union_set *uset) 2286 1.1 mrg { 2287 1.1 mrg return isl_union_map_lexmax(uset); 2288 1.1 mrg } 2289 1.1 mrg 2290 1.1 mrg /* Return the universe in the space of "map". 2291 1.1 mrg */ 2292 1.1 mrg static __isl_give isl_map *universe(__isl_take isl_map *map) 2293 1.1 mrg { 2294 1.1 mrg isl_space *space; 2295 1.1 mrg 2296 1.1 mrg space = isl_map_get_space(map); 2297 1.1 mrg isl_map_free(map); 2298 1.1 mrg return isl_map_universe(space); 2299 1.1 mrg } 2300 1.1 mrg 2301 1.1 mrg __isl_give isl_union_map *isl_union_map_universe(__isl_take isl_union_map *umap) 2302 1.1 mrg { 2303 1.1 mrg struct isl_un_op_control control = { 2304 1.1 mrg .fn_map = &universe, 2305 1.1 mrg }; 2306 1.1 mrg return un_op(umap, &control); 2307 1.1 mrg } 2308 1.1 mrg 2309 1.1 mrg __isl_give isl_union_set *isl_union_set_universe(__isl_take isl_union_set *uset) 2310 1.1 mrg { 2311 1.1 mrg return isl_union_map_universe(uset); 2312 1.1 mrg } 2313 1.1 mrg 2314 1.1 mrg __isl_give isl_union_map *isl_union_map_reverse(__isl_take isl_union_map *umap) 2315 1.1 mrg { 2316 1.1 mrg struct isl_un_op_control control = { 2317 1.1 mrg .fn_map = &isl_map_reverse, 2318 1.1 mrg }; 2319 1.1 mrg return un_op(umap, &control); 2320 1.1 mrg } 2321 1.1 mrg 2322 1.1 mrg /* Given a union map, take the maps of the form (A -> B) -> C and 2323 1.1 mrg * return the union of the corresponding maps (B -> A) -> C. 2324 1.1 mrg */ 2325 1.1 mrg __isl_give isl_union_map *isl_union_map_domain_reverse( 2326 1.1 mrg __isl_take isl_union_map *umap) 2327 1.1 mrg { 2328 1.1 mrg struct isl_un_op_drop_user_data data = { &isl_map_domain_is_wrapping }; 2329 1.1 mrg struct isl_un_op_control control = { 2330 1.1 mrg .filter = &un_op_filter_drop_user, 2331 1.1 mrg .filter_user = &data, 2332 1.1 mrg .fn_map = &isl_map_domain_reverse, 2333 1.1 mrg }; 2334 1.1 mrg return un_op(umap, &control); 2335 1.1 mrg } 2336 1.1 mrg 2337 1.1 mrg /* Given a union map, take the maps of the form A -> (B -> C) and 2338 1.1 mrg * return the union of the corresponding maps A -> (C -> B). 2339 1.1 mrg */ 2340 1.1 mrg __isl_give isl_union_map *isl_union_map_range_reverse( 2341 1.1 mrg __isl_take isl_union_map *umap) 2342 1.1 mrg { 2343 1.1 mrg struct isl_un_op_drop_user_data data = { &isl_map_range_is_wrapping }; 2344 1.1 mrg struct isl_un_op_control control = { 2345 1.1 mrg .filter = &un_op_filter_drop_user, 2346 1.1 mrg .filter_user = &data, 2347 1.1 mrg .fn_map = &isl_map_range_reverse, 2348 1.1 mrg }; 2349 1.1 mrg return un_op(umap, &control); 2350 1.1 mrg } 2351 1.1 mrg 2352 1.1 mrg /* Compute the parameter domain of the given union map. 2353 1.1 mrg */ 2354 1.1 mrg __isl_give isl_set *isl_union_map_params(__isl_take isl_union_map *umap) 2355 1.1 mrg { 2356 1.1 mrg struct isl_un_op_control control = { 2357 1.1 mrg .fn_map = &isl_map_params, 2358 1.1 mrg }; 2359 1.1 mrg int empty; 2360 1.1 mrg 2361 1.1 mrg empty = isl_union_map_is_empty(umap); 2362 1.1 mrg if (empty < 0) 2363 1.1 mrg goto error; 2364 1.1 mrg if (empty) { 2365 1.1 mrg isl_space *space; 2366 1.1 mrg space = isl_union_map_get_space(umap); 2367 1.1 mrg isl_union_map_free(umap); 2368 1.1 mrg return isl_set_empty(space); 2369 1.1 mrg } 2370 1.1 mrg return isl_set_from_union_set(un_op(umap, &control)); 2371 1.1 mrg error: 2372 1.1 mrg isl_union_map_free(umap); 2373 1.1 mrg return NULL; 2374 1.1 mrg } 2375 1.1 mrg 2376 1.1 mrg /* Compute the parameter domain of the given union set. 2377 1.1 mrg */ 2378 1.1 mrg __isl_give isl_set *isl_union_set_params(__isl_take isl_union_set *uset) 2379 1.1 mrg { 2380 1.1 mrg return isl_union_map_params(uset); 2381 1.1 mrg } 2382 1.1 mrg 2383 1.1 mrg __isl_give isl_union_set *isl_union_map_domain(__isl_take isl_union_map *umap) 2384 1.1 mrg { 2385 1.1 mrg struct isl_un_op_control control = { 2386 1.1 mrg .fn_map = &isl_map_domain, 2387 1.1 mrg }; 2388 1.1 mrg return un_op(umap, &control); 2389 1.1 mrg } 2390 1.1 mrg 2391 1.1 mrg __isl_give isl_union_set *isl_union_map_range(__isl_take isl_union_map *umap) 2392 1.1 mrg { 2393 1.1 mrg struct isl_un_op_control control = { 2394 1.1 mrg .fn_map = &isl_map_range, 2395 1.1 mrg }; 2396 1.1 mrg return un_op(umap, &control); 2397 1.1 mrg } 2398 1.1 mrg 2399 1.1 mrg __isl_give isl_union_map *isl_union_map_domain_map( 2400 1.1 mrg __isl_take isl_union_map *umap) 2401 1.1 mrg { 2402 1.1 mrg struct isl_un_op_control control = { 2403 1.1 mrg .fn_map = &isl_map_domain_map, 2404 1.1 mrg }; 2405 1.1 mrg return un_op(umap, &control); 2406 1.1 mrg } 2407 1.1 mrg 2408 1.1 mrg /* Construct an isl_pw_multi_aff that maps "map" to its domain and 2409 1.1 mrg * add the result to "res". 2410 1.1 mrg */ 2411 1.1 mrg static isl_stat domain_map_upma(__isl_take isl_map *map, void *user) 2412 1.1 mrg { 2413 1.1 mrg isl_union_pw_multi_aff **res = user; 2414 1.1 mrg isl_multi_aff *ma; 2415 1.1 mrg isl_pw_multi_aff *pma; 2416 1.1 mrg 2417 1.1 mrg ma = isl_multi_aff_domain_map(isl_map_get_space(map)); 2418 1.1 mrg pma = isl_pw_multi_aff_alloc(isl_map_wrap(map), ma); 2419 1.1 mrg *res = isl_union_pw_multi_aff_add_pw_multi_aff(*res, pma); 2420 1.1 mrg 2421 1.1 mrg return *res ? isl_stat_ok : isl_stat_error; 2422 1.1 mrg 2423 1.1 mrg } 2424 1.1 mrg 2425 1.1 mrg /* Return an isl_union_pw_multi_aff that maps a wrapped copy of "umap" 2426 1.1 mrg * to its domain. 2427 1.1 mrg */ 2428 1.1 mrg __isl_give isl_union_pw_multi_aff *isl_union_map_domain_map_union_pw_multi_aff( 2429 1.1 mrg __isl_take isl_union_map *umap) 2430 1.1 mrg { 2431 1.1 mrg isl_union_pw_multi_aff *res; 2432 1.1 mrg 2433 1.1 mrg res = isl_union_pw_multi_aff_empty(isl_union_map_get_space(umap)); 2434 1.1 mrg if (isl_union_map_foreach_map(umap, &domain_map_upma, &res) < 0) 2435 1.1 mrg res = isl_union_pw_multi_aff_free(res); 2436 1.1 mrg 2437 1.1 mrg isl_union_map_free(umap); 2438 1.1 mrg return res; 2439 1.1 mrg } 2440 1.1 mrg 2441 1.1 mrg __isl_give isl_union_map *isl_union_map_range_map( 2442 1.1 mrg __isl_take isl_union_map *umap) 2443 1.1 mrg { 2444 1.1 mrg struct isl_un_op_control control = { 2445 1.1 mrg .fn_map = &isl_map_range_map, 2446 1.1 mrg }; 2447 1.1 mrg return un_op(umap, &control); 2448 1.1 mrg } 2449 1.1 mrg 2450 1.1 mrg /* Given a collection of wrapped maps of the form A[B -> C], 2451 1.1 mrg * return the collection of maps A[B -> C] -> B. 2452 1.1 mrg */ 2453 1.1 mrg __isl_give isl_union_map *isl_union_set_wrapped_domain_map( 2454 1.1 mrg __isl_take isl_union_set *uset) 2455 1.1 mrg { 2456 1.1 mrg struct isl_un_op_drop_user_data data = { &isl_set_is_wrapping }; 2457 1.1 mrg struct isl_un_op_control control = { 2458 1.1 mrg .filter = &un_op_filter_drop_user, 2459 1.1 mrg .filter_user = &data, 2460 1.1 mrg .fn_map = &isl_set_wrapped_domain_map, 2461 1.1 mrg }; 2462 1.1 mrg return un_op(uset, &control); 2463 1.1 mrg } 2464 1.1 mrg 2465 1.1 mrg /* Does "map" relate elements from the same space? 2466 1.1 mrg */ 2467 1.1 mrg static isl_bool equal_tuples(__isl_keep isl_map *map, void *user) 2468 1.1 mrg { 2469 1.1 mrg return isl_map_tuple_is_equal(map, isl_dim_in, map, isl_dim_out); 2470 1.1 mrg } 2471 1.1 mrg 2472 1.1 mrg __isl_give isl_union_set *isl_union_map_deltas(__isl_take isl_union_map *umap) 2473 1.1 mrg { 2474 1.1 mrg struct isl_un_op_control control = { 2475 1.1 mrg .filter = &equal_tuples, 2476 1.1 mrg .fn_map = &isl_map_deltas, 2477 1.1 mrg }; 2478 1.1 mrg return un_op(umap, &control); 2479 1.1 mrg } 2480 1.1 mrg 2481 1.1 mrg __isl_give isl_union_map *isl_union_map_deltas_map( 2482 1.1 mrg __isl_take isl_union_map *umap) 2483 1.1 mrg { 2484 1.1 mrg struct isl_un_op_control control = { 2485 1.1 mrg .filter = &equal_tuples, 2486 1.1 mrg .fn_map = &isl_map_deltas_map, 2487 1.1 mrg }; 2488 1.1 mrg return un_op(umap, &control); 2489 1.1 mrg } 2490 1.1 mrg 2491 1.1 mrg __isl_give isl_union_map *isl_union_set_identity(__isl_take isl_union_set *uset) 2492 1.1 mrg { 2493 1.1 mrg struct isl_un_op_control control = { 2494 1.1 mrg .fn_map = &isl_set_identity, 2495 1.1 mrg }; 2496 1.1 mrg return un_op(uset, &control); 2497 1.1 mrg } 2498 1.1 mrg 2499 1.1 mrg /* Construct an identity isl_pw_multi_aff on "set" and add it to *res. 2500 1.1 mrg */ 2501 1.1 mrg static isl_stat identity_upma(__isl_take isl_set *set, void *user) 2502 1.1 mrg { 2503 1.1 mrg isl_union_pw_multi_aff **res = user; 2504 1.1 mrg isl_space *space; 2505 1.1 mrg isl_pw_multi_aff *pma; 2506 1.1 mrg 2507 1.1 mrg space = isl_space_map_from_set(isl_set_get_space(set)); 2508 1.1 mrg pma = isl_pw_multi_aff_identity(space); 2509 1.1 mrg pma = isl_pw_multi_aff_intersect_domain(pma, set); 2510 1.1 mrg *res = isl_union_pw_multi_aff_add_pw_multi_aff(*res, pma); 2511 1.1 mrg 2512 1.1 mrg return *res ? isl_stat_ok : isl_stat_error; 2513 1.1 mrg } 2514 1.1 mrg 2515 1.1 mrg /* Return an identity function on "uset" in the form 2516 1.1 mrg * of an isl_union_pw_multi_aff. 2517 1.1 mrg */ 2518 1.1 mrg __isl_give isl_union_pw_multi_aff *isl_union_set_identity_union_pw_multi_aff( 2519 1.1 mrg __isl_take isl_union_set *uset) 2520 1.1 mrg { 2521 1.1 mrg isl_union_pw_multi_aff *res; 2522 1.1 mrg 2523 1.1 mrg res = isl_union_pw_multi_aff_empty(isl_union_set_get_space(uset)); 2524 1.1 mrg if (isl_union_set_foreach_set(uset, &identity_upma, &res) < 0) 2525 1.1 mrg res = isl_union_pw_multi_aff_free(res); 2526 1.1 mrg 2527 1.1 mrg isl_union_set_free(uset); 2528 1.1 mrg return res; 2529 1.1 mrg } 2530 1.1 mrg 2531 1.1 mrg /* For each map in "umap" of the form [A -> B] -> C, 2532 1.1 mrg * construct the map A -> C and collect the results. 2533 1.1 mrg */ 2534 1.1 mrg __isl_give isl_union_map *isl_union_map_domain_factor_domain( 2535 1.1 mrg __isl_take isl_union_map *umap) 2536 1.1 mrg { 2537 1.1 mrg struct isl_un_op_drop_user_data data = { &isl_map_domain_is_wrapping }; 2538 1.1 mrg struct isl_un_op_control control = { 2539 1.1 mrg .filter = &un_op_filter_drop_user, 2540 1.1 mrg .filter_user = &data, 2541 1.1 mrg .fn_map = &isl_map_domain_factor_domain, 2542 1.1 mrg }; 2543 1.1 mrg return un_op(umap, &control); 2544 1.1 mrg } 2545 1.1 mrg 2546 1.1 mrg /* For each map in "umap" of the form [A -> B] -> C, 2547 1.1 mrg * construct the map B -> C and collect the results. 2548 1.1 mrg */ 2549 1.1 mrg __isl_give isl_union_map *isl_union_map_domain_factor_range( 2550 1.1 mrg __isl_take isl_union_map *umap) 2551 1.1 mrg { 2552 1.1 mrg struct isl_un_op_drop_user_data data = { &isl_map_domain_is_wrapping }; 2553 1.1 mrg struct isl_un_op_control control = { 2554 1.1 mrg .filter = &un_op_filter_drop_user, 2555 1.1 mrg .filter_user = &data, 2556 1.1 mrg .fn_map = &isl_map_domain_factor_range, 2557 1.1 mrg }; 2558 1.1 mrg return un_op(umap, &control); 2559 1.1 mrg } 2560 1.1 mrg 2561 1.1 mrg /* For each map in "umap" of the form A -> [B -> C], 2562 1.1 mrg * construct the map A -> B and collect the results. 2563 1.1 mrg */ 2564 1.1 mrg __isl_give isl_union_map *isl_union_map_range_factor_domain( 2565 1.1 mrg __isl_take isl_union_map *umap) 2566 1.1 mrg { 2567 1.1 mrg struct isl_un_op_drop_user_data data = { &isl_map_range_is_wrapping }; 2568 1.1 mrg struct isl_un_op_control control = { 2569 1.1 mrg .filter = &un_op_filter_drop_user, 2570 1.1 mrg .filter_user = &data, 2571 1.1 mrg .fn_map = &isl_map_range_factor_domain, 2572 1.1 mrg }; 2573 1.1 mrg return un_op(umap, &control); 2574 1.1 mrg } 2575 1.1 mrg 2576 1.1 mrg /* For each map in "umap" of the form A -> [B -> C], 2577 1.1 mrg * construct the map A -> C and collect the results. 2578 1.1 mrg */ 2579 1.1 mrg __isl_give isl_union_map *isl_union_map_range_factor_range( 2580 1.1 mrg __isl_take isl_union_map *umap) 2581 1.1 mrg { 2582 1.1 mrg struct isl_un_op_drop_user_data data = { &isl_map_range_is_wrapping }; 2583 1.1 mrg struct isl_un_op_control control = { 2584 1.1 mrg .filter = &un_op_filter_drop_user, 2585 1.1 mrg .filter_user = &data, 2586 1.1 mrg .fn_map = &isl_map_range_factor_range, 2587 1.1 mrg }; 2588 1.1 mrg return un_op(umap, &control); 2589 1.1 mrg } 2590 1.1 mrg 2591 1.1 mrg /* For each map in "umap" of the form [A -> B] -> [C -> D], 2592 1.1 mrg * construct the map A -> C and collect the results. 2593 1.1 mrg */ 2594 1.1 mrg __isl_give isl_union_map *isl_union_map_factor_domain( 2595 1.1 mrg __isl_take isl_union_map *umap) 2596 1.1 mrg { 2597 1.1 mrg struct isl_un_op_drop_user_data data = { &isl_map_is_product }; 2598 1.1 mrg struct isl_un_op_control control = { 2599 1.1 mrg .filter = &un_op_filter_drop_user, 2600 1.1 mrg .filter_user = &data, 2601 1.1 mrg .fn_map = &isl_map_factor_domain, 2602 1.1 mrg }; 2603 1.1 mrg return un_op(umap, &control); 2604 1.1 mrg } 2605 1.1 mrg 2606 1.1 mrg /* For each map in "umap" of the form [A -> B] -> [C -> D], 2607 1.1 mrg * construct the map B -> D and collect the results. 2608 1.1 mrg */ 2609 1.1 mrg __isl_give isl_union_map *isl_union_map_factor_range( 2610 1.1 mrg __isl_take isl_union_map *umap) 2611 1.1 mrg { 2612 1.1 mrg struct isl_un_op_drop_user_data data = { &isl_map_is_product }; 2613 1.1 mrg struct isl_un_op_control control = { 2614 1.1 mrg .filter = &un_op_filter_drop_user, 2615 1.1 mrg .filter_user = &data, 2616 1.1 mrg .fn_map = &isl_map_factor_range, 2617 1.1 mrg }; 2618 1.1 mrg return un_op(umap, &control); 2619 1.1 mrg } 2620 1.1 mrg 2621 1.1 mrg __isl_give isl_union_map *isl_union_set_unwrap(__isl_take isl_union_set *uset) 2622 1.1 mrg { 2623 1.1 mrg struct isl_un_op_drop_user_data data = { &isl_set_is_wrapping }; 2624 1.1 mrg struct isl_un_op_control control = { 2625 1.1 mrg .filter = &un_op_filter_drop_user, 2626 1.1 mrg .filter_user = &data, 2627 1.1 mrg .fn_map = &isl_set_unwrap, 2628 1.1 mrg }; 2629 1.1 mrg return un_op(uset, &control); 2630 1.1 mrg } 2631 1.1 mrg 2632 1.1 mrg __isl_give isl_union_set *isl_union_map_wrap(__isl_take isl_union_map *umap) 2633 1.1 mrg { 2634 1.1 mrg struct isl_un_op_control control = { 2635 1.1 mrg .fn_map = &isl_map_wrap, 2636 1.1 mrg }; 2637 1.1 mrg return un_op(umap, &control); 2638 1.1 mrg } 2639 1.1 mrg 2640 1.1 mrg struct isl_union_map_is_subset_data { 2641 1.1 mrg isl_union_map *umap2; 2642 1.1 mrg isl_bool is_subset; 2643 1.1 mrg }; 2644 1.1 mrg 2645 1.1 mrg static isl_stat is_subset_entry(void **entry, void *user) 2646 1.1 mrg { 2647 1.1 mrg struct isl_union_map_is_subset_data *data = user; 2648 1.1 mrg struct isl_hash_table_entry *entry2; 2649 1.1 mrg isl_space *space; 2650 1.1 mrg isl_map *map = *entry; 2651 1.1 mrg 2652 1.1 mrg space = isl_map_peek_space(map); 2653 1.1 mrg entry2 = isl_union_map_find_entry(data->umap2, space, 0); 2654 1.1 mrg if (!entry2) 2655 1.1 mrg return isl_stat_error; 2656 1.1 mrg if (entry2 == isl_hash_table_entry_none) { 2657 1.1 mrg int empty = isl_map_is_empty(map); 2658 1.1 mrg if (empty < 0) 2659 1.1 mrg return isl_stat_error; 2660 1.1 mrg if (empty) 2661 1.1 mrg return isl_stat_ok; 2662 1.1 mrg data->is_subset = isl_bool_false; 2663 1.1 mrg return isl_stat_error; 2664 1.1 mrg } 2665 1.1 mrg 2666 1.1 mrg data->is_subset = isl_map_is_subset(map, entry2->data); 2667 1.1 mrg if (data->is_subset < 0 || !data->is_subset) 2668 1.1 mrg return isl_stat_error; 2669 1.1 mrg 2670 1.1 mrg return isl_stat_ok; 2671 1.1 mrg } 2672 1.1 mrg 2673 1.1 mrg isl_bool isl_union_map_is_subset(__isl_keep isl_union_map *umap1, 2674 1.1 mrg __isl_keep isl_union_map *umap2) 2675 1.1 mrg { 2676 1.1 mrg struct isl_union_map_is_subset_data data = { NULL, isl_bool_true }; 2677 1.1 mrg 2678 1.1 mrg if (!umap1 || !umap2) 2679 1.1 mrg return isl_bool_error; 2680 1.1 mrg 2681 1.1 mrg data.umap2 = umap2; 2682 1.1 mrg if (isl_hash_table_foreach(umap1->dim->ctx, &umap1->table, 2683 1.1 mrg &is_subset_entry, &data) < 0 && 2684 1.1 mrg data.is_subset) 2685 1.1 mrg return isl_bool_error; 2686 1.1 mrg 2687 1.1 mrg return data.is_subset; 2688 1.1 mrg } 2689 1.1 mrg 2690 1.1 mrg isl_bool isl_union_set_is_subset(__isl_keep isl_union_set *uset1, 2691 1.1 mrg __isl_keep isl_union_set *uset2) 2692 1.1 mrg { 2693 1.1 mrg return isl_union_map_is_subset(uset1, uset2); 2694 1.1 mrg } 2695 1.1 mrg 2696 1.1 mrg isl_bool isl_union_map_is_equal(__isl_keep isl_union_map *umap1, 2697 1.1 mrg __isl_keep isl_union_map *umap2) 2698 1.1 mrg { 2699 1.1 mrg isl_bool is_subset; 2700 1.1 mrg 2701 1.1 mrg if (!umap1 || !umap2) 2702 1.1 mrg return isl_bool_error; 2703 1.1 mrg is_subset = isl_union_map_is_subset(umap1, umap2); 2704 1.1 mrg if (is_subset != isl_bool_true) 2705 1.1 mrg return is_subset; 2706 1.1 mrg is_subset = isl_union_map_is_subset(umap2, umap1); 2707 1.1 mrg return is_subset; 2708 1.1 mrg } 2709 1.1 mrg 2710 1.1 mrg isl_bool isl_union_set_is_equal(__isl_keep isl_union_set *uset1, 2711 1.1 mrg __isl_keep isl_union_set *uset2) 2712 1.1 mrg { 2713 1.1 mrg return isl_union_map_is_equal(uset1, uset2); 2714 1.1 mrg } 2715 1.1 mrg 2716 1.1 mrg isl_bool isl_union_map_is_strict_subset(__isl_keep isl_union_map *umap1, 2717 1.1 mrg __isl_keep isl_union_map *umap2) 2718 1.1 mrg { 2719 1.1 mrg isl_bool is_subset; 2720 1.1 mrg 2721 1.1 mrg if (!umap1 || !umap2) 2722 1.1 mrg return isl_bool_error; 2723 1.1 mrg is_subset = isl_union_map_is_subset(umap1, umap2); 2724 1.1 mrg if (is_subset != isl_bool_true) 2725 1.1 mrg return is_subset; 2726 1.1 mrg is_subset = isl_union_map_is_subset(umap2, umap1); 2727 1.1 mrg return isl_bool_not(is_subset); 2728 1.1 mrg } 2729 1.1 mrg 2730 1.1 mrg isl_bool isl_union_set_is_strict_subset(__isl_keep isl_union_set *uset1, 2731 1.1 mrg __isl_keep isl_union_set *uset2) 2732 1.1 mrg { 2733 1.1 mrg return isl_union_map_is_strict_subset(uset1, uset2); 2734 1.1 mrg } 2735 1.1 mrg 2736 1.1 mrg /* Internal data structure for isl_union_map_is_disjoint. 2737 1.1 mrg * umap2 is the union map with which we are comparing. 2738 1.1 mrg * is_disjoint is initialized to 1 and is set to 0 as soon 2739 1.1 mrg * as the union maps turn out not to be disjoint. 2740 1.1 mrg */ 2741 1.1 mrg struct isl_union_map_is_disjoint_data { 2742 1.1 mrg isl_union_map *umap2; 2743 1.1 mrg isl_bool is_disjoint; 2744 1.1 mrg }; 2745 1.1 mrg 2746 1.1 mrg /* Check if "map" is disjoint from data->umap2 and abort 2747 1.1 mrg * the search if it is not. 2748 1.1 mrg */ 2749 1.1 mrg static isl_stat is_disjoint_entry(void **entry, void *user) 2750 1.1 mrg { 2751 1.1 mrg struct isl_union_map_is_disjoint_data *data = user; 2752 1.1 mrg struct isl_hash_table_entry *entry2; 2753 1.1 mrg isl_space *space; 2754 1.1 mrg isl_map *map = *entry; 2755 1.1 mrg 2756 1.1 mrg space = isl_map_peek_space(map); 2757 1.1 mrg entry2 = isl_union_map_find_entry(data->umap2, space, 0); 2758 1.1 mrg if (!entry2) 2759 1.1 mrg return isl_stat_error; 2760 1.1 mrg if (entry2 == isl_hash_table_entry_none) 2761 1.1 mrg return isl_stat_ok; 2762 1.1 mrg 2763 1.1 mrg data->is_disjoint = isl_map_is_disjoint(map, entry2->data); 2764 1.1 mrg if (data->is_disjoint < 0 || !data->is_disjoint) 2765 1.1 mrg return isl_stat_error; 2766 1.1 mrg 2767 1.1 mrg return isl_stat_ok; 2768 1.1 mrg } 2769 1.1 mrg 2770 1.1 mrg /* Are "umap1" and "umap2" disjoint? 2771 1.1 mrg */ 2772 1.1 mrg isl_bool isl_union_map_is_disjoint(__isl_keep isl_union_map *umap1, 2773 1.1 mrg __isl_keep isl_union_map *umap2) 2774 1.1 mrg { 2775 1.1 mrg struct isl_union_map_is_disjoint_data data = { NULL, isl_bool_true }; 2776 1.1 mrg 2777 1.1 mrg umap1 = isl_union_map_copy(umap1); 2778 1.1 mrg umap2 = isl_union_map_copy(umap2); 2779 1.1 mrg umap1 = isl_union_map_align_params(umap1, 2780 1.1 mrg isl_union_map_get_space(umap2)); 2781 1.1 mrg umap2 = isl_union_map_align_params(umap2, 2782 1.1 mrg isl_union_map_get_space(umap1)); 2783 1.1 mrg 2784 1.1 mrg if (!umap1 || !umap2) 2785 1.1 mrg goto error; 2786 1.1 mrg 2787 1.1 mrg data.umap2 = umap2; 2788 1.1 mrg if (isl_hash_table_foreach(umap1->dim->ctx, &umap1->table, 2789 1.1 mrg &is_disjoint_entry, &data) < 0 && 2790 1.1 mrg data.is_disjoint) 2791 1.1 mrg goto error; 2792 1.1 mrg 2793 1.1 mrg isl_union_map_free(umap1); 2794 1.1 mrg isl_union_map_free(umap2); 2795 1.1 mrg 2796 1.1 mrg return data.is_disjoint; 2797 1.1 mrg error: 2798 1.1 mrg isl_union_map_free(umap1); 2799 1.1 mrg isl_union_map_free(umap2); 2800 1.1 mrg return isl_bool_error; 2801 1.1 mrg } 2802 1.1 mrg 2803 1.1 mrg /* Are "uset1" and "uset2" disjoint? 2804 1.1 mrg */ 2805 1.1 mrg isl_bool isl_union_set_is_disjoint(__isl_keep isl_union_set *uset1, 2806 1.1 mrg __isl_keep isl_union_set *uset2) 2807 1.1 mrg { 2808 1.1 mrg return isl_union_map_is_disjoint(uset1, uset2); 2809 1.1 mrg } 2810 1.1 mrg 2811 1.1 mrg static isl_stat sample_entry(void **entry, void *user) 2812 1.1 mrg { 2813 1.1 mrg isl_basic_map **sample = (isl_basic_map **)user; 2814 1.1 mrg isl_map *map = *entry; 2815 1.1 mrg 2816 1.1 mrg *sample = isl_map_sample(isl_map_copy(map)); 2817 1.1 mrg if (!*sample) 2818 1.1 mrg return isl_stat_error; 2819 1.1 mrg if (!isl_basic_map_plain_is_empty(*sample)) 2820 1.1 mrg return isl_stat_error; 2821 1.1 mrg return isl_stat_ok; 2822 1.1 mrg } 2823 1.1 mrg 2824 1.1 mrg __isl_give isl_basic_map *isl_union_map_sample(__isl_take isl_union_map *umap) 2825 1.1 mrg { 2826 1.1 mrg isl_basic_map *sample = NULL; 2827 1.1 mrg 2828 1.1 mrg if (!umap) 2829 1.1 mrg return NULL; 2830 1.1 mrg 2831 1.1 mrg if (isl_hash_table_foreach(umap->dim->ctx, &umap->table, 2832 1.1 mrg &sample_entry, &sample) < 0 && 2833 1.1 mrg !sample) 2834 1.1 mrg goto error; 2835 1.1 mrg 2836 1.1 mrg if (!sample) 2837 1.1 mrg sample = isl_basic_map_empty(isl_union_map_get_space(umap)); 2838 1.1 mrg 2839 1.1 mrg isl_union_map_free(umap); 2840 1.1 mrg 2841 1.1 mrg return sample; 2842 1.1 mrg error: 2843 1.1 mrg isl_union_map_free(umap); 2844 1.1 mrg return NULL; 2845 1.1 mrg } 2846 1.1 mrg 2847 1.1 mrg __isl_give isl_basic_set *isl_union_set_sample(__isl_take isl_union_set *uset) 2848 1.1 mrg { 2849 1.1 mrg return bset_from_bmap(isl_union_map_sample(uset)); 2850 1.1 mrg } 2851 1.1 mrg 2852 1.1 mrg /* Return an element in "uset" in the form of an isl_point. 2853 1.1 mrg * Return a void isl_point if "uset" is empty. 2854 1.1 mrg */ 2855 1.1 mrg __isl_give isl_point *isl_union_set_sample_point(__isl_take isl_union_set *uset) 2856 1.1 mrg { 2857 1.1 mrg return isl_basic_set_sample_point(isl_union_set_sample(uset)); 2858 1.1 mrg } 2859 1.1 mrg 2860 1.1 mrg struct isl_forall_data { 2861 1.1 mrg isl_bool res; 2862 1.1 mrg isl_bool (*fn)(__isl_keep isl_map *map); 2863 1.1 mrg }; 2864 1.1 mrg 2865 1.1 mrg static isl_stat forall_entry(void **entry, void *user) 2866 1.1 mrg { 2867 1.1 mrg struct isl_forall_data *data = user; 2868 1.1 mrg isl_map *map = *entry; 2869 1.1 mrg 2870 1.1 mrg data->res = data->fn(map); 2871 1.1 mrg if (data->res < 0) 2872 1.1 mrg return isl_stat_error; 2873 1.1 mrg 2874 1.1 mrg if (!data->res) 2875 1.1 mrg return isl_stat_error; 2876 1.1 mrg 2877 1.1 mrg return isl_stat_ok; 2878 1.1 mrg } 2879 1.1 mrg 2880 1.1 mrg static isl_bool union_map_forall(__isl_keep isl_union_map *umap, 2881 1.1 mrg isl_bool (*fn)(__isl_keep isl_map *map)) 2882 1.1 mrg { 2883 1.1 mrg struct isl_forall_data data = { isl_bool_true, fn }; 2884 1.1 mrg 2885 1.1 mrg if (!umap) 2886 1.1 mrg return isl_bool_error; 2887 1.1 mrg 2888 1.1 mrg if (isl_hash_table_foreach(umap->dim->ctx, &umap->table, 2889 1.1 mrg &forall_entry, &data) < 0 && data.res) 2890 1.1 mrg return isl_bool_error; 2891 1.1 mrg 2892 1.1 mrg return data.res; 2893 1.1 mrg } 2894 1.1 mrg 2895 1.1 mrg struct isl_forall_user_data { 2896 1.1 mrg isl_bool res; 2897 1.1 mrg isl_bool (*fn)(__isl_keep isl_map *map, void *user); 2898 1.1 mrg void *user; 2899 1.1 mrg }; 2900 1.1 mrg 2901 1.1 mrg static isl_stat forall_user_entry(void **entry, void *user) 2902 1.1 mrg { 2903 1.1 mrg struct isl_forall_user_data *data = user; 2904 1.1 mrg isl_map *map = *entry; 2905 1.1 mrg 2906 1.1 mrg data->res = data->fn(map, data->user); 2907 1.1 mrg if (data->res < 0) 2908 1.1 mrg return isl_stat_error; 2909 1.1 mrg 2910 1.1 mrg if (!data->res) 2911 1.1 mrg return isl_stat_error; 2912 1.1 mrg 2913 1.1 mrg return isl_stat_ok; 2914 1.1 mrg } 2915 1.1 mrg 2916 1.1 mrg /* Check if fn(map, user) returns true for all maps "map" in umap. 2917 1.1 mrg */ 2918 1.1 mrg static isl_bool union_map_forall_user(__isl_keep isl_union_map *umap, 2919 1.1 mrg isl_bool (*fn)(__isl_keep isl_map *map, void *user), void *user) 2920 1.1 mrg { 2921 1.1 mrg struct isl_forall_user_data data = { isl_bool_true, fn, user }; 2922 1.1 mrg 2923 1.1 mrg if (!umap) 2924 1.1 mrg return isl_bool_error; 2925 1.1 mrg 2926 1.1 mrg if (isl_hash_table_foreach(umap->dim->ctx, &umap->table, 2927 1.1 mrg &forall_user_entry, &data) < 0 && data.res) 2928 1.1 mrg return isl_bool_error; 2929 1.1 mrg 2930 1.1 mrg return data.res; 2931 1.1 mrg } 2932 1.1 mrg 2933 1.1 mrg /* Is "umap" obviously empty? 2934 1.1 mrg */ 2935 1.1 mrg isl_bool isl_union_map_plain_is_empty(__isl_keep isl_union_map *umap) 2936 1.1 mrg { 2937 1.1 mrg isl_size n; 2938 1.1 mrg 2939 1.1 mrg n = isl_union_map_n_map(umap); 2940 1.1 mrg if (n < 0) 2941 1.1 mrg return isl_bool_error; 2942 1.1 mrg return n == 0; 2943 1.1 mrg } 2944 1.1 mrg 2945 1.1 mrg isl_bool isl_union_map_is_empty(__isl_keep isl_union_map *umap) 2946 1.1 mrg { 2947 1.1 mrg return union_map_forall(umap, &isl_map_is_empty); 2948 1.1 mrg } 2949 1.1 mrg 2950 1.1 mrg isl_bool isl_union_set_is_empty(__isl_keep isl_union_set *uset) 2951 1.1 mrg { 2952 1.1 mrg return isl_union_map_is_empty(uset); 2953 1.1 mrg } 2954 1.1 mrg 2955 1.1 mrg static isl_bool is_subset_of_identity(__isl_keep isl_map *map) 2956 1.1 mrg { 2957 1.1 mrg isl_bool is_subset; 2958 1.1 mrg isl_space *space; 2959 1.1 mrg isl_map *id; 2960 1.1 mrg isl_bool match; 2961 1.1 mrg 2962 1.1 mrg match = isl_map_tuple_is_equal(map, isl_dim_in, map, isl_dim_out); 2963 1.1 mrg if (match < 0) 2964 1.1 mrg return isl_bool_error; 2965 1.1 mrg if (!match) 2966 1.1 mrg return isl_bool_false; 2967 1.1 mrg 2968 1.1 mrg space = isl_map_get_space(map); 2969 1.1 mrg id = isl_map_identity(space); 2970 1.1 mrg 2971 1.1 mrg is_subset = isl_map_is_subset(map, id); 2972 1.1 mrg 2973 1.1 mrg isl_map_free(id); 2974 1.1 mrg 2975 1.1 mrg return is_subset; 2976 1.1 mrg } 2977 1.1 mrg 2978 1.1 mrg /* Given an isl_union_map that consists of a single map, check 2979 1.1 mrg * if it is single-valued. 2980 1.1 mrg */ 2981 1.1 mrg static isl_bool single_map_is_single_valued(__isl_keep isl_union_map *umap) 2982 1.1 mrg { 2983 1.1 mrg isl_map *map; 2984 1.1 mrg isl_bool sv; 2985 1.1 mrg 2986 1.1 mrg umap = isl_union_map_copy(umap); 2987 1.1 mrg map = isl_map_from_union_map(umap); 2988 1.1 mrg sv = isl_map_is_single_valued(map); 2989 1.1 mrg isl_map_free(map); 2990 1.1 mrg 2991 1.1 mrg return sv; 2992 1.1 mrg } 2993 1.1 mrg 2994 1.1 mrg /* Internal data structure for single_valued_on_domain. 2995 1.1 mrg * 2996 1.1 mrg * "umap" is the union map to be tested. 2997 1.1 mrg * "sv" is set to 1 as long as "umap" may still be single-valued. 2998 1.1 mrg */ 2999 1.1 mrg struct isl_union_map_is_sv_data { 3000 1.1 mrg isl_union_map *umap; 3001 1.1 mrg isl_bool sv; 3002 1.1 mrg }; 3003 1.1 mrg 3004 1.1 mrg /* Check if the data->umap is single-valued on "set". 3005 1.1 mrg * 3006 1.1 mrg * If data->umap consists of a single map on "set", then test it 3007 1.1 mrg * as an isl_map. 3008 1.1 mrg * 3009 1.1 mrg * Otherwise, compute 3010 1.1 mrg * 3011 1.1 mrg * M \circ M^-1 3012 1.1 mrg * 3013 1.1 mrg * check if the result is a subset of the identity mapping and 3014 1.1 mrg * store the result in data->sv. 3015 1.1 mrg * 3016 1.1 mrg * Terminate as soon as data->umap has been determined not to 3017 1.1 mrg * be single-valued. 3018 1.1 mrg */ 3019 1.1 mrg static isl_stat single_valued_on_domain(__isl_take isl_set *set, void *user) 3020 1.1 mrg { 3021 1.1 mrg struct isl_union_map_is_sv_data *data = user; 3022 1.1 mrg isl_union_map *umap, *test; 3023 1.1 mrg isl_size n; 3024 1.1 mrg 3025 1.1 mrg umap = isl_union_map_copy(data->umap); 3026 1.1 mrg umap = isl_union_map_intersect_domain(umap, 3027 1.1 mrg isl_union_set_from_set(set)); 3028 1.1 mrg 3029 1.1 mrg n = isl_union_map_n_map(umap); 3030 1.1 mrg if (n < 0) { 3031 1.1 mrg data->sv = isl_bool_error; 3032 1.1 mrg } else if (n == 1) { 3033 1.1 mrg data->sv = single_map_is_single_valued(umap); 3034 1.1 mrg isl_union_map_free(umap); 3035 1.1 mrg } else { 3036 1.1 mrg test = isl_union_map_reverse(isl_union_map_copy(umap)); 3037 1.1 mrg test = isl_union_map_apply_range(test, umap); 3038 1.1 mrg 3039 1.1 mrg data->sv = union_map_forall(test, &is_subset_of_identity); 3040 1.1 mrg 3041 1.1 mrg isl_union_map_free(test); 3042 1.1 mrg } 3043 1.1 mrg 3044 1.1 mrg if (data->sv < 0 || !data->sv) 3045 1.1 mrg return isl_stat_error; 3046 1.1 mrg return isl_stat_ok; 3047 1.1 mrg } 3048 1.1 mrg 3049 1.1 mrg /* Check if the given map is single-valued. 3050 1.1 mrg * 3051 1.1 mrg * If the union map consists of a single map, then test it as an isl_map. 3052 1.1 mrg * Otherwise, check if the union map is single-valued on each of its 3053 1.1 mrg * domain spaces. 3054 1.1 mrg */ 3055 1.1 mrg isl_bool isl_union_map_is_single_valued(__isl_keep isl_union_map *umap) 3056 1.1 mrg { 3057 1.1 mrg isl_union_map *universe; 3058 1.1 mrg isl_union_set *domain; 3059 1.1 mrg struct isl_union_map_is_sv_data data; 3060 1.1 mrg isl_size n; 3061 1.1 mrg 3062 1.1 mrg n = isl_union_map_n_map(umap); 3063 1.1 mrg if (n < 0) 3064 1.1 mrg return isl_bool_error; 3065 1.1 mrg if (n == 1) 3066 1.1 mrg return single_map_is_single_valued(umap); 3067 1.1 mrg 3068 1.1 mrg universe = isl_union_map_universe(isl_union_map_copy(umap)); 3069 1.1 mrg domain = isl_union_map_domain(universe); 3070 1.1 mrg 3071 1.1 mrg data.sv = isl_bool_true; 3072 1.1 mrg data.umap = umap; 3073 1.1 mrg if (isl_union_set_foreach_set(domain, 3074 1.1 mrg &single_valued_on_domain, &data) < 0 && data.sv) 3075 1.1 mrg data.sv = isl_bool_error; 3076 1.1 mrg isl_union_set_free(domain); 3077 1.1 mrg 3078 1.1 mrg return data.sv; 3079 1.1 mrg } 3080 1.1 mrg 3081 1.1 mrg isl_bool isl_union_map_is_injective(__isl_keep isl_union_map *umap) 3082 1.1 mrg { 3083 1.1 mrg isl_bool in; 3084 1.1 mrg 3085 1.1 mrg umap = isl_union_map_copy(umap); 3086 1.1 mrg umap = isl_union_map_reverse(umap); 3087 1.1 mrg in = isl_union_map_is_single_valued(umap); 3088 1.1 mrg isl_union_map_free(umap); 3089 1.1 mrg 3090 1.1 mrg return in; 3091 1.1 mrg } 3092 1.1 mrg 3093 1.1 mrg /* Is "map" obviously not an identity relation because 3094 1.1 mrg * it maps elements from one space to another space? 3095 1.1 mrg * Update *non_identity accordingly. 3096 1.1 mrg * 3097 1.1 mrg * In particular, if the domain and range spaces are the same, 3098 1.1 mrg * then the map is not considered to obviously not be an identity relation. 3099 1.1 mrg * Otherwise, the map is considered to obviously not be an identity relation 3100 1.1 mrg * if it is is non-empty. 3101 1.1 mrg * 3102 1.1 mrg * If "map" is determined to obviously not be an identity relation, 3103 1.1 mrg * then the search is aborted. 3104 1.1 mrg */ 3105 1.1 mrg static isl_stat map_plain_is_not_identity(__isl_take isl_map *map, void *user) 3106 1.1 mrg { 3107 1.1 mrg isl_bool *non_identity = user; 3108 1.1 mrg isl_bool equal; 3109 1.1 mrg 3110 1.1 mrg equal = isl_map_tuple_is_equal(map, isl_dim_in, map, isl_dim_out); 3111 1.1 mrg if (equal >= 0 && !equal) 3112 1.1 mrg *non_identity = isl_bool_not(isl_map_is_empty(map)); 3113 1.1 mrg else 3114 1.1 mrg *non_identity = isl_bool_not(equal); 3115 1.1 mrg isl_map_free(map); 3116 1.1 mrg 3117 1.1 mrg if (*non_identity < 0 || *non_identity) 3118 1.1 mrg return isl_stat_error; 3119 1.1 mrg 3120 1.1 mrg return isl_stat_ok; 3121 1.1 mrg } 3122 1.1 mrg 3123 1.1 mrg /* Is "umap" obviously not an identity relation because 3124 1.1 mrg * it maps elements from one space to another space? 3125 1.1 mrg * 3126 1.1 mrg * As soon as a map has been found that maps elements to a different space, 3127 1.1 mrg * non_identity is changed and the search is aborted. 3128 1.1 mrg */ 3129 1.1 mrg static isl_bool isl_union_map_plain_is_not_identity( 3130 1.1 mrg __isl_keep isl_union_map *umap) 3131 1.1 mrg { 3132 1.1 mrg isl_bool non_identity; 3133 1.1 mrg 3134 1.1 mrg non_identity = isl_bool_false; 3135 1.1 mrg if (isl_union_map_foreach_map(umap, &map_plain_is_not_identity, 3136 1.1 mrg &non_identity) < 0 && 3137 1.1 mrg non_identity == isl_bool_false) 3138 1.1 mrg return isl_bool_error; 3139 1.1 mrg 3140 1.1 mrg return non_identity; 3141 1.1 mrg } 3142 1.1 mrg 3143 1.1 mrg /* Does "map" only map elements to themselves? 3144 1.1 mrg * Update *identity accordingly. 3145 1.1 mrg * 3146 1.1 mrg * If "map" is determined not to be an identity relation, 3147 1.1 mrg * then the search is aborted. 3148 1.1 mrg */ 3149 1.1 mrg static isl_stat map_is_identity(__isl_take isl_map *map, void *user) 3150 1.1 mrg { 3151 1.1 mrg isl_bool *identity = user; 3152 1.1 mrg 3153 1.1 mrg *identity = isl_map_is_identity(map); 3154 1.1 mrg isl_map_free(map); 3155 1.1 mrg 3156 1.1 mrg if (*identity < 0 || !*identity) 3157 1.1 mrg return isl_stat_error; 3158 1.1 mrg 3159 1.1 mrg return isl_stat_ok; 3160 1.1 mrg } 3161 1.1 mrg 3162 1.1 mrg /* Does "umap" only map elements to themselves? 3163 1.1 mrg * 3164 1.1 mrg * First check if there are any maps that map elements to different spaces. 3165 1.1 mrg * If not, then check that all the maps (between identical spaces) 3166 1.1 mrg * are identity relations. 3167 1.1 mrg */ 3168 1.1 mrg isl_bool isl_union_map_is_identity(__isl_keep isl_union_map *umap) 3169 1.1 mrg { 3170 1.1 mrg isl_bool non_identity; 3171 1.1 mrg isl_bool identity; 3172 1.1 mrg 3173 1.1 mrg non_identity = isl_union_map_plain_is_not_identity(umap); 3174 1.1 mrg if (non_identity < 0 || non_identity) 3175 1.1 mrg return isl_bool_not(non_identity); 3176 1.1 mrg 3177 1.1 mrg identity = isl_bool_true; 3178 1.1 mrg if (isl_union_map_foreach_map(umap, &map_is_identity, &identity) < 0 && 3179 1.1 mrg identity == isl_bool_true) 3180 1.1 mrg return isl_bool_error; 3181 1.1 mrg 3182 1.1 mrg return identity; 3183 1.1 mrg } 3184 1.1 mrg 3185 1.1 mrg /* Represents a map that has a fixed value (v) for one of its 3186 1.1 mrg * range dimensions. 3187 1.1 mrg * The map in this structure is not reference counted, so it 3188 1.1 mrg * is only valid while the isl_union_map from which it was 3189 1.1 mrg * obtained is still alive. 3190 1.1 mrg */ 3191 1.1 mrg struct isl_fixed_map { 3192 1.1 mrg isl_int v; 3193 1.1 mrg isl_map *map; 3194 1.1 mrg }; 3195 1.1 mrg 3196 1.1 mrg static struct isl_fixed_map *alloc_isl_fixed_map_array(isl_ctx *ctx, 3197 1.1 mrg int n) 3198 1.1 mrg { 3199 1.1 mrg int i; 3200 1.1 mrg struct isl_fixed_map *v; 3201 1.1 mrg 3202 1.1 mrg v = isl_calloc_array(ctx, struct isl_fixed_map, n); 3203 1.1 mrg if (!v) 3204 1.1 mrg return NULL; 3205 1.1 mrg for (i = 0; i < n; ++i) 3206 1.1 mrg isl_int_init(v[i].v); 3207 1.1 mrg return v; 3208 1.1 mrg } 3209 1.1 mrg 3210 1.1 mrg static void free_isl_fixed_map_array(struct isl_fixed_map *v, int n) 3211 1.1 mrg { 3212 1.1 mrg int i; 3213 1.1 mrg 3214 1.1 mrg if (!v) 3215 1.1 mrg return; 3216 1.1 mrg for (i = 0; i < n; ++i) 3217 1.1 mrg isl_int_clear(v[i].v); 3218 1.1 mrg free(v); 3219 1.1 mrg } 3220 1.1 mrg 3221 1.1 mrg /* Compare the "v" field of two isl_fixed_map structs. 3222 1.1 mrg */ 3223 1.1 mrg static int qsort_fixed_map_cmp(const void *p1, const void *p2) 3224 1.1 mrg { 3225 1.1 mrg const struct isl_fixed_map *e1 = (const struct isl_fixed_map *) p1; 3226 1.1 mrg const struct isl_fixed_map *e2 = (const struct isl_fixed_map *) p2; 3227 1.1 mrg 3228 1.1 mrg return isl_int_cmp(e1->v, e2->v); 3229 1.1 mrg } 3230 1.1 mrg 3231 1.1 mrg /* Internal data structure used while checking whether all maps 3232 1.1 mrg * in a union_map have a fixed value for a given output dimension. 3233 1.1 mrg * v is the list of maps, with the fixed value for the dimension 3234 1.1 mrg * n is the number of maps considered so far 3235 1.1 mrg * pos is the output dimension under investigation 3236 1.1 mrg */ 3237 1.1 mrg struct isl_fixed_dim_data { 3238 1.1 mrg struct isl_fixed_map *v; 3239 1.1 mrg int n; 3240 1.1 mrg int pos; 3241 1.1 mrg }; 3242 1.1 mrg 3243 1.1 mrg static isl_bool fixed_at_pos(__isl_keep isl_map *map, void *user) 3244 1.1 mrg { 3245 1.1 mrg struct isl_fixed_dim_data *data = user; 3246 1.1 mrg 3247 1.1 mrg data->v[data->n].map = map; 3248 1.1 mrg return isl_map_plain_is_fixed(map, isl_dim_out, data->pos, 3249 1.1 mrg &data->v[data->n++].v); 3250 1.1 mrg } 3251 1.1 mrg 3252 1.1 mrg static isl_bool plain_injective_on_range(__isl_take isl_union_map *umap, 3253 1.1 mrg int first, int n_range); 3254 1.1 mrg 3255 1.1 mrg /* Given a list of the maps, with their fixed values at output dimension "pos", 3256 1.1 mrg * check whether the ranges of the maps form an obvious partition. 3257 1.1 mrg * 3258 1.1 mrg * We first sort the maps according to their fixed values. 3259 1.1 mrg * If all maps have a different value, then we know the ranges form 3260 1.1 mrg * a partition. 3261 1.1 mrg * Otherwise, we collect the maps with the same fixed value and 3262 1.1 mrg * check whether each such collection is obviously injective 3263 1.1 mrg * based on later dimensions. 3264 1.1 mrg */ 3265 1.1 mrg static int separates(struct isl_fixed_map *v, int n, 3266 1.1 mrg __isl_take isl_space *space, int pos, int n_range) 3267 1.1 mrg { 3268 1.1 mrg int i; 3269 1.1 mrg 3270 1.1 mrg if (!v) 3271 1.1 mrg goto error; 3272 1.1 mrg 3273 1.1 mrg qsort(v, n, sizeof(*v), &qsort_fixed_map_cmp); 3274 1.1 mrg 3275 1.1 mrg for (i = 0; i + 1 < n; ++i) { 3276 1.1 mrg int j, k; 3277 1.1 mrg isl_union_map *part; 3278 1.1 mrg int injective; 3279 1.1 mrg 3280 1.1 mrg for (j = i + 1; j < n; ++j) 3281 1.1 mrg if (isl_int_ne(v[i].v, v[j].v)) 3282 1.1 mrg break; 3283 1.1 mrg 3284 1.1 mrg if (j == i + 1) 3285 1.1 mrg continue; 3286 1.1 mrg 3287 1.1 mrg part = isl_union_map_alloc(isl_space_copy(space), j - i); 3288 1.1 mrg for (k = i; k < j; ++k) 3289 1.1 mrg part = isl_union_map_add_map(part, 3290 1.1 mrg isl_map_copy(v[k].map)); 3291 1.1 mrg 3292 1.1 mrg injective = plain_injective_on_range(part, pos + 1, n_range); 3293 1.1 mrg if (injective < 0) 3294 1.1 mrg goto error; 3295 1.1 mrg if (!injective) 3296 1.1 mrg break; 3297 1.1 mrg 3298 1.1 mrg i = j - 1; 3299 1.1 mrg } 3300 1.1 mrg 3301 1.1 mrg isl_space_free(space); 3302 1.1 mrg free_isl_fixed_map_array(v, n); 3303 1.1 mrg return i + 1 >= n; 3304 1.1 mrg error: 3305 1.1 mrg isl_space_free(space); 3306 1.1 mrg free_isl_fixed_map_array(v, n); 3307 1.1 mrg return -1; 3308 1.1 mrg } 3309 1.1 mrg 3310 1.1 mrg /* Check whether the maps in umap have obviously distinct ranges. 3311 1.1 mrg * In particular, check for an output dimension in the range 3312 1.1 mrg * [first,n_range) for which all maps have a fixed value 3313 1.1 mrg * and then check if these values, possibly along with fixed values 3314 1.1 mrg * at later dimensions, entail distinct ranges. 3315 1.1 mrg */ 3316 1.1 mrg static isl_bool plain_injective_on_range(__isl_take isl_union_map *umap, 3317 1.1 mrg int first, int n_range) 3318 1.1 mrg { 3319 1.1 mrg isl_ctx *ctx; 3320 1.1 mrg isl_size n; 3321 1.1 mrg struct isl_fixed_dim_data data = { NULL }; 3322 1.1 mrg 3323 1.1 mrg ctx = isl_union_map_get_ctx(umap); 3324 1.1 mrg 3325 1.1 mrg n = isl_union_map_n_map(umap); 3326 1.1 mrg if (n < 0) 3327 1.1 mrg goto error; 3328 1.1 mrg 3329 1.1 mrg if (n <= 1) { 3330 1.1 mrg isl_union_map_free(umap); 3331 1.1 mrg return isl_bool_true; 3332 1.1 mrg } 3333 1.1 mrg 3334 1.1 mrg if (first >= n_range) { 3335 1.1 mrg isl_union_map_free(umap); 3336 1.1 mrg return isl_bool_false; 3337 1.1 mrg } 3338 1.1 mrg 3339 1.1 mrg data.v = alloc_isl_fixed_map_array(ctx, n); 3340 1.1 mrg if (!data.v) 3341 1.1 mrg goto error; 3342 1.1 mrg 3343 1.1 mrg for (data.pos = first; data.pos < n_range; ++data.pos) { 3344 1.1 mrg isl_bool fixed; 3345 1.1 mrg int injective; 3346 1.1 mrg isl_space *space; 3347 1.1 mrg 3348 1.1 mrg data.n = 0; 3349 1.1 mrg fixed = union_map_forall_user(umap, &fixed_at_pos, &data); 3350 1.1 mrg if (fixed < 0) 3351 1.1 mrg goto error; 3352 1.1 mrg if (!fixed) 3353 1.1 mrg continue; 3354 1.1 mrg space = isl_union_map_get_space(umap); 3355 1.1 mrg injective = separates(data.v, n, space, data.pos, n_range); 3356 1.1 mrg isl_union_map_free(umap); 3357 1.1 mrg return injective; 3358 1.1 mrg } 3359 1.1 mrg 3360 1.1 mrg free_isl_fixed_map_array(data.v, n); 3361 1.1 mrg isl_union_map_free(umap); 3362 1.1 mrg 3363 1.1 mrg return isl_bool_false; 3364 1.1 mrg error: 3365 1.1 mrg free_isl_fixed_map_array(data.v, n); 3366 1.1 mrg isl_union_map_free(umap); 3367 1.1 mrg return isl_bool_error; 3368 1.1 mrg } 3369 1.1 mrg 3370 1.1 mrg /* Check whether the maps in umap that map to subsets of "ran" 3371 1.1 mrg * have obviously distinct ranges. 3372 1.1 mrg */ 3373 1.1 mrg static isl_bool plain_injective_on_range_wrap(__isl_keep isl_set *ran, 3374 1.1 mrg void *user) 3375 1.1 mrg { 3376 1.1 mrg isl_size dim; 3377 1.1 mrg isl_union_map *umap = user; 3378 1.1 mrg 3379 1.1 mrg dim = isl_set_dim(ran, isl_dim_set); 3380 1.1 mrg if (dim < 0) 3381 1.1 mrg return isl_bool_error; 3382 1.1 mrg 3383 1.1 mrg umap = isl_union_map_copy(umap); 3384 1.1 mrg umap = isl_union_map_intersect_range(umap, 3385 1.1 mrg isl_union_set_from_set(isl_set_copy(ran))); 3386 1.1 mrg return plain_injective_on_range(umap, 0, dim); 3387 1.1 mrg } 3388 1.1 mrg 3389 1.1 mrg /* Check if the given union_map is obviously injective. 3390 1.1 mrg * 3391 1.1 mrg * In particular, we first check if all individual maps are obviously 3392 1.1 mrg * injective and then check if all the ranges of these maps are 3393 1.1 mrg * obviously disjoint. 3394 1.1 mrg */ 3395 1.1 mrg isl_bool isl_union_map_plain_is_injective(__isl_keep isl_union_map *umap) 3396 1.1 mrg { 3397 1.1 mrg isl_bool in; 3398 1.1 mrg isl_union_map *univ; 3399 1.1 mrg isl_union_set *ran; 3400 1.1 mrg 3401 1.1 mrg in = union_map_forall(umap, &isl_map_plain_is_injective); 3402 1.1 mrg if (in < 0) 3403 1.1 mrg return isl_bool_error; 3404 1.1 mrg if (!in) 3405 1.1 mrg return isl_bool_false; 3406 1.1 mrg 3407 1.1 mrg univ = isl_union_map_universe(isl_union_map_copy(umap)); 3408 1.1 mrg ran = isl_union_map_range(univ); 3409 1.1 mrg 3410 1.1 mrg in = union_map_forall_user(ran, &plain_injective_on_range_wrap, umap); 3411 1.1 mrg 3412 1.1 mrg isl_union_set_free(ran); 3413 1.1 mrg 3414 1.1 mrg return in; 3415 1.1 mrg } 3416 1.1 mrg 3417 1.1 mrg isl_bool isl_union_map_is_bijective(__isl_keep isl_union_map *umap) 3418 1.1 mrg { 3419 1.1 mrg isl_bool sv; 3420 1.1 mrg 3421 1.1 mrg sv = isl_union_map_is_single_valued(umap); 3422 1.1 mrg if (sv < 0 || !sv) 3423 1.1 mrg return sv; 3424 1.1 mrg 3425 1.1 mrg return isl_union_map_is_injective(umap); 3426 1.1 mrg } 3427 1.1 mrg 3428 1.1 mrg __isl_give isl_union_map *isl_union_map_zip(__isl_take isl_union_map *umap) 3429 1.1 mrg { 3430 1.1 mrg struct isl_un_op_drop_user_data data = { &isl_map_can_zip }; 3431 1.1 mrg struct isl_un_op_control control = { 3432 1.1 mrg .filter = &un_op_filter_drop_user, 3433 1.1 mrg .filter_user = &data, 3434 1.1 mrg .fn_map = &isl_map_zip, 3435 1.1 mrg }; 3436 1.1 mrg return un_op(umap, &control); 3437 1.1 mrg } 3438 1.1 mrg 3439 1.1 mrg /* Given a union map, take the maps of the form A -> (B -> C) and 3440 1.1 mrg * return the union of the corresponding maps (A -> B) -> C. 3441 1.1 mrg */ 3442 1.1 mrg __isl_give isl_union_map *isl_union_map_uncurry(__isl_take isl_union_map *umap) 3443 1.1 mrg { 3444 1.1 mrg struct isl_un_op_drop_user_data data = { &isl_map_can_uncurry }; 3445 1.1 mrg struct isl_un_op_control control = { 3446 1.1 mrg .filter = &un_op_filter_drop_user, 3447 1.1 mrg .filter_user = &data, 3448 1.1 mrg .fn_map = &isl_map_uncurry, 3449 1.1 mrg }; 3450 1.1 mrg return un_op(umap, &control); 3451 1.1 mrg } 3452 1.1 mrg 3453 1.1 mrg /* Given a union map, take the maps of the form (A -> B) -> C and 3454 1.1 mrg * return the union of the corresponding maps A -> (B -> C). 3455 1.1 mrg */ 3456 1.1 mrg __isl_give isl_union_map *isl_union_map_curry(__isl_take isl_union_map *umap) 3457 1.1 mrg { 3458 1.1 mrg struct isl_un_op_drop_user_data data = { &isl_map_can_curry }; 3459 1.1 mrg struct isl_un_op_control control = { 3460 1.1 mrg .filter = &un_op_filter_drop_user, 3461 1.1 mrg .filter_user = &data, 3462 1.1 mrg .fn_map = &isl_map_curry, 3463 1.1 mrg }; 3464 1.1 mrg return un_op(umap, &control); 3465 1.1 mrg } 3466 1.1 mrg 3467 1.1 mrg /* Given a union map, take the maps of the form A -> ((B -> C) -> D) and 3468 1.1 mrg * return the union of the corresponding maps A -> (B -> (C -> D)). 3469 1.1 mrg */ 3470 1.1 mrg __isl_give isl_union_map *isl_union_map_range_curry( 3471 1.1 mrg __isl_take isl_union_map *umap) 3472 1.1 mrg { 3473 1.1 mrg struct isl_un_op_drop_user_data data = { &isl_map_can_range_curry }; 3474 1.1 mrg struct isl_un_op_control control = { 3475 1.1 mrg .filter = &un_op_filter_drop_user, 3476 1.1 mrg .filter_user = &data, 3477 1.1 mrg .fn_map = &isl_map_range_curry, 3478 1.1 mrg }; 3479 1.1 mrg return un_op(umap, &control); 3480 1.1 mrg } 3481 1.1 mrg 3482 1.1 mrg __isl_give isl_union_set *isl_union_set_lift(__isl_take isl_union_set *uset) 3483 1.1 mrg { 3484 1.1 mrg struct isl_un_op_control control = { 3485 1.1 mrg .fn_map = &isl_set_lift, 3486 1.1 mrg }; 3487 1.1 mrg return un_op(uset, &control); 3488 1.1 mrg } 3489 1.1 mrg 3490 1.1 mrg static isl_stat coefficients_entry(void **entry, void *user) 3491 1.1 mrg { 3492 1.1 mrg isl_set *set = *entry; 3493 1.1 mrg isl_union_set **res = user; 3494 1.1 mrg 3495 1.1 mrg set = isl_set_copy(set); 3496 1.1 mrg set = isl_set_from_basic_set(isl_set_coefficients(set)); 3497 1.1 mrg *res = isl_union_set_add_set(*res, set); 3498 1.1 mrg 3499 1.1 mrg return isl_stat_ok; 3500 1.1 mrg } 3501 1.1 mrg 3502 1.1 mrg __isl_give isl_union_set *isl_union_set_coefficients( 3503 1.1 mrg __isl_take isl_union_set *uset) 3504 1.1 mrg { 3505 1.1 mrg isl_ctx *ctx; 3506 1.1 mrg isl_space *space; 3507 1.1 mrg isl_union_set *res; 3508 1.1 mrg 3509 1.1 mrg if (!uset) 3510 1.1 mrg return NULL; 3511 1.1 mrg 3512 1.1 mrg ctx = isl_union_set_get_ctx(uset); 3513 1.1 mrg space = isl_space_set_alloc(ctx, 0, 0); 3514 1.1 mrg res = isl_union_map_alloc(space, uset->table.n); 3515 1.1 mrg if (isl_hash_table_foreach(uset->dim->ctx, &uset->table, 3516 1.1 mrg &coefficients_entry, &res) < 0) 3517 1.1 mrg goto error; 3518 1.1 mrg 3519 1.1 mrg isl_union_set_free(uset); 3520 1.1 mrg return res; 3521 1.1 mrg error: 3522 1.1 mrg isl_union_set_free(uset); 3523 1.1 mrg isl_union_set_free(res); 3524 1.1 mrg return NULL; 3525 1.1 mrg } 3526 1.1 mrg 3527 1.1 mrg static isl_stat solutions_entry(void **entry, void *user) 3528 1.1 mrg { 3529 1.1 mrg isl_set *set = *entry; 3530 1.1 mrg isl_union_set **res = user; 3531 1.1 mrg 3532 1.1 mrg set = isl_set_copy(set); 3533 1.1 mrg set = isl_set_from_basic_set(isl_set_solutions(set)); 3534 1.1 mrg if (!*res) 3535 1.1 mrg *res = isl_union_set_from_set(set); 3536 1.1 mrg else 3537 1.1 mrg *res = isl_union_set_add_set(*res, set); 3538 1.1 mrg 3539 1.1 mrg if (!*res) 3540 1.1 mrg return isl_stat_error; 3541 1.1 mrg 3542 1.1 mrg return isl_stat_ok; 3543 1.1 mrg } 3544 1.1 mrg 3545 1.1 mrg __isl_give isl_union_set *isl_union_set_solutions( 3546 1.1 mrg __isl_take isl_union_set *uset) 3547 1.1 mrg { 3548 1.1 mrg isl_union_set *res = NULL; 3549 1.1 mrg 3550 1.1 mrg if (!uset) 3551 1.1 mrg return NULL; 3552 1.1 mrg 3553 1.1 mrg if (uset->table.n == 0) { 3554 1.1 mrg res = isl_union_set_empty(isl_union_set_get_space(uset)); 3555 1.1 mrg isl_union_set_free(uset); 3556 1.1 mrg return res; 3557 1.1 mrg } 3558 1.1 mrg 3559 1.1 mrg if (isl_hash_table_foreach(uset->dim->ctx, &uset->table, 3560 1.1 mrg &solutions_entry, &res) < 0) 3561 1.1 mrg goto error; 3562 1.1 mrg 3563 1.1 mrg isl_union_set_free(uset); 3564 1.1 mrg return res; 3565 1.1 mrg error: 3566 1.1 mrg isl_union_set_free(uset); 3567 1.1 mrg isl_union_set_free(res); 3568 1.1 mrg return NULL; 3569 1.1 mrg } 3570 1.1 mrg 3571 1.1 mrg /* Is the domain space of "map" equal to "space"? 3572 1.1 mrg */ 3573 1.1 mrg static int domain_match(__isl_keep isl_map *map, __isl_keep isl_space *space) 3574 1.1 mrg { 3575 1.1 mrg return isl_map_space_tuple_is_equal(map, isl_dim_in, 3576 1.1 mrg space, isl_dim_out); 3577 1.1 mrg } 3578 1.1 mrg 3579 1.1 mrg /* Is the range space of "map" equal to "space"? 3580 1.1 mrg */ 3581 1.1 mrg static int range_match(__isl_keep isl_map *map, __isl_keep isl_space *space) 3582 1.1 mrg { 3583 1.1 mrg return isl_map_space_tuple_is_equal(map, isl_dim_out, 3584 1.1 mrg space, isl_dim_out); 3585 1.1 mrg } 3586 1.1 mrg 3587 1.1 mrg /* Is the set space of "map" equal to "space"? 3588 1.1 mrg */ 3589 1.1 mrg static int set_match(__isl_keep isl_map *map, __isl_keep isl_space *space) 3590 1.1 mrg { 3591 1.1 mrg return isl_map_space_tuple_is_equal(map, isl_dim_set, 3592 1.1 mrg space, isl_dim_out); 3593 1.1 mrg } 3594 1.1 mrg 3595 1.1 mrg /* Internal data structure for preimage_pw_multi_aff. 3596 1.1 mrg * 3597 1.1 mrg * "pma" is the function under which the preimage should be taken. 3598 1.1 mrg * "space" is the space of "pma". 3599 1.1 mrg * "res" collects the results. 3600 1.1 mrg * "fn" computes the preimage for a given map. 3601 1.1 mrg * "match" returns true if "fn" can be called. 3602 1.1 mrg */ 3603 1.1 mrg struct isl_union_map_preimage_data { 3604 1.1 mrg isl_space *space; 3605 1.1 mrg isl_pw_multi_aff *pma; 3606 1.1 mrg isl_union_map *res; 3607 1.1 mrg int (*match)(__isl_keep isl_map *map, __isl_keep isl_space *space); 3608 1.1 mrg __isl_give isl_map *(*fn)(__isl_take isl_map *map, 3609 1.1 mrg __isl_take isl_pw_multi_aff *pma); 3610 1.1 mrg }; 3611 1.1 mrg 3612 1.1 mrg /* Call data->fn to compute the preimage of the domain or range of *entry 3613 1.1 mrg * under the function represented by data->pma, provided the domain/range 3614 1.1 mrg * space of *entry matches the target space of data->pma 3615 1.1 mrg * (as given by data->match), and add the result to data->res. 3616 1.1 mrg */ 3617 1.1 mrg static isl_stat preimage_entry(void **entry, void *user) 3618 1.1 mrg { 3619 1.1 mrg int m; 3620 1.1 mrg isl_map *map = *entry; 3621 1.1 mrg struct isl_union_map_preimage_data *data = user; 3622 1.1 mrg isl_bool empty; 3623 1.1 mrg 3624 1.1 mrg m = data->match(map, data->space); 3625 1.1 mrg if (m < 0) 3626 1.1 mrg return isl_stat_error; 3627 1.1 mrg if (!m) 3628 1.1 mrg return isl_stat_ok; 3629 1.1 mrg 3630 1.1 mrg map = isl_map_copy(map); 3631 1.1 mrg map = data->fn(map, isl_pw_multi_aff_copy(data->pma)); 3632 1.1 mrg 3633 1.1 mrg empty = isl_map_is_empty(map); 3634 1.1 mrg if (empty < 0 || empty) { 3635 1.1 mrg isl_map_free(map); 3636 1.1 mrg return empty < 0 ? isl_stat_error : isl_stat_ok; 3637 1.1 mrg } 3638 1.1 mrg 3639 1.1 mrg data->res = isl_union_map_add_map(data->res, map); 3640 1.1 mrg 3641 1.1 mrg return isl_stat_ok; 3642 1.1 mrg } 3643 1.1 mrg 3644 1.1 mrg /* Compute the preimage of the domain or range of "umap" under the function 3645 1.1 mrg * represented by "pma". 3646 1.1 mrg * In other words, plug in "pma" in the domain or range of "umap". 3647 1.1 mrg * The function "fn" performs the actual preimage computation on a map, 3648 1.1 mrg * while "match" determines to which maps the function should be applied. 3649 1.1 mrg */ 3650 1.1 mrg static __isl_give isl_union_map *preimage_pw_multi_aff( 3651 1.1 mrg __isl_take isl_union_map *umap, __isl_take isl_pw_multi_aff *pma, 3652 1.1 mrg int (*match)(__isl_keep isl_map *map, __isl_keep isl_space *space), 3653 1.1 mrg __isl_give isl_map *(*fn)(__isl_take isl_map *map, 3654 1.1 mrg __isl_take isl_pw_multi_aff *pma)) 3655 1.1 mrg { 3656 1.1 mrg isl_ctx *ctx; 3657 1.1 mrg isl_space *space; 3658 1.1 mrg struct isl_union_map_preimage_data data; 3659 1.1 mrg 3660 1.1 mrg umap = isl_union_map_align_params(umap, 3661 1.1 mrg isl_pw_multi_aff_get_space(pma)); 3662 1.1 mrg pma = isl_pw_multi_aff_align_params(pma, isl_union_map_get_space(umap)); 3663 1.1 mrg 3664 1.1 mrg if (!umap || !pma) 3665 1.1 mrg goto error; 3666 1.1 mrg 3667 1.1 mrg ctx = isl_union_map_get_ctx(umap); 3668 1.1 mrg space = isl_union_map_get_space(umap); 3669 1.1 mrg data.space = isl_pw_multi_aff_get_space(pma); 3670 1.1 mrg data.pma = pma; 3671 1.1 mrg data.res = isl_union_map_alloc(space, umap->table.n); 3672 1.1 mrg data.match = match; 3673 1.1 mrg data.fn = fn; 3674 1.1 mrg if (isl_hash_table_foreach(ctx, &umap->table, &preimage_entry, 3675 1.1 mrg &data) < 0) 3676 1.1 mrg data.res = isl_union_map_free(data.res); 3677 1.1 mrg 3678 1.1 mrg isl_space_free(data.space); 3679 1.1 mrg isl_union_map_free(umap); 3680 1.1 mrg isl_pw_multi_aff_free(pma); 3681 1.1 mrg return data.res; 3682 1.1 mrg error: 3683 1.1 mrg isl_union_map_free(umap); 3684 1.1 mrg isl_pw_multi_aff_free(pma); 3685 1.1 mrg return NULL; 3686 1.1 mrg } 3687 1.1 mrg 3688 1.1 mrg /* Compute the preimage of the domain of "umap" under the function 3689 1.1 mrg * represented by "pma". 3690 1.1 mrg * In other words, plug in "pma" in the domain of "umap". 3691 1.1 mrg * The result contains maps that live in the same spaces as the maps of "umap" 3692 1.1 mrg * with domain space equal to the target space of "pma", 3693 1.1 mrg * except that the domain has been replaced by the domain space of "pma". 3694 1.1 mrg */ 3695 1.1 mrg __isl_give isl_union_map *isl_union_map_preimage_domain_pw_multi_aff( 3696 1.1 mrg __isl_take isl_union_map *umap, __isl_take isl_pw_multi_aff *pma) 3697 1.1 mrg { 3698 1.1 mrg return preimage_pw_multi_aff(umap, pma, &domain_match, 3699 1.1 mrg &isl_map_preimage_domain_pw_multi_aff); 3700 1.1 mrg } 3701 1.1 mrg 3702 1.1 mrg /* Compute the preimage of the range of "umap" under the function 3703 1.1 mrg * represented by "pma". 3704 1.1 mrg * In other words, plug in "pma" in the range of "umap". 3705 1.1 mrg * The result contains maps that live in the same spaces as the maps of "umap" 3706 1.1 mrg * with range space equal to the target space of "pma", 3707 1.1 mrg * except that the range has been replaced by the domain space of "pma". 3708 1.1 mrg */ 3709 1.1 mrg __isl_give isl_union_map *isl_union_map_preimage_range_pw_multi_aff( 3710 1.1 mrg __isl_take isl_union_map *umap, __isl_take isl_pw_multi_aff *pma) 3711 1.1 mrg { 3712 1.1 mrg return preimage_pw_multi_aff(umap, pma, &range_match, 3713 1.1 mrg &isl_map_preimage_range_pw_multi_aff); 3714 1.1 mrg } 3715 1.1 mrg 3716 1.1 mrg /* Compute the preimage of "uset" under the function represented by "pma". 3717 1.1 mrg * In other words, plug in "pma" in "uset". 3718 1.1 mrg * The result contains sets that live in the same spaces as the sets of "uset" 3719 1.1 mrg * with space equal to the target space of "pma", 3720 1.1 mrg * except that the space has been replaced by the domain space of "pma". 3721 1.1 mrg */ 3722 1.1 mrg __isl_give isl_union_set *isl_union_set_preimage_pw_multi_aff( 3723 1.1 mrg __isl_take isl_union_set *uset, __isl_take isl_pw_multi_aff *pma) 3724 1.1 mrg { 3725 1.1 mrg return preimage_pw_multi_aff(uset, pma, &set_match, 3726 1.1 mrg &isl_set_preimage_pw_multi_aff); 3727 1.1 mrg } 3728 1.1 mrg 3729 1.1 mrg /* Compute the preimage of the domain of "umap" under the function 3730 1.1 mrg * represented by "ma". 3731 1.1 mrg * In other words, plug in "ma" in the domain of "umap". 3732 1.1 mrg * The result contains maps that live in the same spaces as the maps of "umap" 3733 1.1 mrg * with domain space equal to the target space of "ma", 3734 1.1 mrg * except that the domain has been replaced by the domain space of "ma". 3735 1.1 mrg */ 3736 1.1 mrg __isl_give isl_union_map *isl_union_map_preimage_domain_multi_aff( 3737 1.1 mrg __isl_take isl_union_map *umap, __isl_take isl_multi_aff *ma) 3738 1.1 mrg { 3739 1.1 mrg return isl_union_map_preimage_domain_pw_multi_aff(umap, 3740 1.1 mrg isl_pw_multi_aff_from_multi_aff(ma)); 3741 1.1 mrg } 3742 1.1 mrg 3743 1.1 mrg /* Compute the preimage of the range of "umap" under the function 3744 1.1 mrg * represented by "ma". 3745 1.1 mrg * In other words, plug in "ma" in the range of "umap". 3746 1.1 mrg * The result contains maps that live in the same spaces as the maps of "umap" 3747 1.1 mrg * with range space equal to the target space of "ma", 3748 1.1 mrg * except that the range has been replaced by the domain space of "ma". 3749 1.1 mrg */ 3750 1.1 mrg __isl_give isl_union_map *isl_union_map_preimage_range_multi_aff( 3751 1.1 mrg __isl_take isl_union_map *umap, __isl_take isl_multi_aff *ma) 3752 1.1 mrg { 3753 1.1 mrg return isl_union_map_preimage_range_pw_multi_aff(umap, 3754 1.1 mrg isl_pw_multi_aff_from_multi_aff(ma)); 3755 1.1 mrg } 3756 1.1 mrg 3757 1.1 mrg /* Compute the preimage of "uset" under the function represented by "ma". 3758 1.1 mrg * In other words, plug in "ma" in "uset". 3759 1.1 mrg * The result contains sets that live in the same spaces as the sets of "uset" 3760 1.1 mrg * with space equal to the target space of "ma", 3761 1.1 mrg * except that the space has been replaced by the domain space of "ma". 3762 1.1 mrg */ 3763 1.1 mrg __isl_give isl_union_map *isl_union_set_preimage_multi_aff( 3764 1.1 mrg __isl_take isl_union_set *uset, __isl_take isl_multi_aff *ma) 3765 1.1 mrg { 3766 1.1 mrg return isl_union_set_preimage_pw_multi_aff(uset, 3767 1.1 mrg isl_pw_multi_aff_from_multi_aff(ma)); 3768 1.1 mrg } 3769 1.1 mrg 3770 1.1 mrg /* Internal data structure for preimage_multi_pw_aff. 3771 1.1 mrg * 3772 1.1 mrg * "mpa" is the function under which the preimage should be taken. 3773 1.1 mrg * "space" is the space of "mpa". 3774 1.1 mrg * "res" collects the results. 3775 1.1 mrg * "fn" computes the preimage for a given map. 3776 1.1 mrg * "match" returns true if "fn" can be called. 3777 1.1 mrg */ 3778 1.1 mrg struct isl_union_map_preimage_mpa_data { 3779 1.1 mrg isl_space *space; 3780 1.1 mrg isl_multi_pw_aff *mpa; 3781 1.1 mrg isl_union_map *res; 3782 1.1 mrg int (*match)(__isl_keep isl_map *map, __isl_keep isl_space *space); 3783 1.1 mrg __isl_give isl_map *(*fn)(__isl_take isl_map *map, 3784 1.1 mrg __isl_take isl_multi_pw_aff *mpa); 3785 1.1 mrg }; 3786 1.1 mrg 3787 1.1 mrg /* Call data->fn to compute the preimage of the domain or range of *entry 3788 1.1 mrg * under the function represented by data->mpa, provided the domain/range 3789 1.1 mrg * space of *entry matches the target space of data->mpa 3790 1.1 mrg * (as given by data->match), and add the result to data->res. 3791 1.1 mrg */ 3792 1.1 mrg static isl_stat preimage_mpa_entry(void **entry, void *user) 3793 1.1 mrg { 3794 1.1 mrg int m; 3795 1.1 mrg isl_map *map = *entry; 3796 1.1 mrg struct isl_union_map_preimage_mpa_data *data = user; 3797 1.1 mrg isl_bool empty; 3798 1.1 mrg 3799 1.1 mrg m = data->match(map, data->space); 3800 1.1 mrg if (m < 0) 3801 1.1 mrg return isl_stat_error; 3802 1.1 mrg if (!m) 3803 1.1 mrg return isl_stat_ok; 3804 1.1 mrg 3805 1.1 mrg map = isl_map_copy(map); 3806 1.1 mrg map = data->fn(map, isl_multi_pw_aff_copy(data->mpa)); 3807 1.1 mrg 3808 1.1 mrg empty = isl_map_is_empty(map); 3809 1.1 mrg if (empty < 0 || empty) { 3810 1.1 mrg isl_map_free(map); 3811 1.1 mrg return empty < 0 ? isl_stat_error : isl_stat_ok; 3812 1.1 mrg } 3813 1.1 mrg 3814 1.1 mrg data->res = isl_union_map_add_map(data->res, map); 3815 1.1 mrg 3816 1.1 mrg return isl_stat_ok; 3817 1.1 mrg } 3818 1.1 mrg 3819 1.1 mrg /* Compute the preimage of the domain or range of "umap" under the function 3820 1.1 mrg * represented by "mpa". 3821 1.1 mrg * In other words, plug in "mpa" in the domain or range of "umap". 3822 1.1 mrg * The function "fn" performs the actual preimage computation on a map, 3823 1.1 mrg * while "match" determines to which maps the function should be applied. 3824 1.1 mrg */ 3825 1.1 mrg static __isl_give isl_union_map *preimage_multi_pw_aff( 3826 1.1 mrg __isl_take isl_union_map *umap, __isl_take isl_multi_pw_aff *mpa, 3827 1.1 mrg int (*match)(__isl_keep isl_map *map, __isl_keep isl_space *space), 3828 1.1 mrg __isl_give isl_map *(*fn)(__isl_take isl_map *map, 3829 1.1 mrg __isl_take isl_multi_pw_aff *mpa)) 3830 1.1 mrg { 3831 1.1 mrg isl_ctx *ctx; 3832 1.1 mrg isl_space *space; 3833 1.1 mrg struct isl_union_map_preimage_mpa_data data; 3834 1.1 mrg 3835 1.1 mrg umap = isl_union_map_align_params(umap, 3836 1.1 mrg isl_multi_pw_aff_get_space(mpa)); 3837 1.1 mrg mpa = isl_multi_pw_aff_align_params(mpa, isl_union_map_get_space(umap)); 3838 1.1 mrg 3839 1.1 mrg if (!umap || !mpa) 3840 1.1 mrg goto error; 3841 1.1 mrg 3842 1.1 mrg ctx = isl_union_map_get_ctx(umap); 3843 1.1 mrg space = isl_union_map_get_space(umap); 3844 1.1 mrg data.space = isl_multi_pw_aff_get_space(mpa); 3845 1.1 mrg data.mpa = mpa; 3846 1.1 mrg data.res = isl_union_map_alloc(space, umap->table.n); 3847 1.1 mrg data.match = match; 3848 1.1 mrg data.fn = fn; 3849 1.1 mrg if (isl_hash_table_foreach(ctx, &umap->table, &preimage_mpa_entry, 3850 1.1 mrg &data) < 0) 3851 1.1 mrg data.res = isl_union_map_free(data.res); 3852 1.1 mrg 3853 1.1 mrg isl_space_free(data.space); 3854 1.1 mrg isl_union_map_free(umap); 3855 1.1 mrg isl_multi_pw_aff_free(mpa); 3856 1.1 mrg return data.res; 3857 1.1 mrg error: 3858 1.1 mrg isl_union_map_free(umap); 3859 1.1 mrg isl_multi_pw_aff_free(mpa); 3860 1.1 mrg return NULL; 3861 1.1 mrg } 3862 1.1 mrg 3863 1.1 mrg /* Compute the preimage of the domain of "umap" under the function 3864 1.1 mrg * represented by "mpa". 3865 1.1 mrg * In other words, plug in "mpa" in the domain of "umap". 3866 1.1 mrg * The result contains maps that live in the same spaces as the maps of "umap" 3867 1.1 mrg * with domain space equal to the target space of "mpa", 3868 1.1 mrg * except that the domain has been replaced by the domain space of "mpa". 3869 1.1 mrg */ 3870 1.1 mrg __isl_give isl_union_map *isl_union_map_preimage_domain_multi_pw_aff( 3871 1.1 mrg __isl_take isl_union_map *umap, __isl_take isl_multi_pw_aff *mpa) 3872 1.1 mrg { 3873 1.1 mrg return preimage_multi_pw_aff(umap, mpa, &domain_match, 3874 1.1 mrg &isl_map_preimage_domain_multi_pw_aff); 3875 1.1 mrg } 3876 1.1 mrg 3877 1.1 mrg /* Internal data structure for preimage_upma. 3878 1.1 mrg * 3879 1.1 mrg * "umap" is the map of which the preimage should be computed. 3880 1.1 mrg * "res" collects the results. 3881 1.1 mrg * "fn" computes the preimage for a given piecewise multi-affine function. 3882 1.1 mrg */ 3883 1.1 mrg struct isl_union_map_preimage_upma_data { 3884 1.1 mrg isl_union_map *umap; 3885 1.1 mrg isl_union_map *res; 3886 1.1 mrg __isl_give isl_union_map *(*fn)(__isl_take isl_union_map *umap, 3887 1.1 mrg __isl_take isl_pw_multi_aff *pma); 3888 1.1 mrg }; 3889 1.1 mrg 3890 1.1 mrg /* Call data->fn to compute the preimage of the domain or range of data->umap 3891 1.1 mrg * under the function represented by pma and add the result to data->res. 3892 1.1 mrg */ 3893 1.1 mrg static isl_stat preimage_upma(__isl_take isl_pw_multi_aff *pma, void *user) 3894 1.1 mrg { 3895 1.1 mrg struct isl_union_map_preimage_upma_data *data = user; 3896 1.1 mrg isl_union_map *umap; 3897 1.1 mrg 3898 1.1 mrg umap = isl_union_map_copy(data->umap); 3899 1.1 mrg umap = data->fn(umap, pma); 3900 1.1 mrg data->res = isl_union_map_union(data->res, umap); 3901 1.1 mrg 3902 1.1 mrg return data->res ? isl_stat_ok : isl_stat_error; 3903 1.1 mrg } 3904 1.1 mrg 3905 1.1 mrg /* Compute the preimage of the domain or range of "umap" under the function 3906 1.1 mrg * represented by "upma". 3907 1.1 mrg * In other words, plug in "upma" in the domain or range of "umap". 3908 1.1 mrg * The function "fn" performs the actual preimage computation 3909 1.1 mrg * on a piecewise multi-affine function. 3910 1.1 mrg */ 3911 1.1 mrg static __isl_give isl_union_map *preimage_union_pw_multi_aff( 3912 1.1 mrg __isl_take isl_union_map *umap, 3913 1.1 mrg __isl_take isl_union_pw_multi_aff *upma, 3914 1.1 mrg __isl_give isl_union_map *(*fn)(__isl_take isl_union_map *umap, 3915 1.1 mrg __isl_take isl_pw_multi_aff *pma)) 3916 1.1 mrg { 3917 1.1 mrg struct isl_union_map_preimage_upma_data data; 3918 1.1 mrg 3919 1.1 mrg data.umap = umap; 3920 1.1 mrg data.res = isl_union_map_empty(isl_union_map_get_space(umap)); 3921 1.1 mrg data.fn = fn; 3922 1.1 mrg if (isl_union_pw_multi_aff_foreach_pw_multi_aff(upma, 3923 1.1 mrg &preimage_upma, &data) < 0) 3924 1.1 mrg data.res = isl_union_map_free(data.res); 3925 1.1 mrg 3926 1.1 mrg isl_union_map_free(umap); 3927 1.1 mrg isl_union_pw_multi_aff_free(upma); 3928 1.1 mrg 3929 1.1 mrg return data.res; 3930 1.1 mrg } 3931 1.1 mrg 3932 1.1 mrg /* Compute the preimage of the domain of "umap" under the function 3933 1.1 mrg * represented by "upma". 3934 1.1 mrg * In other words, plug in "upma" in the domain of "umap". 3935 1.1 mrg * The result contains maps that live in the same spaces as the maps of "umap" 3936 1.1 mrg * with domain space equal to one of the target spaces of "upma", 3937 1.1 mrg * except that the domain has been replaced by one of the domain spaces that 3938 1.1 mrg * correspond to that target space of "upma". 3939 1.1 mrg */ 3940 1.1 mrg __isl_give isl_union_map *isl_union_map_preimage_domain_union_pw_multi_aff( 3941 1.1 mrg __isl_take isl_union_map *umap, 3942 1.1 mrg __isl_take isl_union_pw_multi_aff *upma) 3943 1.1 mrg { 3944 1.1 mrg return preimage_union_pw_multi_aff(umap, upma, 3945 1.1 mrg &isl_union_map_preimage_domain_pw_multi_aff); 3946 1.1 mrg } 3947 1.1 mrg 3948 1.1 mrg /* Compute the preimage of the range of "umap" under the function 3949 1.1 mrg * represented by "upma". 3950 1.1 mrg * In other words, plug in "upma" in the range of "umap". 3951 1.1 mrg * The result contains maps that live in the same spaces as the maps of "umap" 3952 1.1 mrg * with range space equal to one of the target spaces of "upma", 3953 1.1 mrg * except that the range has been replaced by one of the domain spaces that 3954 1.1 mrg * correspond to that target space of "upma". 3955 1.1 mrg */ 3956 1.1 mrg __isl_give isl_union_map *isl_union_map_preimage_range_union_pw_multi_aff( 3957 1.1 mrg __isl_take isl_union_map *umap, 3958 1.1 mrg __isl_take isl_union_pw_multi_aff *upma) 3959 1.1 mrg { 3960 1.1 mrg return preimage_union_pw_multi_aff(umap, upma, 3961 1.1 mrg &isl_union_map_preimage_range_pw_multi_aff); 3962 1.1 mrg } 3963 1.1 mrg 3964 1.1 mrg /* Compute the preimage of "uset" under the function represented by "upma". 3965 1.1 mrg * In other words, plug in "upma" in the range of "uset". 3966 1.1 mrg * The result contains sets that live in the same spaces as the sets of "uset" 3967 1.1 mrg * with space equal to one of the target spaces of "upma", 3968 1.1 mrg * except that the space has been replaced by one of the domain spaces that 3969 1.1 mrg * correspond to that target space of "upma". 3970 1.1 mrg */ 3971 1.1 mrg __isl_give isl_union_set *isl_union_set_preimage_union_pw_multi_aff( 3972 1.1 mrg __isl_take isl_union_set *uset, 3973 1.1 mrg __isl_take isl_union_pw_multi_aff *upma) 3974 1.1 mrg { 3975 1.1 mrg return preimage_union_pw_multi_aff(uset, upma, 3976 1.1 mrg &isl_union_set_preimage_pw_multi_aff); 3977 1.1 mrg } 3978 1.1 mrg 3979 1.1 mrg /* Reset the user pointer on all identifiers of parameters and tuples 3980 1.1 mrg * of the spaces of "umap". 3981 1.1 mrg */ 3982 1.1 mrg __isl_give isl_union_map *isl_union_map_reset_user( 3983 1.1 mrg __isl_take isl_union_map *umap) 3984 1.1 mrg { 3985 1.1 mrg umap = isl_union_map_cow(umap); 3986 1.1 mrg if (!umap) 3987 1.1 mrg return NULL; 3988 1.1 mrg umap->dim = isl_space_reset_user(umap->dim); 3989 1.1 mrg if (!umap->dim) 3990 1.1 mrg return isl_union_map_free(umap); 3991 1.1 mrg return total(umap, &isl_map_reset_user); 3992 1.1 mrg } 3993 1.1 mrg 3994 1.1 mrg /* Reset the user pointer on all identifiers of parameters and tuples 3995 1.1 mrg * of the spaces of "uset". 3996 1.1 mrg */ 3997 1.1 mrg __isl_give isl_union_set *isl_union_set_reset_user( 3998 1.1 mrg __isl_take isl_union_set *uset) 3999 1.1 mrg { 4000 1.1 mrg return isl_union_map_reset_user(uset); 4001 1.1 mrg } 4002 1.1 mrg 4003 1.1 mrg /* Remove all existentially quantified variables and integer divisions 4004 1.1 mrg * from "umap" using Fourier-Motzkin elimination. 4005 1.1 mrg */ 4006 1.1 mrg __isl_give isl_union_map *isl_union_map_remove_divs( 4007 1.1 mrg __isl_take isl_union_map *umap) 4008 1.1 mrg { 4009 1.1 mrg return total(umap, &isl_map_remove_divs); 4010 1.1 mrg } 4011 1.1 mrg 4012 1.1 mrg /* Remove all existentially quantified variables and integer divisions 4013 1.1 mrg * from "uset" using Fourier-Motzkin elimination. 4014 1.1 mrg */ 4015 1.1 mrg __isl_give isl_union_set *isl_union_set_remove_divs( 4016 1.1 mrg __isl_take isl_union_set *uset) 4017 1.1 mrg { 4018 1.1 mrg return isl_union_map_remove_divs(uset); 4019 1.1 mrg } 4020 1.1 mrg 4021 1.1 mrg /* Internal data structure for isl_union_map_project_out. 4022 1.1 mrg * "type", "first" and "n" are the arguments for the isl_map_project_out 4023 1.1 mrg * call. 4024 1.1 mrg * "res" collects the results. 4025 1.1 mrg */ 4026 1.1 mrg struct isl_union_map_project_out_data { 4027 1.1 mrg enum isl_dim_type type; 4028 1.1 mrg unsigned first; 4029 1.1 mrg unsigned n; 4030 1.1 mrg 4031 1.1 mrg isl_union_map *res; 4032 1.1 mrg }; 4033 1.1 mrg 4034 1.1 mrg /* Turn the data->n dimensions of type data->type, starting at data->first 4035 1.1 mrg * into existentially quantified variables and add the result to data->res. 4036 1.1 mrg */ 4037 1.1 mrg static isl_stat project_out(__isl_take isl_map *map, void *user) 4038 1.1 mrg { 4039 1.1 mrg struct isl_union_map_project_out_data *data = user; 4040 1.1 mrg 4041 1.1 mrg map = isl_map_project_out(map, data->type, data->first, data->n); 4042 1.1 mrg data->res = isl_union_map_add_map(data->res, map); 4043 1.1 mrg 4044 1.1 mrg return isl_stat_ok; 4045 1.1 mrg } 4046 1.1 mrg 4047 1.1 mrg /* Turn the "n" dimensions of type "type", starting at "first" 4048 1.1 mrg * into existentially quantified variables. 4049 1.1 mrg * Since the space of an isl_union_map only contains parameters, 4050 1.1 mrg * type is required to be equal to isl_dim_param. 4051 1.1 mrg */ 4052 1.1 mrg __isl_give isl_union_map *isl_union_map_project_out( 4053 1.1 mrg __isl_take isl_union_map *umap, 4054 1.1 mrg enum isl_dim_type type, unsigned first, unsigned n) 4055 1.1 mrg { 4056 1.1 mrg isl_space *space; 4057 1.1 mrg struct isl_union_map_project_out_data data = { type, first, n }; 4058 1.1 mrg 4059 1.1 mrg if (!umap) 4060 1.1 mrg return NULL; 4061 1.1 mrg 4062 1.1 mrg if (type != isl_dim_param) 4063 1.1 mrg isl_die(isl_union_map_get_ctx(umap), isl_error_invalid, 4064 1.1 mrg "can only project out parameters", 4065 1.1 mrg return isl_union_map_free(umap)); 4066 1.1 mrg 4067 1.1 mrg space = isl_union_map_get_space(umap); 4068 1.1 mrg space = isl_space_drop_dims(space, type, first, n); 4069 1.1 mrg data.res = isl_union_map_empty(space); 4070 1.1 mrg if (isl_union_map_foreach_map(umap, &project_out, &data) < 0) 4071 1.1 mrg data.res = isl_union_map_free(data.res); 4072 1.1 mrg 4073 1.1 mrg isl_union_map_free(umap); 4074 1.1 mrg 4075 1.1 mrg return data.res; 4076 1.1 mrg } 4077 1.1 mrg 4078 1.1 mrg #undef TYPE 4079 1.1 mrg #define TYPE isl_union_map 4080 1.1 mrg #include "isl_project_out_all_params_templ.c" 4081 1.1 mrg #include "isl_project_out_param_templ.c" 4082 1.1 mrg 4083 1.1 mrg /* Turn the "n" dimensions of type "type", starting at "first" 4084 1.1 mrg * into existentially quantified variables. 4085 1.1 mrg * Since the space of an isl_union_set only contains parameters, 4086 1.1 mrg * "type" is required to be equal to isl_dim_param. 4087 1.1 mrg */ 4088 1.1 mrg __isl_give isl_union_set *isl_union_set_project_out( 4089 1.1 mrg __isl_take isl_union_set *uset, 4090 1.1 mrg enum isl_dim_type type, unsigned first, unsigned n) 4091 1.1 mrg { 4092 1.1 mrg return isl_union_map_project_out(uset, type, first, n); 4093 1.1 mrg } 4094 1.1 mrg 4095 1.1 mrg /* Project out all parameters from "uset" by existentially quantifying 4096 1.1 mrg * over them. 4097 1.1 mrg */ 4098 1.1 mrg __isl_give isl_union_set *isl_union_set_project_out_all_params( 4099 1.1 mrg __isl_take isl_union_set *uset) 4100 1.1 mrg { 4101 1.1 mrg return uset_from_umap( 4102 1.1 mrg isl_union_map_project_out_all_params(uset_to_umap(uset))); 4103 1.1 mrg } 4104 1.1 mrg 4105 1.1 mrg /* Internal data structure for isl_union_map_involves_dims. 4106 1.1 mrg * "first" and "n" are the arguments for the isl_map_involves_dims calls. 4107 1.1 mrg */ 4108 1.1 mrg struct isl_union_map_involves_dims_data { 4109 1.1 mrg unsigned first; 4110 1.1 mrg unsigned n; 4111 1.1 mrg }; 4112 1.1 mrg 4113 1.1 mrg /* Does "map" _not_ involve the data->n parameters starting at data->first? 4114 1.1 mrg */ 4115 1.1 mrg static isl_bool map_excludes(__isl_keep isl_map *map, void *user) 4116 1.1 mrg { 4117 1.1 mrg struct isl_union_map_involves_dims_data *data = user; 4118 1.1 mrg isl_bool involves; 4119 1.1 mrg 4120 1.1 mrg involves = isl_map_involves_dims(map, 4121 1.1 mrg isl_dim_param, data->first, data->n); 4122 1.1 mrg return isl_bool_not(involves); 4123 1.1 mrg } 4124 1.1 mrg 4125 1.1 mrg /* Does "umap" involve any of the n parameters starting at first? 4126 1.1 mrg * "type" is required to be set to isl_dim_param. 4127 1.1 mrg * 4128 1.1 mrg * "umap" involves any of those parameters if any of its maps 4129 1.1 mrg * involve the parameters. In other words, "umap" does not 4130 1.1 mrg * involve any of the parameters if all its maps to not 4131 1.1 mrg * involve the parameters. 4132 1.1 mrg */ 4133 1.1 mrg isl_bool isl_union_map_involves_dims(__isl_keep isl_union_map *umap, 4134 1.1 mrg enum isl_dim_type type, unsigned first, unsigned n) 4135 1.1 mrg { 4136 1.1 mrg struct isl_union_map_involves_dims_data data = { first, n }; 4137 1.1 mrg isl_bool excludes; 4138 1.1 mrg 4139 1.1 mrg if (type != isl_dim_param) 4140 1.1 mrg isl_die(isl_union_map_get_ctx(umap), isl_error_invalid, 4141 1.1 mrg "can only reference parameters", return isl_bool_error); 4142 1.1 mrg 4143 1.1 mrg excludes = union_map_forall_user(umap, &map_excludes, &data); 4144 1.1 mrg 4145 1.1 mrg return isl_bool_not(excludes); 4146 1.1 mrg } 4147 1.1 mrg 4148 1.1 mrg /* Internal data structure for isl_union_map_reset_range_space. 4149 1.1 mrg * "range" is the space from which to set the range space. 4150 1.1 mrg * "res" collects the results. 4151 1.1 mrg */ 4152 1.1 mrg struct isl_union_map_reset_range_space_data { 4153 1.1 mrg isl_space *range; 4154 1.1 mrg isl_union_map *res; 4155 1.1 mrg }; 4156 1.1 mrg 4157 1.1 mrg /* Replace the range space of "map" by the range space of data->range and 4158 1.1 mrg * add the result to data->res. 4159 1.1 mrg */ 4160 1.1 mrg static isl_stat reset_range_space(__isl_take isl_map *map, void *user) 4161 1.1 mrg { 4162 1.1 mrg struct isl_union_map_reset_range_space_data *data = user; 4163 1.1 mrg isl_space *space; 4164 1.1 mrg 4165 1.1 mrg space = isl_map_get_space(map); 4166 1.1 mrg space = isl_space_domain(space); 4167 1.1 mrg space = isl_space_extend_domain_with_range(space, 4168 1.1 mrg isl_space_copy(data->range)); 4169 1.1 mrg map = isl_map_reset_space(map, space); 4170 1.1 mrg data->res = isl_union_map_add_map(data->res, map); 4171 1.1 mrg 4172 1.1 mrg return data->res ? isl_stat_ok : isl_stat_error; 4173 1.1 mrg } 4174 1.1 mrg 4175 1.1 mrg /* Replace the range space of all the maps in "umap" by 4176 1.1 mrg * the range space of "space". 4177 1.1 mrg * 4178 1.1 mrg * This assumes that all maps have the same output dimension. 4179 1.1 mrg * This function should therefore not be made publicly available. 4180 1.1 mrg * 4181 1.1 mrg * Since the spaces of the maps change, so do their hash value. 4182 1.1 mrg * We therefore need to create a new isl_union_map. 4183 1.1 mrg */ 4184 1.1 mrg __isl_give isl_union_map *isl_union_map_reset_range_space( 4185 1.1 mrg __isl_take isl_union_map *umap, __isl_take isl_space *space) 4186 1.1 mrg { 4187 1.1 mrg struct isl_union_map_reset_range_space_data data = { space }; 4188 1.1 mrg 4189 1.1 mrg data.res = isl_union_map_empty(isl_union_map_get_space(umap)); 4190 1.1 mrg if (isl_union_map_foreach_map(umap, &reset_range_space, &data) < 0) 4191 1.1 mrg data.res = isl_union_map_free(data.res); 4192 1.1 mrg 4193 1.1 mrg isl_space_free(space); 4194 1.1 mrg isl_union_map_free(umap); 4195 1.1 mrg return data.res; 4196 1.1 mrg } 4197 1.1 mrg 4198 1.1 mrg /* Check that "umap" and "space" have the same number of parameters. 4199 1.1 mrg */ 4200 1.1 mrg static isl_stat check_union_map_space_equal_dim(__isl_keep isl_union_map *umap, 4201 1.1 mrg __isl_keep isl_space *space) 4202 1.1 mrg { 4203 1.1 mrg isl_size dim1, dim2; 4204 1.1 mrg 4205 1.1 mrg dim1 = isl_union_map_dim(umap, isl_dim_param); 4206 1.1 mrg dim2 = isl_space_dim(space, isl_dim_param); 4207 1.1 mrg if (dim1 < 0 || dim2 < 0) 4208 1.1 mrg return isl_stat_error; 4209 1.1 mrg if (dim1 == dim2) 4210 1.1 mrg return isl_stat_ok; 4211 1.1 mrg isl_die(isl_union_map_get_ctx(umap), isl_error_invalid, 4212 1.1 mrg "number of parameters does not match", return isl_stat_error); 4213 1.1 mrg } 4214 1.1 mrg 4215 1.1 mrg /* Internal data structure for isl_union_map_reset_equal_dim_space. 4216 1.1 mrg * "space" is the target space. 4217 1.1 mrg * "res" collects the results. 4218 1.1 mrg */ 4219 1.1 mrg struct isl_union_map_reset_params_data { 4220 1.1 mrg isl_space *space; 4221 1.1 mrg isl_union_map *res; 4222 1.1 mrg }; 4223 1.1 mrg 4224 1.1 mrg /* Replace the parameters of "map" by those of data->space and 4225 1.1 mrg * add the result to data->res. 4226 1.1 mrg */ 4227 1.1 mrg static isl_stat reset_params(__isl_take isl_map *map, void *user) 4228 1.1 mrg { 4229 1.1 mrg struct isl_union_map_reset_params_data *data = user; 4230 1.1 mrg isl_space *space; 4231 1.1 mrg 4232 1.1 mrg space = isl_map_get_space(map); 4233 1.1 mrg space = isl_space_replace_params(space, data->space); 4234 1.1 mrg map = isl_map_reset_equal_dim_space(map, space); 4235 1.1 mrg data->res = isl_union_map_add_map(data->res, map); 4236 1.1 mrg 4237 1.1 mrg return data->res ? isl_stat_ok : isl_stat_error; 4238 1.1 mrg } 4239 1.1 mrg 4240 1.1 mrg /* Replace the space of "umap" by "space", without modifying 4241 1.1 mrg * the dimension of "umap", i.e., the number of parameters of "umap". 4242 1.1 mrg * 4243 1.1 mrg * Since the hash values of the maps in the union map depend 4244 1.1 mrg * on the parameters, a new union map needs to be constructed. 4245 1.1 mrg */ 4246 1.1 mrg __isl_give isl_union_map *isl_union_map_reset_equal_dim_space( 4247 1.1 mrg __isl_take isl_union_map *umap, __isl_take isl_space *space) 4248 1.1 mrg { 4249 1.1 mrg struct isl_union_map_reset_params_data data = { space }; 4250 1.1 mrg isl_bool equal; 4251 1.1 mrg isl_space *umap_space; 4252 1.1 mrg 4253 1.1 mrg umap_space = isl_union_map_peek_space(umap); 4254 1.1 mrg equal = isl_space_is_equal(umap_space, space); 4255 1.1 mrg if (equal < 0) 4256 1.1 mrg goto error; 4257 1.1 mrg if (equal) { 4258 1.1 mrg isl_space_free(space); 4259 1.1 mrg return umap; 4260 1.1 mrg } 4261 1.1 mrg if (check_union_map_space_equal_dim(umap, space) < 0) 4262 1.1 mrg goto error; 4263 1.1 mrg 4264 1.1 mrg data.res = isl_union_map_empty(isl_space_copy(space)); 4265 1.1 mrg if (isl_union_map_foreach_map(umap, &reset_params, &data) < 0) 4266 1.1 mrg data.res = isl_union_map_free(data.res); 4267 1.1 mrg 4268 1.1 mrg isl_space_free(space); 4269 1.1 mrg isl_union_map_free(umap); 4270 1.1 mrg return data.res; 4271 1.1 mrg error: 4272 1.1 mrg isl_union_map_free(umap); 4273 1.1 mrg isl_space_free(space); 4274 1.1 mrg return NULL; 4275 1.1 mrg } 4276 1.1 mrg 4277 1.1 mrg /* Internal data structure for isl_union_map_order_at_multi_union_pw_aff. 4278 1.1 mrg * "mupa" is the function from which the isl_multi_pw_affs are extracted. 4279 1.1 mrg * "order" is applied to the extracted isl_multi_pw_affs that correspond 4280 1.1 mrg * to the domain and the range of each map. 4281 1.1 mrg * "res" collects the results. 4282 1.1 mrg */ 4283 1.1 mrg struct isl_union_order_at_data { 4284 1.1 mrg isl_multi_union_pw_aff *mupa; 4285 1.1 mrg __isl_give isl_map *(*order)(__isl_take isl_multi_pw_aff *mpa1, 4286 1.1 mrg __isl_take isl_multi_pw_aff *mpa2); 4287 1.1 mrg isl_union_map *res; 4288 1.1 mrg }; 4289 1.1 mrg 4290 1.1 mrg /* Intersect "map" with the result of applying data->order to 4291 1.1 mrg * the functions in data->mupa that apply to the domain and the range 4292 1.1 mrg * of "map" and add the result to data->res. 4293 1.1 mrg */ 4294 1.1 mrg static isl_stat order_at(__isl_take isl_map *map, void *user) 4295 1.1 mrg { 4296 1.1 mrg struct isl_union_order_at_data *data = user; 4297 1.1 mrg isl_space *space; 4298 1.1 mrg isl_multi_pw_aff *mpa1, *mpa2; 4299 1.1 mrg isl_map *order; 4300 1.1 mrg 4301 1.1 mrg space = isl_space_domain(isl_map_get_space(map)); 4302 1.1 mrg mpa1 = isl_multi_union_pw_aff_extract_multi_pw_aff(data->mupa, space); 4303 1.1 mrg space = isl_space_range(isl_map_get_space(map)); 4304 1.1 mrg mpa2 = isl_multi_union_pw_aff_extract_multi_pw_aff(data->mupa, space); 4305 1.1 mrg order = data->order(mpa1, mpa2); 4306 1.1 mrg map = isl_map_intersect(map, order); 4307 1.1 mrg data->res = isl_union_map_add_map(data->res, map); 4308 1.1 mrg 4309 1.1 mrg return data->res ? isl_stat_ok : isl_stat_error; 4310 1.1 mrg } 4311 1.1 mrg 4312 1.1 mrg /* If "mupa" has a non-trivial explicit domain, then intersect 4313 1.1 mrg * domain and range of "umap" with this explicit domain. 4314 1.1 mrg * If the explicit domain only describes constraints on the parameters, 4315 1.1 mrg * then the intersection only needs to be performed once. 4316 1.1 mrg */ 4317 1.1 mrg static __isl_give isl_union_map *intersect_explicit_domain( 4318 1.1 mrg __isl_take isl_union_map *umap, __isl_keep isl_multi_union_pw_aff *mupa) 4319 1.1 mrg { 4320 1.1 mrg isl_bool non_trivial, is_params; 4321 1.1 mrg isl_union_set *dom; 4322 1.1 mrg 4323 1.1 mrg non_trivial = isl_multi_union_pw_aff_has_non_trivial_domain(mupa); 4324 1.1 mrg if (non_trivial < 0) 4325 1.1 mrg return isl_union_map_free(umap); 4326 1.1 mrg if (!non_trivial) 4327 1.1 mrg return umap; 4328 1.1 mrg mupa = isl_multi_union_pw_aff_copy(mupa); 4329 1.1 mrg dom = isl_multi_union_pw_aff_domain(mupa); 4330 1.1 mrg is_params = isl_union_set_is_params(dom); 4331 1.1 mrg if (is_params < 0) { 4332 1.1 mrg isl_union_set_free(dom); 4333 1.1 mrg return isl_union_map_free(umap); 4334 1.1 mrg } 4335 1.1 mrg if (is_params) { 4336 1.1 mrg isl_set *set; 4337 1.1 mrg 4338 1.1 mrg set = isl_union_set_params(dom); 4339 1.1 mrg umap = isl_union_map_intersect_params(umap, set); 4340 1.1 mrg return umap; 4341 1.1 mrg } 4342 1.1 mrg umap = isl_union_map_intersect_domain(umap, isl_union_set_copy(dom)); 4343 1.1 mrg umap = isl_union_map_intersect_range(umap, dom); 4344 1.1 mrg return umap; 4345 1.1 mrg } 4346 1.1 mrg 4347 1.1 mrg /* Intersect each map in "umap" with the result of calling "order" 4348 1.1 mrg * on the functions is "mupa" that apply to the domain and the range 4349 1.1 mrg * of the map. 4350 1.1 mrg */ 4351 1.1 mrg static __isl_give isl_union_map *isl_union_map_order_at_multi_union_pw_aff( 4352 1.1 mrg __isl_take isl_union_map *umap, __isl_take isl_multi_union_pw_aff *mupa, 4353 1.1 mrg __isl_give isl_map *(*order)(__isl_take isl_multi_pw_aff *mpa1, 4354 1.1 mrg __isl_take isl_multi_pw_aff *mpa2)) 4355 1.1 mrg { 4356 1.1 mrg struct isl_union_order_at_data data; 4357 1.1 mrg 4358 1.1 mrg umap = isl_union_map_align_params(umap, 4359 1.1 mrg isl_multi_union_pw_aff_get_space(mupa)); 4360 1.1 mrg mupa = isl_multi_union_pw_aff_align_params(mupa, 4361 1.1 mrg isl_union_map_get_space(umap)); 4362 1.1 mrg umap = intersect_explicit_domain(umap, mupa); 4363 1.1 mrg data.mupa = mupa; 4364 1.1 mrg data.order = order; 4365 1.1 mrg data.res = isl_union_map_empty(isl_union_map_get_space(umap)); 4366 1.1 mrg if (isl_union_map_foreach_map(umap, &order_at, &data) < 0) 4367 1.1 mrg data.res = isl_union_map_free(data.res); 4368 1.1 mrg 4369 1.1 mrg isl_multi_union_pw_aff_free(mupa); 4370 1.1 mrg isl_union_map_free(umap); 4371 1.1 mrg return data.res; 4372 1.1 mrg } 4373 1.1 mrg 4374 1.1 mrg /* Return the subset of "umap" where the domain and the range 4375 1.1 mrg * have equal "mupa" values. 4376 1.1 mrg */ 4377 1.1 mrg __isl_give isl_union_map *isl_union_map_eq_at_multi_union_pw_aff( 4378 1.1 mrg __isl_take isl_union_map *umap, 4379 1.1 mrg __isl_take isl_multi_union_pw_aff *mupa) 4380 1.1 mrg { 4381 1.1 mrg return isl_union_map_order_at_multi_union_pw_aff(umap, mupa, 4382 1.1 mrg &isl_multi_pw_aff_eq_map); 4383 1.1 mrg } 4384 1.1 mrg 4385 1.1 mrg #undef ORDER 4386 1.1 mrg #define ORDER le 4387 1.1 mrg #include "isl_union_map_lex_templ.c" 4388 1.1 mrg 4389 1.1 mrg #undef ORDER 4390 1.1 mrg #define ORDER lt 4391 1.1 mrg #include "isl_union_map_lex_templ.c" 4392 1.1 mrg 4393 1.1 mrg #undef ORDER 4394 1.1 mrg #define ORDER ge 4395 1.1 mrg #include "isl_union_map_lex_templ.c" 4396 1.1 mrg 4397 1.1 mrg #undef ORDER 4398 1.1 mrg #define ORDER gt 4399 1.1 mrg #include "isl_union_map_lex_templ.c" 4400 1.1 mrg 4401 1.1 mrg /* Return the union of the elements in the list "list". 4402 1.1 mrg */ 4403 1.1 mrg __isl_give isl_union_set *isl_union_set_list_union( 4404 1.1 mrg __isl_take isl_union_set_list *list) 4405 1.1 mrg { 4406 1.1 mrg int i; 4407 1.1 mrg isl_size n; 4408 1.1 mrg isl_ctx *ctx; 4409 1.1 mrg isl_space *space; 4410 1.1 mrg isl_union_set *res; 4411 1.1 mrg 4412 1.1 mrg n = isl_union_set_list_n_union_set(list); 4413 1.1 mrg if (n < 0) 4414 1.1 mrg goto error; 4415 1.1 mrg 4416 1.1 mrg ctx = isl_union_set_list_get_ctx(list); 4417 1.1 mrg space = isl_space_params_alloc(ctx, 0); 4418 1.1 mrg res = isl_union_set_empty(space); 4419 1.1 mrg 4420 1.1 mrg for (i = 0; i < n; ++i) { 4421 1.1 mrg isl_union_set *uset_i; 4422 1.1 mrg 4423 1.1 mrg uset_i = isl_union_set_list_get_union_set(list, i); 4424 1.1 mrg res = isl_union_set_union(res, uset_i); 4425 1.1 mrg } 4426 1.1 mrg 4427 1.1 mrg isl_union_set_list_free(list); 4428 1.1 mrg return res; 4429 1.1 mrg error: 4430 1.1 mrg isl_union_set_list_free(list); 4431 1.1 mrg return NULL; 4432 1.1 mrg } 4433 1.1 mrg 4434 1.1 mrg /* Update *hash with the hash value of "map". 4435 1.1 mrg */ 4436 1.1 mrg static isl_stat add_hash(__isl_take isl_map *map, void *user) 4437 1.1 mrg { 4438 1.1 mrg uint32_t *hash = user; 4439 1.1 mrg uint32_t map_hash; 4440 1.1 mrg 4441 1.1 mrg map_hash = isl_map_get_hash(map); 4442 1.1 mrg isl_hash_hash(*hash, map_hash); 4443 1.1 mrg 4444 1.1 mrg isl_map_free(map); 4445 1.1 mrg return isl_stat_ok; 4446 1.1 mrg } 4447 1.1 mrg 4448 1.1 mrg /* Return a hash value that digests "umap". 4449 1.1 mrg */ 4450 1.1 mrg uint32_t isl_union_map_get_hash(__isl_keep isl_union_map *umap) 4451 1.1 mrg { 4452 1.1 mrg uint32_t hash; 4453 1.1 mrg 4454 1.1 mrg if (!umap) 4455 1.1 mrg return 0; 4456 1.1 mrg 4457 1.1 mrg hash = isl_hash_init(); 4458 1.1 mrg if (isl_union_map_foreach_map(umap, &add_hash, &hash) < 0) 4459 1.1 mrg return 0; 4460 1.1 mrg 4461 1.1 mrg return hash; 4462 1.1 mrg } 4463 1.1 mrg 4464 1.1 mrg /* Return a hash value that digests "uset". 4465 1.1 mrg */ 4466 1.1 mrg uint32_t isl_union_set_get_hash(__isl_keep isl_union_set *uset) 4467 1.1 mrg { 4468 1.1 mrg return isl_union_map_get_hash(uset); 4469 1.1 mrg } 4470 1.1 mrg 4471 1.1 mrg /* Add the number of basic sets in "set" to "n". 4472 1.1 mrg */ 4473 1.1 mrg static isl_stat add_n(__isl_take isl_set *set, void *user) 4474 1.1 mrg { 4475 1.1 mrg int *n = user; 4476 1.1 mrg isl_size set_n; 4477 1.1 mrg 4478 1.1 mrg set_n = isl_set_n_basic_set(set); 4479 1.1 mrg *n += set_n; 4480 1.1 mrg isl_set_free(set); 4481 1.1 mrg 4482 1.1 mrg return set_n < 0 ? isl_stat_error : isl_stat_ok; 4483 1.1 mrg } 4484 1.1 mrg 4485 1.1 mrg /* Return the total number of basic sets in "uset". 4486 1.1 mrg */ 4487 1.1 mrg int isl_union_set_n_basic_set(__isl_keep isl_union_set *uset) 4488 1.1 mrg { 4489 1.1 mrg int n = 0; 4490 1.1 mrg 4491 1.1 mrg if (isl_union_set_foreach_set(uset, &add_n, &n) < 0) 4492 1.1 mrg return -1; 4493 1.1 mrg 4494 1.1 mrg return n; 4495 1.1 mrg } 4496 1.1 mrg 4497 1.1 mrg /* Add the basic sets in "set" to "list". 4498 1.1 mrg */ 4499 1.1 mrg static isl_stat add_list(__isl_take isl_set *set, void *user) 4500 1.1 mrg { 4501 1.1 mrg isl_basic_set_list **list = user; 4502 1.1 mrg isl_basic_set_list *list_i; 4503 1.1 mrg 4504 1.1 mrg list_i = isl_set_get_basic_set_list(set); 4505 1.1 mrg *list = isl_basic_set_list_concat(*list, list_i); 4506 1.1 mrg isl_set_free(set); 4507 1.1 mrg 4508 1.1 mrg if (!*list) 4509 1.1 mrg return isl_stat_error; 4510 1.1 mrg return isl_stat_ok; 4511 1.1 mrg } 4512 1.1 mrg 4513 1.1 mrg /* Return a list containing all the basic sets in "uset". 4514 1.1 mrg * 4515 1.1 mrg * First construct a list of the appropriate size and 4516 1.1 mrg * then add all the elements. 4517 1.1 mrg */ 4518 1.1 mrg __isl_give isl_basic_set_list *isl_union_set_get_basic_set_list( 4519 1.1 mrg __isl_keep isl_union_set *uset) 4520 1.1 mrg { 4521 1.1 mrg int n; 4522 1.1 mrg isl_ctx *ctx; 4523 1.1 mrg isl_basic_set_list *list; 4524 1.1 mrg 4525 1.1 mrg if (!uset) 4526 1.1 mrg return NULL; 4527 1.1 mrg ctx = isl_union_set_get_ctx(uset); 4528 1.1 mrg n = isl_union_set_n_basic_set(uset); 4529 1.1 mrg if (n < 0) 4530 1.1 mrg return NULL; 4531 1.1 mrg list = isl_basic_set_list_alloc(ctx, n); 4532 1.1 mrg if (isl_union_set_foreach_set(uset, &add_list, &list) < 0) 4533 1.1 mrg list = isl_basic_set_list_free(list); 4534 1.1 mrg 4535 1.1 mrg return list; 4536 1.1 mrg } 4537 1.1 mrg 4538 1.1 mrg /* Internal data structure for isl_union_map_remove_map_if. 4539 1.1 mrg * "fn" and "user" are the arguments to isl_union_map_remove_map_if. 4540 1.1 mrg */ 4541 1.1 mrg struct isl_union_map_remove_map_if_data { 4542 1.1 mrg isl_bool (*fn)(__isl_keep isl_map *map, void *user); 4543 1.1 mrg void *user; 4544 1.1 mrg }; 4545 1.1 mrg 4546 1.1 mrg /* isl_un_op_control filter that negates the result of data->fn 4547 1.1 mrg * called on "map". 4548 1.1 mrg */ 4549 1.1 mrg static isl_bool not(__isl_keep isl_map *map, void *user) 4550 1.1 mrg { 4551 1.1 mrg struct isl_union_map_remove_map_if_data *data = user; 4552 1.1 mrg 4553 1.1 mrg return isl_bool_not(data->fn(map, data->user)); 4554 1.1 mrg } 4555 1.1 mrg 4556 1.1 mrg /* Dummy isl_un_op_control transformation callback that 4557 1.1 mrg * simply returns the input. 4558 1.1 mrg */ 4559 1.1 mrg static __isl_give isl_map *map_id(__isl_take isl_map *map) 4560 1.1 mrg { 4561 1.1 mrg return map; 4562 1.1 mrg } 4563 1.1 mrg 4564 1.1 mrg /* Call "fn" on every map in "umap" and remove those maps 4565 1.1 mrg * for which the callback returns true. 4566 1.1 mrg * 4567 1.1 mrg * Use un_op to keep only those maps that are not filtered out, 4568 1.1 mrg * applying an identity transformation on them. 4569 1.1 mrg */ 4570 1.1 mrg __isl_give isl_union_map *isl_union_map_remove_map_if( 4571 1.1 mrg __isl_take isl_union_map *umap, 4572 1.1 mrg isl_bool (*fn)(__isl_keep isl_map *map, void *user), void *user) 4573 1.1 mrg { 4574 1.1 mrg struct isl_union_map_remove_map_if_data data = { fn, user }; 4575 1.1 mrg struct isl_un_op_control control = { 4576 1.1 mrg .filter = ¬, 4577 1.1 mrg .filter_user = &data, 4578 1.1 mrg .fn_map = &map_id, 4579 1.1 mrg }; 4580 1.1 mrg return un_op(umap, &control); 4581 1.1 mrg } 4582 1.1 mrg 4583 1.1 mrg /* Does "map" have "space" as domain (ignoring parameters)? 4584 1.1 mrg */ 4585 1.1 mrg static isl_bool has_domain_space_tuples(__isl_keep isl_map *map, void *user) 4586 1.1 mrg { 4587 1.1 mrg isl_space *space = user; 4588 1.1 mrg 4589 1.1 mrg return isl_space_has_domain_tuples(space, isl_map_peek_space(map)); 4590 1.1 mrg } 4591 1.1 mrg 4592 1.1 mrg /* Does "map" have "space" as range (ignoring parameters)? 4593 1.1 mrg */ 4594 1.1 mrg static isl_bool has_range_space_tuples(__isl_keep isl_map *map, void *user) 4595 1.1 mrg { 4596 1.1 mrg isl_space *space = user; 4597 1.1 mrg 4598 1.1 mrg return isl_space_has_range_tuples(space, isl_map_peek_space(map)); 4599 1.1 mrg } 4600 1.1 mrg 4601 1.1 mrg /* Wrapper around isl_map_bind_range for use as a un_op callback. 4602 1.1 mrg */ 4603 1.1 mrg static __isl_give isl_map *bind_range(__isl_take isl_map *map, void *user) 4604 1.1 mrg { 4605 1.1 mrg isl_multi_id *tuple = user; 4606 1.1 mrg 4607 1.1 mrg return isl_map_bind_range(map, isl_multi_id_copy(tuple)); 4608 1.1 mrg } 4609 1.1 mrg 4610 1.1 mrg /* Bind the output dimensions of "umap" to parameters with identifiers 4611 1.1 mrg * specified by "tuple", living in the range space of "umap", 4612 1.1 mrg * for those maps that have a matching range space. 4613 1.1 mrg */ 4614 1.1 mrg __isl_give isl_union_set *isl_union_map_bind_range( 4615 1.1 mrg __isl_take isl_union_map *umap, __isl_take isl_multi_id *tuple) 4616 1.1 mrg { 4617 1.1 mrg struct isl_un_op_control control = { 4618 1.1 mrg .filter = &has_range_space_tuples, 4619 1.1 mrg .filter_user = isl_multi_id_peek_space(tuple), 4620 1.1 mrg .fn_map2 = &bind_range, 4621 1.1 mrg .fn_map2_user = tuple, 4622 1.1 mrg }; 4623 1.1 mrg isl_union_set *bound; 4624 1.1 mrg 4625 1.1 mrg bound = uset_from_umap(un_op(umap, &control)); 4626 1.1 mrg isl_multi_id_free(tuple); 4627 1.1 mrg return bound; 4628 1.1 mrg } 4629 1.1 mrg 4630 1.1 mrg /* Only keep those elements in "umap" that have a domain in "space". 4631 1.1 mrg */ 4632 1.1 mrg __isl_give isl_union_map *isl_union_map_intersect_domain_space( 4633 1.1 mrg __isl_take isl_union_map *umap, __isl_take isl_space *space) 4634 1.1 mrg { 4635 1.1 mrg struct isl_un_op_control control = { 4636 1.1 mrg .filter = &has_domain_space_tuples, 4637 1.1 mrg .filter_user = space, 4638 1.1 mrg }; 4639 1.1 mrg 4640 1.1 mrg umap = un_op(umap, &control); 4641 1.1 mrg isl_space_free(space); 4642 1.1 mrg return umap; 4643 1.1 mrg } 4644 1.1 mrg 4645 1.1 mrg /* Only keep those elements in "umap" that have a range in "space". 4646 1.1 mrg */ 4647 1.1 mrg __isl_give isl_union_map *isl_union_map_intersect_range_space( 4648 1.1 mrg __isl_take isl_union_map *umap, __isl_take isl_space *space) 4649 1.1 mrg { 4650 1.1 mrg struct isl_un_op_control control = { 4651 1.1 mrg .filter = &has_range_space_tuples, 4652 1.1 mrg .filter_user = space, 4653 1.1 mrg }; 4654 1.1 mrg 4655 1.1 mrg umap = un_op(umap, &control); 4656 1.1 mrg isl_space_free(space); 4657 1.1 mrg return umap; 4658 1.1 mrg } 4659