14473 lines · c
1/*2 * Copyright 2008-2009 Katholieke Universiteit Leuven3 * Copyright 2010 INRIA Saclay4 * Copyright 2012-2014 Ecole Normale Superieure5 * Copyright 2014 INRIA Rocquencourt6 * Copyright 2016 INRIA Paris7 * Copyright 2016 Sven Verdoolaege8 * Copyright 2018-2019 Cerebras Systems9 *10 * Use of this software is governed by the MIT license11 *12 * Written by Sven Verdoolaege, K.U.Leuven, Departement13 * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium14 * and INRIA Saclay - Ile-de-France, Parc Club Orsay Universite,15 * ZAC des vignes, 4 rue Jacques Monod, 91893 Orsay, France 16 * and Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France17 * and Inria Paris - Rocquencourt, Domaine de Voluceau - Rocquencourt,18 * B.P. 105 - 78153 Le Chesnay, France19 * and Centre de Recherche Inria de Paris, 2 rue Simone Iff - Voie DQ12,20 * CS 42112, 75589 Paris Cedex 12, France21 * and Cerebras Systems, 175 S San Antonio Rd, Los Altos, CA, USA22 */23 24#include <string.h>25#include <isl_ctx_private.h>26#include <isl_map_private.h>27#include <isl_blk.h>28#include <isl_id_private.h>29#include <isl/constraint.h>30#include "isl_space_private.h"31#include "isl_equalities.h"32#include <isl_lp_private.h>33#include <isl_seq.h>34#include <isl/set.h>35#include <isl/map.h>36#include <isl_reordering.h>37#include "isl_sample.h"38#include <isl_sort.h>39#include "isl_tab.h"40#include <isl/vec.h>41#include <isl_mat_private.h>42#include <isl_vec_private.h>43#include <isl_dim_map.h>44#include <isl_local_space_private.h>45#include <isl_aff_private.h>46#include <isl_options_private.h>47#include <isl_morph.h>48#include <isl_val_private.h>49#include <isl_printer_private.h>50 51#include <bset_to_bmap.c>52#include <bset_from_bmap.c>53#include <set_to_map.c>54#include <set_from_map.c>55 56/* Treat "bset" as a basic map.57 * Internally, isl_basic_set is defined to isl_basic_map, so in practice,58 * this function performs a redundant cast.59 */60static __isl_keep const isl_basic_map *const_bset_to_bmap(61 __isl_keep const isl_basic_set *bset)62{63 return (const isl_basic_map *) bset;64}65 66#undef TYPE67#define TYPE isl_basic_map68#include "has_single_reference_templ.c"69 70static unsigned pos(__isl_keep isl_space *space, enum isl_dim_type type)71{72 switch (type) {73 case isl_dim_param: return 1;74 case isl_dim_in: return 1 + space->nparam;75 case isl_dim_out: return 1 + space->nparam + space->n_in;76 default: return 0;77 }78}79 80isl_size isl_basic_map_dim(__isl_keep isl_basic_map *bmap,81 enum isl_dim_type type)82{83 if (!bmap)84 return isl_size_error;85 switch (type) {86 case isl_dim_cst: return 1;87 case isl_dim_param:88 case isl_dim_in:89 case isl_dim_out: return isl_space_dim(bmap->dim, type);90 case isl_dim_div: return bmap->n_div;91 case isl_dim_all: return isl_basic_map_total_dim(bmap);92 default: return 0;93 }94}95 96/* Return the space of "map".97 */98__isl_keep isl_space *isl_map_peek_space(__isl_keep const isl_map *map)99{100 return map ? map->dim : NULL;101}102 103/* Return the space of "set".104 */105__isl_keep isl_space *isl_set_peek_space(__isl_keep isl_set *set)106{107 return isl_map_peek_space(set_to_map(set));108}109 110isl_size isl_map_dim(__isl_keep isl_map *map, enum isl_dim_type type)111{112 return isl_space_dim(isl_map_peek_space(map), type);113}114 115/* Return the dimensionality of the domain (tuple) of the map.116 */117isl_size isl_map_domain_tuple_dim(__isl_keep isl_map *map)118{119 return isl_map_dim(map, isl_dim_in);120}121 122/* Return the dimensionality of the range (tuple) of the map.123 */124isl_size isl_map_range_tuple_dim(__isl_keep isl_map *map)125{126 return isl_map_dim(map, isl_dim_out);127}128 129isl_size isl_set_dim(__isl_keep isl_set *set, enum isl_dim_type type)130{131 return isl_map_dim(set_to_map(set), type);132}133 134/* Return the dimensionality of the (tuple of the) set.135 */136isl_size isl_set_tuple_dim(__isl_keep isl_set *set)137{138 return isl_set_dim(set, isl_dim_set);139}140 141/* Return the position of the variables of the given type142 * within the sequence of variables of "bmap".143 */144isl_size isl_basic_map_var_offset(__isl_keep isl_basic_map *bmap,145 enum isl_dim_type type)146{147 isl_space *space;148 149 space = isl_basic_map_peek_space(bmap);150 if (!space)151 return isl_size_error;152 153 switch (type) {154 case isl_dim_param:155 case isl_dim_in:156 case isl_dim_out: return isl_space_offset(space, type);157 case isl_dim_div: return isl_space_dim(space, isl_dim_all);158 case isl_dim_cst:159 default:160 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,161 "invalid dimension type", return isl_size_error);162 }163}164 165/* Return the position of the variables of the given type166 * within the sequence of variables of "bset".167 */168isl_size isl_basic_set_var_offset(__isl_keep isl_basic_set *bset,169 enum isl_dim_type type)170{171 return isl_basic_map_var_offset(bset_to_bmap(bset), type);172}173 174/* Return the position of the coefficients of the variables of the given type175 * within the sequence of coefficients of "bmap".176 */177unsigned isl_basic_map_offset(__isl_keep isl_basic_map *bmap,178 enum isl_dim_type type)179{180 switch (type) {181 case isl_dim_cst: return 0;182 case isl_dim_param:183 case isl_dim_in:184 case isl_dim_out:185 case isl_dim_div: return 1 + isl_basic_map_var_offset(bmap, type);186 default: return 0;187 }188}189 190unsigned isl_basic_set_offset(__isl_keep isl_basic_set *bset,191 enum isl_dim_type type)192{193 return isl_basic_map_offset(bset, type);194}195 196static unsigned map_offset(__isl_keep isl_map *map, enum isl_dim_type type)197{198 return pos(map->dim, type);199}200 201isl_size isl_basic_set_dim(__isl_keep isl_basic_set *bset,202 enum isl_dim_type type)203{204 return isl_basic_map_dim(bset, type);205}206 207isl_size isl_basic_set_n_dim(__isl_keep isl_basic_set *bset)208{209 return isl_basic_set_dim(bset, isl_dim_set);210}211 212isl_size isl_basic_set_n_param(__isl_keep isl_basic_set *bset)213{214 return isl_basic_set_dim(bset, isl_dim_param);215}216 217isl_size isl_basic_set_total_dim(__isl_keep const isl_basic_set *bset)218{219 return isl_basic_map_total_dim(const_bset_to_bmap(bset));220}221 222isl_size isl_set_n_dim(__isl_keep isl_set *set)223{224 return isl_set_dim(set, isl_dim_set);225}226 227isl_size isl_set_n_param(__isl_keep isl_set *set)228{229 return isl_set_dim(set, isl_dim_param);230}231 232isl_size isl_basic_map_total_dim(__isl_keep const isl_basic_map *bmap)233{234 isl_size dim;235 236 if (!bmap)237 return isl_size_error;238 dim = isl_space_dim(bmap->dim, isl_dim_all);239 if (dim < 0)240 return isl_size_error;241 return dim + bmap->n_div;242}243 244/* Return the number of equality constraints in the description of "bmap".245 * Return isl_size_error on error.246 */247isl_size isl_basic_map_n_equality(__isl_keep isl_basic_map *bmap)248{249 if (!bmap)250 return isl_size_error;251 return bmap->n_eq;252}253 254/* Return the number of equality constraints in the description of "bset".255 * Return isl_size_error on error.256 */257isl_size isl_basic_set_n_equality(__isl_keep isl_basic_set *bset)258{259 return isl_basic_map_n_equality(bset_to_bmap(bset));260}261 262/* Return the number of inequality constraints in the description of "bmap".263 * Return isl_size_error on error.264 */265isl_size isl_basic_map_n_inequality(__isl_keep isl_basic_map *bmap)266{267 if (!bmap)268 return isl_size_error;269 return bmap->n_ineq;270}271 272/* Return the number of inequality constraints in the description of "bset".273 * Return isl_size_error on error.274 */275isl_size isl_basic_set_n_inequality(__isl_keep isl_basic_set *bset)276{277 return isl_basic_map_n_inequality(bset_to_bmap(bset));278}279 280/* Do "bmap1" and "bmap2" have the same parameters?281 */282static isl_bool isl_basic_map_has_equal_params(__isl_keep isl_basic_map *bmap1,283 __isl_keep isl_basic_map *bmap2)284{285 isl_space *space1, *space2;286 287 space1 = isl_basic_map_peek_space(bmap1);288 space2 = isl_basic_map_peek_space(bmap2);289 return isl_space_has_equal_params(space1, space2);290}291 292/* Do "map1" and "map2" have the same parameters?293 */294isl_bool isl_map_has_equal_params(__isl_keep isl_map *map1,295 __isl_keep isl_map *map2)296{297 isl_space *space1, *space2;298 299 space1 = isl_map_peek_space(map1);300 space2 = isl_map_peek_space(map2);301 return isl_space_has_equal_params(space1, space2);302}303 304/* Do "map" and "set" have the same parameters?305 */306static isl_bool isl_map_set_has_equal_params(__isl_keep isl_map *map,307 __isl_keep isl_set *set)308{309 return isl_map_has_equal_params(map, set_to_map(set));310}311 312/* Is the tuple of type "type" of "bmap" the same as the single tuple of "bset"?313 */314static isl_bool isl_basic_map_set_tuple_is_equal(__isl_keep isl_basic_map *bmap,315 enum isl_dim_type type, __isl_keep isl_basic_set *bset)316{317 isl_space *bmap_space, *bset_space;318 319 bmap_space = isl_basic_map_peek_space(bmap);320 bset_space = isl_basic_set_peek_space(bset);321 return isl_space_tuple_is_equal(bmap_space, type,322 bset_space, isl_dim_set);323}324 325/* Is the tuple of type "type" of "map" the same as the single tuple of "set"?326 */327static isl_bool isl_map_set_tuple_is_equal(__isl_keep isl_map *map,328 enum isl_dim_type type, __isl_keep isl_set *set)329{330 return isl_map_tuple_is_equal(map, type, set_to_map(set), isl_dim_set);331}332 333isl_bool isl_map_compatible_domain(__isl_keep isl_map *map,334 __isl_keep isl_set *set)335{336 isl_bool m;337 if (!map || !set)338 return isl_bool_error;339 m = isl_map_has_equal_params(map, set_to_map(set));340 if (m < 0 || !m)341 return m;342 return isl_map_set_tuple_is_equal(map, isl_dim_in, set);343}344 345isl_bool isl_basic_map_compatible_domain(__isl_keep isl_basic_map *bmap,346 __isl_keep isl_basic_set *bset)347{348 isl_bool m;349 if (!bmap || !bset)350 return isl_bool_error;351 m = isl_basic_map_has_equal_params(bmap, bset_to_bmap(bset));352 if (m < 0 || !m)353 return m;354 return isl_basic_map_set_tuple_is_equal(bmap, isl_dim_in, bset);355}356 357isl_bool isl_map_compatible_range(__isl_keep isl_map *map,358 __isl_keep isl_set *set)359{360 isl_bool m;361 if (!map || !set)362 return isl_bool_error;363 m = isl_map_has_equal_params(map, set_to_map(set));364 if (m < 0 || !m)365 return m;366 return isl_map_set_tuple_is_equal(map, isl_dim_out, set);367}368 369isl_bool isl_basic_map_compatible_range(__isl_keep isl_basic_map *bmap,370 __isl_keep isl_basic_set *bset)371{372 isl_bool m;373 if (!bmap || !bset)374 return isl_bool_error;375 m = isl_basic_map_has_equal_params(bmap, bset_to_bmap(bset));376 if (m < 0 || !m)377 return m;378 return isl_basic_map_set_tuple_is_equal(bmap, isl_dim_out, bset);379}380 381isl_ctx *isl_basic_map_get_ctx(__isl_keep isl_basic_map *bmap)382{383 return bmap ? bmap->ctx : NULL;384}385 386isl_ctx *isl_basic_set_get_ctx(__isl_keep isl_basic_set *bset)387{388 return bset ? bset->ctx : NULL;389}390 391isl_ctx *isl_map_get_ctx(__isl_keep isl_map *map)392{393 return map ? map->ctx : NULL;394}395 396isl_ctx *isl_set_get_ctx(__isl_keep isl_set *set)397{398 return set ? set->ctx : NULL;399}400 401/* Return the space of "bmap".402 */403__isl_keep isl_space *isl_basic_map_peek_space(404 __isl_keep const isl_basic_map *bmap)405{406 return bmap ? bmap->dim : NULL;407}408 409/* Return the space of "bset".410 */411__isl_keep isl_space *isl_basic_set_peek_space(__isl_keep isl_basic_set *bset)412{413 return isl_basic_map_peek_space(bset_to_bmap(bset));414}415 416__isl_give isl_space *isl_basic_map_get_space(__isl_keep isl_basic_map *bmap)417{418 return isl_space_copy(isl_basic_map_peek_space(bmap));419}420 421__isl_give isl_space *isl_basic_set_get_space(__isl_keep isl_basic_set *bset)422{423 return isl_basic_map_get_space(bset_to_bmap(bset));424}425 426/* Return the space of "bmap".427 * This may be either a copy or the space itself428 * if there is only one reference to "bmap".429 * This allows the space to be modified inplace430 * if both the basic map and its space have only a single reference.431 * The caller is not allowed to modify "bmap" between this call and432 * a subsequent call to isl_basic_map_restore_space.433 * The only exception is that isl_basic_map_free can be called instead.434 */435static __isl_give isl_space *isl_basic_map_take_space(436 __isl_keep isl_basic_map *bmap)437{438 isl_space *space;439 440 if (!bmap)441 return NULL;442 if (bmap->ref != 1)443 return isl_basic_map_get_space(bmap);444 space = bmap->dim;445 bmap->dim = NULL;446 return space;447}448 449/* Set the space of "bmap" to "space", where the space of "bmap" may be missing450 * due to a preceding call to isl_basic_map_take_space.451 * However, in this case, "bmap" only has a single reference and452 * then the call to isl_basic_map_cow has no effect.453 */454static __isl_give isl_basic_map *isl_basic_map_restore_space(455 __isl_take isl_basic_map *bmap, __isl_take isl_space *space)456{457 if (!bmap || !space)458 goto error;459 460 if (bmap->dim == space) {461 isl_space_free(space);462 return bmap;463 }464 465 bmap = isl_basic_map_cow(bmap);466 if (!bmap)467 goto error;468 isl_space_free(bmap->dim);469 bmap->dim = space;470 471 return bmap;472error:473 isl_basic_map_free(bmap);474 isl_space_free(space);475 return NULL;476}477 478/* Extract the divs in "bmap" as a matrix.479 */480__isl_give isl_mat *isl_basic_map_get_divs(__isl_keep isl_basic_map *bmap)481{482 int i;483 isl_ctx *ctx;484 isl_mat *div;485 isl_size v_div;486 unsigned cols;487 488 v_div = isl_basic_map_var_offset(bmap, isl_dim_div);489 if (v_div < 0)490 return NULL;491 492 ctx = isl_basic_map_get_ctx(bmap);493 cols = 1 + 1 + v_div + bmap->n_div;494 div = isl_mat_alloc(ctx, bmap->n_div, cols);495 if (!div)496 return NULL;497 498 for (i = 0; i < bmap->n_div; ++i)499 isl_seq_cpy(div->row[i], bmap->div[i], cols);500 501 return div;502}503 504/* Extract the divs in "bset" as a matrix.505 */506__isl_give isl_mat *isl_basic_set_get_divs(__isl_keep isl_basic_set *bset)507{508 return isl_basic_map_get_divs(bset);509}510 511__isl_give isl_local_space *isl_basic_map_get_local_space(512 __isl_keep isl_basic_map *bmap)513{514 isl_mat *div;515 516 if (!bmap)517 return NULL;518 519 div = isl_basic_map_get_divs(bmap);520 return isl_local_space_alloc_div(isl_space_copy(bmap->dim), div);521}522 523__isl_give isl_local_space *isl_basic_set_get_local_space(524 __isl_keep isl_basic_set *bset)525{526 return isl_basic_map_get_local_space(bset);527}528 529/* For each known div d = floor(f/m), add the constraints530 *531 * f - m d >= 0532 * -(f-(m-1)) + m d >= 0533 *534 * Do not finalize the result.535 */536static __isl_give isl_basic_map *add_known_div_constraints(537 __isl_take isl_basic_map *bmap)538{539 int i;540 isl_size n_div;541 542 n_div = isl_basic_map_dim(bmap, isl_dim_div);543 if (n_div < 0)544 return isl_basic_map_free(bmap);545 if (n_div == 0)546 return bmap;547 bmap = isl_basic_map_cow(bmap);548 bmap = isl_basic_map_extend_constraints(bmap, 0, 2 * n_div);549 if (!bmap)550 return NULL;551 for (i = 0; i < n_div; ++i) {552 if (isl_int_is_zero(bmap->div[i][0]))553 continue;554 bmap = isl_basic_map_add_div_constraints(bmap, i);555 }556 557 return bmap;558}559 560__isl_give isl_basic_map *isl_basic_map_from_local_space(561 __isl_take isl_local_space *ls)562{563 int i;564 isl_size n_div;565 isl_basic_map *bmap;566 567 n_div = isl_local_space_dim(ls, isl_dim_div);568 if (n_div < 0)569 ls = isl_local_space_free(ls);570 if (!ls)571 return NULL;572 573 bmap = isl_basic_map_alloc_space(isl_local_space_get_space(ls),574 n_div, 0, 2 * n_div);575 576 for (i = 0; i < n_div; ++i)577 if (isl_basic_map_alloc_div(bmap) < 0)578 goto error;579 580 for (i = 0; i < n_div; ++i)581 isl_seq_cpy(bmap->div[i], ls->div->row[i], ls->div->n_col);582 bmap = add_known_div_constraints(bmap);583 584 isl_local_space_free(ls);585 return bmap;586error:587 isl_local_space_free(ls);588 isl_basic_map_free(bmap);589 return NULL;590}591 592__isl_give isl_basic_set *isl_basic_set_from_local_space(593 __isl_take isl_local_space *ls)594{595 return isl_basic_map_from_local_space(ls);596}597 598__isl_give isl_space *isl_map_get_space(__isl_keep isl_map *map)599{600 return isl_space_copy(isl_map_peek_space(map));601}602 603__isl_give isl_space *isl_set_get_space(__isl_keep isl_set *set)604{605 if (!set)606 return NULL;607 return isl_space_copy(set->dim);608}609 610/* Return the space of "map".611 * This may be either a copy or the space itself612 * if there is only one reference to "map".613 * This allows the space to be modified inplace614 * if both the map and its space have only a single reference.615 * The caller is not allowed to modify "map" between this call and616 * a subsequent call to isl_map_restore_space.617 * The only exception is that isl_map_free can be called instead.618 */619static __isl_give isl_space *isl_map_take_space(__isl_keep isl_map *map)620{621 isl_space *space;622 623 if (!map)624 return NULL;625 if (map->ref != 1)626 return isl_map_get_space(map);627 space = map->dim;628 map->dim = NULL;629 return space;630}631 632/* Set the space of "map" to "space", where the space of "map" may be missing633 * due to a preceding call to isl_map_take_space.634 * However, in this case, "map" only has a single reference and635 * then the call to isl_map_cow has no effect.636 */637static __isl_give isl_map *isl_map_restore_space(__isl_take isl_map *map,638 __isl_take isl_space *space)639{640 if (!map || !space)641 goto error;642 643 if (map->dim == space) {644 isl_space_free(space);645 return map;646 }647 648 map = isl_map_cow(map);649 if (!map)650 goto error;651 isl_space_free(map->dim);652 map->dim = space;653 654 return map;655error:656 isl_map_free(map);657 isl_space_free(space);658 return NULL;659}660 661__isl_give isl_basic_map *isl_basic_map_set_tuple_name(662 __isl_take isl_basic_map *bmap, enum isl_dim_type type, const char *s)663{664 isl_space *space;665 666 space = isl_basic_map_take_space(bmap);667 space = isl_space_set_tuple_name(space, type, s);668 bmap = isl_basic_map_restore_space(bmap, space);669 bmap = isl_basic_map_finalize(bmap);670 return bmap;671}672 673__isl_give isl_basic_set *isl_basic_set_set_tuple_name(674 __isl_take isl_basic_set *bset, const char *s)675{676 return isl_basic_map_set_tuple_name(bset, isl_dim_set, s);677}678 679const char *isl_basic_map_get_tuple_name(__isl_keep isl_basic_map *bmap,680 enum isl_dim_type type)681{682 return bmap ? isl_space_get_tuple_name(bmap->dim, type) : NULL;683}684 685__isl_give isl_map *isl_map_set_tuple_name(__isl_take isl_map *map,686 enum isl_dim_type type, const char *s)687{688 int i;689 isl_space *space;690 691 map = isl_map_cow(map);692 if (!map)693 return NULL;694 695 for (i = 0; i < map->n; ++i) {696 map->p[i] = isl_basic_map_set_tuple_name(map->p[i], type, s);697 if (!map->p[i])698 goto error;699 }700 701 space = isl_map_take_space(map);702 space = isl_space_set_tuple_name(space, type, s);703 map = isl_map_restore_space(map, space);704 705 return map;706error:707 isl_map_free(map);708 return NULL;709}710 711/* Replace the identifier of the tuple of type "type" by "id".712 */713__isl_give isl_basic_map *isl_basic_map_set_tuple_id(714 __isl_take isl_basic_map *bmap,715 enum isl_dim_type type, __isl_take isl_id *id)716{717 isl_space *space;718 719 space = isl_basic_map_take_space(bmap);720 space = isl_space_set_tuple_id(space, type, id);721 bmap = isl_basic_map_restore_space(bmap, space);722 bmap = isl_basic_map_finalize(bmap);723 return bmap;724}725 726/* Replace the identifier of the tuple by "id".727 */728__isl_give isl_basic_set *isl_basic_set_set_tuple_id(729 __isl_take isl_basic_set *bset, __isl_take isl_id *id)730{731 return isl_basic_map_set_tuple_id(bset, isl_dim_set, id);732}733 734/* Does the input or output tuple have a name?735 */736isl_bool isl_map_has_tuple_name(__isl_keep isl_map *map, enum isl_dim_type type)737{738 return map ? isl_space_has_tuple_name(map->dim, type) : isl_bool_error;739}740 741const char *isl_map_get_tuple_name(__isl_keep isl_map *map,742 enum isl_dim_type type)743{744 return map ? isl_space_get_tuple_name(map->dim, type) : NULL;745}746 747__isl_give isl_set *isl_set_set_tuple_name(__isl_take isl_set *set,748 const char *s)749{750 return set_from_map(isl_map_set_tuple_name(set_to_map(set),751 isl_dim_set, s));752}753 754__isl_give isl_map *isl_map_set_tuple_id(__isl_take isl_map *map,755 enum isl_dim_type type, __isl_take isl_id *id)756{757 isl_space *space;758 759 space = isl_map_take_space(map);760 space = isl_space_set_tuple_id(space, type, id);761 map = isl_map_restore_space(map, space);762 763 return isl_map_reset_space(map, isl_map_get_space(map));764}765 766/* Replace the identifier of the domain tuple of "map" by "id".767 */768__isl_give isl_map *isl_map_set_domain_tuple_id(__isl_take isl_map *map,769 __isl_take isl_id *id)770{771 return isl_map_set_tuple_id(map, isl_dim_in, id);772}773 774/* Replace the identifier of the range tuple of "map" by "id".775 */776__isl_give isl_map *isl_map_set_range_tuple_id(__isl_take isl_map *map,777 __isl_take isl_id *id)778{779 return isl_map_set_tuple_id(map, isl_dim_out, id);780}781 782__isl_give isl_set *isl_set_set_tuple_id(__isl_take isl_set *set,783 __isl_take isl_id *id)784{785 return isl_map_set_tuple_id(set, isl_dim_set, id);786}787 788__isl_give isl_map *isl_map_reset_tuple_id(__isl_take isl_map *map,789 enum isl_dim_type type)790{791 isl_space *space;792 793 space = isl_map_take_space(map);794 space = isl_space_reset_tuple_id(space, type);795 map = isl_map_restore_space(map, space);796 797 return isl_map_reset_space(map, isl_map_get_space(map));798}799 800__isl_give isl_set *isl_set_reset_tuple_id(__isl_take isl_set *set)801{802 return isl_map_reset_tuple_id(set, isl_dim_set);803}804 805isl_bool isl_map_has_tuple_id(__isl_keep isl_map *map, enum isl_dim_type type)806{807 return map ? isl_space_has_tuple_id(map->dim, type) : isl_bool_error;808}809 810/* Does the domain tuple of "map" have an identifier?811 */812isl_bool isl_map_has_domain_tuple_id(__isl_keep isl_map *map)813{814 return isl_map_has_tuple_id(map, isl_dim_in);815}816 817/* Does the range tuple of "map" have an identifier?818 */819isl_bool isl_map_has_range_tuple_id(__isl_keep isl_map *map)820{821 return isl_map_has_tuple_id(map, isl_dim_out);822}823 824__isl_give isl_id *isl_map_get_tuple_id(__isl_keep isl_map *map,825 enum isl_dim_type type)826{827 return map ? isl_space_get_tuple_id(map->dim, type) : NULL;828}829 830/* Return the identifier of the domain tuple of "map", assuming it has one.831 */832__isl_give isl_id *isl_map_get_domain_tuple_id(__isl_keep isl_map *map)833{834 return isl_map_get_tuple_id(map, isl_dim_in);835}836 837/* Return the identifier of the range tuple of "map", assuming it has one.838 */839__isl_give isl_id *isl_map_get_range_tuple_id(__isl_keep isl_map *map)840{841 return isl_map_get_tuple_id(map, isl_dim_out);842}843 844isl_bool isl_set_has_tuple_id(__isl_keep isl_set *set)845{846 return isl_map_has_tuple_id(set, isl_dim_set);847}848 849__isl_give isl_id *isl_set_get_tuple_id(__isl_keep isl_set *set)850{851 return isl_map_get_tuple_id(set, isl_dim_set);852}853 854/* Does the set tuple have a name?855 */856isl_bool isl_set_has_tuple_name(__isl_keep isl_set *set)857{858 if (!set)859 return isl_bool_error;860 return isl_space_has_tuple_name(set->dim, isl_dim_set);861}862 863 864const char *isl_basic_set_get_tuple_name(__isl_keep isl_basic_set *bset)865{866 return bset ? isl_space_get_tuple_name(bset->dim, isl_dim_set) : NULL;867}868 869const char *isl_set_get_tuple_name(__isl_keep isl_set *set)870{871 return set ? isl_space_get_tuple_name(set->dim, isl_dim_set) : NULL;872}873 874const char *isl_basic_map_get_dim_name(__isl_keep isl_basic_map *bmap,875 enum isl_dim_type type, unsigned pos)876{877 return bmap ? isl_space_get_dim_name(bmap->dim, type, pos) : NULL;878}879 880const char *isl_basic_set_get_dim_name(__isl_keep isl_basic_set *bset,881 enum isl_dim_type type, unsigned pos)882{883 return bset ? isl_space_get_dim_name(bset->dim, type, pos) : NULL;884}885 886/* Does the given dimension have a name?887 */888isl_bool isl_map_has_dim_name(__isl_keep isl_map *map,889 enum isl_dim_type type, unsigned pos)890{891 if (!map)892 return isl_bool_error;893 return isl_space_has_dim_name(map->dim, type, pos);894}895 896const char *isl_map_get_dim_name(__isl_keep isl_map *map,897 enum isl_dim_type type, unsigned pos)898{899 return map ? isl_space_get_dim_name(map->dim, type, pos) : NULL;900}901 902const char *isl_set_get_dim_name(__isl_keep isl_set *set,903 enum isl_dim_type type, unsigned pos)904{905 return set ? isl_space_get_dim_name(set->dim, type, pos) : NULL;906}907 908/* Does the given dimension have a name?909 */910isl_bool isl_set_has_dim_name(__isl_keep isl_set *set,911 enum isl_dim_type type, unsigned pos)912{913 if (!set)914 return isl_bool_error;915 return isl_space_has_dim_name(set->dim, type, pos);916}917 918__isl_give isl_basic_map *isl_basic_map_set_dim_name(919 __isl_take isl_basic_map *bmap,920 enum isl_dim_type type, unsigned pos, const char *s)921{922 isl_space *space;923 924 space = isl_basic_map_take_space(bmap);925 space = isl_space_set_dim_name(space, type, pos, s);926 bmap = isl_basic_map_restore_space(bmap, space);927 return isl_basic_map_finalize(bmap);928}929 930__isl_give isl_map *isl_map_set_dim_name(__isl_take isl_map *map,931 enum isl_dim_type type, unsigned pos, const char *s)932{933 int i;934 isl_space *space;935 936 map = isl_map_cow(map);937 if (!map)938 return NULL;939 940 for (i = 0; i < map->n; ++i) {941 map->p[i] = isl_basic_map_set_dim_name(map->p[i], type, pos, s);942 if (!map->p[i])943 goto error;944 }945 946 space = isl_map_take_space(map);947 space = isl_space_set_dim_name(space, type, pos, s);948 map = isl_map_restore_space(map, space);949 950 return map;951error:952 isl_map_free(map);953 return NULL;954}955 956__isl_give isl_basic_set *isl_basic_set_set_dim_name(957 __isl_take isl_basic_set *bset,958 enum isl_dim_type type, unsigned pos, const char *s)959{960 return bset_from_bmap(isl_basic_map_set_dim_name(bset_to_bmap(bset),961 type, pos, s));962}963 964__isl_give isl_set *isl_set_set_dim_name(__isl_take isl_set *set,965 enum isl_dim_type type, unsigned pos, const char *s)966{967 return set_from_map(isl_map_set_dim_name(set_to_map(set),968 type, pos, s));969}970 971isl_bool isl_basic_map_has_dim_id(__isl_keep isl_basic_map *bmap,972 enum isl_dim_type type, unsigned pos)973{974 if (!bmap)975 return isl_bool_error;976 return isl_space_has_dim_id(bmap->dim, type, pos);977}978 979__isl_give isl_id *isl_basic_set_get_dim_id(__isl_keep isl_basic_set *bset,980 enum isl_dim_type type, unsigned pos)981{982 return bset ? isl_space_get_dim_id(bset->dim, type, pos) : NULL;983}984 985isl_bool isl_map_has_dim_id(__isl_keep isl_map *map,986 enum isl_dim_type type, unsigned pos)987{988 return map ? isl_space_has_dim_id(map->dim, type, pos) : isl_bool_error;989}990 991__isl_give isl_id *isl_map_get_dim_id(__isl_keep isl_map *map,992 enum isl_dim_type type, unsigned pos)993{994 return map ? isl_space_get_dim_id(map->dim, type, pos) : NULL;995}996 997isl_bool isl_set_has_dim_id(__isl_keep isl_set *set,998 enum isl_dim_type type, unsigned pos)999{1000 return isl_map_has_dim_id(set, type, pos);1001}1002 1003__isl_give isl_id *isl_set_get_dim_id(__isl_keep isl_set *set,1004 enum isl_dim_type type, unsigned pos)1005{1006 return isl_map_get_dim_id(set, type, pos);1007}1008 1009__isl_give isl_map *isl_map_set_dim_id(__isl_take isl_map *map,1010 enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)1011{1012 isl_space *space;1013 1014 space = isl_map_take_space(map);1015 space = isl_space_set_dim_id(space, type, pos, id);1016 map = isl_map_restore_space(map, space);1017 1018 return isl_map_reset_space(map, isl_map_get_space(map));1019}1020 1021__isl_give isl_set *isl_set_set_dim_id(__isl_take isl_set *set,1022 enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)1023{1024 return isl_map_set_dim_id(set, type, pos, id);1025}1026 1027int isl_map_find_dim_by_id(__isl_keep isl_map *map, enum isl_dim_type type,1028 __isl_keep isl_id *id)1029{1030 if (!map)1031 return -1;1032 return isl_space_find_dim_by_id(map->dim, type, id);1033}1034 1035int isl_set_find_dim_by_id(__isl_keep isl_set *set, enum isl_dim_type type,1036 __isl_keep isl_id *id)1037{1038 return isl_map_find_dim_by_id(set, type, id);1039}1040 1041/* Return the position of the dimension of the given type and name1042 * in "bmap".1043 * Return -1 if no such dimension can be found.1044 */1045int isl_basic_map_find_dim_by_name(__isl_keep isl_basic_map *bmap,1046 enum isl_dim_type type, const char *name)1047{1048 if (!bmap)1049 return -1;1050 return isl_space_find_dim_by_name(bmap->dim, type, name);1051}1052 1053int isl_map_find_dim_by_name(__isl_keep isl_map *map, enum isl_dim_type type,1054 const char *name)1055{1056 if (!map)1057 return -1;1058 return isl_space_find_dim_by_name(map->dim, type, name);1059}1060 1061int isl_set_find_dim_by_name(__isl_keep isl_set *set, enum isl_dim_type type,1062 const char *name)1063{1064 return isl_map_find_dim_by_name(set, type, name);1065}1066 1067/* Check whether equality i of bset is a pure stride constraint1068 * on a single dimension, i.e., of the form1069 *1070 * v = k e1071 *1072 * with k a constant and e an existentially quantified variable.1073 */1074isl_bool isl_basic_set_eq_is_stride(__isl_keep isl_basic_set *bset, int i)1075{1076 isl_size nparam;1077 isl_size d;1078 isl_size n_div;1079 int pos1;1080 int pos2;1081 1082 nparam = isl_basic_set_dim(bset, isl_dim_param);1083 d = isl_basic_set_dim(bset, isl_dim_set);1084 n_div = isl_basic_set_dim(bset, isl_dim_div);1085 if (nparam < 0 || d < 0 || n_div < 0)1086 return isl_bool_error;1087 1088 if (!isl_int_is_zero(bset->eq[i][0]))1089 return isl_bool_false;1090 1091 if (isl_seq_first_non_zero(bset->eq[i] + 1, nparam) != -1)1092 return isl_bool_false;1093 pos1 = isl_seq_first_non_zero(bset->eq[i] + 1 + nparam, d);1094 if (pos1 == -1)1095 return isl_bool_false;1096 if (isl_seq_first_non_zero(bset->eq[i] + 1 + nparam + pos1 + 1,1097 d - pos1 - 1) != -1)1098 return isl_bool_false;1099 1100 pos2 = isl_seq_first_non_zero(bset->eq[i] + 1 + nparam + d, n_div);1101 if (pos2 == -1)1102 return isl_bool_false;1103 if (isl_seq_first_non_zero(bset->eq[i] + 1 + nparam + d + pos2 + 1,1104 n_div - pos2 - 1) != -1)1105 return isl_bool_false;1106 if (!isl_int_is_one(bset->eq[i][1 + nparam + pos1]) &&1107 !isl_int_is_negone(bset->eq[i][1 + nparam + pos1]))1108 return isl_bool_false;1109 1110 return isl_bool_true;1111}1112 1113/* Reset the user pointer on all identifiers of parameters and tuples1114 * of the space of "map".1115 */1116__isl_give isl_map *isl_map_reset_user(__isl_take isl_map *map)1117{1118 isl_space *space;1119 1120 space = isl_map_get_space(map);1121 space = isl_space_reset_user(space);1122 map = isl_map_reset_space(map, space);1123 1124 return map;1125}1126 1127/* Reset the user pointer on all identifiers of parameters and tuples1128 * of the space of "set".1129 */1130__isl_give isl_set *isl_set_reset_user(__isl_take isl_set *set)1131{1132 return isl_map_reset_user(set);1133}1134 1135isl_bool isl_basic_map_is_rational(__isl_keep isl_basic_map *bmap)1136{1137 if (!bmap)1138 return isl_bool_error;1139 return ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL);1140}1141 1142/* Has "map" been marked as a rational map?1143 * In particular, have all basic maps in "map" been marked this way?1144 * An empty map is not considered to be rational.1145 * Maps where only some of the basic maps are marked rational1146 * are not allowed.1147 */1148isl_bool isl_map_is_rational(__isl_keep isl_map *map)1149{1150 int i;1151 isl_bool rational;1152 1153 if (!map)1154 return isl_bool_error;1155 if (map->n == 0)1156 return isl_bool_false;1157 rational = isl_basic_map_is_rational(map->p[0]);1158 if (rational < 0)1159 return rational;1160 for (i = 1; i < map->n; ++i) {1161 isl_bool rational_i;1162 1163 rational_i = isl_basic_map_is_rational(map->p[i]);1164 if (rational_i < 0)1165 return rational_i;1166 if (rational != rational_i)1167 isl_die(isl_map_get_ctx(map), isl_error_unsupported,1168 "mixed rational and integer basic maps "1169 "not supported", return isl_bool_error);1170 }1171 1172 return rational;1173}1174 1175/* Has "set" been marked as a rational set?1176 * In particular, have all basic set in "set" been marked this way?1177 * An empty set is not considered to be rational.1178 * Sets where only some of the basic sets are marked rational1179 * are not allowed.1180 */1181isl_bool isl_set_is_rational(__isl_keep isl_set *set)1182{1183 return isl_map_is_rational(set);1184}1185 1186int isl_basic_set_is_rational(__isl_keep isl_basic_set *bset)1187{1188 return isl_basic_map_is_rational(bset);1189}1190 1191/* Does "bmap" contain any rational points?1192 *1193 * If "bmap" has an equality for each dimension, equating the dimension1194 * to an integer constant, then it has no rational points, even if it1195 * is marked as rational.1196 */1197isl_bool isl_basic_map_has_rational(__isl_keep isl_basic_map *bmap)1198{1199 isl_bool has_rational = isl_bool_true;1200 isl_size total;1201 1202 if (!bmap)1203 return isl_bool_error;1204 if (isl_basic_map_plain_is_empty(bmap))1205 return isl_bool_false;1206 if (!isl_basic_map_is_rational(bmap))1207 return isl_bool_false;1208 bmap = isl_basic_map_copy(bmap);1209 bmap = isl_basic_map_implicit_equalities(bmap);1210 total = isl_basic_map_dim(bmap, isl_dim_all);1211 if (total < 0)1212 return isl_bool_error;1213 if (bmap->n_eq == total) {1214 int i, j;1215 for (i = 0; i < bmap->n_eq; ++i) {1216 j = isl_seq_first_non_zero(bmap->eq[i] + 1, total);1217 if (j < 0)1218 break;1219 if (!isl_int_is_one(bmap->eq[i][1 + j]) &&1220 !isl_int_is_negone(bmap->eq[i][1 + j]))1221 break;1222 j = isl_seq_first_non_zero(bmap->eq[i] + 1 + j + 1,1223 total - j - 1);1224 if (j >= 0)1225 break;1226 }1227 if (i == bmap->n_eq)1228 has_rational = isl_bool_false;1229 }1230 isl_basic_map_free(bmap);1231 1232 return has_rational;1233}1234 1235/* Does "map" contain any rational points?1236 */1237isl_bool isl_map_has_rational(__isl_keep isl_map *map)1238{1239 int i;1240 isl_bool has_rational;1241 1242 if (!map)1243 return isl_bool_error;1244 for (i = 0; i < map->n; ++i) {1245 has_rational = isl_basic_map_has_rational(map->p[i]);1246 if (has_rational < 0 || has_rational)1247 return has_rational;1248 }1249 return isl_bool_false;1250}1251 1252/* Does "set" contain any rational points?1253 */1254isl_bool isl_set_has_rational(__isl_keep isl_set *set)1255{1256 return isl_map_has_rational(set);1257}1258 1259/* Is this basic set a parameter domain?1260 */1261isl_bool isl_basic_set_is_params(__isl_keep isl_basic_set *bset)1262{1263 if (!bset)1264 return isl_bool_error;1265 return isl_space_is_params(bset->dim);1266}1267 1268/* Is this set a parameter domain?1269 */1270isl_bool isl_set_is_params(__isl_keep isl_set *set)1271{1272 if (!set)1273 return isl_bool_error;1274 return isl_space_is_params(set->dim);1275}1276 1277/* Is this map actually a parameter domain?1278 * Users should never call this function. Outside of isl,1279 * a map can never be a parameter domain.1280 */1281isl_bool isl_map_is_params(__isl_keep isl_map *map)1282{1283 if (!map)1284 return isl_bool_error;1285 return isl_space_is_params(map->dim);1286}1287 1288static __isl_give isl_basic_map *basic_map_init(isl_ctx *ctx,1289 __isl_take isl_basic_map *bmap, unsigned extra,1290 unsigned n_eq, unsigned n_ineq)1291{1292 int i;1293 isl_space *space = isl_basic_map_peek_space(bmap);1294 isl_size n_var = isl_space_dim(space, isl_dim_all);1295 size_t row_size = 1 + n_var + extra;1296 1297 bmap->ctx = ctx;1298 isl_ctx_ref(ctx);1299 1300 if (n_var < 0)1301 return isl_basic_map_free(bmap);1302 1303 bmap->block = isl_blk_alloc(ctx, (n_ineq + n_eq) * row_size);1304 if (isl_blk_is_error(bmap->block))1305 goto error;1306 1307 bmap->ineq = isl_alloc_array(ctx, isl_int *, n_ineq + n_eq);1308 if ((n_ineq + n_eq) && !bmap->ineq)1309 goto error;1310 1311 if (extra == 0) {1312 bmap->block2 = isl_blk_empty();1313 bmap->div = NULL;1314 } else {1315 bmap->block2 = isl_blk_alloc(ctx, extra * (1 + row_size));1316 if (isl_blk_is_error(bmap->block2))1317 goto error;1318 1319 bmap->div = isl_alloc_array(ctx, isl_int *, extra);1320 if (!bmap->div)1321 goto error;1322 }1323 1324 for (i = 0; i < n_ineq + n_eq; ++i)1325 bmap->ineq[i] = bmap->block.data + i * row_size;1326 1327 for (i = 0; i < extra; ++i)1328 bmap->div[i] = bmap->block2.data + i * (1 + row_size);1329 1330 bmap->ref = 1;1331 bmap->flags = 0;1332 bmap->c_size = n_eq + n_ineq;1333 bmap->eq = bmap->ineq + n_ineq;1334 bmap->extra = extra;1335 bmap->n_eq = 0;1336 bmap->n_ineq = 0;1337 bmap->n_div = 0;1338 bmap->sample = NULL;1339 1340 return bmap;1341error:1342 isl_basic_map_free(bmap);1343 return NULL;1344}1345 1346__isl_give isl_basic_set *isl_basic_set_alloc(isl_ctx *ctx,1347 unsigned nparam, unsigned dim, unsigned extra,1348 unsigned n_eq, unsigned n_ineq)1349{1350 struct isl_basic_map *bmap;1351 isl_space *space;1352 1353 space = isl_space_set_alloc(ctx, nparam, dim);1354 if (!space)1355 return NULL;1356 1357 bmap = isl_basic_map_alloc_space(space, extra, n_eq, n_ineq);1358 return bset_from_bmap(bmap);1359}1360 1361__isl_give isl_basic_set *isl_basic_set_alloc_space(__isl_take isl_space *space,1362 unsigned extra, unsigned n_eq, unsigned n_ineq)1363{1364 struct isl_basic_map *bmap;1365 if (!space)1366 return NULL;1367 isl_assert(space->ctx, space->n_in == 0, goto error);1368 bmap = isl_basic_map_alloc_space(space, extra, n_eq, n_ineq);1369 return bset_from_bmap(bmap);1370error:1371 isl_space_free(space);1372 return NULL;1373}1374 1375__isl_give isl_basic_map *isl_basic_map_alloc_space(__isl_take isl_space *space,1376 unsigned extra, unsigned n_eq, unsigned n_ineq)1377{1378 struct isl_basic_map *bmap;1379 1380 if (!space)1381 return NULL;1382 bmap = isl_calloc_type(space->ctx, struct isl_basic_map);1383 if (!bmap)1384 goto error;1385 bmap->dim = space;1386 1387 return basic_map_init(space->ctx, bmap, extra, n_eq, n_ineq);1388error:1389 isl_space_free(space);1390 return NULL;1391}1392 1393__isl_give isl_basic_map *isl_basic_map_alloc(isl_ctx *ctx,1394 unsigned nparam, unsigned in, unsigned out, unsigned extra,1395 unsigned n_eq, unsigned n_ineq)1396{1397 struct isl_basic_map *bmap;1398 isl_space *space;1399 1400 space = isl_space_alloc(ctx, nparam, in, out);1401 if (!space)1402 return NULL;1403 1404 bmap = isl_basic_map_alloc_space(space, extra, n_eq, n_ineq);1405 return bmap;1406}1407 1408static __isl_give isl_basic_map *dup_constraints(__isl_take isl_basic_map *dst,1409 __isl_keep isl_basic_map *src)1410{1411 int i;1412 isl_size total = isl_basic_map_dim(src, isl_dim_all);1413 1414 if (!dst || total < 0)1415 return isl_basic_map_free(dst);1416 1417 for (i = 0; i < src->n_eq; ++i) {1418 int j = isl_basic_map_alloc_equality(dst);1419 if (j < 0)1420 return isl_basic_map_free(dst);1421 isl_seq_cpy(dst->eq[j], src->eq[i], 1+total);1422 }1423 1424 for (i = 0; i < src->n_ineq; ++i) {1425 int j = isl_basic_map_alloc_inequality(dst);1426 if (j < 0)1427 return isl_basic_map_free(dst);1428 isl_seq_cpy(dst->ineq[j], src->ineq[i], 1+total);1429 }1430 1431 for (i = 0; i < src->n_div; ++i) {1432 int j = isl_basic_map_alloc_div(dst);1433 if (j < 0)1434 return isl_basic_map_free(dst);1435 isl_seq_cpy(dst->div[j], src->div[i], 1+1+total);1436 }1437 ISL_F_SET(dst, ISL_BASIC_SET_FINAL);1438 return dst;1439}1440 1441__isl_give isl_basic_map *isl_basic_map_dup(__isl_keep isl_basic_map *bmap)1442{1443 struct isl_basic_map *dup;1444 1445 if (!bmap)1446 return NULL;1447 dup = isl_basic_map_alloc_space(isl_space_copy(bmap->dim),1448 bmap->n_div, bmap->n_eq, bmap->n_ineq);1449 dup = dup_constraints(dup, bmap);1450 if (!dup)1451 return NULL;1452 dup->flags = bmap->flags;1453 dup->sample = isl_vec_copy(bmap->sample);1454 return dup;1455}1456 1457__isl_give isl_basic_set *isl_basic_set_dup(__isl_keep isl_basic_set *bset)1458{1459 struct isl_basic_map *dup;1460 1461 dup = isl_basic_map_dup(bset_to_bmap(bset));1462 return bset_from_bmap(dup);1463}1464 1465__isl_give isl_basic_set *isl_basic_set_copy(__isl_keep isl_basic_set *bset)1466{1467 return bset_from_bmap(isl_basic_map_copy(bset_to_bmap(bset)));1468}1469 1470__isl_give isl_set *isl_set_copy(__isl_keep isl_set *set)1471{1472 if (!set)1473 return NULL;1474 1475 set->ref++;1476 return set;1477}1478 1479__isl_give isl_basic_map *isl_basic_map_copy(__isl_keep isl_basic_map *bmap)1480{1481 if (!bmap)1482 return NULL;1483 1484 if (ISL_F_ISSET(bmap, ISL_BASIC_SET_FINAL)) {1485 bmap->ref++;1486 return bmap;1487 }1488 bmap = isl_basic_map_dup(bmap);1489 if (bmap)1490 ISL_F_SET(bmap, ISL_BASIC_SET_FINAL);1491 return bmap;1492}1493 1494__isl_give isl_map *isl_map_copy(__isl_keep isl_map *map)1495{1496 if (!map)1497 return NULL;1498 1499 map->ref++;1500 return map;1501}1502 1503__isl_null isl_basic_map *isl_basic_map_free(__isl_take isl_basic_map *bmap)1504{1505 if (!bmap)1506 return NULL;1507 1508 if (--bmap->ref > 0)1509 return NULL;1510 1511 isl_ctx_deref(bmap->ctx);1512 free(bmap->div);1513 isl_blk_free(bmap->ctx, bmap->block2);1514 free(bmap->ineq);1515 isl_blk_free(bmap->ctx, bmap->block);1516 isl_vec_free(bmap->sample);1517 isl_space_free(bmap->dim);1518 free(bmap);1519 1520 return NULL;1521}1522 1523__isl_null isl_basic_set *isl_basic_set_free(__isl_take isl_basic_set *bset)1524{1525 return isl_basic_map_free(bset_to_bmap(bset));1526}1527 1528static int room_for_con(__isl_keep isl_basic_map *bmap, unsigned n)1529{1530 return bmap->n_eq + bmap->n_ineq + n <= bmap->c_size;1531}1532 1533/* Check that "bset" does not involve any parameters.1534 */1535isl_stat isl_basic_set_check_no_params(__isl_keep isl_basic_set *bset)1536{1537 isl_size nparam;1538 1539 nparam = isl_basic_set_dim(bset, isl_dim_param);1540 if (nparam < 0)1541 return isl_stat_error;1542 if (nparam != 0)1543 isl_die(isl_basic_set_get_ctx(bset), isl_error_invalid,1544 "basic set should not have any parameters",1545 return isl_stat_error);1546 return isl_stat_ok;1547}1548 1549/* Check that "bset" does not involve any local variables.1550 */1551isl_stat isl_basic_set_check_no_locals(__isl_keep isl_basic_set *bset)1552{1553 isl_size n_div;1554 1555 n_div = isl_basic_set_dim(bset, isl_dim_div);1556 if (n_div < 0)1557 return isl_stat_error;1558 if (n_div != 0)1559 isl_die(isl_basic_set_get_ctx(bset), isl_error_invalid,1560 "basic set should not have any local variables",1561 return isl_stat_error);1562 return isl_stat_ok;1563}1564 1565#undef TYPE1566#define TYPE isl_map1567 1568#include "isl_check_named_params_templ.c"1569 1570#undef TYPE1571#define TYPE isl_basic_map1572 1573static1574#include "isl_check_named_params_templ.c"1575 1576/* Check that "bmap1" and "bmap2" have the same parameters,1577 * reporting an error if they do not.1578 */1579static isl_stat isl_basic_map_check_equal_params(1580 __isl_keep isl_basic_map *bmap1, __isl_keep isl_basic_map *bmap2)1581{1582 isl_bool match;1583 1584 match = isl_basic_map_has_equal_params(bmap1, bmap2);1585 if (match < 0)1586 return isl_stat_error;1587 if (!match)1588 isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,1589 "parameters don't match", return isl_stat_error);1590 return isl_stat_ok;1591}1592 1593#undef TYPE1594#define TYPE isl_map1595 1596#include "isl_align_params_bin_templ.c"1597 1598#undef SUFFIX1599#define SUFFIX set1600#undef ARG11601#define ARG1 isl_map1602#undef ARG21603#define ARG2 isl_set1604 1605#include "isl_align_params_templ.c"1606 1607isl_bool isl_map_align_params_map_map_and_test(__isl_keep isl_map *map1,1608 __isl_keep isl_map *map2,1609 isl_bool (*fn)(__isl_keep isl_map *map1, __isl_keep isl_map *map2))1610{1611 isl_bool r;1612 1613 if (!map1 || !map2)1614 return isl_bool_error;1615 if (isl_map_has_equal_params(map1, map2))1616 return fn(map1, map2);1617 if (isl_map_check_named_params(map1) < 0)1618 return isl_bool_error;1619 if (isl_map_check_named_params(map2) < 0)1620 return isl_bool_error;1621 map1 = isl_map_copy(map1);1622 map2 = isl_map_copy(map2);1623 map1 = isl_map_align_params(map1, isl_map_get_space(map2));1624 map2 = isl_map_align_params(map2, isl_map_get_space(map1));1625 r = fn(map1, map2);1626 isl_map_free(map1);1627 isl_map_free(map2);1628 return r;1629}1630 1631int isl_basic_map_alloc_equality(__isl_keep isl_basic_map *bmap)1632{1633 isl_size total;1634 struct isl_ctx *ctx;1635 1636 total = isl_basic_map_dim(bmap, isl_dim_all);1637 if (total < 0)1638 return -1;1639 ctx = bmap->ctx;1640 isl_assert(ctx, room_for_con(bmap, 1), return -1);1641 isl_assert(ctx, (bmap->eq - bmap->ineq) + bmap->n_eq <= bmap->c_size,1642 return -1);1643 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);1644 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_IMPLICIT);1645 ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES);1646 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);1647 if ((bmap->eq - bmap->ineq) + bmap->n_eq == bmap->c_size) {1648 isl_int *t;1649 int j = isl_basic_map_alloc_inequality(bmap);1650 if (j < 0)1651 return -1;1652 t = bmap->ineq[j];1653 bmap->ineq[j] = bmap->ineq[bmap->n_ineq - 1];1654 bmap->ineq[bmap->n_ineq - 1] = bmap->eq[-1];1655 bmap->eq[-1] = t;1656 bmap->n_eq++;1657 bmap->n_ineq--;1658 bmap->eq--;1659 return 0;1660 }1661 isl_seq_clr(bmap->eq[bmap->n_eq] + 1 + total,1662 bmap->extra - bmap->n_div);1663 return bmap->n_eq++;1664}1665 1666int isl_basic_set_alloc_equality(__isl_keep isl_basic_set *bset)1667{1668 return isl_basic_map_alloc_equality(bset_to_bmap(bset));1669}1670 1671__isl_give isl_basic_map *isl_basic_map_free_equality(1672 __isl_take isl_basic_map *bmap, unsigned n)1673{1674 if (!bmap)1675 return NULL;1676 if (n > bmap->n_eq)1677 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,1678 "invalid number of equalities",1679 isl_basic_map_free(bmap));1680 bmap->n_eq -= n;1681 return bmap;1682}1683 1684__isl_give isl_basic_set *isl_basic_set_free_equality(1685 __isl_take isl_basic_set *bset, unsigned n)1686{1687 return bset_from_bmap(isl_basic_map_free_equality(bset_to_bmap(bset),1688 n));1689}1690 1691/* Drop the equality constraint at position "pos",1692 * preserving the order of the other equality constraints.1693 */1694int isl_basic_map_drop_equality(__isl_keep isl_basic_map *bmap, unsigned pos)1695{1696 isl_int *t;1697 int r;1698 1699 if (!bmap)1700 return -1;1701 isl_assert(bmap->ctx, pos < bmap->n_eq, return -1);1702 1703 t = bmap->eq[pos];1704 bmap->n_eq--;1705 for (r = pos; r < bmap->n_eq; ++r)1706 bmap->eq[r] = bmap->eq[r + 1];1707 bmap->eq[bmap->n_eq] = t;1708 1709 return 0;1710}1711 1712/* Turn inequality "pos" of "bmap" into an equality.1713 *1714 * In particular, we move the inequality in front of the equalities1715 * and move the last inequality in the position of the moved inequality.1716 * Note that isl_tab_make_equalities_explicit depends on this particular1717 * change in the ordering of the constraints.1718 */1719void isl_basic_map_inequality_to_equality(1720 __isl_keep isl_basic_map *bmap, unsigned pos)1721{1722 isl_int *t;1723 1724 t = bmap->ineq[pos];1725 bmap->ineq[pos] = bmap->ineq[bmap->n_ineq - 1];1726 bmap->ineq[bmap->n_ineq - 1] = bmap->eq[-1];1727 bmap->eq[-1] = t;1728 bmap->n_eq++;1729 bmap->n_ineq--;1730 bmap->eq--;1731 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);1732 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);1733 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);1734 ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES);1735}1736 1737static int room_for_ineq(__isl_keep isl_basic_map *bmap, unsigned n)1738{1739 return bmap->n_ineq + n <= bmap->eq - bmap->ineq;1740}1741 1742int isl_basic_map_alloc_inequality(__isl_keep isl_basic_map *bmap)1743{1744 isl_size total;1745 struct isl_ctx *ctx;1746 1747 total = isl_basic_map_dim(bmap, isl_dim_all);1748 if (total < 0)1749 return -1;1750 ctx = bmap->ctx;1751 isl_assert(ctx, room_for_ineq(bmap, 1), return -1);1752 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_IMPLICIT);1753 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);1754 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);1755 ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES);1756 isl_seq_clr(bmap->ineq[bmap->n_ineq] + 1 + total,1757 bmap->extra - bmap->n_div);1758 return bmap->n_ineq++;1759}1760 1761int isl_basic_set_alloc_inequality(__isl_keep isl_basic_set *bset)1762{1763 return isl_basic_map_alloc_inequality(bset_to_bmap(bset));1764}1765 1766__isl_give isl_basic_map *isl_basic_map_free_inequality(1767 __isl_take isl_basic_map *bmap, unsigned n)1768{1769 if (!bmap)1770 return NULL;1771 if (n > bmap->n_ineq)1772 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,1773 "invalid number of inequalities",1774 return isl_basic_map_free(bmap));1775 bmap->n_ineq -= n;1776 return bmap;1777}1778 1779__isl_give isl_basic_set *isl_basic_set_free_inequality(1780 __isl_take isl_basic_set *bset, unsigned n)1781{1782 return bset_from_bmap(isl_basic_map_free_inequality(bset_to_bmap(bset),1783 n));1784}1785 1786int isl_basic_map_drop_inequality(__isl_keep isl_basic_map *bmap, unsigned pos)1787{1788 isl_int *t;1789 if (!bmap)1790 return -1;1791 isl_assert(bmap->ctx, pos < bmap->n_ineq, return -1);1792 1793 if (pos != bmap->n_ineq - 1) {1794 t = bmap->ineq[pos];1795 bmap->ineq[pos] = bmap->ineq[bmap->n_ineq - 1];1796 bmap->ineq[bmap->n_ineq - 1] = t;1797 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);1798 }1799 bmap->n_ineq--;1800 return 0;1801}1802 1803int isl_basic_set_drop_inequality(__isl_keep isl_basic_set *bset, unsigned pos)1804{1805 return isl_basic_map_drop_inequality(bset_to_bmap(bset), pos);1806}1807 1808__isl_give isl_basic_map *isl_basic_map_add_eq(__isl_take isl_basic_map *bmap,1809 isl_int *eq)1810{1811 isl_bool empty;1812 isl_size total;1813 int k;1814 1815 empty = isl_basic_map_plain_is_empty(bmap);1816 if (empty < 0)1817 return isl_basic_map_free(bmap);1818 if (empty)1819 return bmap;1820 1821 bmap = isl_basic_map_cow(bmap);1822 bmap = isl_basic_map_extend_constraints(bmap, 1, 0);1823 total = isl_basic_map_dim(bmap, isl_dim_all);1824 if (total < 0)1825 return isl_basic_map_free(bmap);1826 k = isl_basic_map_alloc_equality(bmap);1827 if (k < 0)1828 goto error;1829 isl_seq_cpy(bmap->eq[k], eq, 1 + total);1830 return bmap;1831error:1832 isl_basic_map_free(bmap);1833 return NULL;1834}1835 1836__isl_give isl_basic_set *isl_basic_set_add_eq(__isl_take isl_basic_set *bset,1837 isl_int *eq)1838{1839 return bset_from_bmap(isl_basic_map_add_eq(bset_to_bmap(bset), eq));1840}1841 1842__isl_give isl_basic_map *isl_basic_map_add_ineq(__isl_take isl_basic_map *bmap,1843 isl_int *ineq)1844{1845 isl_size total;1846 int k;1847 1848 bmap = isl_basic_map_cow(bmap);1849 bmap = isl_basic_map_extend_constraints(bmap, 0, 1);1850 total = isl_basic_map_dim(bmap, isl_dim_all);1851 if (total < 0)1852 return isl_basic_map_free(bmap);1853 k = isl_basic_map_alloc_inequality(bmap);1854 if (k < 0)1855 goto error;1856 isl_seq_cpy(bmap->ineq[k], ineq, 1 + total);1857 return bmap;1858error:1859 isl_basic_map_free(bmap);1860 return NULL;1861}1862 1863__isl_give isl_basic_set *isl_basic_set_add_ineq(__isl_take isl_basic_set *bset,1864 isl_int *ineq)1865{1866 return bset_from_bmap(isl_basic_map_add_ineq(bset_to_bmap(bset), ineq));1867}1868 1869int isl_basic_map_alloc_div(__isl_keep isl_basic_map *bmap)1870{1871 isl_size total;1872 1873 total = isl_basic_map_dim(bmap, isl_dim_all);1874 if (total < 0)1875 return -1;1876 isl_assert(bmap->ctx, bmap->n_div < bmap->extra, return -1);1877 isl_seq_clr(bmap->div[bmap->n_div] + 1 + 1 + total,1878 bmap->extra - bmap->n_div);1879 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);1880 return bmap->n_div++;1881}1882 1883int isl_basic_set_alloc_div(__isl_keep isl_basic_set *bset)1884{1885 return isl_basic_map_alloc_div(bset_to_bmap(bset));1886}1887 1888#undef TYPE1889#define TYPE isl_basic_map1890#include "check_type_range_templ.c"1891 1892/* Check that there are "n" dimensions of type "type" starting at "first"1893 * in "bset".1894 */1895isl_stat isl_basic_set_check_range(__isl_keep isl_basic_set *bset,1896 enum isl_dim_type type, unsigned first, unsigned n)1897{1898 return isl_basic_map_check_range(bset_to_bmap(bset),1899 type, first, n);1900}1901 1902/* Insert an extra integer division, prescribed by "div", to "bmap"1903 * at (integer division) position "pos".1904 *1905 * The integer division is first added at the end and then moved1906 * into the right position.1907 */1908__isl_give isl_basic_map *isl_basic_map_insert_div(1909 __isl_take isl_basic_map *bmap, int pos, __isl_keep isl_vec *div)1910{1911 int i, k;1912 isl_size total;1913 1914 bmap = isl_basic_map_cow(bmap);1915 total = isl_basic_map_dim(bmap, isl_dim_all);1916 if (total < 0 || !div)1917 return isl_basic_map_free(bmap);1918 1919 if (div->size != 1 + 1 + total)1920 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,1921 "unexpected size", return isl_basic_map_free(bmap));1922 if (isl_basic_map_check_range(bmap, isl_dim_div, pos, 0) < 0)1923 return isl_basic_map_free(bmap);1924 1925 bmap = isl_basic_map_extend(bmap, 1, 0, 2);1926 k = isl_basic_map_alloc_div(bmap);1927 if (k < 0)1928 return isl_basic_map_free(bmap);1929 isl_seq_cpy(bmap->div[k], div->el, div->size);1930 isl_int_set_si(bmap->div[k][div->size], 0);1931 1932 for (i = k; i > pos; --i)1933 bmap = isl_basic_map_swap_div(bmap, i, i - 1);1934 1935 return bmap;1936}1937 1938isl_stat isl_basic_map_free_div(__isl_keep isl_basic_map *bmap, unsigned n)1939{1940 if (!bmap)1941 return isl_stat_error;1942 isl_assert(bmap->ctx, n <= bmap->n_div, return isl_stat_error);1943 bmap->n_div -= n;1944 return isl_stat_ok;1945}1946 1947static __isl_give isl_basic_map *add_constraints(1948 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2,1949 unsigned i_pos, unsigned o_pos)1950{1951 isl_size total, n_param, n_in, n_out, n_div;1952 unsigned o_in, o_out;1953 isl_ctx *ctx;1954 isl_space *space;1955 struct isl_dim_map *dim_map;1956 1957 space = isl_basic_map_peek_space(bmap2);1958 if (!bmap1 || !space)1959 goto error;1960 1961 total = isl_basic_map_dim(bmap1, isl_dim_all);1962 n_param = isl_basic_map_dim(bmap2, isl_dim_param);1963 n_in = isl_basic_map_dim(bmap2, isl_dim_in);1964 o_in = isl_basic_map_offset(bmap1, isl_dim_in) - 1 + i_pos;1965 n_out = isl_basic_map_dim(bmap2, isl_dim_out);1966 o_out = isl_basic_map_offset(bmap1, isl_dim_out) - 1 + o_pos;1967 n_div = isl_basic_map_dim(bmap2, isl_dim_div);1968 if (total < 0 || n_param < 0 || n_in < 0 || n_out < 0 || n_div < 0)1969 goto error;1970 ctx = isl_basic_map_get_ctx(bmap1);1971 dim_map = isl_dim_map_alloc(ctx, total + n_div);1972 isl_dim_map_dim_range(dim_map, space, isl_dim_param, 0, n_param, 0);1973 isl_dim_map_dim_range(dim_map, space, isl_dim_in, 0, n_in, o_in);1974 isl_dim_map_dim_range(dim_map, space, isl_dim_out, 0, n_out, o_out);1975 isl_dim_map_div(dim_map, bmap2, total);1976 1977 return isl_basic_map_add_constraints_dim_map(bmap1, bmap2, dim_map);1978error:1979 isl_basic_map_free(bmap1);1980 isl_basic_map_free(bmap2);1981 return NULL;1982}1983 1984__isl_give isl_basic_map *isl_basic_map_extend(__isl_take isl_basic_map *base,1985 unsigned extra, unsigned n_eq, unsigned n_ineq)1986{1987 isl_space *space;1988 struct isl_basic_map *ext;1989 unsigned flags;1990 int dims_ok;1991 1992 if (!base)1993 goto error;1994 1995 dims_ok = base->extra >= base->n_div + extra;1996 1997 if (dims_ok && room_for_con(base, n_eq + n_ineq) &&1998 room_for_ineq(base, n_ineq))1999 return base;2000 2001 extra += base->extra;2002 n_eq += base->n_eq;2003 n_ineq += base->n_ineq;2004 2005 space = isl_basic_map_get_space(base);2006 ext = isl_basic_map_alloc_space(space, extra, n_eq, n_ineq);2007 if (!ext)2008 goto error;2009 2010 if (dims_ok)2011 ext->sample = isl_vec_copy(base->sample);2012 flags = base->flags;2013 ext = add_constraints(ext, base, 0, 0);2014 if (ext) {2015 ext->flags = flags;2016 ISL_F_CLR(ext, ISL_BASIC_SET_FINAL);2017 }2018 2019 return ext;2020 2021error:2022 isl_basic_map_free(base);2023 return NULL;2024}2025 2026__isl_give isl_basic_set *isl_basic_set_extend(__isl_take isl_basic_set *base,2027 unsigned extra, unsigned n_eq, unsigned n_ineq)2028{2029 return bset_from_bmap(isl_basic_map_extend(bset_to_bmap(base),2030 extra, n_eq, n_ineq));2031}2032 2033__isl_give isl_basic_map *isl_basic_map_extend_constraints(2034 __isl_take isl_basic_map *base, unsigned n_eq, unsigned n_ineq)2035{2036 return isl_basic_map_extend(base, 0, n_eq, n_ineq);2037}2038 2039__isl_give isl_basic_set *isl_basic_set_extend_constraints(2040 __isl_take isl_basic_set *base, unsigned n_eq, unsigned n_ineq)2041{2042 isl_basic_map *bmap = bset_to_bmap(base);2043 bmap = isl_basic_map_extend_constraints(bmap, n_eq, n_ineq);2044 return bset_from_bmap(bmap);2045}2046 2047__isl_give isl_basic_set *isl_basic_set_cow(__isl_take isl_basic_set *bset)2048{2049 return bset_from_bmap(isl_basic_map_cow(bset_to_bmap(bset)));2050}2051 2052__isl_give isl_basic_map *isl_basic_map_cow(__isl_take isl_basic_map *bmap)2053{2054 if (!bmap)2055 return NULL;2056 2057 if (bmap->ref > 1) {2058 bmap->ref--;2059 bmap = isl_basic_map_dup(bmap);2060 }2061 if (bmap) {2062 ISL_F_CLR(bmap, ISL_BASIC_SET_FINAL);2063 ISL_F_CLR(bmap, ISL_BASIC_MAP_REDUCED_COEFFICIENTS);2064 }2065 return bmap;2066}2067 2068/* Clear all cached information in "map", either because it is about2069 * to be modified or because it is being freed.2070 * Always return the same pointer that is passed in.2071 * This is needed for the use in isl_map_free.2072 */2073static __isl_give isl_map *clear_caches(__isl_take isl_map *map)2074{2075 isl_basic_map_free(map->cached_simple_hull[0]);2076 isl_basic_map_free(map->cached_simple_hull[1]);2077 map->cached_simple_hull[0] = NULL;2078 map->cached_simple_hull[1] = NULL;2079 return map;2080}2081 2082__isl_give isl_set *isl_set_cow(__isl_take isl_set *set)2083{2084 return isl_map_cow(set);2085}2086 2087/* Return an isl_map that is equal to "map" and that has only2088 * a single reference.2089 *2090 * If the original input already has only one reference, then2091 * simply return it, but clear all cached information, since2092 * it may be rendered invalid by the operations that will be2093 * performed on the result.2094 *2095 * Otherwise, create a duplicate (without any cached information).2096 */2097__isl_give isl_map *isl_map_cow(__isl_take isl_map *map)2098{2099 if (!map)2100 return NULL;2101 2102 if (map->ref == 1)2103 return clear_caches(map);2104 map->ref--;2105 return isl_map_dup(map);2106}2107 2108static void swap_vars(struct isl_blk blk, isl_int *a,2109 unsigned a_len, unsigned b_len)2110{2111 isl_seq_cpy(blk.data, a+a_len, b_len);2112 isl_seq_cpy(blk.data+b_len, a, a_len);2113 isl_seq_cpy(a, blk.data, b_len+a_len);2114}2115 2116static __isl_give isl_basic_map *isl_basic_map_swap_vars(2117 __isl_take isl_basic_map *bmap, unsigned pos, unsigned n1, unsigned n2)2118{2119 int i;2120 struct isl_blk blk;2121 2122 if (isl_basic_map_check_range(bmap, isl_dim_all, pos - 1, n1 + n2) < 0)2123 goto error;2124 2125 if (n1 == 0 || n2 == 0)2126 return bmap;2127 2128 bmap = isl_basic_map_cow(bmap);2129 if (!bmap)2130 return NULL;2131 2132 blk = isl_blk_alloc(bmap->ctx, n1 + n2);2133 if (isl_blk_is_error(blk))2134 goto error;2135 2136 for (i = 0; i < bmap->n_eq; ++i)2137 swap_vars(blk,2138 bmap->eq[i] + pos, n1, n2);2139 2140 for (i = 0; i < bmap->n_ineq; ++i)2141 swap_vars(blk,2142 bmap->ineq[i] + pos, n1, n2);2143 2144 for (i = 0; i < bmap->n_div; ++i)2145 swap_vars(blk,2146 bmap->div[i]+1 + pos, n1, n2);2147 2148 isl_blk_free(bmap->ctx, blk);2149 2150 ISL_F_CLR(bmap, ISL_BASIC_SET_SORTED);2151 bmap = isl_basic_map_gauss(bmap, NULL);2152 return isl_basic_map_finalize(bmap);2153error:2154 isl_basic_map_free(bmap);2155 return NULL;2156}2157 2158/* The given basic map has turned out to be empty.2159 * Explicitly mark it as such and change the representation2160 * to a canonical representation of the empty basic map.2161 * Since the basic map has conflicting constraints,2162 * it must have at least one constraint, except perhaps2163 * if it was already explicitly marked as being empty.2164 * Do nothing in the latter case, i.e., if it has been marked empty and2165 * has no constraints.2166 */2167__isl_give isl_basic_map *isl_basic_map_set_to_empty(2168 __isl_take isl_basic_map *bmap)2169{2170 int i = 0;2171 isl_bool empty;2172 isl_size n;2173 isl_size total;2174 2175 n = isl_basic_map_n_constraint(bmap);2176 empty = isl_basic_map_plain_is_empty(bmap);2177 if (n < 0 || empty < 0)2178 return isl_basic_map_free(bmap);2179 if (n == 0 && empty)2180 return bmap;2181 total = isl_basic_map_dim(bmap, isl_dim_all);2182 if (total < 0)2183 return isl_basic_map_free(bmap);2184 if (isl_basic_map_free_div(bmap, bmap->n_div) < 0)2185 return isl_basic_map_free(bmap);2186 bmap = isl_basic_map_free_inequality(bmap, bmap->n_ineq);2187 if (!bmap)2188 return NULL;2189 if (bmap->n_eq > 0) {2190 bmap = isl_basic_map_free_equality(bmap, bmap->n_eq - 1);2191 if (!bmap)2192 return NULL;2193 } else {2194 i = isl_basic_map_alloc_equality(bmap);2195 if (i < 0)2196 goto error;2197 }2198 isl_int_set_si(bmap->eq[i][0], 1);2199 isl_seq_clr(bmap->eq[i]+1, total);2200 ISL_F_SET(bmap, ISL_BASIC_MAP_EMPTY);2201 isl_vec_free(bmap->sample);2202 bmap->sample = NULL;2203 return isl_basic_map_finalize(bmap);2204error:2205 isl_basic_map_free(bmap);2206 return NULL;2207}2208 2209__isl_give isl_basic_set *isl_basic_set_set_to_empty(2210 __isl_take isl_basic_set *bset)2211{2212 return bset_from_bmap(isl_basic_map_set_to_empty(bset_to_bmap(bset)));2213}2214 2215__isl_give isl_basic_map *isl_basic_map_set_rational(2216 __isl_take isl_basic_map *bmap)2217{2218 if (!bmap)2219 return NULL;2220 2221 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL))2222 return bmap;2223 2224 bmap = isl_basic_map_cow(bmap);2225 if (!bmap)2226 return NULL;2227 2228 ISL_F_SET(bmap, ISL_BASIC_MAP_RATIONAL);2229 2230 return isl_basic_map_finalize(bmap);2231}2232 2233__isl_give isl_basic_set *isl_basic_set_set_rational(2234 __isl_take isl_basic_set *bset)2235{2236 return isl_basic_map_set_rational(bset);2237}2238 2239__isl_give isl_basic_set *isl_basic_set_set_integral(2240 __isl_take isl_basic_set *bset)2241{2242 if (!bset)2243 return NULL;2244 2245 if (!ISL_F_ISSET(bset, ISL_BASIC_MAP_RATIONAL))2246 return bset;2247 2248 bset = isl_basic_set_cow(bset);2249 if (!bset)2250 return NULL;2251 2252 ISL_F_CLR(bset, ISL_BASIC_MAP_RATIONAL);2253 2254 return isl_basic_set_finalize(bset);2255}2256 2257__isl_give isl_map *isl_map_set_rational(__isl_take isl_map *map)2258{2259 int i;2260 2261 map = isl_map_cow(map);2262 if (!map)2263 return NULL;2264 for (i = 0; i < map->n; ++i) {2265 map->p[i] = isl_basic_map_set_rational(map->p[i]);2266 if (!map->p[i])2267 goto error;2268 }2269 return map;2270error:2271 isl_map_free(map);2272 return NULL;2273}2274 2275__isl_give isl_set *isl_set_set_rational(__isl_take isl_set *set)2276{2277 return isl_map_set_rational(set);2278}2279 2280/* Swap divs "a" and "b" in "bmap" (without modifying any of the constraints2281 * of "bmap").2282 */2283static void swap_div(__isl_keep isl_basic_map *bmap, int a, int b)2284{2285 isl_int *t = bmap->div[a];2286 bmap->div[a] = bmap->div[b];2287 bmap->div[b] = t;2288}2289 2290/* Swap divs "a" and "b" in "bmap" and adjust the constraints and2291 * div definitions accordingly.2292 */2293__isl_give isl_basic_map *isl_basic_map_swap_div(__isl_take isl_basic_map *bmap,2294 int a, int b)2295{2296 int i;2297 isl_size off;2298 2299 off = isl_basic_map_var_offset(bmap, isl_dim_div);2300 if (off < 0)2301 return isl_basic_map_free(bmap);2302 2303 swap_div(bmap, a, b);2304 2305 for (i = 0; i < bmap->n_eq; ++i)2306 isl_int_swap(bmap->eq[i][1+off+a], bmap->eq[i][1+off+b]);2307 2308 for (i = 0; i < bmap->n_ineq; ++i)2309 isl_int_swap(bmap->ineq[i][1+off+a], bmap->ineq[i][1+off+b]);2310 2311 for (i = 0; i < bmap->n_div; ++i)2312 isl_int_swap(bmap->div[i][1+1+off+a], bmap->div[i][1+1+off+b]);2313 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);2314 2315 return bmap;2316}2317 2318static void constraint_drop_vars(isl_int *c, unsigned n, unsigned rem)2319{2320 isl_seq_cpy(c, c + n, rem);2321 isl_seq_clr(c + rem, n);2322}2323 2324/* Drop n dimensions starting at first.2325 *2326 * In principle, this frees up some extra variables as the number2327 * of columns remains constant, but we would have to extend2328 * the div array too as the number of rows in this array is assumed2329 * to be equal to extra.2330 */2331__isl_give isl_basic_set *isl_basic_set_drop_dims(2332 __isl_take isl_basic_set *bset, unsigned first, unsigned n)2333{2334 return isl_basic_map_drop(bset_to_bmap(bset), isl_dim_set, first, n);2335}2336 2337/* Move "n" divs starting at "first" to the end of the list of divs.2338 */2339static __isl_give isl_basic_map *move_divs_last(__isl_take isl_basic_map *bmap,2340 unsigned first, unsigned n)2341{2342 isl_int **div;2343 int i;2344 2345 if (first + n == bmap->n_div)2346 return bmap;2347 2348 div = isl_alloc_array(bmap->ctx, isl_int *, n);2349 if (!div)2350 goto error;2351 for (i = 0; i < n; ++i)2352 div[i] = bmap->div[first + i];2353 for (i = 0; i < bmap->n_div - first - n; ++i)2354 bmap->div[first + i] = bmap->div[first + n + i];2355 for (i = 0; i < n; ++i)2356 bmap->div[bmap->n_div - n + i] = div[i];2357 free(div);2358 return bmap;2359error:2360 isl_basic_map_free(bmap);2361 return NULL;2362}2363 2364#undef TYPE2365#define TYPE isl_map2366static2367#include "check_type_range_templ.c"2368 2369/* Check that there are "n" dimensions of type "type" starting at "first"2370 * in "set".2371 */2372isl_stat isl_set_check_range(__isl_keep isl_set *set,2373 enum isl_dim_type type, unsigned first, unsigned n)2374{2375 return isl_map_check_range(set_to_map(set), type, first, n);2376}2377 2378/* Drop "n" dimensions of type "type" starting at "first".2379 * Perform the core computation, without cowing or2380 * simplifying and finalizing the result.2381 *2382 * In principle, this frees up some extra variables as the number2383 * of columns remains constant, but we would have to extend2384 * the div array too as the number of rows in this array is assumed2385 * to be equal to extra.2386 */2387__isl_give isl_basic_map *isl_basic_map_drop_core(2388 __isl_take isl_basic_map *bmap, enum isl_dim_type type,2389 unsigned first, unsigned n)2390{2391 int i;2392 unsigned offset;2393 unsigned left;2394 isl_size total;2395 2396 if (isl_basic_map_check_range(bmap, type, first, n) < 0)2397 return isl_basic_map_free(bmap);2398 2399 total = isl_basic_map_dim(bmap, isl_dim_all);2400 if (total < 0)2401 return isl_basic_map_free(bmap);2402 2403 offset = isl_basic_map_offset(bmap, type) + first;2404 left = total - (offset - 1) - n;2405 for (i = 0; i < bmap->n_eq; ++i)2406 constraint_drop_vars(bmap->eq[i]+offset, n, left);2407 2408 for (i = 0; i < bmap->n_ineq; ++i)2409 constraint_drop_vars(bmap->ineq[i]+offset, n, left);2410 2411 for (i = 0; i < bmap->n_div; ++i)2412 constraint_drop_vars(bmap->div[i]+1+offset, n, left);2413 2414 if (type == isl_dim_div) {2415 bmap = move_divs_last(bmap, first, n);2416 if (!bmap)2417 return NULL;2418 if (isl_basic_map_free_div(bmap, n) < 0)2419 return isl_basic_map_free(bmap);2420 } else2421 bmap->dim = isl_space_drop_dims(bmap->dim, type, first, n);2422 if (!bmap->dim)2423 return isl_basic_map_free(bmap);2424 2425 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);2426 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);2427 return bmap;2428}2429 2430/* Drop "n" dimensions of type "type" starting at "first".2431 *2432 * In principle, this frees up some extra variables as the number2433 * of columns remains constant, but we would have to extend2434 * the div array too as the number of rows in this array is assumed2435 * to be equal to extra.2436 */2437__isl_give isl_basic_map *isl_basic_map_drop(__isl_take isl_basic_map *bmap,2438 enum isl_dim_type type, unsigned first, unsigned n)2439{2440 if (!bmap)2441 return NULL;2442 if (n == 0 && !isl_space_is_named_or_nested(bmap->dim, type))2443 return bmap;2444 2445 bmap = isl_basic_map_cow(bmap);2446 if (!bmap)2447 return NULL;2448 2449 bmap = isl_basic_map_drop_core(bmap, type, first, n);2450 2451 bmap = isl_basic_map_simplify(bmap);2452 return isl_basic_map_finalize(bmap);2453}2454 2455__isl_give isl_basic_set *isl_basic_set_drop(__isl_take isl_basic_set *bset,2456 enum isl_dim_type type, unsigned first, unsigned n)2457{2458 return bset_from_bmap(isl_basic_map_drop(bset_to_bmap(bset),2459 type, first, n));2460}2461 2462/* No longer consider "map" to be normalized.2463 */2464static __isl_give isl_map *isl_map_unmark_normalized(__isl_take isl_map *map)2465{2466 if (!map)2467 return NULL;2468 ISL_F_CLR(map, ISL_MAP_NORMALIZED);2469 return map;2470}2471 2472__isl_give isl_map *isl_map_drop(__isl_take isl_map *map,2473 enum isl_dim_type type, unsigned first, unsigned n)2474{2475 int i;2476 isl_space *space;2477 2478 if (isl_map_check_range(map, type, first, n) < 0)2479 return isl_map_free(map);2480 2481 if (n == 0 && !isl_space_is_named_or_nested(map->dim, type))2482 return map;2483 map = isl_map_cow(map);2484 if (!map)2485 goto error;2486 2487 for (i = 0; i < map->n; ++i) {2488 map->p[i] = isl_basic_map_drop(map->p[i], type, first, n);2489 if (!map->p[i])2490 goto error;2491 }2492 map = isl_map_unmark_normalized(map);2493 2494 space = isl_map_take_space(map);2495 space = isl_space_drop_dims(space, type, first, n);2496 map = isl_map_restore_space(map, space);2497 2498 return map;2499error:2500 isl_map_free(map);2501 return NULL;2502}2503 2504__isl_give isl_set *isl_set_drop(__isl_take isl_set *set,2505 enum isl_dim_type type, unsigned first, unsigned n)2506{2507 return set_from_map(isl_map_drop(set_to_map(set), type, first, n));2508}2509 2510/* Drop the integer division at position "div", which is assumed2511 * not to appear in any of the constraints or2512 * in any of the other integer divisions.2513 *2514 * Since the integer division is redundant, there is no need to cow.2515 */2516__isl_give isl_basic_map *isl_basic_map_drop_div(2517 __isl_take isl_basic_map *bmap, unsigned div)2518{2519 return isl_basic_map_drop_core(bmap, isl_dim_div, div, 1);2520}2521 2522/* Eliminate the specified n dimensions starting at first from the2523 * constraints, without removing the dimensions from the space.2524 * If the set is rational, the dimensions are eliminated using Fourier-Motzkin.2525 */2526__isl_give isl_map *isl_map_eliminate(__isl_take isl_map *map,2527 enum isl_dim_type type, unsigned first, unsigned n)2528{2529 int i;2530 2531 if (n == 0)2532 return map;2533 2534 if (isl_map_check_range(map, type, first, n) < 0)2535 return isl_map_free(map);2536 2537 map = isl_map_cow(map);2538 if (!map)2539 return NULL;2540 2541 for (i = 0; i < map->n; ++i) {2542 map->p[i] = isl_basic_map_eliminate(map->p[i], type, first, n);2543 if (!map->p[i])2544 goto error;2545 }2546 return map;2547error:2548 isl_map_free(map);2549 return NULL;2550}2551 2552/* Eliminate the specified n dimensions starting at first from the2553 * constraints, without removing the dimensions from the space.2554 * If the set is rational, the dimensions are eliminated using Fourier-Motzkin.2555 */2556__isl_give isl_set *isl_set_eliminate(__isl_take isl_set *set,2557 enum isl_dim_type type, unsigned first, unsigned n)2558{2559 return set_from_map(isl_map_eliminate(set_to_map(set), type, first, n));2560}2561 2562/* Eliminate the specified n dimensions starting at first from the2563 * constraints, without removing the dimensions from the space.2564 * If the set is rational, the dimensions are eliminated using Fourier-Motzkin.2565 */2566__isl_give isl_set *isl_set_eliminate_dims(__isl_take isl_set *set,2567 unsigned first, unsigned n)2568{2569 return isl_set_eliminate(set, isl_dim_set, first, n);2570}2571 2572__isl_give isl_basic_map *isl_basic_map_remove_divs(2573 __isl_take isl_basic_map *bmap)2574{2575 isl_size v_div;2576 2577 v_div = isl_basic_map_var_offset(bmap, isl_dim_div);2578 if (v_div < 0)2579 return isl_basic_map_free(bmap);2580 bmap = isl_basic_map_eliminate_vars(bmap, v_div, bmap->n_div);2581 if (!bmap)2582 return NULL;2583 bmap->n_div = 0;2584 return isl_basic_map_finalize(bmap);2585}2586 2587__isl_give isl_basic_set *isl_basic_set_remove_divs(2588 __isl_take isl_basic_set *bset)2589{2590 return bset_from_bmap(isl_basic_map_remove_divs(bset_to_bmap(bset)));2591}2592 2593__isl_give isl_map *isl_map_remove_divs(__isl_take isl_map *map)2594{2595 int i;2596 2597 if (!map)2598 return NULL;2599 if (map->n == 0)2600 return map;2601 2602 map = isl_map_cow(map);2603 if (!map)2604 return NULL;2605 2606 for (i = 0; i < map->n; ++i) {2607 map->p[i] = isl_basic_map_remove_divs(map->p[i]);2608 if (!map->p[i])2609 goto error;2610 }2611 return map;2612error:2613 isl_map_free(map);2614 return NULL;2615}2616 2617__isl_give isl_set *isl_set_remove_divs(__isl_take isl_set *set)2618{2619 return isl_map_remove_divs(set);2620}2621 2622__isl_give isl_basic_map *isl_basic_map_remove_dims(2623 __isl_take isl_basic_map *bmap, enum isl_dim_type type,2624 unsigned first, unsigned n)2625{2626 if (isl_basic_map_check_range(bmap, type, first, n) < 0)2627 return isl_basic_map_free(bmap);2628 if (n == 0 && !isl_space_is_named_or_nested(bmap->dim, type))2629 return bmap;2630 bmap = isl_basic_map_eliminate_vars(bmap,2631 isl_basic_map_offset(bmap, type) - 1 + first, n);2632 if (!bmap)2633 return bmap;2634 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY) && type == isl_dim_div)2635 return bmap;2636 bmap = isl_basic_map_drop(bmap, type, first, n);2637 return bmap;2638}2639 2640/* Return true if the definition of the given div (recursively) involves2641 * any of the given variables.2642 */2643static isl_bool div_involves_vars(__isl_keep isl_basic_map *bmap, int div,2644 unsigned first, unsigned n)2645{2646 int i;2647 unsigned div_offset = isl_basic_map_offset(bmap, isl_dim_div);2648 2649 if (isl_int_is_zero(bmap->div[div][0]))2650 return isl_bool_false;2651 if (isl_seq_first_non_zero(bmap->div[div] + 1 + first, n) >= 0)2652 return isl_bool_true;2653 2654 for (i = bmap->n_div - 1; i >= 0; --i) {2655 isl_bool involves;2656 2657 if (isl_int_is_zero(bmap->div[div][1 + div_offset + i]))2658 continue;2659 involves = div_involves_vars(bmap, i, first, n);2660 if (involves < 0 || involves)2661 return involves;2662 }2663 2664 return isl_bool_false;2665}2666 2667/* Try and add a lower and/or upper bound on "div" to "bmap"2668 * based on inequality "i".2669 * "total" is the total number of variables (excluding the divs).2670 * "v" is a temporary object that can be used during the calculations.2671 * If "lb" is set, then a lower bound should be constructed.2672 * If "ub" is set, then an upper bound should be constructed.2673 *2674 * The calling function has already checked that the inequality does not2675 * reference "div", but we still need to check that the inequality is2676 * of the right form. We'll consider the case where we want to construct2677 * a lower bound. The construction of upper bounds is similar.2678 *2679 * Let "div" be of the form2680 *2681 * q = floor((a + f(x))/d)2682 *2683 * We essentially check if constraint "i" is of the form2684 *2685 * b + f(x) >= 02686 *2687 * so that we can use it to derive a lower bound on "div".2688 * However, we allow a slightly more general form2689 *2690 * b + g(x) >= 02691 *2692 * with the condition that the coefficients of g(x) - f(x) are all2693 * divisible by d.2694 * Rewriting this constraint as2695 *2696 * 0 >= -b - g(x)2697 *2698 * adding a + f(x) to both sides and dividing by d, we obtain2699 *2700 * (a + f(x))/d >= (a-b)/d + (f(x)-g(x))/d2701 *2702 * Taking the floor on both sides, we obtain2703 *2704 * q >= floor((a-b)/d) + (f(x)-g(x))/d2705 *2706 * or2707 *2708 * (g(x)-f(x))/d + ceil((b-a)/d) + q >= 02709 *2710 * In the case of an upper bound, we construct the constraint2711 *2712 * (g(x)+f(x))/d + floor((b+a)/d) - q >= 02713 *2714 */2715static __isl_give isl_basic_map *insert_bounds_on_div_from_ineq(2716 __isl_take isl_basic_map *bmap, int div, int i,2717 unsigned total, isl_int v, int lb, int ub)2718{2719 int j;2720 2721 for (j = 0; (lb || ub) && j < total + bmap->n_div; ++j) {2722 if (lb) {2723 isl_int_sub(v, bmap->ineq[i][1 + j],2724 bmap->div[div][1 + 1 + j]);2725 lb = isl_int_is_divisible_by(v, bmap->div[div][0]);2726 }2727 if (ub) {2728 isl_int_add(v, bmap->ineq[i][1 + j],2729 bmap->div[div][1 + 1 + j]);2730 ub = isl_int_is_divisible_by(v, bmap->div[div][0]);2731 }2732 }2733 if (!lb && !ub)2734 return bmap;2735 2736 bmap = isl_basic_map_cow(bmap);2737 bmap = isl_basic_map_extend_constraints(bmap, 0, lb + ub);2738 if (lb) {2739 int k = isl_basic_map_alloc_inequality(bmap);2740 if (k < 0)2741 goto error;2742 for (j = 0; j < 1 + total + bmap->n_div; ++j) {2743 isl_int_sub(bmap->ineq[k][j], bmap->ineq[i][j],2744 bmap->div[div][1 + j]);2745 isl_int_cdiv_q(bmap->ineq[k][j],2746 bmap->ineq[k][j], bmap->div[div][0]);2747 }2748 isl_int_set_si(bmap->ineq[k][1 + total + div], 1);2749 }2750 if (ub) {2751 int k = isl_basic_map_alloc_inequality(bmap);2752 if (k < 0)2753 goto error;2754 for (j = 0; j < 1 + total + bmap->n_div; ++j) {2755 isl_int_add(bmap->ineq[k][j], bmap->ineq[i][j],2756 bmap->div[div][1 + j]);2757 isl_int_fdiv_q(bmap->ineq[k][j],2758 bmap->ineq[k][j], bmap->div[div][0]);2759 }2760 isl_int_set_si(bmap->ineq[k][1 + total + div], -1);2761 }2762 2763 return bmap;2764error:2765 isl_basic_map_free(bmap);2766 return NULL;2767}2768 2769/* This function is called right before "div" is eliminated from "bmap"2770 * using Fourier-Motzkin.2771 * Look through the constraints of "bmap" for constraints on the argument2772 * of the integer division and use them to construct constraints on the2773 * integer division itself. These constraints can then be combined2774 * during the Fourier-Motzkin elimination.2775 * Note that it is only useful to introduce lower bounds on "div"2776 * if "bmap" already contains upper bounds on "div" as the newly2777 * introduce lower bounds can then be combined with the pre-existing2778 * upper bounds. Similarly for upper bounds.2779 * We therefore first check if "bmap" contains any lower and/or upper bounds2780 * on "div".2781 *2782 * It is interesting to note that the introduction of these constraints2783 * can indeed lead to more accurate results, even when compared to2784 * deriving constraints on the argument of "div" from constraints on "div".2785 * Consider, for example, the set2786 *2787 * { [i,j,k] : 3 + i + 2j >= 0 and 2 * [(i+2j)/4] <= k }2788 *2789 * The second constraint can be rewritten as2790 *2791 * 2 * [(-i-2j+3)/4] + k >= 02792 *2793 * from which we can derive2794 *2795 * -i - 2j + 3 >= -2k2796 *2797 * or2798 *2799 * i + 2j <= 3 + 2k2800 *2801 * Combined with the first constraint, we obtain2802 *2803 * -3 <= 3 + 2k or k >= -32804 *2805 * If, on the other hand we derive a constraint on [(i+2j)/4] from2806 * the first constraint, we obtain2807 *2808 * [(i + 2j)/4] >= [-3/4] = -12809 *2810 * Combining this constraint with the second constraint, we obtain2811 *2812 * k >= -22813 */2814static __isl_give isl_basic_map *insert_bounds_on_div(2815 __isl_take isl_basic_map *bmap, int div)2816{2817 int i;2818 int check_lb, check_ub;2819 isl_int v;2820 isl_size v_div;2821 2822 if (!bmap)2823 return NULL;2824 2825 if (isl_int_is_zero(bmap->div[div][0]))2826 return bmap;2827 2828 v_div = isl_basic_map_var_offset(bmap, isl_dim_div);2829 if (v_div < 0)2830 return isl_basic_map_free(bmap);2831 2832 check_lb = 0;2833 check_ub = 0;2834 for (i = 0; (!check_lb || !check_ub) && i < bmap->n_ineq; ++i) {2835 int s = isl_int_sgn(bmap->ineq[i][1 + v_div + div]);2836 if (s > 0)2837 check_ub = 1;2838 if (s < 0)2839 check_lb = 1;2840 }2841 2842 if (!check_lb && !check_ub)2843 return bmap;2844 2845 isl_int_init(v);2846 2847 for (i = 0; bmap && i < bmap->n_ineq; ++i) {2848 if (!isl_int_is_zero(bmap->ineq[i][1 + v_div + div]))2849 continue;2850 2851 bmap = insert_bounds_on_div_from_ineq(bmap, div, i, v_div, v,2852 check_lb, check_ub);2853 }2854 2855 isl_int_clear(v);2856 2857 return bmap;2858}2859 2860/* Remove all divs (recursively) involving any of the given dimensions2861 * in their definitions.2862 */2863__isl_give isl_basic_map *isl_basic_map_remove_divs_involving_dims(2864 __isl_take isl_basic_map *bmap,2865 enum isl_dim_type type, unsigned first, unsigned n)2866{2867 int i;2868 2869 if (isl_basic_map_check_range(bmap, type, first, n) < 0)2870 return isl_basic_map_free(bmap);2871 first += isl_basic_map_offset(bmap, type);2872 2873 for (i = bmap->n_div - 1; i >= 0; --i) {2874 isl_bool involves;2875 2876 involves = div_involves_vars(bmap, i, first, n);2877 if (involves < 0)2878 return isl_basic_map_free(bmap);2879 if (!involves)2880 continue;2881 bmap = insert_bounds_on_div(bmap, i);2882 bmap = isl_basic_map_remove_dims(bmap, isl_dim_div, i, 1);2883 if (!bmap)2884 return NULL;2885 i = bmap->n_div;2886 }2887 2888 return bmap;2889}2890 2891__isl_give isl_basic_set *isl_basic_set_remove_divs_involving_dims(2892 __isl_take isl_basic_set *bset,2893 enum isl_dim_type type, unsigned first, unsigned n)2894{2895 return isl_basic_map_remove_divs_involving_dims(bset, type, first, n);2896}2897 2898__isl_give isl_map *isl_map_remove_divs_involving_dims(__isl_take isl_map *map,2899 enum isl_dim_type type, unsigned first, unsigned n)2900{2901 int i;2902 2903 if (!map)2904 return NULL;2905 if (map->n == 0)2906 return map;2907 2908 map = isl_map_cow(map);2909 if (!map)2910 return NULL;2911 2912 for (i = 0; i < map->n; ++i) {2913 map->p[i] = isl_basic_map_remove_divs_involving_dims(map->p[i],2914 type, first, n);2915 if (!map->p[i])2916 goto error;2917 }2918 return map;2919error:2920 isl_map_free(map);2921 return NULL;2922}2923 2924__isl_give isl_set *isl_set_remove_divs_involving_dims(__isl_take isl_set *set,2925 enum isl_dim_type type, unsigned first, unsigned n)2926{2927 return set_from_map(isl_map_remove_divs_involving_dims(set_to_map(set),2928 type, first, n));2929}2930 2931/* Does the description of "bmap" depend on the specified dimensions?2932 * We also check whether the dimensions appear in any of the div definitions.2933 * In principle there is no need for this check. If the dimensions appear2934 * in a div definition, they also appear in the defining constraints of that2935 * div.2936 */2937isl_bool isl_basic_map_involves_dims(__isl_keep isl_basic_map *bmap,2938 enum isl_dim_type type, unsigned first, unsigned n)2939{2940 int i;2941 2942 if (isl_basic_map_check_range(bmap, type, first, n) < 0)2943 return isl_bool_error;2944 2945 first += isl_basic_map_offset(bmap, type);2946 for (i = 0; i < bmap->n_eq; ++i)2947 if (isl_seq_first_non_zero(bmap->eq[i] + first, n) >= 0)2948 return isl_bool_true;2949 for (i = 0; i < bmap->n_ineq; ++i)2950 if (isl_seq_first_non_zero(bmap->ineq[i] + first, n) >= 0)2951 return isl_bool_true;2952 for (i = 0; i < bmap->n_div; ++i) {2953 if (isl_int_is_zero(bmap->div[i][0]))2954 continue;2955 if (isl_seq_first_non_zero(bmap->div[i] + 1 + first, n) >= 0)2956 return isl_bool_true;2957 }2958 2959 return isl_bool_false;2960}2961 2962isl_bool isl_map_involves_dims(__isl_keep isl_map *map,2963 enum isl_dim_type type, unsigned first, unsigned n)2964{2965 int i;2966 2967 if (isl_map_check_range(map, type, first, n) < 0)2968 return isl_bool_error;2969 2970 for (i = 0; i < map->n; ++i) {2971 isl_bool involves = isl_basic_map_involves_dims(map->p[i],2972 type, first, n);2973 if (involves < 0 || involves)2974 return involves;2975 }2976 2977 return isl_bool_false;2978}2979 2980isl_bool isl_basic_set_involves_dims(__isl_keep isl_basic_set *bset,2981 enum isl_dim_type type, unsigned first, unsigned n)2982{2983 return isl_basic_map_involves_dims(bset, type, first, n);2984}2985 2986isl_bool isl_set_involves_dims(__isl_keep isl_set *set,2987 enum isl_dim_type type, unsigned first, unsigned n)2988{2989 return isl_map_involves_dims(set, type, first, n);2990}2991 2992/* Does "bset" involve any local variables, i.e., integer divisions?2993 */2994static isl_bool isl_basic_set_involves_locals(__isl_keep isl_basic_set *bset)2995{2996 isl_size n;2997 2998 n = isl_basic_set_dim(bset, isl_dim_div);2999 if (n < 0)3000 return isl_bool_error;3001 return isl_bool_ok(n > 0);3002}3003 3004/* isl_set_every_basic_set callback that checks whether "bset"3005 * is free of local variables.3006 */3007static isl_bool basic_set_no_locals(__isl_keep isl_basic_set *bset, void *user)3008{3009 return isl_bool_not(isl_basic_set_involves_locals(bset));3010}3011 3012/* Does "set" involve any local variables, i.e., integer divisions?3013 */3014isl_bool isl_set_involves_locals(__isl_keep isl_set *set)3015{3016 isl_bool no_locals;3017 3018 no_locals = isl_set_every_basic_set(set, &basic_set_no_locals, NULL);3019 return isl_bool_not(no_locals);3020}3021 3022/* Drop all constraints in bmap that involve any of the dimensions3023 * first to first+n-1.3024 * This function only performs the actual removal of constraints.3025 *3026 * This function should not call finalize since it is used by3027 * remove_redundant_divs, which in turn is called by isl_basic_map_finalize.3028 */3029__isl_give isl_basic_map *isl_basic_map_drop_constraints_involving(3030 __isl_take isl_basic_map *bmap, unsigned first, unsigned n)3031{3032 int i;3033 3034 if (n == 0)3035 return bmap;3036 3037 bmap = isl_basic_map_cow(bmap);3038 3039 if (!bmap)3040 return NULL;3041 3042 for (i = bmap->n_eq - 1; i >= 0; --i) {3043 if (isl_seq_first_non_zero(bmap->eq[i] + 1 + first, n) == -1)3044 continue;3045 if (isl_basic_map_drop_equality(bmap, i) < 0)3046 return isl_basic_map_free(bmap);3047 }3048 3049 for (i = bmap->n_ineq - 1; i >= 0; --i) {3050 if (isl_seq_first_non_zero(bmap->ineq[i] + 1 + first, n) == -1)3051 continue;3052 if (isl_basic_map_drop_inequality(bmap, i) < 0)3053 return isl_basic_map_free(bmap);3054 }3055 3056 return bmap;3057}3058 3059/* Drop all constraints in bset that involve any of the dimensions3060 * first to first+n-1.3061 * This function only performs the actual removal of constraints.3062 */3063__isl_give isl_basic_set *isl_basic_set_drop_constraints_involving(3064 __isl_take isl_basic_set *bset, unsigned first, unsigned n)3065{3066 return isl_basic_map_drop_constraints_involving(bset, first, n);3067}3068 3069/* Drop all constraints in bmap that do not involve any of the dimensions3070 * first to first + n - 1 of the given type.3071 */3072__isl_give isl_basic_map *isl_basic_map_drop_constraints_not_involving_dims(3073 __isl_take isl_basic_map *bmap,3074 enum isl_dim_type type, unsigned first, unsigned n)3075{3076 int i;3077 3078 if (n == 0) {3079 isl_space *space = isl_basic_map_get_space(bmap);3080 isl_basic_map_free(bmap);3081 return isl_basic_map_universe(space);3082 }3083 bmap = isl_basic_map_cow(bmap);3084 if (!bmap)3085 return NULL;3086 3087 if (isl_basic_map_check_range(bmap, type, first, n) < 0)3088 return isl_basic_map_free(bmap);3089 3090 first += isl_basic_map_offset(bmap, type) - 1;3091 3092 for (i = bmap->n_eq - 1; i >= 0; --i) {3093 if (isl_seq_first_non_zero(bmap->eq[i] + 1 + first, n) != -1)3094 continue;3095 if (isl_basic_map_drop_equality(bmap, i) < 0)3096 return isl_basic_map_free(bmap);3097 }3098 3099 for (i = bmap->n_ineq - 1; i >= 0; --i) {3100 if (isl_seq_first_non_zero(bmap->ineq[i] + 1 + first, n) != -1)3101 continue;3102 if (isl_basic_map_drop_inequality(bmap, i) < 0)3103 return isl_basic_map_free(bmap);3104 }3105 3106 bmap = isl_basic_map_add_known_div_constraints(bmap);3107 return bmap;3108}3109 3110/* Drop all constraints in bset that do not involve any of the dimensions3111 * first to first + n - 1 of the given type.3112 */3113__isl_give isl_basic_set *isl_basic_set_drop_constraints_not_involving_dims(3114 __isl_take isl_basic_set *bset,3115 enum isl_dim_type type, unsigned first, unsigned n)3116{3117 return isl_basic_map_drop_constraints_not_involving_dims(bset,3118 type, first, n);3119}3120 3121/* Drop all constraints in bmap that involve any of the dimensions3122 * first to first + n - 1 of the given type.3123 */3124__isl_give isl_basic_map *isl_basic_map_drop_constraints_involving_dims(3125 __isl_take isl_basic_map *bmap,3126 enum isl_dim_type type, unsigned first, unsigned n)3127{3128 if (!bmap)3129 return NULL;3130 if (n == 0)3131 return bmap;3132 3133 if (isl_basic_map_check_range(bmap, type, first, n) < 0)3134 return isl_basic_map_free(bmap);3135 3136 bmap = isl_basic_map_remove_divs_involving_dims(bmap, type, first, n);3137 first += isl_basic_map_offset(bmap, type) - 1;3138 bmap = isl_basic_map_drop_constraints_involving(bmap, first, n);3139 bmap = isl_basic_map_add_known_div_constraints(bmap);3140 return bmap;3141}3142 3143/* Drop all constraints in bset that involve any of the dimensions3144 * first to first + n - 1 of the given type.3145 */3146__isl_give isl_basic_set *isl_basic_set_drop_constraints_involving_dims(3147 __isl_take isl_basic_set *bset,3148 enum isl_dim_type type, unsigned first, unsigned n)3149{3150 return isl_basic_map_drop_constraints_involving_dims(bset,3151 type, first, n);3152}3153 3154/* Drop constraints from "map" by applying "drop" to each basic map.3155 */3156static __isl_give isl_map *drop_constraints(__isl_take isl_map *map,3157 enum isl_dim_type type, unsigned first, unsigned n,3158 __isl_give isl_basic_map *(*drop)(__isl_take isl_basic_map *bmap,3159 enum isl_dim_type type, unsigned first, unsigned n))3160{3161 int i;3162 3163 if (isl_map_check_range(map, type, first, n) < 0)3164 return isl_map_free(map);3165 3166 map = isl_map_cow(map);3167 if (!map)3168 return NULL;3169 3170 for (i = 0; i < map->n; ++i) {3171 map->p[i] = drop(map->p[i], type, first, n);3172 if (!map->p[i])3173 return isl_map_free(map);3174 }3175 3176 if (map->n > 1)3177 ISL_F_CLR(map, ISL_MAP_DISJOINT);3178 3179 return map;3180}3181 3182/* Drop all constraints in map that involve any of the dimensions3183 * first to first + n - 1 of the given type.3184 */3185__isl_give isl_map *isl_map_drop_constraints_involving_dims(3186 __isl_take isl_map *map,3187 enum isl_dim_type type, unsigned first, unsigned n)3188{3189 if (n == 0)3190 return map;3191 return drop_constraints(map, type, first, n,3192 &isl_basic_map_drop_constraints_involving_dims);3193}3194 3195/* Drop all constraints in "map" that do not involve any of the dimensions3196 * first to first + n - 1 of the given type.3197 */3198__isl_give isl_map *isl_map_drop_constraints_not_involving_dims(3199 __isl_take isl_map *map,3200 enum isl_dim_type type, unsigned first, unsigned n)3201{3202 if (n == 0) {3203 isl_space *space = isl_map_get_space(map);3204 isl_map_free(map);3205 return isl_map_universe(space);3206 }3207 return drop_constraints(map, type, first, n,3208 &isl_basic_map_drop_constraints_not_involving_dims);3209}3210 3211/* Drop all constraints in set that involve any of the dimensions3212 * first to first + n - 1 of the given type.3213 */3214__isl_give isl_set *isl_set_drop_constraints_involving_dims(3215 __isl_take isl_set *set,3216 enum isl_dim_type type, unsigned first, unsigned n)3217{3218 return isl_map_drop_constraints_involving_dims(set, type, first, n);3219}3220 3221/* Drop all constraints in "set" that do not involve any of the dimensions3222 * first to first + n - 1 of the given type.3223 */3224__isl_give isl_set *isl_set_drop_constraints_not_involving_dims(3225 __isl_take isl_set *set,3226 enum isl_dim_type type, unsigned first, unsigned n)3227{3228 return isl_map_drop_constraints_not_involving_dims(set, type, first, n);3229}3230 3231/* Does local variable "div" of "bmap" have a complete explicit representation?3232 * Having a complete explicit representation requires not only3233 * an explicit representation, but also that all local variables3234 * that appear in this explicit representation in turn have3235 * a complete explicit representation.3236 */3237isl_bool isl_basic_map_div_is_known(__isl_keep isl_basic_map *bmap, int div)3238{3239 int i;3240 unsigned div_offset = isl_basic_map_offset(bmap, isl_dim_div);3241 isl_bool marked;3242 3243 marked = isl_basic_map_div_is_marked_unknown(bmap, div);3244 if (marked < 0 || marked)3245 return isl_bool_not(marked);3246 3247 for (i = bmap->n_div - 1; i >= 0; --i) {3248 isl_bool known;3249 3250 if (isl_int_is_zero(bmap->div[div][1 + div_offset + i]))3251 continue;3252 known = isl_basic_map_div_is_known(bmap, i);3253 if (known < 0 || !known)3254 return known;3255 }3256 3257 return isl_bool_true;3258}3259 3260/* Remove all divs that are unknown or defined in terms of unknown divs.3261 */3262__isl_give isl_basic_map *isl_basic_map_remove_unknown_divs(3263 __isl_take isl_basic_map *bmap)3264{3265 int i;3266 3267 if (!bmap)3268 return NULL;3269 3270 for (i = bmap->n_div - 1; i >= 0; --i) {3271 if (isl_basic_map_div_is_known(bmap, i))3272 continue;3273 bmap = isl_basic_map_remove_dims(bmap, isl_dim_div, i, 1);3274 if (!bmap)3275 return NULL;3276 i = bmap->n_div;3277 }3278 3279 return bmap;3280}3281 3282/* Remove all divs that are unknown or defined in terms of unknown divs.3283 */3284__isl_give isl_basic_set *isl_basic_set_remove_unknown_divs(3285 __isl_take isl_basic_set *bset)3286{3287 return isl_basic_map_remove_unknown_divs(bset);3288}3289 3290__isl_give isl_map *isl_map_remove_unknown_divs(__isl_take isl_map *map)3291{3292 int i;3293 3294 if (!map)3295 return NULL;3296 if (map->n == 0)3297 return map;3298 3299 map = isl_map_cow(map);3300 if (!map)3301 return NULL;3302 3303 for (i = 0; i < map->n; ++i) {3304 map->p[i] = isl_basic_map_remove_unknown_divs(map->p[i]);3305 if (!map->p[i])3306 goto error;3307 }3308 return map;3309error:3310 isl_map_free(map);3311 return NULL;3312}3313 3314__isl_give isl_set *isl_set_remove_unknown_divs(__isl_take isl_set *set)3315{3316 return set_from_map(isl_map_remove_unknown_divs(set_to_map(set)));3317}3318 3319__isl_give isl_basic_set *isl_basic_set_remove_dims(3320 __isl_take isl_basic_set *bset,3321 enum isl_dim_type type, unsigned first, unsigned n)3322{3323 isl_basic_map *bmap = bset_to_bmap(bset);3324 bmap = isl_basic_map_remove_dims(bmap, type, first, n);3325 return bset_from_bmap(bmap);3326}3327 3328__isl_give isl_map *isl_map_remove_dims(__isl_take isl_map *map,3329 enum isl_dim_type type, unsigned first, unsigned n)3330{3331 int i;3332 3333 if (n == 0)3334 return map;3335 3336 map = isl_map_cow(map);3337 if (isl_map_check_range(map, type, first, n) < 0)3338 return isl_map_free(map);3339 3340 for (i = 0; i < map->n; ++i) {3341 map->p[i] = isl_basic_map_eliminate_vars(map->p[i],3342 isl_basic_map_offset(map->p[i], type) - 1 + first, n);3343 if (!map->p[i])3344 goto error;3345 }3346 map = isl_map_drop(map, type, first, n);3347 return map;3348error:3349 isl_map_free(map);3350 return NULL;3351}3352 3353__isl_give isl_set *isl_set_remove_dims(__isl_take isl_set *bset,3354 enum isl_dim_type type, unsigned first, unsigned n)3355{3356 return set_from_map(isl_map_remove_dims(set_to_map(bset),3357 type, first, n));3358}3359 3360/* Project out n inputs starting at first using Fourier-Motzkin */3361__isl_give isl_map *isl_map_remove_inputs(__isl_take isl_map *map,3362 unsigned first, unsigned n)3363{3364 return isl_map_remove_dims(map, isl_dim_in, first, n);3365}3366 3367void isl_basic_set_print_internal(__isl_keep isl_basic_set *bset,3368 FILE *out, int indent)3369{3370 isl_printer *p;3371 3372 if (!bset) {3373 fprintf(out, "null basic set\n");3374 return;3375 }3376 3377 fprintf(out, "%*s", indent, "");3378 fprintf(out, "ref: %d, nparam: %d, dim: %d, extra: %d, flags: %x\n",3379 bset->ref, bset->dim->nparam, bset->dim->n_out,3380 bset->extra, bset->flags);3381 3382 p = isl_printer_to_file(isl_basic_set_get_ctx(bset), out);3383 p = isl_printer_set_dump(p, 1);3384 p = isl_printer_set_indent(p, indent);3385 p = isl_printer_start_line(p);3386 p = isl_printer_print_basic_set(p, bset);3387 p = isl_printer_end_line(p);3388 isl_printer_free(p);3389}3390 3391void isl_basic_map_print_internal(__isl_keep isl_basic_map *bmap,3392 FILE *out, int indent)3393{3394 isl_printer *p;3395 3396 if (!bmap) {3397 fprintf(out, "null basic map\n");3398 return;3399 }3400 3401 fprintf(out, "%*s", indent, "");3402 fprintf(out, "ref: %d, nparam: %d, in: %d, out: %d, extra: %d, "3403 "flags: %x, n_name: %d\n",3404 bmap->ref,3405 bmap->dim->nparam, bmap->dim->n_in, bmap->dim->n_out,3406 bmap->extra, bmap->flags, bmap->dim->n_id);3407 3408 p = isl_printer_to_file(isl_basic_map_get_ctx(bmap), out);3409 p = isl_printer_set_dump(p, 1);3410 p = isl_printer_set_indent(p, indent);3411 p = isl_printer_start_line(p);3412 p = isl_printer_print_basic_map(p, bmap);3413 p = isl_printer_end_line(p);3414 isl_printer_free(p);3415}3416 3417__isl_give isl_basic_map *isl_inequality_negate(__isl_take isl_basic_map *bmap,3418 unsigned pos)3419{3420 isl_size total;3421 3422 total = isl_basic_map_dim(bmap, isl_dim_all);3423 if (total < 0)3424 return isl_basic_map_free(bmap);3425 if (pos >= bmap->n_ineq)3426 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,3427 "invalid position", return isl_basic_map_free(bmap));3428 isl_seq_neg(bmap->ineq[pos], bmap->ineq[pos], 1 + total);3429 isl_int_sub_ui(bmap->ineq[pos][0], bmap->ineq[pos][0], 1);3430 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);3431 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);3432 return bmap;3433}3434 3435__isl_give isl_set *isl_set_alloc_space(__isl_take isl_space *space, int n,3436 unsigned flags)3437{3438 if (isl_space_check_is_set(space) < 0)3439 goto error;3440 return isl_map_alloc_space(space, n, flags);3441error:3442 isl_space_free(space);3443 return NULL;3444}3445 3446/* Make sure "map" has room for at least "n" more basic maps.3447 */3448__isl_give isl_map *isl_map_grow(__isl_take isl_map *map, int n)3449{3450 int i;3451 struct isl_map *grown = NULL;3452 3453 if (!map)3454 return NULL;3455 isl_assert(map->ctx, n >= 0, goto error);3456 if (map->n + n <= map->size)3457 return map;3458 grown = isl_map_alloc_space(isl_map_get_space(map), map->n + n, map->flags);3459 if (!grown)3460 goto error;3461 for (i = 0; i < map->n; ++i) {3462 grown->p[i] = isl_basic_map_copy(map->p[i]);3463 if (!grown->p[i])3464 goto error;3465 grown->n++;3466 }3467 isl_map_free(map);3468 return grown;3469error:3470 isl_map_free(grown);3471 isl_map_free(map);3472 return NULL;3473}3474 3475/* Make sure "set" has room for at least "n" more basic sets.3476 */3477__isl_give isl_set *isl_set_grow(__isl_take isl_set *set, int n)3478{3479 return set_from_map(isl_map_grow(set_to_map(set), n));3480}3481 3482__isl_give isl_set *isl_set_from_basic_set(__isl_take isl_basic_set *bset)3483{3484 return isl_map_from_basic_map(bset);3485}3486 3487/* This function performs the same operation as isl_set_from_basic_set,3488 * but is considered as a function on an isl_basic_set when exported.3489 */3490__isl_give isl_set *isl_basic_set_to_set(__isl_take isl_basic_set *bset)3491{3492 return isl_set_from_basic_set(bset);3493}3494 3495__isl_give isl_map *isl_map_from_basic_map(__isl_take isl_basic_map *bmap)3496{3497 struct isl_map *map;3498 3499 if (!bmap)3500 return NULL;3501 3502 map = isl_map_alloc_space(isl_space_copy(bmap->dim), 1, ISL_MAP_DISJOINT);3503 return isl_map_add_basic_map(map, bmap);3504}3505 3506__isl_give isl_set *isl_set_add_basic_set(__isl_take isl_set *set,3507 __isl_take isl_basic_set *bset)3508{3509 return set_from_map(isl_map_add_basic_map(set_to_map(set),3510 bset_to_bmap(bset)));3511}3512 3513__isl_null isl_set *isl_set_free(__isl_take isl_set *set)3514{3515 return isl_map_free(set);3516}3517 3518void isl_set_print_internal(__isl_keep isl_set *set, FILE *out, int indent)3519{3520 int i;3521 3522 if (!set) {3523 fprintf(out, "null set\n");3524 return;3525 }3526 3527 fprintf(out, "%*s", indent, "");3528 fprintf(out, "ref: %d, n: %d, nparam: %d, dim: %d, flags: %x\n",3529 set->ref, set->n, set->dim->nparam, set->dim->n_out,3530 set->flags);3531 for (i = 0; i < set->n; ++i) {3532 fprintf(out, "%*s", indent, "");3533 fprintf(out, "basic set %d:\n", i);3534 isl_basic_set_print_internal(set->p[i], out, indent+4);3535 }3536}3537 3538void isl_map_print_internal(__isl_keep isl_map *map, FILE *out, int indent)3539{3540 int i;3541 3542 if (!map) {3543 fprintf(out, "null map\n");3544 return;3545 }3546 3547 fprintf(out, "%*s", indent, "");3548 fprintf(out, "ref: %d, n: %d, nparam: %d, in: %d, out: %d, "3549 "flags: %x, n_name: %d\n",3550 map->ref, map->n, map->dim->nparam, map->dim->n_in,3551 map->dim->n_out, map->flags, map->dim->n_id);3552 for (i = 0; i < map->n; ++i) {3553 fprintf(out, "%*s", indent, "");3554 fprintf(out, "basic map %d:\n", i);3555 isl_basic_map_print_internal(map->p[i], out, indent+4);3556 }3557}3558 3559/* Check that the space of "bset" is the same as that of the domain of "bmap".3560 */3561static isl_stat isl_basic_map_check_compatible_domain(3562 __isl_keep isl_basic_map *bmap, __isl_keep isl_basic_set *bset)3563{3564 isl_bool ok;3565 3566 ok = isl_basic_map_compatible_domain(bmap, bset);3567 if (ok < 0)3568 return isl_stat_error;3569 if (!ok)3570 isl_die(isl_basic_set_get_ctx(bset), isl_error_invalid,3571 "incompatible spaces", return isl_stat_error);3572 3573 return isl_stat_ok;3574}3575 3576__isl_give isl_basic_map *isl_basic_map_intersect_domain(3577 __isl_take isl_basic_map *bmap, __isl_take isl_basic_set *bset)3578{3579 struct isl_basic_map *bmap_domain;3580 isl_size dim;3581 3582 if (isl_basic_map_check_equal_params(bmap, bset_to_bmap(bset)) < 0)3583 goto error;3584 3585 dim = isl_basic_set_dim(bset, isl_dim_set);3586 if (dim < 0)3587 goto error;3588 if (dim != 0 &&3589 isl_basic_map_check_compatible_domain(bmap, bset) < 0)3590 goto error;3591 3592 bmap = isl_basic_map_cow(bmap);3593 if (!bmap)3594 goto error;3595 bmap = isl_basic_map_extend(bmap,3596 bset->n_div, bset->n_eq, bset->n_ineq);3597 bmap_domain = isl_basic_map_from_domain(bset);3598 bmap = add_constraints(bmap, bmap_domain, 0, 0);3599 3600 bmap = isl_basic_map_simplify(bmap);3601 return isl_basic_map_finalize(bmap);3602error:3603 isl_basic_map_free(bmap);3604 isl_basic_set_free(bset);3605 return NULL;3606}3607 3608/* Check that the space of "bset" is the same as that of the range of "bmap".3609 */3610static isl_stat isl_basic_map_check_compatible_range(3611 __isl_keep isl_basic_map *bmap, __isl_keep isl_basic_set *bset)3612{3613 isl_bool ok;3614 3615 ok = isl_basic_map_compatible_range(bmap, bset);3616 if (ok < 0)3617 return isl_stat_error;3618 if (!ok)3619 isl_die(isl_basic_set_get_ctx(bset), isl_error_invalid,3620 "incompatible spaces", return isl_stat_error);3621 3622 return isl_stat_ok;3623}3624 3625__isl_give isl_basic_map *isl_basic_map_intersect_range(3626 __isl_take isl_basic_map *bmap, __isl_take isl_basic_set *bset)3627{3628 struct isl_basic_map *bmap_range;3629 isl_size dim;3630 3631 if (isl_basic_map_check_equal_params(bmap, bset_to_bmap(bset)) < 0)3632 goto error;3633 3634 dim = isl_basic_set_dim(bset, isl_dim_set);3635 if (dim < 0)3636 goto error;3637 if (dim != 0 && isl_basic_map_check_compatible_range(bmap, bset) < 0)3638 goto error;3639 3640 if (isl_basic_set_plain_is_universe(bset)) {3641 isl_basic_set_free(bset);3642 return bmap;3643 }3644 3645 bmap = isl_basic_map_cow(bmap);3646 if (!bmap)3647 goto error;3648 bmap = isl_basic_map_extend(bmap,3649 bset->n_div, bset->n_eq, bset->n_ineq);3650 bmap_range = bset_to_bmap(bset);3651 bmap = add_constraints(bmap, bmap_range, 0, 0);3652 3653 bmap = isl_basic_map_simplify(bmap);3654 return isl_basic_map_finalize(bmap);3655error:3656 isl_basic_map_free(bmap);3657 isl_basic_set_free(bset);3658 return NULL;3659}3660 3661isl_bool isl_basic_map_contains(__isl_keep isl_basic_map *bmap,3662 __isl_keep isl_vec *vec)3663{3664 int i;3665 isl_size total;3666 isl_int s;3667 3668 total = isl_basic_map_dim(bmap, isl_dim_all);3669 if (total < 0 || !vec)3670 return isl_bool_error;3671 3672 if (1 + total != vec->size)3673 return isl_bool_false;3674 3675 isl_int_init(s);3676 3677 for (i = 0; i < bmap->n_eq; ++i) {3678 isl_seq_inner_product(vec->el, bmap->eq[i], 1 + total, &s);3679 if (!isl_int_is_zero(s)) {3680 isl_int_clear(s);3681 return isl_bool_false;3682 }3683 }3684 3685 for (i = 0; i < bmap->n_ineq; ++i) {3686 isl_seq_inner_product(vec->el, bmap->ineq[i], 1 + total, &s);3687 if (isl_int_is_neg(s)) {3688 isl_int_clear(s);3689 return isl_bool_false;3690 }3691 }3692 3693 isl_int_clear(s);3694 3695 return isl_bool_true;3696}3697 3698isl_bool isl_basic_set_contains(__isl_keep isl_basic_set *bset,3699 __isl_keep isl_vec *vec)3700{3701 return isl_basic_map_contains(bset_to_bmap(bset), vec);3702}3703 3704__isl_give isl_basic_map *isl_basic_map_intersect(3705 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)3706{3707 struct isl_vec *sample = NULL;3708 isl_space *space1, *space2;3709 isl_size dim1, dim2, nparam1, nparam2;3710 3711 if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)3712 goto error;3713 space1 = isl_basic_map_peek_space(bmap1);3714 space2 = isl_basic_map_peek_space(bmap2);3715 dim1 = isl_space_dim(space1, isl_dim_all);3716 dim2 = isl_space_dim(space2, isl_dim_all);3717 nparam1 = isl_space_dim(space1, isl_dim_param);3718 nparam2 = isl_space_dim(space2, isl_dim_param);3719 if (dim1 < 0 || dim2 < 0 || nparam1 < 0 || nparam2 < 0)3720 goto error;3721 if (dim1 == nparam1 && dim2 != nparam2)3722 return isl_basic_map_intersect(bmap2, bmap1);3723 3724 if (dim2 != nparam2 &&3725 isl_basic_map_check_equal_space(bmap1, bmap2) < 0)3726 goto error;3727 3728 if (isl_basic_map_plain_is_empty(bmap1)) {3729 isl_basic_map_free(bmap2);3730 return bmap1;3731 }3732 if (isl_basic_map_plain_is_empty(bmap2)) {3733 isl_basic_map_free(bmap1);3734 return bmap2;3735 }3736 3737 if (bmap1->sample &&3738 isl_basic_map_contains(bmap1, bmap1->sample) > 0 &&3739 isl_basic_map_contains(bmap2, bmap1->sample) > 0)3740 sample = isl_vec_copy(bmap1->sample);3741 else if (bmap2->sample &&3742 isl_basic_map_contains(bmap1, bmap2->sample) > 0 &&3743 isl_basic_map_contains(bmap2, bmap2->sample) > 0)3744 sample = isl_vec_copy(bmap2->sample);3745 3746 bmap1 = isl_basic_map_cow(bmap1);3747 if (!bmap1)3748 goto error;3749 bmap1 = isl_basic_map_extend(bmap1,3750 bmap2->n_div, bmap2->n_eq, bmap2->n_ineq);3751 bmap1 = add_constraints(bmap1, bmap2, 0, 0);3752 3753 if (!bmap1)3754 isl_vec_free(sample);3755 else if (sample) {3756 isl_vec_free(bmap1->sample);3757 bmap1->sample = sample;3758 }3759 3760 bmap1 = isl_basic_map_simplify(bmap1);3761 return isl_basic_map_finalize(bmap1);3762error:3763 if (sample)3764 isl_vec_free(sample);3765 isl_basic_map_free(bmap1);3766 isl_basic_map_free(bmap2);3767 return NULL;3768}3769 3770__isl_give isl_basic_set *isl_basic_set_intersect(3771 __isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2)3772{3773 return bset_from_bmap(isl_basic_map_intersect(bset_to_bmap(bset1),3774 bset_to_bmap(bset2)));3775}3776 3777__isl_give isl_basic_set *isl_basic_set_intersect_params(3778 __isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2)3779{3780 return isl_basic_set_intersect(bset1, bset2);3781}3782 3783/* Does "map" consist of a single disjunct, without any local variables?3784 */3785static isl_bool is_convex_no_locals(__isl_keep isl_map *map)3786{3787 isl_size n_div;3788 3789 if (!map)3790 return isl_bool_error;3791 if (map->n != 1)3792 return isl_bool_false;3793 n_div = isl_basic_map_dim(map->p[0], isl_dim_div);3794 if (n_div < 0)3795 return isl_bool_error;3796 if (n_div != 0)3797 return isl_bool_false;3798 return isl_bool_true;3799}3800 3801/* Check that "map" consists of a single disjunct, without any local variables.3802 */3803static isl_stat check_convex_no_locals(__isl_keep isl_map *map)3804{3805 isl_bool ok;3806 3807 ok = is_convex_no_locals(map);3808 if (ok < 0)3809 return isl_stat_error;3810 if (ok)3811 return isl_stat_ok;3812 3813 isl_die(isl_map_get_ctx(map), isl_error_internal,3814 "unexpectedly not convex or involving local variables",3815 return isl_stat_error);3816}3817 3818/* Special case of isl_map_intersect, where both map1 and map23819 * are convex, without any divs and such that either map1 or map23820 * contains a single constraint. This constraint is then simply3821 * added to the other map.3822 */3823static __isl_give isl_map *map_intersect_add_constraint(3824 __isl_take isl_map *map1, __isl_take isl_map *map2)3825{3826 if (check_convex_no_locals(map1) < 0 ||3827 check_convex_no_locals(map2) < 0)3828 goto error;3829 3830 if (map2->p[0]->n_eq + map2->p[0]->n_ineq != 1)3831 return isl_map_intersect(map2, map1);3832 3833 map1 = isl_map_cow(map1);3834 if (!map1)3835 goto error;3836 if (isl_map_plain_is_empty(map1)) {3837 isl_map_free(map2);3838 return map1;3839 }3840 if (map2->p[0]->n_eq == 1)3841 map1->p[0] = isl_basic_map_add_eq(map1->p[0], map2->p[0]->eq[0]);3842 else3843 map1->p[0] = isl_basic_map_add_ineq(map1->p[0],3844 map2->p[0]->ineq[0]);3845 3846 map1->p[0] = isl_basic_map_simplify(map1->p[0]);3847 map1->p[0] = isl_basic_map_finalize(map1->p[0]);3848 if (!map1->p[0])3849 goto error;3850 3851 if (isl_basic_map_plain_is_empty(map1->p[0])) {3852 isl_basic_map_free(map1->p[0]);3853 map1->n = 0;3854 }3855 3856 isl_map_free(map2);3857 3858 map1 = isl_map_unmark_normalized(map1);3859 return map1;3860error:3861 isl_map_free(map1);3862 isl_map_free(map2);3863 return NULL;3864}3865 3866/* map2 may be either a parameter domain or a map living in the same3867 * space as map1.3868 */3869static __isl_give isl_map *map_intersect_internal(__isl_take isl_map *map1,3870 __isl_take isl_map *map2)3871{3872 unsigned flags = 0;3873 isl_bool equal;3874 isl_map *result;3875 int i, j;3876 isl_size dim2, nparam2;3877 3878 if (!map1 || !map2)3879 goto error;3880 3881 if ((isl_map_plain_is_empty(map1) ||3882 isl_map_plain_is_universe(map2)) &&3883 isl_space_is_equal(map1->dim, map2->dim)) {3884 isl_map_free(map2);3885 return map1;3886 }3887 if ((isl_map_plain_is_empty(map2) ||3888 isl_map_plain_is_universe(map1)) &&3889 isl_space_is_equal(map1->dim, map2->dim)) {3890 isl_map_free(map1);3891 return map2;3892 }3893 3894 if (is_convex_no_locals(map1) == isl_bool_true &&3895 is_convex_no_locals(map2) == isl_bool_true &&3896 isl_space_is_equal(map1->dim, map2->dim) &&3897 (map1->p[0]->n_eq + map1->p[0]->n_ineq == 1 ||3898 map2->p[0]->n_eq + map2->p[0]->n_ineq == 1))3899 return map_intersect_add_constraint(map1, map2);3900 3901 equal = isl_map_plain_is_equal(map1, map2);3902 if (equal < 0)3903 goto error;3904 if (equal) {3905 isl_map_free(map2);3906 return map1;3907 }3908 3909 dim2 = isl_map_dim(map2, isl_dim_all);3910 nparam2 = isl_map_dim(map2, isl_dim_param);3911 if (dim2 < 0 || nparam2 < 0)3912 goto error;3913 if (dim2 != nparam2)3914 isl_assert(map1->ctx,3915 isl_space_is_equal(map1->dim, map2->dim), goto error);3916 3917 if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) &&3918 ISL_F_ISSET(map2, ISL_MAP_DISJOINT))3919 ISL_FL_SET(flags, ISL_MAP_DISJOINT);3920 3921 result = isl_map_alloc_space(isl_space_copy(map1->dim),3922 map1->n * map2->n, flags);3923 if (!result)3924 goto error;3925 for (i = 0; i < map1->n; ++i)3926 for (j = 0; j < map2->n; ++j) {3927 struct isl_basic_map *part;3928 part = isl_basic_map_intersect(3929 isl_basic_map_copy(map1->p[i]),3930 isl_basic_map_copy(map2->p[j]));3931 if (isl_basic_map_is_empty(part) < 0)3932 part = isl_basic_map_free(part);3933 result = isl_map_add_basic_map(result, part);3934 if (!result)3935 goto error;3936 }3937 isl_map_free(map1);3938 isl_map_free(map2);3939 return result;3940error:3941 isl_map_free(map1);3942 isl_map_free(map2);3943 return NULL;3944}3945 3946static __isl_give isl_map *map_intersect(__isl_take isl_map *map1,3947 __isl_take isl_map *map2)3948{3949 if (isl_map_check_equal_space(map1, map2) < 0)3950 goto error;3951 return map_intersect_internal(map1, map2);3952error:3953 isl_map_free(map1);3954 isl_map_free(map2);3955 return NULL;3956}3957 3958__isl_give isl_map *isl_map_intersect(__isl_take isl_map *map1,3959 __isl_take isl_map *map2)3960{3961 isl_map_align_params_bin(&map1, &map2);3962 return map_intersect(map1, map2);3963}3964 3965__isl_give isl_set *isl_set_intersect(__isl_take isl_set *set1,3966 __isl_take isl_set *set2)3967{3968 return set_from_map(isl_map_intersect(set_to_map(set1),3969 set_to_map(set2)));3970}3971 3972/* map_intersect_internal accepts intersections3973 * with parameter domains, so we can just call that function.3974 */3975__isl_give isl_map *isl_map_intersect_params(__isl_take isl_map *map,3976 __isl_take isl_set *params)3977{3978 isl_map_align_params_set(&map, ¶ms);3979 return map_intersect_internal(map, params);3980}3981 3982__isl_give isl_set *isl_set_intersect_params(__isl_take isl_set *set,3983 __isl_take isl_set *params)3984{3985 return isl_map_intersect_params(set, params);3986}3987 3988__isl_give isl_basic_map *isl_basic_map_reverse(__isl_take isl_basic_map *bmap)3989{3990 isl_space *space;3991 unsigned pos;3992 isl_size n1, n2;3993 3994 if (!bmap)3995 return NULL;3996 bmap = isl_basic_map_cow(bmap);3997 if (!bmap)3998 return NULL;3999 space = isl_space_reverse(isl_space_copy(bmap->dim));4000 pos = isl_basic_map_offset(bmap, isl_dim_in);4001 n1 = isl_basic_map_dim(bmap, isl_dim_in);4002 n2 = isl_basic_map_dim(bmap, isl_dim_out);4003 if (n1 < 0 || n2 < 0)4004 bmap = isl_basic_map_free(bmap);4005 bmap = isl_basic_map_swap_vars(bmap, pos, n1, n2);4006 return isl_basic_map_reset_space(bmap, space);4007}4008 4009/* Given a basic map A -> (B -> C), return the corresponding basic map4010 * A -> (C -> B).4011 */4012static __isl_give isl_basic_map *isl_basic_map_range_reverse(4013 __isl_take isl_basic_map *bmap)4014{4015 isl_space *space;4016 isl_size offset, n1, n2;4017 4018 space = isl_basic_map_peek_space(bmap);4019 if (isl_space_check_range_is_wrapping(space) < 0)4020 return isl_basic_map_free(bmap);4021 offset = isl_basic_map_var_offset(bmap, isl_dim_out);4022 n1 = isl_space_wrapped_dim(space, isl_dim_out, isl_dim_in);4023 n2 = isl_space_wrapped_dim(space, isl_dim_out, isl_dim_out);4024 if (offset < 0 || n1 < 0 || n2 < 0)4025 return isl_basic_map_free(bmap);4026 4027 bmap = isl_basic_map_swap_vars(bmap, 1 + offset, n1, n2);4028 4029 space = isl_basic_map_take_space(bmap);4030 space = isl_space_range_reverse(space);4031 bmap = isl_basic_map_restore_space(bmap, space);4032 4033 return bmap;4034}4035 4036static __isl_give isl_basic_map *basic_map_space_reset(4037 __isl_take isl_basic_map *bmap, enum isl_dim_type type)4038{4039 isl_space *space;4040 4041 if (!bmap)4042 return NULL;4043 if (!isl_space_is_named_or_nested(bmap->dim, type))4044 return bmap;4045 4046 space = isl_basic_map_get_space(bmap);4047 space = isl_space_reset(space, type);4048 bmap = isl_basic_map_reset_space(bmap, space);4049 return bmap;4050}4051 4052__isl_give isl_basic_map *isl_basic_map_insert_dims(4053 __isl_take isl_basic_map *bmap, enum isl_dim_type type,4054 unsigned pos, unsigned n)4055{4056 isl_bool rational, is_empty;4057 isl_space *res_space;4058 struct isl_basic_map *res;4059 struct isl_dim_map *dim_map;4060 isl_size total;4061 unsigned off;4062 enum isl_dim_type t;4063 4064 if (n == 0)4065 return basic_map_space_reset(bmap, type);4066 4067 is_empty = isl_basic_map_plain_is_empty(bmap);4068 total = isl_basic_map_dim(bmap, isl_dim_all);4069 if (is_empty < 0 || total < 0)4070 return isl_basic_map_free(bmap);4071 res_space = isl_space_insert_dims(isl_basic_map_get_space(bmap),4072 type, pos, n);4073 if (!res_space)4074 return isl_basic_map_free(bmap);4075 if (is_empty) {4076 isl_basic_map_free(bmap);4077 return isl_basic_map_empty(res_space);4078 }4079 4080 dim_map = isl_dim_map_alloc(bmap->ctx, total + n);4081 off = 0;4082 for (t = isl_dim_param; t <= isl_dim_out; ++t) {4083 isl_size dim;4084 4085 if (t != type) {4086 isl_dim_map_dim(dim_map, bmap->dim, t, off);4087 } else {4088 isl_size size = isl_basic_map_dim(bmap, t);4089 if (size < 0)4090 dim_map = isl_dim_map_free(dim_map);4091 isl_dim_map_dim_range(dim_map, bmap->dim, t,4092 0, pos, off);4093 isl_dim_map_dim_range(dim_map, bmap->dim, t,4094 pos, size - pos, off + pos + n);4095 }4096 dim = isl_space_dim(res_space, t);4097 if (dim < 0)4098 dim_map = isl_dim_map_free(dim_map);4099 off += dim;4100 }4101 isl_dim_map_div(dim_map, bmap, off);4102 4103 res = isl_basic_map_alloc_space(res_space,4104 bmap->n_div, bmap->n_eq, bmap->n_ineq);4105 rational = isl_basic_map_is_rational(bmap);4106 if (rational < 0)4107 res = isl_basic_map_free(res);4108 if (rational)4109 res = isl_basic_map_set_rational(res);4110 res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);4111 return isl_basic_map_finalize(res);4112}4113 4114__isl_give isl_basic_set *isl_basic_set_insert_dims(4115 __isl_take isl_basic_set *bset,4116 enum isl_dim_type type, unsigned pos, unsigned n)4117{4118 return isl_basic_map_insert_dims(bset, type, pos, n);4119}4120 4121__isl_give isl_basic_map *isl_basic_map_add_dims(__isl_take isl_basic_map *bmap,4122 enum isl_dim_type type, unsigned n)4123{4124 isl_size dim;4125 4126 dim = isl_basic_map_dim(bmap, type);4127 if (dim < 0)4128 return isl_basic_map_free(bmap);4129 return isl_basic_map_insert_dims(bmap, type, dim, n);4130}4131 4132__isl_give isl_basic_set *isl_basic_set_add_dims(__isl_take isl_basic_set *bset,4133 enum isl_dim_type type, unsigned n)4134{4135 if (!bset)4136 return NULL;4137 isl_assert(bset->ctx, type != isl_dim_in, goto error);4138 return isl_basic_map_add_dims(bset, type, n);4139error:4140 isl_basic_set_free(bset);4141 return NULL;4142}4143 4144static __isl_give isl_map *map_space_reset(__isl_take isl_map *map,4145 enum isl_dim_type type)4146{4147 isl_space *space;4148 4149 if (!map || !isl_space_is_named_or_nested(map->dim, type))4150 return map;4151 4152 space = isl_map_get_space(map);4153 space = isl_space_reset(space, type);4154 map = isl_map_reset_space(map, space);4155 return map;4156}4157 4158__isl_give isl_map *isl_map_insert_dims(__isl_take isl_map *map,4159 enum isl_dim_type type, unsigned pos, unsigned n)4160{4161 int i;4162 isl_space *space;4163 4164 if (n == 0)4165 return map_space_reset(map, type);4166 4167 map = isl_map_cow(map);4168 if (!map)4169 return NULL;4170 4171 for (i = 0; i < map->n; ++i) {4172 map->p[i] = isl_basic_map_insert_dims(map->p[i], type, pos, n);4173 if (!map->p[i])4174 goto error;4175 }4176 4177 space = isl_map_take_space(map);4178 space = isl_space_insert_dims(space, type, pos, n);4179 map = isl_map_restore_space(map, space);4180 4181 return map;4182error:4183 isl_map_free(map);4184 return NULL;4185}4186 4187__isl_give isl_set *isl_set_insert_dims(__isl_take isl_set *set,4188 enum isl_dim_type type, unsigned pos, unsigned n)4189{4190 return isl_map_insert_dims(set, type, pos, n);4191}4192 4193__isl_give isl_map *isl_map_add_dims(__isl_take isl_map *map,4194 enum isl_dim_type type, unsigned n)4195{4196 isl_size dim;4197 4198 dim = isl_map_dim(map, type);4199 if (dim < 0)4200 return isl_map_free(map);4201 return isl_map_insert_dims(map, type, dim, n);4202}4203 4204__isl_give isl_set *isl_set_add_dims(__isl_take isl_set *set,4205 enum isl_dim_type type, unsigned n)4206{4207 if (!set)4208 return NULL;4209 isl_assert(set->ctx, type != isl_dim_in, goto error);4210 return set_from_map(isl_map_add_dims(set_to_map(set), type, n));4211error:4212 isl_set_free(set);4213 return NULL;4214}4215 4216__isl_give isl_basic_map *isl_basic_map_move_dims(4217 __isl_take isl_basic_map *bmap,4218 enum isl_dim_type dst_type, unsigned dst_pos,4219 enum isl_dim_type src_type, unsigned src_pos, unsigned n)4220{4221 isl_space *space;4222 struct isl_dim_map *dim_map;4223 struct isl_basic_map *res;4224 enum isl_dim_type t;4225 isl_size total;4226 unsigned off;4227 4228 if (!bmap)4229 return NULL;4230 if (n == 0) {4231 bmap = isl_basic_map_reset(bmap, src_type);4232 bmap = isl_basic_map_reset(bmap, dst_type);4233 return bmap;4234 }4235 4236 if (isl_basic_map_check_range(bmap, src_type, src_pos, n) < 0)4237 return isl_basic_map_free(bmap);4238 4239 if (dst_type == src_type && dst_pos == src_pos)4240 return bmap;4241 4242 isl_assert(bmap->ctx, dst_type != src_type, goto error);4243 4244 if (pos(bmap->dim, dst_type) + dst_pos ==4245 pos(bmap->dim, src_type) + src_pos +4246 ((src_type < dst_type) ? n : 0)) {4247 space = isl_basic_map_take_space(bmap);4248 space = isl_space_move_dims(space, dst_type, dst_pos,4249 src_type, src_pos, n);4250 bmap = isl_basic_map_restore_space(bmap, space);4251 bmap = isl_basic_map_finalize(bmap);4252 4253 return bmap;4254 }4255 4256 total = isl_basic_map_dim(bmap, isl_dim_all);4257 if (total < 0)4258 return isl_basic_map_free(bmap);4259 dim_map = isl_dim_map_alloc(bmap->ctx, total);4260 4261 off = 0;4262 space = isl_basic_map_peek_space(bmap);4263 for (t = isl_dim_param; t <= isl_dim_out; ++t) {4264 isl_size size = isl_space_dim(space, t);4265 if (size < 0)4266 dim_map = isl_dim_map_free(dim_map);4267 if (t == dst_type) {4268 isl_dim_map_dim_range(dim_map, space, t,4269 0, dst_pos, off);4270 off += dst_pos;4271 isl_dim_map_dim_range(dim_map, space, src_type,4272 src_pos, n, off);4273 off += n;4274 isl_dim_map_dim_range(dim_map, space, t,4275 dst_pos, size - dst_pos, off);4276 off += size - dst_pos;4277 } else if (t == src_type) {4278 isl_dim_map_dim_range(dim_map, space, t,4279 0, src_pos, off);4280 off += src_pos;4281 isl_dim_map_dim_range(dim_map, space, t,4282 src_pos + n, size - src_pos - n, off);4283 off += size - src_pos - n;4284 } else {4285 isl_dim_map_dim(dim_map, space, t, off);4286 off += size;4287 }4288 }4289 isl_dim_map_div(dim_map, bmap, off);4290 4291 res = isl_basic_map_alloc_space(isl_basic_map_get_space(bmap),4292 bmap->n_div, bmap->n_eq, bmap->n_ineq);4293 bmap = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);4294 space = isl_basic_map_take_space(bmap);4295 space = isl_space_move_dims(space, dst_type, dst_pos,4296 src_type, src_pos, n);4297 bmap = isl_basic_map_restore_space(bmap, space);4298 if (!bmap)4299 goto error;4300 4301 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);4302 bmap = isl_basic_map_gauss(bmap, NULL);4303 bmap = isl_basic_map_finalize(bmap);4304 4305 return bmap;4306error:4307 isl_basic_map_free(bmap);4308 return NULL;4309}4310 4311__isl_give isl_basic_set *isl_basic_set_move_dims(__isl_take isl_basic_set *bset,4312 enum isl_dim_type dst_type, unsigned dst_pos,4313 enum isl_dim_type src_type, unsigned src_pos, unsigned n)4314{4315 isl_basic_map *bmap = bset_to_bmap(bset);4316 bmap = isl_basic_map_move_dims(bmap, dst_type, dst_pos,4317 src_type, src_pos, n);4318 return bset_from_bmap(bmap);4319}4320 4321__isl_give isl_set *isl_set_move_dims(__isl_take isl_set *set,4322 enum isl_dim_type dst_type, unsigned dst_pos,4323 enum isl_dim_type src_type, unsigned src_pos, unsigned n)4324{4325 if (!set)4326 return NULL;4327 isl_assert(set->ctx, dst_type != isl_dim_in, goto error);4328 return set_from_map(isl_map_move_dims(set_to_map(set),4329 dst_type, dst_pos, src_type, src_pos, n));4330error:4331 isl_set_free(set);4332 return NULL;4333}4334 4335__isl_give isl_map *isl_map_move_dims(__isl_take isl_map *map,4336 enum isl_dim_type dst_type, unsigned dst_pos,4337 enum isl_dim_type src_type, unsigned src_pos, unsigned n)4338{4339 int i;4340 isl_space *space;4341 4342 if (n == 0) {4343 map = isl_map_reset(map, src_type);4344 map = isl_map_reset(map, dst_type);4345 return map;4346 }4347 4348 if (isl_map_check_range(map, src_type, src_pos, n))4349 return isl_map_free(map);4350 4351 if (dst_type == src_type && dst_pos == src_pos)4352 return map;4353 4354 isl_assert(map->ctx, dst_type != src_type, goto error);4355 4356 map = isl_map_cow(map);4357 if (!map)4358 return NULL;4359 4360 for (i = 0; i < map->n; ++i) {4361 map->p[i] = isl_basic_map_move_dims(map->p[i],4362 dst_type, dst_pos,4363 src_type, src_pos, n);4364 if (!map->p[i])4365 goto error;4366 }4367 4368 space = isl_map_take_space(map);4369 space = isl_space_move_dims(space, dst_type, dst_pos,4370 src_type, src_pos, n);4371 map = isl_map_restore_space(map, space);4372 4373 return map;4374error:4375 isl_map_free(map);4376 return NULL;4377}4378 4379/* Move the specified dimensions to the last columns right before4380 * the divs. Don't change the dimension specification of bmap.4381 * That's the responsibility of the caller.4382 */4383static __isl_give isl_basic_map *move_last(__isl_take isl_basic_map *bmap,4384 enum isl_dim_type type, unsigned first, unsigned n)4385{4386 isl_space *space;4387 struct isl_dim_map *dim_map;4388 struct isl_basic_map *res;4389 enum isl_dim_type t;4390 isl_size total;4391 unsigned off;4392 4393 if (!bmap)4394 return NULL;4395 if (isl_basic_map_offset(bmap, type) + first + n ==4396 isl_basic_map_offset(bmap, isl_dim_div))4397 return bmap;4398 4399 total = isl_basic_map_dim(bmap, isl_dim_all);4400 if (total < 0)4401 return isl_basic_map_free(bmap);4402 dim_map = isl_dim_map_alloc(bmap->ctx, total);4403 4404 off = 0;4405 space = isl_basic_map_peek_space(bmap);4406 for (t = isl_dim_param; t <= isl_dim_out; ++t) {4407 isl_size size = isl_space_dim(space, t);4408 if (size < 0)4409 dim_map = isl_dim_map_free(dim_map);4410 if (t == type) {4411 isl_dim_map_dim_range(dim_map, space, t,4412 0, first, off);4413 off += first;4414 isl_dim_map_dim_range(dim_map, space, t,4415 first, n, total - bmap->n_div - n);4416 isl_dim_map_dim_range(dim_map, space, t,4417 first + n, size - (first + n), off);4418 off += size - (first + n);4419 } else {4420 isl_dim_map_dim(dim_map, space, t, off);4421 off += size;4422 }4423 }4424 isl_dim_map_div(dim_map, bmap, off + n);4425 4426 res = isl_basic_map_alloc_space(isl_basic_map_get_space(bmap),4427 bmap->n_div, bmap->n_eq, bmap->n_ineq);4428 res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);4429 return res;4430}4431 4432/* Insert "n" rows in the divs of "bmap".4433 *4434 * The number of columns is not changed, which means that the last4435 * dimensions of "bmap" are being reintepreted as the new divs.4436 * The space of "bmap" is not adjusted, however, which means4437 * that "bmap" is left in an inconsistent state. Removing "n" dimensions4438 * from the space of "bmap" is the responsibility of the caller.4439 */4440static __isl_give isl_basic_map *insert_div_rows(__isl_take isl_basic_map *bmap,4441 int n)4442{4443 int i;4444 size_t row_size;4445 isl_int **new_div;4446 isl_int *old;4447 4448 bmap = isl_basic_map_cow(bmap);4449 if (!bmap)4450 return NULL;4451 4452 row_size = isl_basic_map_offset(bmap, isl_dim_div) + bmap->extra;4453 old = bmap->block2.data;4454 bmap->block2 = isl_blk_extend(bmap->ctx, bmap->block2,4455 (bmap->extra + n) * (1 + row_size));4456 if (!bmap->block2.data)4457 return isl_basic_map_free(bmap);4458 new_div = isl_alloc_array(bmap->ctx, isl_int *, bmap->extra + n);4459 if (!new_div)4460 return isl_basic_map_free(bmap);4461 for (i = 0; i < n; ++i) {4462 new_div[i] = bmap->block2.data +4463 (bmap->extra + i) * (1 + row_size);4464 isl_seq_clr(new_div[i], 1 + row_size);4465 }4466 for (i = 0; i < bmap->extra; ++i)4467 new_div[n + i] = bmap->block2.data + (bmap->div[i] - old);4468 free(bmap->div);4469 bmap->div = new_div;4470 bmap->n_div += n;4471 bmap->extra += n;4472 4473 return bmap;4474}4475 4476/* Drop constraints from "bmap" that only involve the variables4477 * of "type" in the range [first, first + n] that are not related4478 * to any of the variables outside that interval.4479 * These constraints cannot influence the values for the variables4480 * outside the interval, except in case they cause "bmap" to be empty.4481 * Only drop the constraints if "bmap" is known to be non-empty.4482 */4483static __isl_give isl_basic_map *drop_irrelevant_constraints(4484 __isl_take isl_basic_map *bmap, enum isl_dim_type type,4485 unsigned first, unsigned n)4486{4487 int i;4488 int *groups;4489 isl_size dim, n_div;4490 isl_bool non_empty;4491 4492 non_empty = isl_basic_map_plain_is_non_empty(bmap);4493 if (non_empty < 0)4494 return isl_basic_map_free(bmap);4495 if (!non_empty)4496 return bmap;4497 4498 dim = isl_basic_map_dim(bmap, isl_dim_all);4499 n_div = isl_basic_map_dim(bmap, isl_dim_div);4500 if (dim < 0 || n_div < 0)4501 return isl_basic_map_free(bmap);4502 groups = isl_calloc_array(isl_basic_map_get_ctx(bmap), int, dim);4503 if (!groups)4504 return isl_basic_map_free(bmap);4505 first += isl_basic_map_offset(bmap, type) - 1;4506 for (i = 0; i < first; ++i)4507 groups[i] = -1;4508 for (i = first + n; i < dim - n_div; ++i)4509 groups[i] = -1;4510 4511 bmap = isl_basic_map_drop_unrelated_constraints(bmap, groups);4512 4513 return bmap;4514}4515 4516/* Turn the n dimensions of type type, starting at first4517 * into existentially quantified variables.4518 *4519 * If a subset of the projected out variables are unrelated4520 * to any of the variables that remain, then the constraints4521 * involving this subset are simply dropped first.4522 */4523__isl_give isl_basic_map *isl_basic_map_project_out(4524 __isl_take isl_basic_map *bmap,4525 enum isl_dim_type type, unsigned first, unsigned n)4526{4527 isl_bool empty;4528 isl_space *space;4529 4530 if (n == 0)4531 return basic_map_space_reset(bmap, type);4532 if (type == isl_dim_div)4533 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,4534 "cannot project out existentially quantified variables",4535 return isl_basic_map_free(bmap));4536 4537 empty = isl_basic_map_plain_is_empty(bmap);4538 if (empty < 0)4539 return isl_basic_map_free(bmap);4540 if (empty)4541 bmap = isl_basic_map_set_to_empty(bmap);4542 4543 bmap = drop_irrelevant_constraints(bmap, type, first, n);4544 if (!bmap)4545 return NULL;4546 4547 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL))4548 return isl_basic_map_remove_dims(bmap, type, first, n);4549 4550 if (isl_basic_map_check_range(bmap, type, first, n) < 0)4551 return isl_basic_map_free(bmap);4552 4553 bmap = move_last(bmap, type, first, n);4554 bmap = isl_basic_map_cow(bmap);4555 bmap = insert_div_rows(bmap, n);4556 4557 space = isl_basic_map_take_space(bmap);4558 space = isl_space_drop_dims(space, type, first, n);4559 bmap = isl_basic_map_restore_space(bmap, space);4560 bmap = isl_basic_map_simplify(bmap);4561 bmap = isl_basic_map_drop_redundant_divs(bmap);4562 return isl_basic_map_finalize(bmap);4563}4564 4565/* Turn the n dimensions of type type, starting at first4566 * into existentially quantified variables.4567 */4568__isl_give isl_basic_set *isl_basic_set_project_out(4569 __isl_take isl_basic_set *bset, enum isl_dim_type type,4570 unsigned first, unsigned n)4571{4572 return bset_from_bmap(isl_basic_map_project_out(bset_to_bmap(bset),4573 type, first, n));4574}4575 4576/* Turn the n dimensions of type type, starting at first4577 * into existentially quantified variables.4578 */4579__isl_give isl_map *isl_map_project_out(__isl_take isl_map *map,4580 enum isl_dim_type type, unsigned first, unsigned n)4581{4582 int i;4583 isl_space *space;4584 4585 if (n == 0)4586 return map_space_reset(map, type);4587 4588 if (isl_map_check_range(map, type, first, n) < 0)4589 return isl_map_free(map);4590 4591 map = isl_map_cow(map);4592 if (!map)4593 return NULL;4594 4595 for (i = 0; i < map->n; ++i) {4596 map->p[i] = isl_basic_map_project_out(map->p[i], type, first, n);4597 if (!map->p[i])4598 goto error;4599 }4600 4601 if (map->n > 1)4602 ISL_F_CLR(map, ISL_MAP_DISJOINT);4603 map = isl_map_unmark_normalized(map);4604 4605 space = isl_map_take_space(map);4606 space = isl_space_drop_dims(space, type, first, n);4607 map = isl_map_restore_space(map, space);4608 4609 return map;4610error:4611 isl_map_free(map);4612 return NULL;4613}4614 4615#undef TYPE4616#define TYPE isl_map4617#include "isl_project_out_all_params_templ.c"4618#include "isl_project_out_param_templ.c"4619 4620/* Turn all the dimensions of type "type", except the "n" starting at "first"4621 * into existentially quantified variables.4622 */4623__isl_give isl_map *isl_map_project_onto(__isl_take isl_map *map,4624 enum isl_dim_type type, unsigned first, unsigned n)4625{4626 isl_size dim;4627 4628 dim = isl_map_dim(map, type);4629 if (isl_map_check_range(map, type, first, n) < 0 || dim < 0)4630 return isl_map_free(map);4631 map = isl_map_project_out(map, type, first + n, dim - (first + n));4632 map = isl_map_project_out(map, type, 0, first);4633 return map;4634}4635 4636/* Turn the n dimensions of type type, starting at first4637 * into existentially quantified variables.4638 */4639__isl_give isl_set *isl_set_project_out(__isl_take isl_set *set,4640 enum isl_dim_type type, unsigned first, unsigned n)4641{4642 return set_from_map(isl_map_project_out(set_to_map(set),4643 type, first, n));4644}4645 4646/* If "set" involves a parameter with identifier "id",4647 * then turn it into an existentially quantified variable.4648 */4649__isl_give isl_set *isl_set_project_out_param_id(__isl_take isl_set *set,4650 __isl_take isl_id *id)4651{4652 return set_from_map(isl_map_project_out_param_id(set_to_map(set), id));4653}4654 4655/* If "set" involves any of the parameters with identifiers in "list",4656 * then turn them into existentially quantified variables.4657 */4658__isl_give isl_set *isl_set_project_out_param_id_list(__isl_take isl_set *set,4659 __isl_take isl_id_list *list)4660{4661 isl_map *map;4662 4663 map = set_to_map(set);4664 map = isl_map_project_out_param_id_list(map, list);4665 return set_from_map(map);4666}4667 4668/* Project out all parameters from "set" by existentially quantifying4669 * over them.4670 */4671__isl_give isl_set *isl_set_project_out_all_params(__isl_take isl_set *set)4672{4673 return set_from_map(isl_map_project_out_all_params(set_to_map(set)));4674}4675 4676/* Return a map that projects the elements in "set" onto their4677 * "n" set dimensions starting at "first".4678 * "type" should be equal to isl_dim_set.4679 */4680__isl_give isl_map *isl_set_project_onto_map(__isl_take isl_set *set,4681 enum isl_dim_type type, unsigned first, unsigned n)4682{4683 int i;4684 isl_map *map;4685 4686 if (type != isl_dim_set)4687 isl_die(isl_set_get_ctx(set), isl_error_invalid,4688 "only set dimensions can be projected out", goto error);4689 if (isl_set_check_range(set, type, first, n) < 0)4690 return isl_set_free(set);4691 4692 map = isl_map_from_domain(set);4693 map = isl_map_add_dims(map, isl_dim_out, n);4694 for (i = 0; i < n; ++i)4695 map = isl_map_equate(map, isl_dim_in, first + i,4696 isl_dim_out, i);4697 return map;4698error:4699 isl_set_free(set);4700 return NULL;4701}4702 4703static __isl_give isl_basic_map *add_divs(__isl_take isl_basic_map *bmap,4704 unsigned n)4705{4706 int i, j;4707 isl_size total;4708 4709 total = isl_basic_map_dim(bmap, isl_dim_all);4710 if (total < 0)4711 return isl_basic_map_free(bmap);4712 for (i = 0; i < n; ++i) {4713 j = isl_basic_map_alloc_div(bmap);4714 if (j < 0)4715 goto error;4716 isl_seq_clr(bmap->div[j], 1 + 1 + total);4717 }4718 return bmap;4719error:4720 isl_basic_map_free(bmap);4721 return NULL;4722}4723 4724/* Does "bmap2" apply to the range of "bmap1" (ignoring parameters)?4725 */4726isl_bool isl_basic_map_applies_range(__isl_keep isl_basic_map *bmap1,4727 __isl_keep isl_basic_map *bmap2)4728{4729 isl_space *space1, *space2;4730 4731 space1 = isl_basic_map_peek_space(bmap1);4732 space2 = isl_basic_map_peek_space(bmap2);4733 return isl_space_tuple_is_equal(space1, isl_dim_out,4734 space2, isl_dim_in);4735}4736 4737/* Check that "bmap2" applies to the range of "bmap1" (ignoring parameters).4738 */4739static isl_stat isl_basic_map_check_applies_range(4740 __isl_keep isl_basic_map *bmap1, __isl_keep isl_basic_map *bmap2)4741{4742 isl_bool equal;4743 4744 equal = isl_basic_map_applies_range(bmap1, bmap2);4745 if (equal < 0)4746 return isl_stat_error;4747 if (!equal)4748 isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,4749 "spaces don't match", return isl_stat_error);4750 return isl_stat_ok;4751}4752 4753__isl_give isl_basic_map *isl_basic_map_apply_range(4754 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)4755{4756 isl_space *space_result = NULL;4757 struct isl_basic_map *bmap;4758 isl_size n_in, n_out, n, nparam;4759 unsigned total, pos;4760 struct isl_dim_map *dim_map1, *dim_map2;4761 4762 if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)4763 goto error;4764 if (isl_basic_map_check_applies_range(bmap1, bmap2) < 0)4765 goto error;4766 4767 n_in = isl_basic_map_dim(bmap1, isl_dim_in);4768 n_out = isl_basic_map_dim(bmap2, isl_dim_out);4769 n = isl_basic_map_dim(bmap1, isl_dim_out);4770 nparam = isl_basic_map_dim(bmap1, isl_dim_param);4771 if (n_in < 0 || n_out < 0 || n < 0 || nparam < 0)4772 goto error;4773 4774 space_result = isl_space_join(isl_basic_map_get_space(bmap1),4775 isl_basic_map_get_space(bmap2));4776 4777 total = nparam + n_in + n_out + bmap1->n_div + bmap2->n_div + n;4778 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);4779 dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);4780 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);4781 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);4782 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);4783 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += n_in);4784 isl_dim_map_div(dim_map1, bmap1, pos += n_out);4785 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);4786 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += bmap2->n_div);4787 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos);4788 4789 bmap = isl_basic_map_alloc_space(space_result,4790 bmap1->n_div + bmap2->n_div + n,4791 bmap1->n_eq + bmap2->n_eq,4792 bmap1->n_ineq + bmap2->n_ineq);4793 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);4794 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);4795 bmap = add_divs(bmap, n);4796 bmap = isl_basic_map_simplify(bmap);4797 bmap = isl_basic_map_drop_redundant_divs(bmap);4798 return isl_basic_map_finalize(bmap);4799error:4800 isl_basic_map_free(bmap1);4801 isl_basic_map_free(bmap2);4802 return NULL;4803}4804 4805__isl_give isl_basic_set *isl_basic_set_apply(__isl_take isl_basic_set *bset,4806 __isl_take isl_basic_map *bmap)4807{4808 if (isl_basic_map_check_compatible_domain(bmap, bset) < 0)4809 goto error;4810 4811 return bset_from_bmap(isl_basic_map_apply_range(bset_to_bmap(bset),4812 bmap));4813error:4814 isl_basic_set_free(bset);4815 isl_basic_map_free(bmap);4816 return NULL;4817}4818 4819__isl_give isl_basic_map *isl_basic_map_apply_domain(4820 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)4821{4822 if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)4823 goto error;4824 if (!isl_space_tuple_is_equal(bmap1->dim, isl_dim_in,4825 bmap2->dim, isl_dim_in))4826 isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,4827 "spaces don't match", goto error);4828 4829 bmap1 = isl_basic_map_reverse(bmap1);4830 bmap1 = isl_basic_map_apply_range(bmap1, bmap2);4831 return isl_basic_map_reverse(bmap1);4832error:4833 isl_basic_map_free(bmap1);4834 isl_basic_map_free(bmap2);4835 return NULL;4836}4837 4838/* Given two basic maps A -> f(A) and B -> g(B), construct a basic map4839 * A \cap B -> f(A) + f(B)4840 */4841__isl_give isl_basic_map *isl_basic_map_sum(__isl_take isl_basic_map *bmap1,4842 __isl_take isl_basic_map *bmap2)4843{4844 isl_size n_in, n_out, nparam;4845 unsigned total, pos;4846 struct isl_basic_map *bmap = NULL;4847 struct isl_dim_map *dim_map1, *dim_map2;4848 int i;4849 4850 if (isl_basic_map_check_equal_space(bmap1, bmap2) < 0)4851 goto error;4852 4853 nparam = isl_basic_map_dim(bmap1, isl_dim_param);4854 n_in = isl_basic_map_dim(bmap1, isl_dim_in);4855 n_out = isl_basic_map_dim(bmap1, isl_dim_out);4856 if (nparam < 0 || n_in < 0 || n_out < 0)4857 goto error;4858 4859 total = nparam + n_in + n_out + bmap1->n_div + bmap2->n_div + 2 * n_out;4860 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);4861 dim_map2 = isl_dim_map_alloc(bmap2->ctx, total);4862 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);4863 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos);4864 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);4865 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos);4866 isl_dim_map_div(dim_map1, bmap1, pos += n_in + n_out);4867 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);4868 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += bmap2->n_div);4869 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += n_out);4870 4871 bmap = isl_basic_map_alloc_space(isl_space_copy(bmap1->dim),4872 bmap1->n_div + bmap2->n_div + 2 * n_out,4873 bmap1->n_eq + bmap2->n_eq + n_out,4874 bmap1->n_ineq + bmap2->n_ineq);4875 for (i = 0; i < n_out; ++i) {4876 int j = isl_basic_map_alloc_equality(bmap);4877 if (j < 0)4878 goto error;4879 isl_seq_clr(bmap->eq[j], 1+total);4880 isl_int_set_si(bmap->eq[j][1+nparam+n_in+i], -1);4881 isl_int_set_si(bmap->eq[j][1+pos+i], 1);4882 isl_int_set_si(bmap->eq[j][1+pos-n_out+i], 1);4883 }4884 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);4885 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);4886 bmap = add_divs(bmap, 2 * n_out);4887 4888 bmap = isl_basic_map_simplify(bmap);4889 return isl_basic_map_finalize(bmap);4890error:4891 isl_basic_map_free(bmap);4892 isl_basic_map_free(bmap1);4893 isl_basic_map_free(bmap2);4894 return NULL;4895}4896 4897/* Given two maps A -> f(A) and B -> g(B), construct a map4898 * A \cap B -> f(A) + f(B)4899 */4900__isl_give isl_map *isl_map_sum(__isl_take isl_map *map1,4901 __isl_take isl_map *map2)4902{4903 struct isl_map *result;4904 int i, j;4905 4906 if (isl_map_check_equal_space(map1, map2) < 0)4907 goto error;4908 4909 result = isl_map_alloc_space(isl_space_copy(map1->dim),4910 map1->n * map2->n, 0);4911 if (!result)4912 goto error;4913 for (i = 0; i < map1->n; ++i)4914 for (j = 0; j < map2->n; ++j) {4915 struct isl_basic_map *part;4916 part = isl_basic_map_sum(4917 isl_basic_map_copy(map1->p[i]),4918 isl_basic_map_copy(map2->p[j]));4919 if (isl_basic_map_is_empty(part))4920 isl_basic_map_free(part);4921 else4922 result = isl_map_add_basic_map(result, part);4923 if (!result)4924 goto error;4925 }4926 isl_map_free(map1);4927 isl_map_free(map2);4928 return result;4929error:4930 isl_map_free(map1);4931 isl_map_free(map2);4932 return NULL;4933}4934 4935__isl_give isl_set *isl_set_sum(__isl_take isl_set *set1,4936 __isl_take isl_set *set2)4937{4938 return set_from_map(isl_map_sum(set_to_map(set1), set_to_map(set2)));4939}4940 4941/* Given a basic map A -> f(A), construct A -> -f(A).4942 */4943__isl_give isl_basic_map *isl_basic_map_neg(__isl_take isl_basic_map *bmap)4944{4945 int i, j;4946 unsigned off;4947 isl_size n;4948 4949 bmap = isl_basic_map_cow(bmap);4950 n = isl_basic_map_dim(bmap, isl_dim_out);4951 if (n < 0)4952 return isl_basic_map_free(bmap);4953 4954 off = isl_basic_map_offset(bmap, isl_dim_out);4955 for (i = 0; i < bmap->n_eq; ++i)4956 for (j = 0; j < n; ++j)4957 isl_int_neg(bmap->eq[i][off+j], bmap->eq[i][off+j]);4958 for (i = 0; i < bmap->n_ineq; ++i)4959 for (j = 0; j < n; ++j)4960 isl_int_neg(bmap->ineq[i][off+j], bmap->ineq[i][off+j]);4961 for (i = 0; i < bmap->n_div; ++i)4962 for (j = 0; j < n; ++j)4963 isl_int_neg(bmap->div[i][1+off+j], bmap->div[i][1+off+j]);4964 bmap = isl_basic_map_gauss(bmap, NULL);4965 return isl_basic_map_finalize(bmap);4966}4967 4968__isl_give isl_basic_set *isl_basic_set_neg(__isl_take isl_basic_set *bset)4969{4970 return isl_basic_map_neg(bset);4971}4972 4973/* Given a map A -> f(A), construct A -> -f(A).4974 */4975__isl_give isl_map *isl_map_neg(__isl_take isl_map *map)4976{4977 int i;4978 4979 map = isl_map_cow(map);4980 if (!map)4981 return NULL;4982 4983 for (i = 0; i < map->n; ++i) {4984 map->p[i] = isl_basic_map_neg(map->p[i]);4985 if (!map->p[i])4986 goto error;4987 }4988 4989 return map;4990error:4991 isl_map_free(map);4992 return NULL;4993}4994 4995__isl_give isl_set *isl_set_neg(__isl_take isl_set *set)4996{4997 return set_from_map(isl_map_neg(set_to_map(set)));4998}4999 5000/* Given a basic map A -> f(A) and an integer d, construct a basic map5001 * A -> floor(f(A)/d).5002 */5003__isl_give isl_basic_map *isl_basic_map_floordiv(__isl_take isl_basic_map *bmap,5004 isl_int d)5005{5006 isl_size n_in, n_out, nparam;5007 unsigned total, pos;5008 struct isl_basic_map *result = NULL;5009 struct isl_dim_map *dim_map;5010 int i;5011 5012 nparam = isl_basic_map_dim(bmap, isl_dim_param);5013 n_in = isl_basic_map_dim(bmap, isl_dim_in);5014 n_out = isl_basic_map_dim(bmap, isl_dim_out);5015 if (nparam < 0 || n_in < 0 || n_out < 0)5016 return isl_basic_map_free(bmap);5017 5018 total = nparam + n_in + n_out + bmap->n_div + n_out;5019 dim_map = isl_dim_map_alloc(bmap->ctx, total);5020 isl_dim_map_dim(dim_map, bmap->dim, isl_dim_param, pos = 0);5021 isl_dim_map_dim(dim_map, bmap->dim, isl_dim_in, pos += nparam);5022 isl_dim_map_div(dim_map, bmap, pos += n_in + n_out);5023 isl_dim_map_dim(dim_map, bmap->dim, isl_dim_out, pos += bmap->n_div);5024 5025 result = isl_basic_map_alloc_space(isl_space_copy(bmap->dim),5026 bmap->n_div + n_out,5027 bmap->n_eq, bmap->n_ineq + 2 * n_out);5028 result = isl_basic_map_add_constraints_dim_map(result, bmap, dim_map);5029 result = add_divs(result, n_out);5030 for (i = 0; i < n_out; ++i) {5031 int j;5032 j = isl_basic_map_alloc_inequality(result);5033 if (j < 0)5034 goto error;5035 isl_seq_clr(result->ineq[j], 1+total);5036 isl_int_neg(result->ineq[j][1+nparam+n_in+i], d);5037 isl_int_set_si(result->ineq[j][1+pos+i], 1);5038 j = isl_basic_map_alloc_inequality(result);5039 if (j < 0)5040 goto error;5041 isl_seq_clr(result->ineq[j], 1+total);5042 isl_int_set(result->ineq[j][1+nparam+n_in+i], d);5043 isl_int_set_si(result->ineq[j][1+pos+i], -1);5044 isl_int_sub_ui(result->ineq[j][0], d, 1);5045 }5046 5047 result = isl_basic_map_simplify(result);5048 return isl_basic_map_finalize(result);5049error:5050 isl_basic_map_free(result);5051 return NULL;5052}5053 5054/* Given a map A -> f(A) and an integer d, construct a map5055 * A -> floor(f(A)/d).5056 */5057__isl_give isl_map *isl_map_floordiv(__isl_take isl_map *map, isl_int d)5058{5059 int i;5060 5061 map = isl_map_cow(map);5062 if (!map)5063 return NULL;5064 5065 ISL_F_CLR(map, ISL_MAP_DISJOINT);5066 for (i = 0; i < map->n; ++i) {5067 map->p[i] = isl_basic_map_floordiv(map->p[i], d);5068 if (!map->p[i])5069 goto error;5070 }5071 map = isl_map_unmark_normalized(map);5072 5073 return map;5074error:5075 isl_map_free(map);5076 return NULL;5077}5078 5079/* Given a map A -> f(A) and an integer d, construct a map5080 * A -> floor(f(A)/d).5081 */5082__isl_give isl_map *isl_map_floordiv_val(__isl_take isl_map *map,5083 __isl_take isl_val *d)5084{5085 if (!map || !d)5086 goto error;5087 if (!isl_val_is_int(d))5088 isl_die(isl_val_get_ctx(d), isl_error_invalid,5089 "expecting integer denominator", goto error);5090 map = isl_map_floordiv(map, d->n);5091 isl_val_free(d);5092 return map;5093error:5094 isl_map_free(map);5095 isl_val_free(d);5096 return NULL;5097}5098 5099static __isl_give isl_basic_map *var_equal(__isl_take isl_basic_map *bmap,5100 unsigned pos)5101{5102 int i;5103 isl_size nparam;5104 isl_size n_in;5105 isl_size total;5106 5107 total = isl_basic_map_dim(bmap, isl_dim_all);5108 nparam = isl_basic_map_dim(bmap, isl_dim_param);5109 n_in = isl_basic_map_dim(bmap, isl_dim_in);5110 if (total < 0 || nparam < 0 || n_in < 0)5111 return isl_basic_map_free(bmap);5112 i = isl_basic_map_alloc_equality(bmap);5113 if (i < 0)5114 goto error;5115 isl_seq_clr(bmap->eq[i], 1 + total);5116 isl_int_set_si(bmap->eq[i][1+nparam+pos], -1);5117 isl_int_set_si(bmap->eq[i][1+nparam+n_in+pos], 1);5118 return isl_basic_map_finalize(bmap);5119error:5120 isl_basic_map_free(bmap);5121 return NULL;5122}5123 5124/* Add a constraint to "bmap" expressing i_pos < o_pos5125 */5126static __isl_give isl_basic_map *var_less(__isl_take isl_basic_map *bmap,5127 unsigned pos)5128{5129 int i;5130 isl_size nparam;5131 isl_size n_in;5132 isl_size total;5133 5134 total = isl_basic_map_dim(bmap, isl_dim_all);5135 nparam = isl_basic_map_dim(bmap, isl_dim_param);5136 n_in = isl_basic_map_dim(bmap, isl_dim_in);5137 if (total < 0 || nparam < 0 || n_in < 0)5138 return isl_basic_map_free(bmap);5139 i = isl_basic_map_alloc_inequality(bmap);5140 if (i < 0)5141 goto error;5142 isl_seq_clr(bmap->ineq[i], 1 + total);5143 isl_int_set_si(bmap->ineq[i][0], -1);5144 isl_int_set_si(bmap->ineq[i][1+nparam+pos], -1);5145 isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], 1);5146 return isl_basic_map_finalize(bmap);5147error:5148 isl_basic_map_free(bmap);5149 return NULL;5150}5151 5152/* Add a constraint to "bmap" expressing i_pos <= o_pos5153 */5154static __isl_give isl_basic_map *var_less_or_equal(5155 __isl_take isl_basic_map *bmap, unsigned pos)5156{5157 int i;5158 isl_size nparam;5159 isl_size n_in;5160 isl_size total;5161 5162 total = isl_basic_map_dim(bmap, isl_dim_all);5163 nparam = isl_basic_map_dim(bmap, isl_dim_param);5164 n_in = isl_basic_map_dim(bmap, isl_dim_in);5165 if (total < 0 || nparam < 0 || n_in < 0)5166 return isl_basic_map_free(bmap);5167 i = isl_basic_map_alloc_inequality(bmap);5168 if (i < 0)5169 goto error;5170 isl_seq_clr(bmap->ineq[i], 1 + total);5171 isl_int_set_si(bmap->ineq[i][1+nparam+pos], -1);5172 isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], 1);5173 return isl_basic_map_finalize(bmap);5174error:5175 isl_basic_map_free(bmap);5176 return NULL;5177}5178 5179/* Add a constraint to "bmap" expressing i_pos > o_pos5180 */5181static __isl_give isl_basic_map *var_more(__isl_take isl_basic_map *bmap,5182 unsigned pos)5183{5184 int i;5185 isl_size nparam;5186 isl_size n_in;5187 isl_size total;5188 5189 total = isl_basic_map_dim(bmap, isl_dim_all);5190 nparam = isl_basic_map_dim(bmap, isl_dim_param);5191 n_in = isl_basic_map_dim(bmap, isl_dim_in);5192 if (total < 0 || nparam < 0 || n_in < 0)5193 return isl_basic_map_free(bmap);5194 i = isl_basic_map_alloc_inequality(bmap);5195 if (i < 0)5196 goto error;5197 isl_seq_clr(bmap->ineq[i], 1 + total);5198 isl_int_set_si(bmap->ineq[i][0], -1);5199 isl_int_set_si(bmap->ineq[i][1+nparam+pos], 1);5200 isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], -1);5201 return isl_basic_map_finalize(bmap);5202error:5203 isl_basic_map_free(bmap);5204 return NULL;5205}5206 5207/* Add a constraint to "bmap" expressing i_pos >= o_pos5208 */5209static __isl_give isl_basic_map *var_more_or_equal(5210 __isl_take isl_basic_map *bmap, unsigned pos)5211{5212 int i;5213 isl_size nparam;5214 isl_size n_in;5215 isl_size total;5216 5217 total = isl_basic_map_dim(bmap, isl_dim_all);5218 nparam = isl_basic_map_dim(bmap, isl_dim_param);5219 n_in = isl_basic_map_dim(bmap, isl_dim_in);5220 if (total < 0 || nparam < 0 || n_in < 0)5221 return isl_basic_map_free(bmap);5222 i = isl_basic_map_alloc_inequality(bmap);5223 if (i < 0)5224 goto error;5225 isl_seq_clr(bmap->ineq[i], 1 + total);5226 isl_int_set_si(bmap->ineq[i][1+nparam+pos], 1);5227 isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], -1);5228 return isl_basic_map_finalize(bmap);5229error:5230 isl_basic_map_free(bmap);5231 return NULL;5232}5233 5234__isl_give isl_basic_map *isl_basic_map_equal(5235 __isl_take isl_space *space, unsigned n_equal)5236{5237 int i;5238 struct isl_basic_map *bmap;5239 bmap = isl_basic_map_alloc_space(space, 0, n_equal, 0);5240 if (!bmap)5241 return NULL;5242 for (i = 0; i < n_equal && bmap; ++i)5243 bmap = var_equal(bmap, i);5244 return isl_basic_map_finalize(bmap);5245}5246 5247/* Return a relation on of dimension "space" expressing i_[0..pos] << o_[0..pos]5248 */5249__isl_give isl_basic_map *isl_basic_map_less_at(__isl_take isl_space *space,5250 unsigned pos)5251{5252 int i;5253 struct isl_basic_map *bmap;5254 bmap = isl_basic_map_alloc_space(space, 0, pos, 1);5255 if (!bmap)5256 return NULL;5257 for (i = 0; i < pos && bmap; ++i)5258 bmap = var_equal(bmap, i);5259 if (bmap)5260 bmap = var_less(bmap, pos);5261 return isl_basic_map_finalize(bmap);5262}5263 5264/* Return a relation on "space" expressing i_[0..pos] <<= o_[0..pos]5265 */5266__isl_give isl_basic_map *isl_basic_map_less_or_equal_at(5267 __isl_take isl_space *space, unsigned pos)5268{5269 int i;5270 isl_basic_map *bmap;5271 5272 bmap = isl_basic_map_alloc_space(space, 0, pos, 1);5273 for (i = 0; i < pos; ++i)5274 bmap = var_equal(bmap, i);5275 bmap = var_less_or_equal(bmap, pos);5276 return isl_basic_map_finalize(bmap);5277}5278 5279/* Return a relation on "space" expressing i_pos > o_pos5280 */5281__isl_give isl_basic_map *isl_basic_map_more_at(__isl_take isl_space *space,5282 unsigned pos)5283{5284 int i;5285 struct isl_basic_map *bmap;5286 bmap = isl_basic_map_alloc_space(space, 0, pos, 1);5287 if (!bmap)5288 return NULL;5289 for (i = 0; i < pos && bmap; ++i)5290 bmap = var_equal(bmap, i);5291 if (bmap)5292 bmap = var_more(bmap, pos);5293 return isl_basic_map_finalize(bmap);5294}5295 5296/* Return a relation on "space" expressing i_[0..pos] >>= o_[0..pos]5297 */5298__isl_give isl_basic_map *isl_basic_map_more_or_equal_at(5299 __isl_take isl_space *space, unsigned pos)5300{5301 int i;5302 isl_basic_map *bmap;5303 5304 bmap = isl_basic_map_alloc_space(space, 0, pos, 1);5305 for (i = 0; i < pos; ++i)5306 bmap = var_equal(bmap, i);5307 bmap = var_more_or_equal(bmap, pos);5308 return isl_basic_map_finalize(bmap);5309}5310 5311static __isl_give isl_map *map_lex_lte_first(__isl_take isl_space *space,5312 unsigned n, int equal)5313{5314 struct isl_map *map;5315 int i;5316 5317 if (n == 0 && equal)5318 return isl_map_universe(space);5319 5320 map = isl_map_alloc_space(isl_space_copy(space), n, ISL_MAP_DISJOINT);5321 5322 for (i = 0; i + 1 < n; ++i)5323 map = isl_map_add_basic_map(map,5324 isl_basic_map_less_at(isl_space_copy(space), i));5325 if (n > 0) {5326 if (equal)5327 map = isl_map_add_basic_map(map,5328 isl_basic_map_less_or_equal_at(space, n - 1));5329 else5330 map = isl_map_add_basic_map(map,5331 isl_basic_map_less_at(space, n - 1));5332 } else5333 isl_space_free(space);5334 5335 return map;5336}5337 5338static __isl_give isl_map *map_lex_lte(__isl_take isl_space *space, int equal)5339{5340 if (!space)5341 return NULL;5342 return map_lex_lte_first(space, space->n_out, equal);5343}5344 5345__isl_give isl_map *isl_map_lex_lt_first(__isl_take isl_space *space,5346 unsigned n)5347{5348 return map_lex_lte_first(space, n, 0);5349}5350 5351__isl_give isl_map *isl_map_lex_le_first(__isl_take isl_space *space,5352 unsigned n)5353{5354 return map_lex_lte_first(space, n, 1);5355}5356 5357__isl_give isl_map *isl_map_lex_lt(__isl_take isl_space *set_space)5358{5359 return map_lex_lte(isl_space_map_from_set(set_space), 0);5360}5361 5362__isl_give isl_map *isl_map_lex_le(__isl_take isl_space *set_space)5363{5364 return map_lex_lte(isl_space_map_from_set(set_space), 1);5365}5366 5367static __isl_give isl_map *map_lex_gte_first(__isl_take isl_space *space,5368 unsigned n, int equal)5369{5370 struct isl_map *map;5371 int i;5372 5373 if (n == 0 && equal)5374 return isl_map_universe(space);5375 5376 map = isl_map_alloc_space(isl_space_copy(space), n, ISL_MAP_DISJOINT);5377 5378 for (i = 0; i + 1 < n; ++i)5379 map = isl_map_add_basic_map(map,5380 isl_basic_map_more_at(isl_space_copy(space), i));5381 if (n > 0) {5382 if (equal)5383 map = isl_map_add_basic_map(map,5384 isl_basic_map_more_or_equal_at(space, n - 1));5385 else5386 map = isl_map_add_basic_map(map,5387 isl_basic_map_more_at(space, n - 1));5388 } else5389 isl_space_free(space);5390 5391 return map;5392}5393 5394static __isl_give isl_map *map_lex_gte(__isl_take isl_space *space, int equal)5395{5396 if (!space)5397 return NULL;5398 return map_lex_gte_first(space, space->n_out, equal);5399}5400 5401__isl_give isl_map *isl_map_lex_gt_first(__isl_take isl_space *space,5402 unsigned n)5403{5404 return map_lex_gte_first(space, n, 0);5405}5406 5407__isl_give isl_map *isl_map_lex_ge_first(__isl_take isl_space *space,5408 unsigned n)5409{5410 return map_lex_gte_first(space, n, 1);5411}5412 5413__isl_give isl_map *isl_map_lex_gt(__isl_take isl_space *set_space)5414{5415 return map_lex_gte(isl_space_map_from_set(set_space), 0);5416}5417 5418__isl_give isl_map *isl_map_lex_ge(__isl_take isl_space *set_space)5419{5420 return map_lex_gte(isl_space_map_from_set(set_space), 1);5421}5422 5423__isl_give isl_map *isl_set_lex_le_set(__isl_take isl_set *set1,5424 __isl_take isl_set *set2)5425{5426 isl_map *map;5427 map = isl_map_lex_le(isl_set_get_space(set1));5428 map = isl_map_intersect_domain(map, set1);5429 map = isl_map_intersect_range(map, set2);5430 return map;5431}5432 5433__isl_give isl_map *isl_set_lex_lt_set(__isl_take isl_set *set1,5434 __isl_take isl_set *set2)5435{5436 isl_map *map;5437 map = isl_map_lex_lt(isl_set_get_space(set1));5438 map = isl_map_intersect_domain(map, set1);5439 map = isl_map_intersect_range(map, set2);5440 return map;5441}5442 5443__isl_give isl_map *isl_set_lex_ge_set(__isl_take isl_set *set1,5444 __isl_take isl_set *set2)5445{5446 isl_map *map;5447 map = isl_map_lex_ge(isl_set_get_space(set1));5448 map = isl_map_intersect_domain(map, set1);5449 map = isl_map_intersect_range(map, set2);5450 return map;5451}5452 5453__isl_give isl_map *isl_set_lex_gt_set(__isl_take isl_set *set1,5454 __isl_take isl_set *set2)5455{5456 isl_map *map;5457 map = isl_map_lex_gt(isl_set_get_space(set1));5458 map = isl_map_intersect_domain(map, set1);5459 map = isl_map_intersect_range(map, set2);5460 return map;5461}5462 5463__isl_give isl_map *isl_map_lex_le_map(__isl_take isl_map *map1,5464 __isl_take isl_map *map2)5465{5466 isl_map *map;5467 map = isl_map_lex_le(isl_space_range(isl_map_get_space(map1)));5468 map = isl_map_apply_domain(map, isl_map_reverse(map1));5469 map = isl_map_apply_range(map, isl_map_reverse(map2));5470 return map;5471}5472 5473__isl_give isl_map *isl_map_lex_lt_map(__isl_take isl_map *map1,5474 __isl_take isl_map *map2)5475{5476 isl_map *map;5477 map = isl_map_lex_lt(isl_space_range(isl_map_get_space(map1)));5478 map = isl_map_apply_domain(map, isl_map_reverse(map1));5479 map = isl_map_apply_range(map, isl_map_reverse(map2));5480 return map;5481}5482 5483__isl_give isl_map *isl_map_lex_ge_map(__isl_take isl_map *map1,5484 __isl_take isl_map *map2)5485{5486 isl_map *map;5487 map = isl_map_lex_ge(isl_space_range(isl_map_get_space(map1)));5488 map = isl_map_apply_domain(map, isl_map_reverse(map1));5489 map = isl_map_apply_range(map, isl_map_reverse(map2));5490 return map;5491}5492 5493__isl_give isl_map *isl_map_lex_gt_map(__isl_take isl_map *map1,5494 __isl_take isl_map *map2)5495{5496 isl_map *map;5497 map = isl_map_lex_gt(isl_space_range(isl_map_get_space(map1)));5498 map = isl_map_apply_domain(map, isl_map_reverse(map1));5499 map = isl_map_apply_range(map, isl_map_reverse(map2));5500 return map;5501}5502 5503/* For the div d = floor(f/m) at position "div", add the constraint5504 *5505 * f - m d >= 05506 */5507static __isl_give isl_basic_map *add_upper_div_constraint(5508 __isl_take isl_basic_map *bmap, unsigned div)5509{5510 int i;5511 isl_size v_div = isl_basic_map_var_offset(bmap, isl_dim_div);5512 isl_size n_div;5513 unsigned pos;5514 5515 n_div = isl_basic_map_dim(bmap, isl_dim_div);5516 if (v_div < 0 || n_div < 0)5517 return isl_basic_map_free(bmap);5518 pos = v_div + div;5519 i = isl_basic_map_alloc_inequality(bmap);5520 if (i < 0)5521 return isl_basic_map_free(bmap);5522 isl_seq_cpy(bmap->ineq[i], bmap->div[div] + 1, 1 + v_div + n_div);5523 isl_int_neg(bmap->ineq[i][1 + pos], bmap->div[div][0]);5524 5525 return bmap;5526}5527 5528/* For the div d = floor(f/m) at position "div", add the constraint5529 *5530 * -(f-(m-1)) + m d >= 05531 */5532static __isl_give isl_basic_map *add_lower_div_constraint(5533 __isl_take isl_basic_map *bmap, unsigned div)5534{5535 int i;5536 isl_size v_div = isl_basic_map_var_offset(bmap, isl_dim_div);5537 isl_size n_div;5538 unsigned pos;5539 5540 n_div = isl_basic_map_dim(bmap, isl_dim_div);5541 if (v_div < 0 || n_div < 0)5542 return isl_basic_map_free(bmap);5543 pos = v_div + div;5544 i = isl_basic_map_alloc_inequality(bmap);5545 if (i < 0)5546 return isl_basic_map_free(bmap);5547 isl_seq_neg(bmap->ineq[i], bmap->div[div] + 1, 1 + v_div + n_div);5548 isl_int_set(bmap->ineq[i][1 + pos], bmap->div[div][0]);5549 isl_int_add(bmap->ineq[i][0], bmap->ineq[i][0], bmap->ineq[i][1 + pos]);5550 isl_int_sub_ui(bmap->ineq[i][0], bmap->ineq[i][0], 1);5551 5552 return bmap;5553}5554 5555/* For the div d = floor(f/m) at position "pos", add the constraints5556 *5557 * f - m d >= 05558 * -(f-(m-1)) + m d >= 05559 *5560 * Note that the second constraint is the negation of5561 *5562 * f - m d >= m5563 */5564__isl_give isl_basic_map *isl_basic_map_add_div_constraints(5565 __isl_take isl_basic_map *bmap, unsigned pos)5566{5567 bmap = add_upper_div_constraint(bmap, pos);5568 bmap = add_lower_div_constraint(bmap, pos);5569 return bmap;5570}5571 5572/* For each known div d = floor(f/m), add the constraints5573 *5574 * f - m d >= 05575 * -(f-(m-1)) + m d >= 05576 *5577 * Remove duplicate constraints in case of some these div constraints5578 * already appear in "bmap".5579 */5580__isl_give isl_basic_map *isl_basic_map_add_known_div_constraints(5581 __isl_take isl_basic_map *bmap)5582{5583 isl_size n_div;5584 5585 n_div = isl_basic_map_dim(bmap, isl_dim_div);5586 if (n_div < 0)5587 return isl_basic_map_free(bmap);5588 if (n_div == 0)5589 return bmap;5590 5591 bmap = add_known_div_constraints(bmap);5592 bmap = isl_basic_map_remove_duplicate_constraints(bmap, NULL, 0);5593 bmap = isl_basic_map_finalize(bmap);5594 return bmap;5595}5596 5597/* Add the div constraint of sign "sign" for div "div" of "bmap".5598 *5599 * In particular, if this div is of the form d = floor(f/m),5600 * then add the constraint5601 *5602 * f - m d >= 05603 *5604 * if sign < 0 or the constraint5605 *5606 * -(f-(m-1)) + m d >= 05607 *5608 * if sign > 0.5609 */5610__isl_give isl_basic_map *isl_basic_map_add_div_constraint(5611 __isl_take isl_basic_map *bmap, unsigned div, int sign)5612{5613 if (sign < 0)5614 return add_upper_div_constraint(bmap, div);5615 else5616 return add_lower_div_constraint(bmap, div);5617}5618 5619__isl_give isl_basic_set *isl_basic_map_underlying_set(5620 __isl_take isl_basic_map *bmap)5621{5622 isl_space *space;5623 5624 if (!bmap)5625 goto error;5626 if (bmap->dim->nparam == 0 && bmap->dim->n_in == 0 &&5627 bmap->n_div == 0 &&5628 !isl_space_is_named_or_nested(bmap->dim, isl_dim_in) &&5629 !isl_space_is_named_or_nested(bmap->dim, isl_dim_out))5630 return bset_from_bmap(bmap);5631 bmap = isl_basic_map_cow(bmap);5632 if (!bmap)5633 return NULL;5634 space = isl_basic_map_take_space(bmap);5635 space = isl_space_underlying(space, bmap->n_div);5636 bmap = isl_basic_map_restore_space(bmap, space);5637 if (!bmap)5638 return NULL;5639 bmap->extra -= bmap->n_div;5640 bmap->n_div = 0;5641 bmap = isl_basic_map_finalize(bmap);5642 return bset_from_bmap(bmap);5643error:5644 isl_basic_map_free(bmap);5645 return NULL;5646}5647 5648__isl_give isl_basic_set *isl_basic_set_underlying_set(5649 __isl_take isl_basic_set *bset)5650{5651 return isl_basic_map_underlying_set(bset_to_bmap(bset));5652}5653 5654/* Replace each element in "list" by the result of applying5655 * isl_basic_map_underlying_set to the element.5656 */5657__isl_give isl_basic_set_list *isl_basic_map_list_underlying_set(5658 __isl_take isl_basic_map_list *list)5659{5660 int i;5661 isl_size n;5662 5663 n = isl_basic_map_list_n_basic_map(list);5664 if (n < 0)5665 goto error;5666 5667 for (i = 0; i < n; ++i) {5668 isl_basic_map *bmap;5669 isl_basic_set *bset;5670 5671 bmap = isl_basic_map_list_get_basic_map(list, i);5672 bset = isl_basic_set_underlying_set(bmap);5673 list = isl_basic_set_list_set_basic_set(list, i, bset);5674 }5675 5676 return list;5677error:5678 isl_basic_map_list_free(list);5679 return NULL;5680}5681 5682__isl_give isl_basic_map *isl_basic_map_overlying_set(5683 __isl_take isl_basic_set *bset, __isl_take isl_basic_map *like)5684{5685 struct isl_basic_map *bmap;5686 struct isl_ctx *ctx;5687 isl_size dim, bmap_total;5688 unsigned total;5689 int i;5690 5691 if (!bset || !like)5692 goto error;5693 ctx = bset->ctx;5694 if (isl_basic_set_check_no_params(bset) < 0 ||5695 isl_basic_set_check_no_locals(bset) < 0)5696 goto error;5697 dim = isl_basic_set_dim(bset, isl_dim_set);5698 bmap_total = isl_basic_map_dim(like, isl_dim_all);5699 if (dim < 0 || bmap_total < 0)5700 goto error;5701 isl_assert(ctx, dim == bmap_total, goto error);5702 if (like->n_div == 0) {5703 isl_space *space = isl_basic_map_get_space(like);5704 isl_basic_map_free(like);5705 return isl_basic_map_reset_space(bset, space);5706 }5707 bset = isl_basic_set_cow(bset);5708 if (!bset)5709 goto error;5710 total = dim + bset->extra;5711 bmap = bset_to_bmap(bset);5712 isl_space_free(isl_basic_map_take_space(bmap));5713 bmap = isl_basic_map_restore_space(bmap, isl_basic_map_get_space(like));5714 if (!bmap)5715 goto error;5716 bmap->n_div = like->n_div;5717 bmap->extra += like->n_div;5718 if (bmap->extra) {5719 unsigned ltotal;5720 isl_int **div;5721 ltotal = total - bmap->extra + like->extra;5722 if (ltotal > total)5723 ltotal = total;5724 bmap->block2 = isl_blk_extend(ctx, bmap->block2,5725 bmap->extra * (1 + 1 + total));5726 if (isl_blk_is_error(bmap->block2))5727 goto error;5728 div = isl_realloc_array(ctx, bmap->div, isl_int *, bmap->extra);5729 if (!div)5730 goto error;5731 bmap->div = div;5732 for (i = 0; i < bmap->extra; ++i)5733 bmap->div[i] = bmap->block2.data + i * (1 + 1 + total);5734 for (i = 0; i < like->n_div; ++i) {5735 isl_seq_cpy(bmap->div[i], like->div[i], 1 + 1 + ltotal);5736 isl_seq_clr(bmap->div[i]+1+1+ltotal, total - ltotal);5737 }5738 bmap = isl_basic_map_add_known_div_constraints(bmap);5739 }5740 isl_basic_map_free(like);5741 bmap = isl_basic_map_simplify(bmap);5742 bmap = isl_basic_map_finalize(bmap);5743 return bmap;5744error:5745 isl_basic_map_free(like);5746 isl_basic_set_free(bset);5747 return NULL;5748}5749 5750__isl_give isl_basic_set *isl_basic_set_from_underlying_set(5751 __isl_take isl_basic_set *bset, __isl_take isl_basic_set *like)5752{5753 return bset_from_bmap(isl_basic_map_overlying_set(bset,5754 bset_to_bmap(like)));5755}5756 5757__isl_give isl_set *isl_map_underlying_set(__isl_take isl_map *map)5758{5759 int i;5760 5761 map = isl_map_cow(map);5762 if (!map)5763 return NULL;5764 map->dim = isl_space_cow(map->dim);5765 if (!map->dim)5766 goto error;5767 5768 for (i = 1; i < map->n; ++i)5769 isl_assert(map->ctx, map->p[0]->n_div == map->p[i]->n_div,5770 goto error);5771 for (i = 0; i < map->n; ++i) {5772 map->p[i] = bset_to_bmap(5773 isl_basic_map_underlying_set(map->p[i]));5774 if (!map->p[i])5775 goto error;5776 }5777 if (map->n == 0)5778 map->dim = isl_space_underlying(map->dim, 0);5779 else {5780 isl_space_free(map->dim);5781 map->dim = isl_space_copy(map->p[0]->dim);5782 }5783 if (!map->dim)5784 goto error;5785 return set_from_map(map);5786error:5787 isl_map_free(map);5788 return NULL;5789}5790 5791/* Replace the space of "bmap" by "space".5792 *5793 * If the space of "bmap" is identical to "space" (including the identifiers5794 * of the input and output dimensions), then simply return the original input.5795 */5796__isl_give isl_basic_map *isl_basic_map_reset_space(5797 __isl_take isl_basic_map *bmap, __isl_take isl_space *space)5798{5799 isl_bool equal;5800 isl_space *bmap_space;5801 5802 bmap_space = isl_basic_map_peek_space(bmap);5803 equal = isl_space_is_equal(bmap_space, space);5804 if (equal >= 0 && equal)5805 equal = isl_space_has_equal_ids(bmap_space, space);5806 if (equal < 0)5807 goto error;5808 if (equal) {5809 isl_space_free(space);5810 return bmap;5811 }5812 isl_space_free(isl_basic_map_take_space(bmap));5813 bmap = isl_basic_map_restore_space(bmap, space);5814 5815 bmap = isl_basic_map_finalize(bmap);5816 5817 return bmap;5818error:5819 isl_basic_map_free(bmap);5820 isl_space_free(space);5821 return NULL;5822}5823 5824__isl_give isl_basic_set *isl_basic_set_reset_space(5825 __isl_take isl_basic_set *bset, __isl_take isl_space *space)5826{5827 return bset_from_bmap(isl_basic_map_reset_space(bset_to_bmap(bset),5828 space));5829}5830 5831/* Check that the total dimensions of "map" and "space" are the same.5832 */5833static isl_stat check_map_space_equal_total_dim(__isl_keep isl_map *map,5834 __isl_keep isl_space *space)5835{5836 isl_size dim1, dim2;5837 5838 dim1 = isl_map_dim(map, isl_dim_all);5839 dim2 = isl_space_dim(space, isl_dim_all);5840 if (dim1 < 0 || dim2 < 0)5841 return isl_stat_error;5842 if (dim1 == dim2)5843 return isl_stat_ok;5844 isl_die(isl_map_get_ctx(map), isl_error_invalid,5845 "total dimensions do not match", return isl_stat_error);5846}5847 5848__isl_give isl_map *isl_map_reset_space(__isl_take isl_map *map,5849 __isl_take isl_space *space)5850{5851 int i;5852 5853 map = isl_map_cow(map);5854 if (!map || !space)5855 goto error;5856 5857 for (i = 0; i < map->n; ++i) {5858 map->p[i] = isl_basic_map_reset_space(map->p[i],5859 isl_space_copy(space));5860 if (!map->p[i])5861 goto error;5862 }5863 isl_space_free(isl_map_take_space(map));5864 map = isl_map_restore_space(map, space);5865 5866 return map;5867error:5868 isl_map_free(map);5869 isl_space_free(space);5870 return NULL;5871}5872 5873/* Replace the space of "map" by "space", without modifying5874 * the dimension of "map".5875 *5876 * If the space of "map" is identical to "space" (including the identifiers5877 * of the input and output dimensions), then simply return the original input.5878 */5879__isl_give isl_map *isl_map_reset_equal_dim_space(__isl_take isl_map *map,5880 __isl_take isl_space *space)5881{5882 isl_bool equal;5883 isl_space *map_space;5884 5885 map_space = isl_map_peek_space(map);5886 equal = isl_space_is_equal(map_space, space);5887 if (equal >= 0 && equal)5888 equal = isl_space_has_equal_ids(map_space, space);5889 if (equal < 0)5890 goto error;5891 if (equal) {5892 isl_space_free(space);5893 return map;5894 }5895 if (check_map_space_equal_total_dim(map, space) < 0)5896 goto error;5897 return isl_map_reset_space(map, space);5898error:5899 isl_map_free(map);5900 isl_space_free(space);5901 return NULL;5902}5903 5904__isl_give isl_set *isl_set_reset_space(__isl_take isl_set *set,5905 __isl_take isl_space *space)5906{5907 return set_from_map(isl_map_reset_space(set_to_map(set), space));5908}5909 5910/* Compute the parameter domain of the given basic set.5911 */5912__isl_give isl_basic_set *isl_basic_set_params(__isl_take isl_basic_set *bset)5913{5914 isl_bool is_params;5915 isl_space *space;5916 isl_size n;5917 5918 is_params = isl_basic_set_is_params(bset);5919 if (is_params < 0)5920 return isl_basic_set_free(bset);5921 if (is_params)5922 return bset;5923 5924 n = isl_basic_set_dim(bset, isl_dim_set);5925 if (n < 0)5926 return isl_basic_set_free(bset);5927 bset = isl_basic_set_project_out(bset, isl_dim_set, 0, n);5928 space = isl_basic_set_get_space(bset);5929 space = isl_space_params(space);5930 bset = isl_basic_set_reset_space(bset, space);5931 return bset;5932}5933 5934/* Construct a zero-dimensional basic set with the given parameter domain.5935 */5936__isl_give isl_basic_set *isl_basic_set_from_params(5937 __isl_take isl_basic_set *bset)5938{5939 isl_space *space;5940 space = isl_basic_set_get_space(bset);5941 space = isl_space_set_from_params(space);5942 bset = isl_basic_set_reset_space(bset, space);5943 return bset;5944}5945 5946/* Compute the parameter domain of the given set.5947 */5948__isl_give isl_set *isl_set_params(__isl_take isl_set *set)5949{5950 return isl_map_params(set_to_map(set));5951}5952 5953/* Construct a zero-dimensional set with the given parameter domain.5954 */5955__isl_give isl_set *isl_set_from_params(__isl_take isl_set *set)5956{5957 isl_space *space;5958 space = isl_set_get_space(set);5959 space = isl_space_set_from_params(space);5960 set = isl_set_reset_space(set, space);5961 return set;5962}5963 5964/* Compute the parameter domain of the given map.5965 */5966__isl_give isl_set *isl_map_params(__isl_take isl_map *map)5967{5968 isl_space *space;5969 isl_size n_in, n_out;5970 5971 n_in = isl_map_dim(map, isl_dim_in);5972 n_out = isl_map_dim(map, isl_dim_out);5973 if (n_in < 0 || n_out < 0)5974 return isl_map_free(map);5975 map = isl_map_project_out(map, isl_dim_in, 0, n_in);5976 map = isl_map_project_out(map, isl_dim_out, 0, n_out);5977 space = isl_map_get_space(map);5978 space = isl_space_params(space);5979 map = isl_map_reset_space(map, space);5980 return map;5981}5982 5983__isl_give isl_basic_set *isl_basic_map_domain(__isl_take isl_basic_map *bmap)5984{5985 isl_space *space;5986 isl_size n_out;5987 5988 n_out = isl_basic_map_dim(bmap, isl_dim_out);5989 if (n_out < 0)5990 return isl_basic_map_free(bmap);5991 space = isl_space_domain(isl_basic_map_get_space(bmap));5992 5993 bmap = isl_basic_map_project_out(bmap, isl_dim_out, 0, n_out);5994 5995 return isl_basic_map_reset_space(bmap, space);5996}5997 5998isl_bool isl_basic_map_may_be_set(__isl_keep isl_basic_map *bmap)5999{6000 if (!bmap)6001 return isl_bool_error;6002 return isl_space_may_be_set(bmap->dim);6003}6004 6005/* Is this basic map actually a set?6006 * Users should never call this function. Outside of isl,6007 * the type should indicate whether something is a set or a map.6008 */6009isl_bool isl_basic_map_is_set(__isl_keep isl_basic_map *bmap)6010{6011 if (!bmap)6012 return isl_bool_error;6013 return isl_space_is_set(bmap->dim);6014}6015 6016__isl_give isl_basic_set *isl_basic_map_range(__isl_take isl_basic_map *bmap)6017{6018 isl_bool is_set;6019 6020 is_set = isl_basic_map_is_set(bmap);6021 if (is_set < 0)6022 goto error;6023 if (is_set)6024 return bmap;6025 return isl_basic_map_domain(isl_basic_map_reverse(bmap));6026error:6027 isl_basic_map_free(bmap);6028 return NULL;6029}6030 6031__isl_give isl_basic_map *isl_basic_map_domain_map(6032 __isl_take isl_basic_map *bmap)6033{6034 int i;6035 isl_space *space;6036 isl_basic_map *domain;6037 isl_size nparam, n_in, n_out;6038 6039 nparam = isl_basic_map_dim(bmap, isl_dim_param);6040 n_in = isl_basic_map_dim(bmap, isl_dim_in);6041 n_out = isl_basic_map_dim(bmap, isl_dim_out);6042 if (nparam < 0 || n_in < 0 || n_out < 0)6043 return isl_basic_map_free(bmap);6044 6045 space = isl_basic_map_get_space(bmap);6046 space = isl_space_from_range(isl_space_domain(space));6047 domain = isl_basic_map_universe(space);6048 6049 bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap));6050 bmap = isl_basic_map_apply_range(bmap, domain);6051 bmap = isl_basic_map_extend_constraints(bmap, n_in, 0);6052 6053 for (i = 0; i < n_in; ++i)6054 bmap = isl_basic_map_equate(bmap, isl_dim_in, i,6055 isl_dim_out, i);6056 6057 bmap = isl_basic_map_gauss(bmap, NULL);6058 return isl_basic_map_finalize(bmap);6059}6060 6061__isl_give isl_basic_map *isl_basic_map_range_map(6062 __isl_take isl_basic_map *bmap)6063{6064 int i;6065 isl_space *space;6066 isl_basic_map *range;6067 isl_size nparam, n_in, n_out;6068 6069 nparam = isl_basic_map_dim(bmap, isl_dim_param);6070 n_in = isl_basic_map_dim(bmap, isl_dim_in);6071 n_out = isl_basic_map_dim(bmap, isl_dim_out);6072 if (nparam < 0 || n_in < 0 || n_out < 0)6073 return isl_basic_map_free(bmap);6074 6075 space = isl_basic_map_get_space(bmap);6076 space = isl_space_from_range(isl_space_range(space));6077 range = isl_basic_map_universe(space);6078 6079 bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap));6080 bmap = isl_basic_map_apply_range(bmap, range);6081 bmap = isl_basic_map_extend_constraints(bmap, n_out, 0);6082 6083 for (i = 0; i < n_out; ++i)6084 bmap = isl_basic_map_equate(bmap, isl_dim_in, n_in + i,6085 isl_dim_out, i);6086 6087 bmap = isl_basic_map_gauss(bmap, NULL);6088 return isl_basic_map_finalize(bmap);6089}6090 6091int isl_map_may_be_set(__isl_keep isl_map *map)6092{6093 if (!map)6094 return -1;6095 return isl_space_may_be_set(map->dim);6096}6097 6098/* Is this map actually a set?6099 * Users should never call this function. Outside of isl,6100 * the type should indicate whether something is a set or a map.6101 */6102isl_bool isl_map_is_set(__isl_keep isl_map *map)6103{6104 if (!map)6105 return isl_bool_error;6106 return isl_space_is_set(map->dim);6107}6108 6109__isl_give isl_set *isl_map_range(__isl_take isl_map *map)6110{6111 isl_space *space;6112 isl_size n_in;6113 6114 n_in = isl_map_dim(map, isl_dim_in);6115 if (n_in < 0)6116 return set_from_map(isl_map_free(map));6117 space = isl_space_range(isl_map_get_space(map));6118 6119 map = isl_map_project_out(map, isl_dim_in, 0, n_in);6120 6121 return set_from_map(isl_map_reset_space(map, space));6122}6123 6124/* Transform "map" by applying "fn_space" to its space and "fn_bmap"6125 * to each of its basic maps.6126 */6127static __isl_give isl_map *isl_map_transform(__isl_take isl_map *map,6128 __isl_give isl_space *(*fn_space)(__isl_take isl_space *space),6129 __isl_give isl_basic_map *(*fn_bmap)(__isl_take isl_basic_map *bmap))6130{6131 int i;6132 isl_space *space;6133 6134 map = isl_map_cow(map);6135 if (!map)6136 return NULL;6137 6138 for (i = 0; i < map->n; ++i) {6139 map->p[i] = fn_bmap(map->p[i]);6140 if (!map->p[i])6141 return isl_map_free(map);6142 }6143 map = isl_map_unmark_normalized(map);6144 6145 space = isl_map_take_space(map);6146 space = fn_space(space);6147 map = isl_map_restore_space(map, space);6148 6149 return map;6150}6151 6152__isl_give isl_map *isl_map_domain_map(__isl_take isl_map *map)6153{6154 return isl_map_transform(map, &isl_space_domain_map,6155 &isl_basic_map_domain_map);6156}6157 6158__isl_give isl_map *isl_map_range_map(__isl_take isl_map *map)6159{6160 return isl_map_transform(map, &isl_space_range_map,6161 &isl_basic_map_range_map);6162}6163 6164/* Given a wrapped map of the form A[B -> C],6165 * return the map A[B -> C] -> B.6166 */6167__isl_give isl_map *isl_set_wrapped_domain_map(__isl_take isl_set *set)6168{6169 isl_id *id;6170 isl_map *map;6171 6172 if (!set)6173 return NULL;6174 if (!isl_set_has_tuple_id(set))6175 return isl_map_domain_map(isl_set_unwrap(set));6176 6177 id = isl_set_get_tuple_id(set);6178 map = isl_map_domain_map(isl_set_unwrap(set));6179 map = isl_map_set_tuple_id(map, isl_dim_in, id);6180 6181 return map;6182}6183 6184__isl_give isl_basic_map *isl_basic_map_from_domain(6185 __isl_take isl_basic_set *bset)6186{6187 return isl_basic_map_reverse(isl_basic_map_from_range(bset));6188}6189 6190__isl_give isl_basic_map *isl_basic_map_from_range(6191 __isl_take isl_basic_set *bset)6192{6193 isl_space *space;6194 space = isl_basic_set_get_space(bset);6195 space = isl_space_from_range(space);6196 bset = isl_basic_set_reset_space(bset, space);6197 return bset_to_bmap(bset);6198}6199 6200/* Create a relation with the given set as range.6201 * The domain of the created relation is a zero-dimensional6202 * flat anonymous space.6203 */6204__isl_give isl_map *isl_map_from_range(__isl_take isl_set *set)6205{6206 isl_space *space;6207 space = isl_set_get_space(set);6208 space = isl_space_from_range(space);6209 set = isl_set_reset_space(set, space);6210 return set_to_map(set);6211}6212 6213/* Create a relation with the given set as domain.6214 * The range of the created relation is a zero-dimensional6215 * flat anonymous space.6216 */6217__isl_give isl_map *isl_map_from_domain(__isl_take isl_set *set)6218{6219 return isl_map_reverse(isl_map_from_range(set));6220}6221 6222__isl_give isl_basic_map *isl_basic_map_from_domain_and_range(6223 __isl_take isl_basic_set *domain, __isl_take isl_basic_set *range)6224{6225 return isl_basic_map_apply_range(isl_basic_map_reverse(domain), range);6226}6227 6228__isl_give isl_map *isl_map_from_domain_and_range(__isl_take isl_set *domain,6229 __isl_take isl_set *range)6230{6231 return isl_map_apply_range(isl_map_reverse(domain), range);6232}6233 6234/* Return a newly allocated isl_map with given space and flags and6235 * room for "n" basic maps.6236 * Make sure that all cached information is cleared.6237 */6238__isl_give isl_map *isl_map_alloc_space(__isl_take isl_space *space, int n,6239 unsigned flags)6240{6241 struct isl_map *map;6242 6243 if (!space)6244 return NULL;6245 if (n < 0)6246 isl_die(space->ctx, isl_error_internal,6247 "negative number of basic maps", goto error);6248 map = isl_calloc(space->ctx, struct isl_map,6249 sizeof(struct isl_map) +6250 (n - 1) * sizeof(struct isl_basic_map *));6251 if (!map)6252 goto error;6253 6254 map->ctx = space->ctx;6255 isl_ctx_ref(map->ctx);6256 map->ref = 1;6257 map->size = n;6258 map->n = 0;6259 map->dim = space;6260 map->flags = flags;6261 return map;6262error:6263 isl_space_free(space);6264 return NULL;6265}6266 6267__isl_give isl_basic_map *isl_basic_map_empty(__isl_take isl_space *space)6268{6269 struct isl_basic_map *bmap;6270 bmap = isl_basic_map_alloc_space(space, 0, 1, 0);6271 bmap = isl_basic_map_set_to_empty(bmap);6272 return bmap;6273}6274 6275__isl_give isl_basic_set *isl_basic_set_empty(__isl_take isl_space *space)6276{6277 struct isl_basic_set *bset;6278 bset = isl_basic_set_alloc_space(space, 0, 1, 0);6279 bset = isl_basic_set_set_to_empty(bset);6280 return bset;6281}6282 6283__isl_give isl_basic_map *isl_basic_map_universe(__isl_take isl_space *space)6284{6285 struct isl_basic_map *bmap;6286 bmap = isl_basic_map_alloc_space(space, 0, 0, 0);6287 bmap = isl_basic_map_finalize(bmap);6288 return bmap;6289}6290 6291__isl_give isl_basic_set *isl_basic_set_universe(__isl_take isl_space *space)6292{6293 struct isl_basic_set *bset;6294 bset = isl_basic_set_alloc_space(space, 0, 0, 0);6295 bset = isl_basic_set_finalize(bset);6296 return bset;6297}6298 6299__isl_give isl_basic_map *isl_basic_map_nat_universe(6300 __isl_take isl_space *space)6301{6302 int i;6303 isl_size total = isl_space_dim(space, isl_dim_all);6304 isl_basic_map *bmap;6305 6306 if (total < 0)6307 space = isl_space_free(space);6308 bmap = isl_basic_map_alloc_space(space, 0, 0, total);6309 for (i = 0; i < total; ++i) {6310 int k = isl_basic_map_alloc_inequality(bmap);6311 if (k < 0)6312 goto error;6313 isl_seq_clr(bmap->ineq[k], 1 + total);6314 isl_int_set_si(bmap->ineq[k][1 + i], 1);6315 }6316 return bmap;6317error:6318 isl_basic_map_free(bmap);6319 return NULL;6320}6321 6322__isl_give isl_basic_set *isl_basic_set_nat_universe(6323 __isl_take isl_space *space)6324{6325 return isl_basic_map_nat_universe(space);6326}6327 6328__isl_give isl_map *isl_map_nat_universe(__isl_take isl_space *space)6329{6330 return isl_map_from_basic_map(isl_basic_map_nat_universe(space));6331}6332 6333__isl_give isl_set *isl_set_nat_universe(__isl_take isl_space *space)6334{6335 return isl_map_nat_universe(space);6336}6337 6338__isl_give isl_map *isl_map_empty(__isl_take isl_space *space)6339{6340 return isl_map_alloc_space(space, 0, ISL_MAP_DISJOINT);6341}6342 6343__isl_give isl_set *isl_set_empty(__isl_take isl_space *space)6344{6345 return isl_set_alloc_space(space, 0, ISL_MAP_DISJOINT);6346}6347 6348__isl_give isl_map *isl_map_universe(__isl_take isl_space *space)6349{6350 struct isl_map *map;6351 if (!space)6352 return NULL;6353 map = isl_map_alloc_space(isl_space_copy(space), 1, ISL_MAP_DISJOINT);6354 map = isl_map_add_basic_map(map, isl_basic_map_universe(space));6355 return map;6356}6357 6358/* This function performs the same operation as isl_map_universe,6359 * but is considered as a function on an isl_space when exported.6360 */6361__isl_give isl_map *isl_space_universe_map(__isl_take isl_space *space)6362{6363 return isl_map_universe(space);6364}6365 6366__isl_give isl_set *isl_set_universe(__isl_take isl_space *space)6367{6368 struct isl_set *set;6369 if (!space)6370 return NULL;6371 set = isl_set_alloc_space(isl_space_copy(space), 1, ISL_MAP_DISJOINT);6372 set = isl_set_add_basic_set(set, isl_basic_set_universe(space));6373 return set;6374}6375 6376/* This function performs the same operation as isl_set_universe,6377 * but is considered as a function on an isl_space when exported.6378 */6379__isl_give isl_set *isl_space_universe_set(__isl_take isl_space *space)6380{6381 return isl_set_universe(space);6382}6383 6384__isl_give isl_map *isl_map_dup(__isl_keep isl_map *map)6385{6386 int i;6387 struct isl_map *dup;6388 6389 if (!map)6390 return NULL;6391 dup = isl_map_alloc_space(isl_space_copy(map->dim), map->n, map->flags);6392 for (i = 0; i < map->n; ++i)6393 dup = isl_map_add_basic_map(dup, isl_basic_map_copy(map->p[i]));6394 return dup;6395}6396 6397__isl_give isl_map *isl_map_add_basic_map(__isl_take isl_map *map,6398 __isl_take isl_basic_map *bmap)6399{6400 if (!bmap || !map)6401 goto error;6402 if (isl_basic_map_plain_is_empty(bmap)) {6403 isl_basic_map_free(bmap);6404 return map;6405 }6406 if (isl_map_basic_map_check_equal_space(map, bmap) < 0)6407 goto error;6408 isl_assert(map->ctx, map->n < map->size, goto error);6409 map->p[map->n] = bmap;6410 map->n++;6411 map = isl_map_unmark_normalized(map);6412 return map;6413error:6414 if (map)6415 isl_map_free(map);6416 if (bmap)6417 isl_basic_map_free(bmap);6418 return NULL;6419}6420 6421__isl_null isl_map *isl_map_free(__isl_take isl_map *map)6422{6423 int i;6424 6425 if (!map)6426 return NULL;6427 6428 if (--map->ref > 0)6429 return NULL;6430 6431 clear_caches(map);6432 isl_ctx_deref(map->ctx);6433 for (i = 0; i < map->n; ++i)6434 isl_basic_map_free(map->p[i]);6435 isl_space_free(map->dim);6436 free(map);6437 6438 return NULL;6439}6440 6441static __isl_give isl_basic_map *isl_basic_map_fix_pos_si(6442 __isl_take isl_basic_map *bmap, unsigned pos, int value)6443{6444 int j;6445 isl_size total;6446 6447 total = isl_basic_map_dim(bmap, isl_dim_all);6448 if (total < 0)6449 return isl_basic_map_free(bmap);6450 6451 bmap = isl_basic_map_cow(bmap);6452 bmap = isl_basic_map_extend_constraints(bmap, 1, 0);6453 j = isl_basic_map_alloc_equality(bmap);6454 if (j < 0)6455 goto error;6456 isl_seq_clr(bmap->eq[j] + 1, total);6457 isl_int_set_si(bmap->eq[j][pos], -1);6458 isl_int_set_si(bmap->eq[j][0], value);6459 bmap = isl_basic_map_simplify(bmap);6460 return isl_basic_map_finalize(bmap);6461error:6462 isl_basic_map_free(bmap);6463 return NULL;6464}6465 6466static __isl_give isl_basic_map *isl_basic_map_fix_pos(6467 __isl_take isl_basic_map *bmap, unsigned pos, isl_int value)6468{6469 int j;6470 isl_size total;6471 6472 total = isl_basic_map_dim(bmap, isl_dim_all);6473 if (total < 0)6474 return isl_basic_map_free(bmap);6475 6476 bmap = isl_basic_map_cow(bmap);6477 bmap = isl_basic_map_extend_constraints(bmap, 1, 0);6478 j = isl_basic_map_alloc_equality(bmap);6479 if (j < 0)6480 goto error;6481 isl_seq_clr(bmap->eq[j] + 1, total);6482 isl_int_set_si(bmap->eq[j][pos], -1);6483 isl_int_set(bmap->eq[j][0], value);6484 bmap = isl_basic_map_simplify(bmap);6485 return isl_basic_map_finalize(bmap);6486error:6487 isl_basic_map_free(bmap);6488 return NULL;6489}6490 6491__isl_give isl_basic_map *isl_basic_map_fix_si(__isl_take isl_basic_map *bmap,6492 enum isl_dim_type type, unsigned pos, int value)6493{6494 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)6495 return isl_basic_map_free(bmap);6496 return isl_basic_map_fix_pos_si(bmap,6497 isl_basic_map_offset(bmap, type) + pos, value);6498}6499 6500__isl_give isl_basic_map *isl_basic_map_fix(__isl_take isl_basic_map *bmap,6501 enum isl_dim_type type, unsigned pos, isl_int value)6502{6503 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)6504 return isl_basic_map_free(bmap);6505 return isl_basic_map_fix_pos(bmap,6506 isl_basic_map_offset(bmap, type) + pos, value);6507}6508 6509/* Fix the value of the variable at position "pos" of type "type" of "bmap"6510 * to be equal to "v".6511 */6512__isl_give isl_basic_map *isl_basic_map_fix_val(__isl_take isl_basic_map *bmap,6513 enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)6514{6515 if (!bmap || !v)6516 goto error;6517 if (!isl_val_is_int(v))6518 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,6519 "expecting integer value", goto error);6520 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)6521 goto error;6522 pos += isl_basic_map_offset(bmap, type);6523 bmap = isl_basic_map_fix_pos(bmap, pos, v->n);6524 isl_val_free(v);6525 return bmap;6526error:6527 isl_basic_map_free(bmap);6528 isl_val_free(v);6529 return NULL;6530}6531 6532/* Fix the value of the variable at position "pos" of type "type" of "bset"6533 * to be equal to "v".6534 */6535__isl_give isl_basic_set *isl_basic_set_fix_val(__isl_take isl_basic_set *bset,6536 enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)6537{6538 return isl_basic_map_fix_val(bset, type, pos, v);6539}6540 6541__isl_give isl_basic_set *isl_basic_set_fix_si(__isl_take isl_basic_set *bset,6542 enum isl_dim_type type, unsigned pos, int value)6543{6544 return bset_from_bmap(isl_basic_map_fix_si(bset_to_bmap(bset),6545 type, pos, value));6546}6547 6548__isl_give isl_basic_set *isl_basic_set_fix(__isl_take isl_basic_set *bset,6549 enum isl_dim_type type, unsigned pos, isl_int value)6550{6551 return bset_from_bmap(isl_basic_map_fix(bset_to_bmap(bset),6552 type, pos, value));6553}6554 6555/* Remove the basic map at position "i" from "map" if this basic map6556 * is (obviously) empty.6557 */6558static __isl_give isl_map *remove_if_empty(__isl_take isl_map *map, int i)6559{6560 isl_bool empty;6561 6562 if (!map)6563 return NULL;6564 6565 empty = isl_basic_map_plain_is_empty(map->p[i]);6566 if (empty < 0)6567 return isl_map_free(map);6568 if (!empty)6569 return map;6570 6571 isl_basic_map_free(map->p[i]);6572 map->n--;6573 if (i != map->n) {6574 map->p[i] = map->p[map->n];6575 map = isl_map_unmark_normalized(map);6576 6577 }6578 6579 return map;6580}6581 6582/* Perform "fn" on each basic map of "map", where we may not be holding6583 * the only reference to "map".6584 * In particular, "fn" should be a semantics preserving operation6585 * that we want to apply to all copies of "map". We therefore need6586 * to be careful not to modify "map" in a way that breaks "map"6587 * in case anything goes wrong.6588 */6589__isl_give isl_map *isl_map_inline_foreach_basic_map(__isl_take isl_map *map,6590 __isl_give isl_basic_map *(*fn)(__isl_take isl_basic_map *bmap))6591{6592 struct isl_basic_map *bmap;6593 int i;6594 6595 if (!map)6596 return NULL;6597 6598 for (i = map->n - 1; i >= 0; --i) {6599 bmap = isl_basic_map_copy(map->p[i]);6600 bmap = fn(bmap);6601 if (!bmap)6602 goto error;6603 isl_basic_map_free(map->p[i]);6604 map->p[i] = bmap;6605 map = remove_if_empty(map, i);6606 if (!map)6607 return NULL;6608 }6609 6610 return map;6611error:6612 isl_map_free(map);6613 return NULL;6614}6615 6616__isl_give isl_map *isl_map_fix_si(__isl_take isl_map *map,6617 enum isl_dim_type type, unsigned pos, int value)6618{6619 int i;6620 6621 map = isl_map_cow(map);6622 if (isl_map_check_range(map, type, pos, 1) < 0)6623 return isl_map_free(map);6624 for (i = map->n - 1; i >= 0; --i) {6625 map->p[i] = isl_basic_map_fix_si(map->p[i], type, pos, value);6626 map = remove_if_empty(map, i);6627 if (!map)6628 return NULL;6629 }6630 map = isl_map_unmark_normalized(map);6631 return map;6632}6633 6634__isl_give isl_set *isl_set_fix_si(__isl_take isl_set *set,6635 enum isl_dim_type type, unsigned pos, int value)6636{6637 return set_from_map(isl_map_fix_si(set_to_map(set), type, pos, value));6638}6639 6640__isl_give isl_map *isl_map_fix(__isl_take isl_map *map,6641 enum isl_dim_type type, unsigned pos, isl_int value)6642{6643 int i;6644 6645 map = isl_map_cow(map);6646 if (isl_map_check_range(map, type, pos, 1) < 0)6647 return isl_map_free(map);6648 for (i = 0; i < map->n; ++i) {6649 map->p[i] = isl_basic_map_fix(map->p[i], type, pos, value);6650 if (!map->p[i])6651 goto error;6652 }6653 map = isl_map_unmark_normalized(map);6654 return map;6655error:6656 isl_map_free(map);6657 return NULL;6658}6659 6660__isl_give isl_set *isl_set_fix(__isl_take isl_set *set,6661 enum isl_dim_type type, unsigned pos, isl_int value)6662{6663 return set_from_map(isl_map_fix(set_to_map(set), type, pos, value));6664}6665 6666/* Fix the value of the variable at position "pos" of type "type" of "map"6667 * to be equal to "v".6668 */6669__isl_give isl_map *isl_map_fix_val(__isl_take isl_map *map,6670 enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)6671{6672 int i;6673 6674 map = isl_map_cow(map);6675 if (!map || !v)6676 goto error;6677 6678 if (!isl_val_is_int(v))6679 isl_die(isl_map_get_ctx(map), isl_error_invalid,6680 "expecting integer value", goto error);6681 if (isl_map_check_range(map, type, pos, 1) < 0)6682 goto error;6683 for (i = map->n - 1; i >= 0; --i) {6684 map->p[i] = isl_basic_map_fix_val(map->p[i], type, pos,6685 isl_val_copy(v));6686 map = remove_if_empty(map, i);6687 if (!map)6688 goto error;6689 }6690 map = isl_map_unmark_normalized(map);6691 isl_val_free(v);6692 return map;6693error:6694 isl_map_free(map);6695 isl_val_free(v);6696 return NULL;6697}6698 6699/* Fix the value of the variable at position "pos" of type "type" of "set"6700 * to be equal to "v".6701 */6702__isl_give isl_set *isl_set_fix_val(__isl_take isl_set *set,6703 enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)6704{6705 return isl_map_fix_val(set, type, pos, v);6706}6707 6708__isl_give isl_map *isl_map_fix_input_si(__isl_take isl_map *map,6709 unsigned input, int value)6710{6711 return isl_map_fix_si(map, isl_dim_in, input, value);6712}6713 6714__isl_give isl_set *isl_set_fix_dim_si(__isl_take isl_set *set, unsigned dim,6715 int value)6716{6717 return set_from_map(isl_map_fix_si(set_to_map(set),6718 isl_dim_set, dim, value));6719}6720 6721static __isl_give isl_basic_map *basic_map_bound_si(6722 __isl_take isl_basic_map *bmap,6723 enum isl_dim_type type, unsigned pos, int value, int upper)6724{6725 int j;6726 isl_size total;6727 6728 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)6729 return isl_basic_map_free(bmap);6730 total = isl_basic_map_dim(bmap, isl_dim_all);6731 if (total < 0)6732 return isl_basic_map_free(bmap);6733 pos += isl_basic_map_offset(bmap, type);6734 bmap = isl_basic_map_cow(bmap);6735 bmap = isl_basic_map_extend_constraints(bmap, 0, 1);6736 j = isl_basic_map_alloc_inequality(bmap);6737 if (j < 0)6738 goto error;6739 isl_seq_clr(bmap->ineq[j], 1 + total);6740 if (upper) {6741 isl_int_set_si(bmap->ineq[j][pos], -1);6742 isl_int_set_si(bmap->ineq[j][0], value);6743 } else {6744 isl_int_set_si(bmap->ineq[j][pos], 1);6745 isl_int_set_si(bmap->ineq[j][0], -value);6746 }6747 bmap = isl_basic_map_simplify(bmap);6748 return isl_basic_map_finalize(bmap);6749error:6750 isl_basic_map_free(bmap);6751 return NULL;6752}6753 6754__isl_give isl_basic_map *isl_basic_map_lower_bound_si(6755 __isl_take isl_basic_map *bmap,6756 enum isl_dim_type type, unsigned pos, int value)6757{6758 return basic_map_bound_si(bmap, type, pos, value, 0);6759}6760 6761/* Constrain the values of the given dimension to be no greater than "value".6762 */6763__isl_give isl_basic_map *isl_basic_map_upper_bound_si(6764 __isl_take isl_basic_map *bmap,6765 enum isl_dim_type type, unsigned pos, int value)6766{6767 return basic_map_bound_si(bmap, type, pos, value, 1);6768}6769 6770static __isl_give isl_map *map_bound_si(__isl_take isl_map *map,6771 enum isl_dim_type type, unsigned pos, int value, int upper)6772{6773 int i;6774 6775 map = isl_map_cow(map);6776 if (isl_map_check_range(map, type, pos, 1) < 0)6777 return isl_map_free(map);6778 for (i = 0; i < map->n; ++i) {6779 map->p[i] = basic_map_bound_si(map->p[i],6780 type, pos, value, upper);6781 if (!map->p[i])6782 goto error;6783 }6784 map = isl_map_unmark_normalized(map);6785 return map;6786error:6787 isl_map_free(map);6788 return NULL;6789}6790 6791__isl_give isl_map *isl_map_lower_bound_si(__isl_take isl_map *map,6792 enum isl_dim_type type, unsigned pos, int value)6793{6794 return map_bound_si(map, type, pos, value, 0);6795}6796 6797__isl_give isl_map *isl_map_upper_bound_si(__isl_take isl_map *map,6798 enum isl_dim_type type, unsigned pos, int value)6799{6800 return map_bound_si(map, type, pos, value, 1);6801}6802 6803__isl_give isl_set *isl_set_lower_bound_si(__isl_take isl_set *set,6804 enum isl_dim_type type, unsigned pos, int value)6805{6806 return set_from_map(isl_map_lower_bound_si(set_to_map(set),6807 type, pos, value));6808}6809 6810__isl_give isl_set *isl_set_upper_bound_si(__isl_take isl_set *set,6811 enum isl_dim_type type, unsigned pos, int value)6812{6813 return isl_map_upper_bound_si(set, type, pos, value);6814}6815 6816/* Bound the given variable of "bmap" from below (or above is "upper"6817 * is set) to "value".6818 */6819static __isl_give isl_basic_map *basic_map_bound(6820 __isl_take isl_basic_map *bmap,6821 enum isl_dim_type type, unsigned pos, isl_int value, int upper)6822{6823 int j;6824 isl_size total;6825 6826 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)6827 return isl_basic_map_free(bmap);6828 total = isl_basic_map_dim(bmap, isl_dim_all);6829 if (total < 0)6830 return isl_basic_map_free(bmap);6831 pos += isl_basic_map_offset(bmap, type);6832 bmap = isl_basic_map_cow(bmap);6833 bmap = isl_basic_map_extend_constraints(bmap, 0, 1);6834 j = isl_basic_map_alloc_inequality(bmap);6835 if (j < 0)6836 goto error;6837 isl_seq_clr(bmap->ineq[j], 1 + total);6838 if (upper) {6839 isl_int_set_si(bmap->ineq[j][pos], -1);6840 isl_int_set(bmap->ineq[j][0], value);6841 } else {6842 isl_int_set_si(bmap->ineq[j][pos], 1);6843 isl_int_neg(bmap->ineq[j][0], value);6844 }6845 bmap = isl_basic_map_simplify(bmap);6846 return isl_basic_map_finalize(bmap);6847error:6848 isl_basic_map_free(bmap);6849 return NULL;6850}6851 6852/* Bound the given variable of "map" from below (or above is "upper"6853 * is set) to "value".6854 */6855static __isl_give isl_map *map_bound(__isl_take isl_map *map,6856 enum isl_dim_type type, unsigned pos, isl_int value, int upper)6857{6858 int i;6859 6860 map = isl_map_cow(map);6861 if (isl_map_check_range(map, type, pos, 1) < 0)6862 return isl_map_free(map);6863 for (i = map->n - 1; i >= 0; --i) {6864 map->p[i] = basic_map_bound(map->p[i], type, pos, value, upper);6865 map = remove_if_empty(map, i);6866 if (!map)6867 return NULL;6868 }6869 map = isl_map_unmark_normalized(map);6870 return map;6871}6872 6873__isl_give isl_map *isl_map_lower_bound(__isl_take isl_map *map,6874 enum isl_dim_type type, unsigned pos, isl_int value)6875{6876 return map_bound(map, type, pos, value, 0);6877}6878 6879__isl_give isl_map *isl_map_upper_bound(__isl_take isl_map *map,6880 enum isl_dim_type type, unsigned pos, isl_int value)6881{6882 return map_bound(map, type, pos, value, 1);6883}6884 6885__isl_give isl_set *isl_set_lower_bound(__isl_take isl_set *set,6886 enum isl_dim_type type, unsigned pos, isl_int value)6887{6888 return isl_map_lower_bound(set, type, pos, value);6889}6890 6891__isl_give isl_set *isl_set_upper_bound(__isl_take isl_set *set,6892 enum isl_dim_type type, unsigned pos, isl_int value)6893{6894 return isl_map_upper_bound(set, type, pos, value);6895}6896 6897/* Force the values of the variable at position "pos" of type "type" of "map"6898 * to be no smaller than "value".6899 */6900__isl_give isl_map *isl_map_lower_bound_val(__isl_take isl_map *map,6901 enum isl_dim_type type, unsigned pos, __isl_take isl_val *value)6902{6903 if (!value)6904 goto error;6905 if (!isl_val_is_int(value))6906 isl_die(isl_map_get_ctx(map), isl_error_invalid,6907 "expecting integer value", goto error);6908 map = isl_map_lower_bound(map, type, pos, value->n);6909 isl_val_free(value);6910 return map;6911error:6912 isl_val_free(value);6913 isl_map_free(map);6914 return NULL;6915}6916 6917/* Force the values of the variable at position "pos" of type "type" of "set"6918 * to be no smaller than "value".6919 */6920__isl_give isl_set *isl_set_lower_bound_val(__isl_take isl_set *set,6921 enum isl_dim_type type, unsigned pos, __isl_take isl_val *value)6922{6923 isl_map *map;6924 6925 map = set_to_map(set);6926 return set_from_map(isl_map_lower_bound_val(map, type, pos, value));6927}6928 6929/* Force the values of the variable at position "pos" of type "type" of "map"6930 * to be no greater than "value".6931 */6932__isl_give isl_map *isl_map_upper_bound_val(__isl_take isl_map *map,6933 enum isl_dim_type type, unsigned pos, __isl_take isl_val *value)6934{6935 if (!value)6936 goto error;6937 if (!isl_val_is_int(value))6938 isl_die(isl_map_get_ctx(map), isl_error_invalid,6939 "expecting integer value", goto error);6940 map = isl_map_upper_bound(map, type, pos, value->n);6941 isl_val_free(value);6942 return map;6943error:6944 isl_val_free(value);6945 isl_map_free(map);6946 return NULL;6947}6948 6949/* Force the values of the variable at position "pos" of type "type" of "set"6950 * to be no greater than "value".6951 */6952__isl_give isl_set *isl_set_upper_bound_val(__isl_take isl_set *set,6953 enum isl_dim_type type, unsigned pos, __isl_take isl_val *value)6954{6955 isl_map *map;6956 6957 map = set_to_map(set);6958 return set_from_map(isl_map_upper_bound_val(map, type, pos, value));6959}6960 6961/* If "mv" has an explicit domain, then intersect the domain of "map"6962 * with this explicit domain.6963 *6964 * An isl_multi_val object never has an explicit domain,6965 * so simply return "map".6966 */6967static __isl_give isl_map *isl_map_intersect_multi_val_explicit_domain(6968 __isl_take isl_map *map, __isl_keep isl_multi_val *mv)6969{6970 return map;6971}6972 6973#undef BASE6974#define BASE val6975#include "isl_map_bound_templ.c"6976 6977/* Apply "map_bound" to "set" with the corresponding value in "bound"6978 * for each set dimension, by treating the set as a map.6979 */6980static __isl_give isl_set *set_bound_multi_val(__isl_take isl_set *set,6981 __isl_take isl_multi_val *bound,6982 __isl_give isl_map *map_bound(__isl_take isl_map *map,6983 unsigned pos, __isl_take isl_val *value))6984{6985 isl_map *map;6986 6987 map = set_to_map(set);6988 return set_from_map(map_bound_multi_val(map, bound, map_bound));6989}6990 6991#undef BASE6992#define BASE pw_aff6993#include "isl_map_bound_templ.c"6994 6995/* Apply "map_bound" to "set" with the corresponding value in "bound"6996 * for each set dimension, by converting the set and the bound6997 * to objects living in a map space.6998 */6999static __isl_give isl_set *set_bound_multi_pw_aff(__isl_take isl_set *set,7000 __isl_take isl_multi_pw_aff *bound,7001 __isl_give isl_map *set_bound(__isl_take isl_map *map,7002 unsigned pos, __isl_take TYPE *value))7003{7004 isl_map *map;7005 7006 map = isl_map_from_range(set);7007 bound = isl_multi_pw_aff_from_range(bound);7008 map = map_bound_multi_pw_aff(map, bound, set_bound);7009 return isl_map_range(map);7010}7011 7012/* Wrapper around isl_map_lower_bound_val for use in map_bound_multi_val,7013 * setting a bound on the given output dimension.7014 */7015static __isl_give isl_map *map_lower_bound_val(__isl_take isl_map *map,7016 unsigned pos, __isl_take isl_val *v)7017{7018 return isl_map_lower_bound_val(map, isl_dim_out, pos, v);7019}7020 7021/* Force the values of the set dimensions of "set"7022 * to be no smaller than the corresponding values in "lower".7023 */7024__isl_give isl_set *isl_set_lower_bound_multi_val(__isl_take isl_set *set,7025 __isl_take isl_multi_val *lower)7026{7027 return set_bound_multi_val(set, lower, &map_lower_bound_val);7028}7029 7030/* Wrapper around isl_map_upper_bound_val for use in map_bound_multi_val,7031 * setting a bound on the given output dimension.7032 */7033static __isl_give isl_map *map_upper_bound_val(__isl_take isl_map *map,7034 unsigned pos, __isl_take isl_val *v)7035{7036 return isl_map_upper_bound_val(map, isl_dim_out, pos, v);7037}7038 7039/* Force the values of the set dimensions of "set"7040 * to be no greater than the corresponding values in "upper".7041 */7042__isl_give isl_set *isl_set_upper_bound_multi_val(__isl_take isl_set *set,7043 __isl_take isl_multi_val *upper)7044{7045 return set_bound_multi_val(set, upper, &map_upper_bound_val);7046}7047 7048/* Force the symbolic constant expression "bound"7049 * to satisfy the relation "order" with respect to7050 * the output variable at position "pos" of "map".7051 *7052 * Create an affine expression representing the output variable7053 * in terms of the range and7054 * compare it using "order" to "bound" (defined on the domain).7055 * The result is a relation between elements in domain and range that7056 * can be intersected with "map".7057 */7058static __isl_give isl_map *map_bound_pw_aff(__isl_take isl_map *map,7059 unsigned pos, __isl_take isl_pw_aff *bound,7060 __isl_give isl_map *(*order)(__isl_take isl_pw_aff *pa1,7061 __isl_take isl_pw_aff *pa2))7062{7063 isl_space *space;7064 isl_local_space *ls;7065 isl_pw_aff *var;7066 7067 space = isl_space_range(isl_map_get_space(map));7068 ls = isl_local_space_from_space(space);7069 var = isl_pw_aff_var_on_domain(ls, isl_dim_set, pos);7070 map = isl_map_intersect(map, order(bound, var));7071 return map;7072}7073 7074/* Force the values of the output variable at position "pos" of "map"7075 * to be no smaller than the symbolic constant expression "lower".7076 */7077static __isl_give isl_map *map_lower_bound_pw_aff(__isl_take isl_map *map,7078 unsigned pos, __isl_take isl_pw_aff *lower)7079{7080 return map_bound_pw_aff(map, pos, lower, &isl_pw_aff_le_map);7081}7082 7083/* Force the values of the output variable at position "pos" of "map"7084 * to be no greater than the symbolic constant expression "upper".7085 */7086static __isl_give isl_map *map_upper_bound_pw_aff(__isl_take isl_map *map,7087 unsigned pos, __isl_take isl_pw_aff *upper)7088{7089 return map_bound_pw_aff(map, pos, upper, &isl_pw_aff_ge_map);7090}7091 7092/* Force the values of the set dimensions of "set"7093 * to be no smaller than the corresponding constant symbolic expressions7094 * in "lower".7095 */7096__isl_give isl_set *isl_set_lower_bound_multi_pw_aff(__isl_take isl_set *set,7097 __isl_take isl_multi_pw_aff *lower)7098{7099 return set_bound_multi_pw_aff(set, lower, &map_lower_bound_pw_aff);7100}7101 7102/* Force the values of the set dimensions of "set"7103 * to be no greater than the corresponding constant symbolic expressions7104 * in "upper".7105 */7106__isl_give isl_set *isl_set_upper_bound_multi_pw_aff(__isl_take isl_set *set,7107 __isl_take isl_multi_pw_aff *upper)7108{7109 return set_bound_multi_pw_aff(set, upper, &map_upper_bound_pw_aff);7110}7111 7112/* Force the values of the output dimensions of "map"7113 * to be no smaller than the corresponding constant symbolic expressions7114 * in "lower".7115 */7116__isl_give isl_map *isl_map_lower_bound_multi_pw_aff(__isl_take isl_map *map,7117 __isl_take isl_multi_pw_aff *lower)7118{7119 return map_bound_multi_pw_aff(map, lower, &map_lower_bound_pw_aff);7120}7121 7122/* Force the values of the output dimensions of "map"7123 * to be no greater than the corresponding constant symbolic expressions7124 * in "upper".7125 */7126__isl_give isl_map *isl_map_upper_bound_multi_pw_aff(__isl_take isl_map *map,7127 __isl_take isl_multi_pw_aff *upper)7128{7129 return map_bound_multi_pw_aff(map, upper, &map_upper_bound_pw_aff);7130}7131 7132/* Bound the given variable of "bset" from below (or above is "upper"7133 * is set) to "value".7134 */7135static __isl_give isl_basic_set *isl_basic_set_bound(7136 __isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned pos,7137 isl_int value, int upper)7138{7139 return bset_from_bmap(basic_map_bound(bset_to_bmap(bset),7140 type, pos, value, upper));7141}7142 7143/* Bound the given variable of "bset" from below (or above is "upper"7144 * is set) to "value".7145 */7146static __isl_give isl_basic_set *isl_basic_set_bound_val(7147 __isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned pos,7148 __isl_take isl_val *value, int upper)7149{7150 if (!value)7151 goto error;7152 if (!isl_val_is_int(value))7153 isl_die(isl_basic_set_get_ctx(bset), isl_error_invalid,7154 "expecting integer value", goto error);7155 bset = isl_basic_set_bound(bset, type, pos, value->n, upper);7156 isl_val_free(value);7157 return bset;7158error:7159 isl_val_free(value);7160 isl_basic_set_free(bset);7161 return NULL;7162}7163 7164/* Bound the given variable of "bset" from below to "value".7165 */7166__isl_give isl_basic_set *isl_basic_set_lower_bound_val(7167 __isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned pos,7168 __isl_take isl_val *value)7169{7170 return isl_basic_set_bound_val(bset, type, pos, value, 0);7171}7172 7173/* Bound the given variable of "bset" from above to "value".7174 */7175__isl_give isl_basic_set *isl_basic_set_upper_bound_val(7176 __isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned pos,7177 __isl_take isl_val *value)7178{7179 return isl_basic_set_bound_val(bset, type, pos, value, 1);7180}7181 7182__isl_give isl_map *isl_map_reverse(__isl_take isl_map *map)7183{7184 return isl_map_transform(map, &isl_space_reverse,7185 &isl_basic_map_reverse);7186}7187 7188/* Given a map A -> (B -> C), return the corresponding map A -> (C -> B).7189 */7190__isl_give isl_map *isl_map_range_reverse(__isl_take isl_map *map)7191{7192 return isl_map_transform(map, &isl_space_range_reverse,7193 &isl_basic_map_range_reverse);7194}7195 7196#undef TYPE7197#define TYPE isl_pw_multi_aff7198#undef SUFFIX7199#define SUFFIX _pw_multi_aff7200#undef EMPTY7201#define EMPTY isl_pw_multi_aff_empty7202#undef ADD7203#define ADD isl_pw_multi_aff_union_add7204#include "isl_map_lexopt_templ.c"7205 7206/* Given a map "map", compute the lexicographically minimal7207 * (or maximal) image element for each domain element in dom,7208 * in the form of an isl_pw_multi_aff.7209 * If "empty" is not NULL, then set *empty to those elements in dom that7210 * do not have an image element.7211 * If "flags" includes ISL_OPT_FULL, then "dom" is NULL and the optimum7212 * should be computed over the domain of "map". "empty" is also NULL7213 * in this case.7214 *7215 * We first compute the lexicographically minimal or maximal element7216 * in the first basic map. This results in a partial solution "res"7217 * and a subset "todo" of dom that still need to be handled.7218 * We then consider each of the remaining maps in "map" and successively7219 * update both "res" and "todo".7220 * If "empty" is NULL, then the todo sets are not needed and therefore7221 * also not computed.7222 */7223static __isl_give isl_pw_multi_aff *isl_map_partial_lexopt_aligned_pw_multi_aff(7224 __isl_take isl_map *map, __isl_take isl_set *dom,7225 __isl_give isl_set **empty, unsigned flags)7226{7227 int i;7228 int full;7229 isl_pw_multi_aff *res;7230 isl_set *todo;7231 7232 full = ISL_FL_ISSET(flags, ISL_OPT_FULL);7233 if (!map || (!full && !dom))7234 goto error;7235 7236 if (isl_map_plain_is_empty(map)) {7237 if (empty)7238 *empty = dom;7239 else7240 isl_set_free(dom);7241 return isl_pw_multi_aff_from_map(map);7242 }7243 7244 res = basic_map_partial_lexopt_pw_multi_aff(7245 isl_basic_map_copy(map->p[0]),7246 isl_set_copy(dom), empty, flags);7247 7248 if (empty)7249 todo = *empty;7250 for (i = 1; i < map->n; ++i) {7251 isl_pw_multi_aff *res_i;7252 7253 res_i = basic_map_partial_lexopt_pw_multi_aff(7254 isl_basic_map_copy(map->p[i]),7255 isl_set_copy(dom), empty, flags);7256 7257 if (ISL_FL_ISSET(flags, ISL_OPT_MAX))7258 res = isl_pw_multi_aff_union_lexmax(res, res_i);7259 else7260 res = isl_pw_multi_aff_union_lexmin(res, res_i);7261 7262 if (empty)7263 todo = isl_set_intersect(todo, *empty);7264 }7265 7266 isl_set_free(dom);7267 isl_map_free(map);7268 7269 if (empty)7270 *empty = todo;7271 7272 return res;7273error:7274 if (empty)7275 *empty = NULL;7276 isl_set_free(dom);7277 isl_map_free(map);7278 return NULL;7279}7280 7281#undef TYPE7282#define TYPE isl_map7283#undef SUFFIX7284#define SUFFIX7285#undef EMPTY7286#define EMPTY isl_map_empty7287#undef ADD7288#define ADD isl_map_union_disjoint7289#include "isl_map_lexopt_templ.c"7290 7291/* Given a map "map", compute the lexicographically minimal7292 * (or maximal) image element for each domain element in "dom",7293 * in the form of an isl_map.7294 * If "empty" is not NULL, then set *empty to those elements in "dom" that7295 * do not have an image element.7296 * If "flags" includes ISL_OPT_FULL, then "dom" is NULL and the optimum7297 * should be computed over the domain of "map". "empty" is also NULL7298 * in this case.7299 *7300 * If the input consists of more than one disjunct, then first7301 * compute the desired result in the form of an isl_pw_multi_aff and7302 * then convert that into an isl_map.7303 *7304 * This function used to have an explicit implementation in terms7305 * of isl_maps, but it would continually intersect the domains of7306 * partial results with the complement of the domain of the next7307 * partial solution, potentially leading to an explosion in the number7308 * of disjuncts if there are several disjuncts in the input.7309 * An even earlier implementation of this function would look for7310 * better results in the domain of the partial result and for extra7311 * results in the complement of this domain, which would lead to7312 * even more splintering.7313 */7314static __isl_give isl_map *isl_map_partial_lexopt_aligned(7315 __isl_take isl_map *map, __isl_take isl_set *dom,7316 __isl_give isl_set **empty, unsigned flags)7317{7318 int full;7319 struct isl_map *res;7320 isl_pw_multi_aff *pma;7321 7322 full = ISL_FL_ISSET(flags, ISL_OPT_FULL);7323 if (!map || (!full && !dom))7324 goto error;7325 7326 if (isl_map_plain_is_empty(map)) {7327 if (empty)7328 *empty = dom;7329 else7330 isl_set_free(dom);7331 return map;7332 }7333 7334 if (map->n == 1) {7335 res = basic_map_partial_lexopt(isl_basic_map_copy(map->p[0]),7336 dom, empty, flags);7337 isl_map_free(map);7338 return res;7339 }7340 7341 pma = isl_map_partial_lexopt_aligned_pw_multi_aff(map, dom, empty,7342 flags);7343 return isl_map_from_pw_multi_aff_internal(pma);7344error:7345 if (empty)7346 *empty = NULL;7347 isl_set_free(dom);7348 isl_map_free(map);7349 return NULL;7350}7351 7352__isl_give isl_map *isl_map_partial_lexmax(7353 __isl_take isl_map *map, __isl_take isl_set *dom,7354 __isl_give isl_set **empty)7355{7356 return isl_map_partial_lexopt(map, dom, empty, ISL_OPT_MAX);7357}7358 7359__isl_give isl_map *isl_map_partial_lexmin(7360 __isl_take isl_map *map, __isl_take isl_set *dom,7361 __isl_give isl_set **empty)7362{7363 return isl_map_partial_lexopt(map, dom, empty, 0);7364}7365 7366__isl_give isl_set *isl_set_partial_lexmin(7367 __isl_take isl_set *set, __isl_take isl_set *dom,7368 __isl_give isl_set **empty)7369{7370 return set_from_map(isl_map_partial_lexmin(set_to_map(set),7371 dom, empty));7372}7373 7374__isl_give isl_set *isl_set_partial_lexmax(7375 __isl_take isl_set *set, __isl_take isl_set *dom,7376 __isl_give isl_set **empty)7377{7378 return set_from_map(isl_map_partial_lexmax(set_to_map(set),7379 dom, empty));7380}7381 7382/* Compute the lexicographic minimum (or maximum if "flags" includes7383 * ISL_OPT_MAX) of "bset" over its parametric domain.7384 */7385__isl_give isl_set *isl_basic_set_lexopt(__isl_take isl_basic_set *bset,7386 unsigned flags)7387{7388 return isl_basic_map_lexopt(bset, flags);7389}7390 7391__isl_give isl_map *isl_basic_map_lexmax(__isl_take isl_basic_map *bmap)7392{7393 return isl_basic_map_lexopt(bmap, ISL_OPT_MAX);7394}7395 7396__isl_give isl_set *isl_basic_set_lexmin(__isl_take isl_basic_set *bset)7397{7398 return set_from_map(isl_basic_map_lexmin(bset_to_bmap(bset)));7399}7400 7401__isl_give isl_set *isl_basic_set_lexmax(__isl_take isl_basic_set *bset)7402{7403 return set_from_map(isl_basic_map_lexmax(bset_to_bmap(bset)));7404}7405 7406/* Compute the lexicographic minimum of "bset" over its parametric domain7407 * for the purpose of quantifier elimination.7408 * That is, find an explicit representation for all the existentially7409 * quantified variables in "bset" by computing their lexicographic7410 * minimum.7411 */7412static __isl_give isl_set *isl_basic_set_lexmin_compute_divs(7413 __isl_take isl_basic_set *bset)7414{7415 return isl_basic_set_lexopt(bset, ISL_OPT_QE);7416}7417 7418/* Given a basic map with one output dimension, compute the minimum or7419 * maximum of that dimension as an isl_pw_aff.7420 *7421 * Compute the optimum as a lexicographic optimum over the single7422 * output dimension and extract the single isl_pw_aff from the result.7423 */7424static __isl_give isl_pw_aff *basic_map_dim_opt(__isl_keep isl_basic_map *bmap,7425 int max)7426{7427 isl_pw_multi_aff *pma;7428 isl_pw_aff *pwaff;7429 7430 bmap = isl_basic_map_copy(bmap);7431 pma = isl_basic_map_lexopt_pw_multi_aff(bmap, max ? ISL_OPT_MAX : 0);7432 pwaff = isl_pw_multi_aff_get_pw_aff(pma, 0);7433 isl_pw_multi_aff_free(pma);7434 7435 return pwaff;7436}7437 7438/* Compute the minimum or maximum of the given output dimension7439 * as a function of the parameters and the input dimensions,7440 * but independently of the other output dimensions.7441 *7442 * We first project out the other output dimension and then compute7443 * the "lexicographic" maximum in each basic map, combining the results7444 * using isl_pw_aff_union_max.7445 */7446static __isl_give isl_pw_aff *map_dim_opt(__isl_take isl_map *map, int pos,7447 int max)7448{7449 int i;7450 isl_pw_aff *pwaff;7451 isl_size n_out;7452 7453 n_out = isl_map_dim(map, isl_dim_out);7454 if (n_out < 0)7455 map = isl_map_free(map);7456 map = isl_map_project_out(map, isl_dim_out, pos + 1, n_out - (pos + 1));7457 map = isl_map_project_out(map, isl_dim_out, 0, pos);7458 if (!map)7459 return NULL;7460 7461 if (map->n == 0) {7462 isl_space *space = isl_map_get_space(map);7463 isl_map_free(map);7464 return isl_pw_aff_empty(space);7465 }7466 7467 pwaff = basic_map_dim_opt(map->p[0], max);7468 for (i = 1; i < map->n; ++i) {7469 isl_pw_aff *pwaff_i;7470 7471 pwaff_i = basic_map_dim_opt(map->p[i], max);7472 pwaff = isl_pw_aff_union_opt(pwaff, pwaff_i, max);7473 }7474 7475 isl_map_free(map);7476 7477 return pwaff;7478}7479 7480/* Compute the minimum of the given output dimension as a function of the7481 * parameters and input dimensions, but independently of7482 * the other output dimensions.7483 */7484__isl_give isl_pw_aff *isl_map_dim_min(__isl_take isl_map *map, int pos)7485{7486 return map_dim_opt(map, pos, 0);7487}7488 7489/* Compute the maximum of the given output dimension as a function of the7490 * parameters and input dimensions, but independently of7491 * the other output dimensions.7492 */7493__isl_give isl_pw_aff *isl_map_dim_max(__isl_take isl_map *map, int pos)7494{7495 return map_dim_opt(map, pos, 1);7496}7497 7498/* Compute the minimum or maximum of the given set dimension7499 * as a function of the parameters,7500 * but independently of the other set dimensions.7501 */7502static __isl_give isl_pw_aff *set_dim_opt(__isl_take isl_set *set, int pos,7503 int max)7504{7505 return map_dim_opt(set, pos, max);7506}7507 7508/* Compute the maximum of the given set dimension as a function of the7509 * parameters, but independently of the other set dimensions.7510 */7511__isl_give isl_pw_aff *isl_set_dim_max(__isl_take isl_set *set, int pos)7512{7513 return set_dim_opt(set, pos, 1);7514}7515 7516/* Compute the minimum of the given set dimension as a function of the7517 * parameters, but independently of the other set dimensions.7518 */7519__isl_give isl_pw_aff *isl_set_dim_min(__isl_take isl_set *set, int pos)7520{7521 return set_dim_opt(set, pos, 0);7522}7523 7524/* Apply a preimage specified by "mat" on the parameters of "bset".7525 * bset is assumed to have only parameters and divs.7526 */7527static __isl_give isl_basic_set *basic_set_parameter_preimage(7528 __isl_take isl_basic_set *bset, __isl_take isl_mat *mat)7529{7530 isl_size nparam;7531 7532 nparam = isl_basic_set_dim(bset, isl_dim_param);7533 if (nparam < 0 || !mat)7534 goto error;7535 7536 bset->dim = isl_space_cow(bset->dim);7537 if (!bset->dim)7538 goto error;7539 7540 isl_assert(bset->ctx, mat->n_row == 1 + nparam, goto error);7541 7542 bset->dim->nparam = 0;7543 bset->dim->n_out = nparam;7544 bset = isl_basic_set_preimage(bset, mat);7545 if (bset) {7546 bset->dim->nparam = bset->dim->n_out;7547 bset->dim->n_out = 0;7548 }7549 return bset;7550error:7551 isl_mat_free(mat);7552 isl_basic_set_free(bset);7553 return NULL;7554}7555 7556/* Apply a preimage specified by "mat" on the parameters of "set".7557 * set is assumed to have only parameters and divs.7558 */7559static __isl_give isl_set *set_parameter_preimage(__isl_take isl_set *set,7560 __isl_take isl_mat *mat)7561{7562 isl_space *space;7563 isl_size nparam;7564 7565 nparam = isl_set_dim(set, isl_dim_param);7566 if (nparam < 0 || !mat)7567 goto error;7568 7569 if (mat->n_row != 1 + nparam)7570 isl_die(isl_set_get_ctx(set), isl_error_internal,7571 "unexpected number of rows", goto error);7572 7573 space = isl_set_get_space(set);7574 space = isl_space_move_dims(space, isl_dim_set, 0,7575 isl_dim_param, 0, nparam);7576 set = isl_set_reset_space(set, space);7577 set = isl_set_preimage(set, mat);7578 nparam = isl_set_dim(set, isl_dim_out);7579 if (nparam < 0)7580 set = isl_set_free(set);7581 space = isl_set_get_space(set);7582 space = isl_space_move_dims(space, isl_dim_param, 0,7583 isl_dim_out, 0, nparam);7584 set = isl_set_reset_space(set, space);7585 return set;7586error:7587 isl_mat_free(mat);7588 isl_set_free(set);7589 return NULL;7590}7591 7592/* Intersect the basic set "bset" with the affine space specified by the7593 * equalities in "eq".7594 */7595static __isl_give isl_basic_set *basic_set_append_equalities(7596 __isl_take isl_basic_set *bset, __isl_take isl_mat *eq)7597{7598 int i, k;7599 unsigned len;7600 7601 if (!bset || !eq)7602 goto error;7603 7604 bset = isl_basic_set_extend(bset, 0, eq->n_row, 0);7605 if (!bset)7606 goto error;7607 7608 len = isl_basic_set_offset(bset, isl_dim_div) + bset->extra;7609 for (i = 0; i < eq->n_row; ++i) {7610 k = isl_basic_set_alloc_equality(bset);7611 if (k < 0)7612 goto error;7613 isl_seq_cpy(bset->eq[k], eq->row[i], eq->n_col);7614 isl_seq_clr(bset->eq[k] + eq->n_col, len - eq->n_col);7615 }7616 isl_mat_free(eq);7617 7618 bset = isl_basic_set_gauss(bset, NULL);7619 bset = isl_basic_set_finalize(bset);7620 7621 return bset;7622error:7623 isl_mat_free(eq);7624 isl_basic_set_free(bset);7625 return NULL;7626}7627 7628/* Intersect the set "set" with the affine space specified by the7629 * equalities in "eq".7630 */7631static __isl_give isl_set *set_append_equalities(__isl_take isl_set *set,7632 __isl_take isl_mat *eq)7633{7634 int i;7635 7636 if (!set || !eq)7637 goto error;7638 7639 for (i = 0; i < set->n; ++i) {7640 set->p[i] = basic_set_append_equalities(set->p[i],7641 isl_mat_copy(eq));7642 if (!set->p[i])7643 goto error;7644 }7645 isl_mat_free(eq);7646 return set;7647error:7648 isl_mat_free(eq);7649 isl_set_free(set);7650 return NULL;7651}7652 7653/* Given a basic set "bset" that only involves parameters and existentially7654 * quantified variables, return the index of the first equality7655 * that only involves parameters. If there is no such equality then7656 * return bset->n_eq.7657 *7658 * This function assumes that isl_basic_set_gauss has been called on "bset".7659 */7660static int first_parameter_equality(__isl_keep isl_basic_set *bset)7661{7662 int i, j;7663 isl_size nparam, n_div;7664 7665 nparam = isl_basic_set_dim(bset, isl_dim_param);7666 n_div = isl_basic_set_dim(bset, isl_dim_div);7667 if (nparam < 0 || n_div < 0)7668 return -1;7669 7670 for (i = 0, j = n_div - 1; i < bset->n_eq && j >= 0; --j) {7671 if (!isl_int_is_zero(bset->eq[i][1 + nparam + j]))7672 ++i;7673 }7674 7675 return i;7676}7677 7678/* Compute an explicit representation for the existentially quantified7679 * variables in "bset" by computing the "minimal value" of the set7680 * variables. Since there are no set variables, the computation of7681 * the minimal value essentially computes an explicit representation7682 * of the non-empty part(s) of "bset".7683 *7684 * The input only involves parameters and existentially quantified variables.7685 * All equalities among parameters have been removed.7686 *7687 * Since the existentially quantified variables in the result are in general7688 * going to be different from those in the input, we first replace7689 * them by the minimal number of variables based on their equalities.7690 * This should simplify the parametric integer programming.7691 */7692static __isl_give isl_set *base_compute_divs(__isl_take isl_basic_set *bset)7693{7694 isl_morph *morph1, *morph2;7695 isl_set *set;7696 isl_size n;7697 7698 if (!bset)7699 return NULL;7700 if (bset->n_eq == 0)7701 return isl_basic_set_lexmin_compute_divs(bset);7702 7703 morph1 = isl_basic_set_parameter_compression(bset);7704 bset = isl_morph_basic_set(isl_morph_copy(morph1), bset);7705 bset = isl_basic_set_lift(bset);7706 morph2 = isl_basic_set_variable_compression(bset, isl_dim_set);7707 bset = isl_morph_basic_set(morph2, bset);7708 n = isl_basic_set_dim(bset, isl_dim_set);7709 if (n < 0)7710 bset = isl_basic_set_free(bset);7711 bset = isl_basic_set_project_out(bset, isl_dim_set, 0, n);7712 7713 set = isl_basic_set_lexmin_compute_divs(bset);7714 7715 set = isl_morph_set(isl_morph_inverse(morph1), set);7716 7717 return set;7718}7719 7720/* Project the given basic set onto its parameter domain, possibly introducing7721 * new, explicit, existential variables in the constraints.7722 * The input has parameters and (possibly implicit) existential variables.7723 * The output has the same parameters, but only7724 * explicit existentially quantified variables.7725 *7726 * The actual projection is performed by pip, but pip doesn't seem7727 * to like equalities very much, so we first remove the equalities7728 * among the parameters by performing a variable compression on7729 * the parameters. Afterward, an inverse transformation is performed7730 * and the equalities among the parameters are inserted back in.7731 *7732 * The variable compression on the parameters may uncover additional7733 * equalities that were only implicit before. We therefore check7734 * if there are any new parameter equalities in the result and7735 * if so recurse. The removal of parameter equalities is required7736 * for the parameter compression performed by base_compute_divs.7737 */7738static __isl_give isl_set *parameter_compute_divs(7739 __isl_take isl_basic_set *bset)7740{7741 int i;7742 struct isl_mat *eq;7743 struct isl_mat *T, *T2;7744 struct isl_set *set;7745 isl_size nparam;7746 7747 bset = isl_basic_set_cow(bset);7748 if (!bset)7749 return NULL;7750 7751 if (bset->n_eq == 0)7752 return base_compute_divs(bset);7753 7754 bset = isl_basic_set_gauss(bset, NULL);7755 if (!bset)7756 return NULL;7757 if (isl_basic_set_plain_is_empty(bset))7758 return isl_set_from_basic_set(bset);7759 7760 i = first_parameter_equality(bset);7761 if (i == bset->n_eq)7762 return base_compute_divs(bset);7763 7764 nparam = isl_basic_set_dim(bset, isl_dim_param);7765 if (nparam < 0)7766 return isl_set_from_basic_set(isl_basic_set_free(bset));7767 eq = isl_mat_sub_alloc6(bset->ctx, bset->eq, i, bset->n_eq - i,7768 0, 1 + nparam);7769 eq = isl_mat_cow(eq);7770 T = isl_mat_variable_compression(isl_mat_copy(eq), &T2);7771 if (T && T->n_col == 0) {7772 isl_mat_free(T);7773 isl_mat_free(T2);7774 isl_mat_free(eq);7775 bset = isl_basic_set_set_to_empty(bset);7776 return isl_set_from_basic_set(bset);7777 }7778 bset = basic_set_parameter_preimage(bset, T);7779 7780 i = first_parameter_equality(bset);7781 if (!bset)7782 set = NULL;7783 else if (i == bset->n_eq)7784 set = base_compute_divs(bset);7785 else7786 set = parameter_compute_divs(bset);7787 set = set_parameter_preimage(set, T2);7788 set = set_append_equalities(set, eq);7789 return set;7790}7791 7792/* Insert the divs from "ls" before those of "bmap".7793 *7794 * The number of columns is not changed, which means that the last7795 * dimensions of "bmap" are being reintepreted as the divs from "ls".7796 * The caller is responsible for removing the same number of dimensions7797 * from the space of "bmap".7798 */7799static __isl_give isl_basic_map *insert_divs_from_local_space(7800 __isl_take isl_basic_map *bmap, __isl_keep isl_local_space *ls)7801{7802 int i;7803 isl_size n_div;7804 int old_n_div;7805 7806 n_div = isl_local_space_dim(ls, isl_dim_div);7807 if (n_div < 0)7808 return isl_basic_map_free(bmap);7809 if (n_div == 0)7810 return bmap;7811 7812 old_n_div = bmap->n_div;7813 bmap = insert_div_rows(bmap, n_div);7814 if (!bmap)7815 return NULL;7816 7817 for (i = 0; i < n_div; ++i) {7818 isl_seq_cpy(bmap->div[i], ls->div->row[i], ls->div->n_col);7819 isl_seq_clr(bmap->div[i] + ls->div->n_col, old_n_div);7820 }7821 7822 return bmap;7823}7824 7825/* Replace the space of "bmap" by the space and divs of "ls".7826 *7827 * If "ls" has any divs, then we simplify the result since we may7828 * have discovered some additional equalities that could simplify7829 * the div expressions.7830 */7831static __isl_give isl_basic_map *basic_replace_space_by_local_space(7832 __isl_take isl_basic_map *bmap, __isl_take isl_local_space *ls)7833{7834 isl_size n_div;7835 7836 bmap = isl_basic_map_cow(bmap);7837 n_div = isl_local_space_dim(ls, isl_dim_div);7838 if (!bmap || n_div < 0)7839 goto error;7840 7841 bmap = insert_divs_from_local_space(bmap, ls);7842 if (!bmap)7843 goto error;7844 7845 isl_space_free(bmap->dim);7846 bmap->dim = isl_local_space_get_space(ls);7847 if (!bmap->dim)7848 goto error;7849 7850 isl_local_space_free(ls);7851 if (n_div > 0)7852 bmap = isl_basic_map_simplify(bmap);7853 bmap = isl_basic_map_finalize(bmap);7854 return bmap;7855error:7856 isl_basic_map_free(bmap);7857 isl_local_space_free(ls);7858 return NULL;7859}7860 7861/* Replace the space of "map" by the space and divs of "ls".7862 */7863static __isl_give isl_map *replace_space_by_local_space(__isl_take isl_map *map,7864 __isl_take isl_local_space *ls)7865{7866 int i;7867 7868 map = isl_map_cow(map);7869 if (!map || !ls)7870 goto error;7871 7872 for (i = 0; i < map->n; ++i) {7873 map->p[i] = basic_replace_space_by_local_space(map->p[i],7874 isl_local_space_copy(ls));7875 if (!map->p[i])7876 goto error;7877 }7878 isl_space_free(isl_map_take_space(map));7879 map = isl_map_restore_space(map, isl_local_space_get_space(ls));7880 7881 isl_local_space_free(ls);7882 return map;7883error:7884 isl_local_space_free(ls);7885 isl_map_free(map);7886 return NULL;7887}7888 7889/* Compute an explicit representation for the existentially7890 * quantified variables for which do not know any explicit representation yet.7891 *7892 * We first sort the existentially quantified variables so that the7893 * existentially quantified variables for which we already have an explicit7894 * representation are placed before those for which we do not.7895 * The input dimensions, the output dimensions and the existentially7896 * quantified variables for which we already have an explicit7897 * representation are then turned into parameters.7898 * compute_divs returns a map with the same parameters and7899 * no input or output dimensions and the dimension specification7900 * is reset to that of the input, including the existentially quantified7901 * variables for which we already had an explicit representation.7902 */7903static __isl_give isl_map *compute_divs(__isl_take isl_basic_map *bmap)7904{7905 struct isl_basic_set *bset;7906 struct isl_set *set;7907 struct isl_map *map;7908 isl_space *space;7909 isl_local_space *ls;7910 isl_size nparam;7911 isl_size n_in;7912 isl_size n_out;7913 int n_known;7914 int i;7915 7916 bmap = isl_basic_map_sort_divs(bmap);7917 bmap = isl_basic_map_cow(bmap);7918 if (!bmap)7919 return NULL;7920 7921 n_known = isl_basic_map_first_unknown_div(bmap);7922 nparam = isl_basic_map_dim(bmap, isl_dim_param);7923 n_in = isl_basic_map_dim(bmap, isl_dim_in);7924 n_out = isl_basic_map_dim(bmap, isl_dim_out);7925 if (n_known < 0 || nparam < 0 || n_in < 0 || n_out < 0)7926 return isl_map_from_basic_map(isl_basic_map_free(bmap));7927 7928 space = isl_space_set_alloc(bmap->ctx,7929 nparam + n_in + n_out + n_known, 0);7930 if (!space)7931 goto error;7932 7933 ls = isl_basic_map_get_local_space(bmap);7934 ls = isl_local_space_drop_dims(ls, isl_dim_div,7935 n_known, bmap->n_div - n_known);7936 if (n_known > 0) {7937 for (i = n_known; i < bmap->n_div; ++i)7938 swap_div(bmap, i - n_known, i);7939 bmap->n_div -= n_known;7940 bmap->extra -= n_known;7941 }7942 bmap = isl_basic_map_reset_space(bmap, space);7943 bset = bset_from_bmap(bmap);7944 7945 set = parameter_compute_divs(bset);7946 map = set_to_map(set);7947 map = replace_space_by_local_space(map, ls);7948 7949 return map;7950error:7951 isl_basic_map_free(bmap);7952 return NULL;7953}7954 7955/* Remove the explicit representation of local variable "div",7956 * if there is any.7957 */7958__isl_give isl_basic_map *isl_basic_map_mark_div_unknown(7959 __isl_take isl_basic_map *bmap, int div)7960{7961 isl_bool unknown;7962 7963 unknown = isl_basic_map_div_is_marked_unknown(bmap, div);7964 if (unknown < 0)7965 return isl_basic_map_free(bmap);7966 if (unknown)7967 return bmap;7968 7969 bmap = isl_basic_map_cow(bmap);7970 if (!bmap)7971 return NULL;7972 isl_int_set_si(bmap->div[div][0], 0);7973 return bmap;7974}7975 7976/* Is local variable "div" of "bmap" marked as not having an explicit7977 * representation?7978 * Note that even if "div" is not marked in this way and therefore7979 * has an explicit representation, this representation may still7980 * depend (indirectly) on other local variables that do not7981 * have an explicit representation.7982 */7983isl_bool isl_basic_map_div_is_marked_unknown(__isl_keep isl_basic_map *bmap,7984 int div)7985{7986 if (isl_basic_map_check_range(bmap, isl_dim_div, div, 1) < 0)7987 return isl_bool_error;7988 return isl_int_is_zero(bmap->div[div][0]);7989}7990 7991/* Return the position of the first local variable that does not7992 * have an explicit representation.7993 * Return the total number of local variables if they all have7994 * an explicit representation.7995 * Return -1 on error.7996 */7997int isl_basic_map_first_unknown_div(__isl_keep isl_basic_map *bmap)7998{7999 int i;8000 8001 if (!bmap)8002 return -1;8003 8004 for (i = 0; i < bmap->n_div; ++i) {8005 if (!isl_basic_map_div_is_known(bmap, i))8006 return i;8007 }8008 return bmap->n_div;8009}8010 8011/* Return the position of the first local variable that does not8012 * have an explicit representation.8013 * Return the total number of local variables if they all have8014 * an explicit representation.8015 * Return -1 on error.8016 */8017int isl_basic_set_first_unknown_div(__isl_keep isl_basic_set *bset)8018{8019 return isl_basic_map_first_unknown_div(bset);8020}8021 8022/* Does "bmap" have an explicit representation for all local variables?8023 */8024isl_bool isl_basic_map_divs_known(__isl_keep isl_basic_map *bmap)8025{8026 int first;8027 isl_size n;8028 8029 n = isl_basic_map_dim(bmap, isl_dim_div);8030 first = isl_basic_map_first_unknown_div(bmap);8031 if (n < 0 || first < 0)8032 return isl_bool_error;8033 return first == n;8034}8035 8036/* Do all basic maps in "map" have an explicit representation8037 * for all local variables?8038 */8039isl_bool isl_map_divs_known(__isl_keep isl_map *map)8040{8041 int i;8042 8043 if (!map)8044 return isl_bool_error;8045 8046 for (i = 0; i < map->n; ++i) {8047 int known = isl_basic_map_divs_known(map->p[i]);8048 if (known <= 0)8049 return known;8050 }8051 8052 return isl_bool_true;8053}8054 8055/* If bmap contains any unknown divs, then compute explicit8056 * expressions for them. However, this computation may be8057 * quite expensive, so first try to remove divs that aren't8058 * strictly needed.8059 */8060__isl_give isl_map *isl_basic_map_compute_divs(__isl_take isl_basic_map *bmap)8061{8062 int known;8063 struct isl_map *map;8064 8065 known = isl_basic_map_divs_known(bmap);8066 if (known < 0)8067 goto error;8068 if (known)8069 return isl_map_from_basic_map(bmap);8070 8071 bmap = isl_basic_map_drop_redundant_divs(bmap);8072 8073 known = isl_basic_map_divs_known(bmap);8074 if (known < 0)8075 goto error;8076 if (known)8077 return isl_map_from_basic_map(bmap);8078 8079 map = compute_divs(bmap);8080 return map;8081error:8082 isl_basic_map_free(bmap);8083 return NULL;8084}8085 8086__isl_give isl_map *isl_map_compute_divs(__isl_take isl_map *map)8087{8088 int i;8089 int known;8090 struct isl_map *res;8091 8092 if (!map)8093 return NULL;8094 if (map->n == 0)8095 return map;8096 8097 known = isl_map_divs_known(map);8098 if (known < 0) {8099 isl_map_free(map);8100 return NULL;8101 }8102 if (known)8103 return map;8104 8105 res = isl_basic_map_compute_divs(isl_basic_map_copy(map->p[0]));8106 for (i = 1 ; i < map->n; ++i) {8107 struct isl_map *r2;8108 r2 = isl_basic_map_compute_divs(isl_basic_map_copy(map->p[i]));8109 if (ISL_F_ISSET(map, ISL_MAP_DISJOINT))8110 res = isl_map_union_disjoint(res, r2);8111 else8112 res = isl_map_union(res, r2);8113 }8114 isl_map_free(map);8115 8116 return res;8117}8118 8119__isl_give isl_set *isl_basic_set_compute_divs(__isl_take isl_basic_set *bset)8120{8121 return set_from_map(isl_basic_map_compute_divs(bset_to_bmap(bset)));8122}8123 8124__isl_give isl_set *isl_set_compute_divs(__isl_take isl_set *set)8125{8126 return set_from_map(isl_map_compute_divs(set_to_map(set)));8127}8128 8129__isl_give isl_set *isl_map_domain(__isl_take isl_map *map)8130{8131 isl_space *space;8132 isl_size n_out;8133 8134 n_out = isl_map_dim(map, isl_dim_out);8135 if (n_out < 0)8136 return set_from_map(isl_map_free(map));8137 space = isl_space_domain(isl_map_get_space(map));8138 8139 map = isl_map_project_out(map, isl_dim_out, 0, n_out);8140 8141 return set_from_map(isl_map_reset_space(map, space));8142}8143 8144/* Return the union of "map1" and "map2", where we assume for now that8145 * "map1" and "map2" are disjoint. Note that the basic maps inside8146 * "map1" or "map2" may not be disjoint from each other.8147 * Also note that this function is also called from isl_map_union,8148 * which takes care of handling the situation where "map1" and "map2"8149 * may not be disjoint.8150 *8151 * If one of the inputs is empty, we can simply return the other input.8152 * Similarly, if one of the inputs is universal, then it is equal to the union.8153 */8154static __isl_give isl_map *map_union_disjoint(__isl_take isl_map *map1,8155 __isl_take isl_map *map2)8156{8157 int i;8158 unsigned flags = 0;8159 struct isl_map *map = NULL;8160 int is_universe;8161 8162 if (isl_map_check_equal_space(map1, map2) < 0)8163 goto error;8164 8165 if (map1->n == 0) {8166 isl_map_free(map1);8167 return map2;8168 }8169 if (map2->n == 0) {8170 isl_map_free(map2);8171 return map1;8172 }8173 8174 is_universe = isl_map_plain_is_universe(map1);8175 if (is_universe < 0)8176 goto error;8177 if (is_universe) {8178 isl_map_free(map2);8179 return map1;8180 }8181 8182 is_universe = isl_map_plain_is_universe(map2);8183 if (is_universe < 0)8184 goto error;8185 if (is_universe) {8186 isl_map_free(map1);8187 return map2;8188 }8189 8190 if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) &&8191 ISL_F_ISSET(map2, ISL_MAP_DISJOINT))8192 ISL_FL_SET(flags, ISL_MAP_DISJOINT);8193 8194 map = isl_map_alloc_space(isl_space_copy(map1->dim),8195 map1->n + map2->n, flags);8196 if (!map)8197 goto error;8198 for (i = 0; i < map1->n; ++i) {8199 map = isl_map_add_basic_map(map,8200 isl_basic_map_copy(map1->p[i]));8201 if (!map)8202 goto error;8203 }8204 for (i = 0; i < map2->n; ++i) {8205 map = isl_map_add_basic_map(map,8206 isl_basic_map_copy(map2->p[i]));8207 if (!map)8208 goto error;8209 }8210 isl_map_free(map1);8211 isl_map_free(map2);8212 return map;8213error:8214 isl_map_free(map);8215 isl_map_free(map1);8216 isl_map_free(map2);8217 return NULL;8218}8219 8220/* Return the union of "map1" and "map2", where "map1" and "map2" are8221 * guaranteed to be disjoint by the caller.8222 *8223 * Note that this functions is called from within isl_map_make_disjoint,8224 * so we have to be careful not to touch the constraints of the inputs8225 * in any way.8226 */8227__isl_give isl_map *isl_map_union_disjoint(__isl_take isl_map *map1,8228 __isl_take isl_map *map2)8229{8230 isl_map_align_params_bin(&map1, &map2);8231 return map_union_disjoint(map1, map2);8232}8233 8234/* Return the union of "map1" and "map2", where "map1" and "map2" may8235 * not be disjoint.8236 *8237 * We currently simply call map_union_disjoint, the internal operation8238 * of which does not really depend on the inputs being disjoint.8239 * If the result contains more than one basic map, then we clear8240 * the disjoint flag since the result may contain basic maps from8241 * both inputs and these are not guaranteed to be disjoint.8242 *8243 * As a special case, if "map1" and "map2" are obviously equal,8244 * then we simply return "map1".8245 */8246__isl_give isl_map *isl_map_union(__isl_take isl_map *map1,8247 __isl_take isl_map *map2)8248{8249 int equal;8250 8251 if (isl_map_align_params_bin(&map1, &map2) < 0)8252 goto error;8253 8254 equal = isl_map_plain_is_equal(map1, map2);8255 if (equal < 0)8256 goto error;8257 if (equal) {8258 isl_map_free(map2);8259 return map1;8260 }8261 8262 map1 = map_union_disjoint(map1, map2);8263 if (!map1)8264 return NULL;8265 if (map1->n > 1)8266 ISL_F_CLR(map1, ISL_MAP_DISJOINT);8267 return map1;8268error:8269 isl_map_free(map1);8270 isl_map_free(map2);8271 return NULL;8272}8273 8274__isl_give isl_set *isl_set_union_disjoint(8275 __isl_take isl_set *set1, __isl_take isl_set *set2)8276{8277 return set_from_map(isl_map_union_disjoint(set_to_map(set1),8278 set_to_map(set2)));8279}8280 8281__isl_give isl_set *isl_set_union(__isl_take isl_set *set1,8282 __isl_take isl_set *set2)8283{8284 return set_from_map(isl_map_union(set_to_map(set1), set_to_map(set2)));8285}8286 8287/* Apply "fn" to pairs of elements from "map" and "set" and collect8288 * the results in a map living in "space".8289 *8290 * "map" and "set" are assumed to be compatible and non-NULL.8291 */8292static __isl_give isl_map *map_intersect_set(__isl_take isl_map *map,8293 __isl_take isl_space *space, __isl_take isl_set *set,8294 __isl_give isl_basic_map *fn(__isl_take isl_basic_map *bmap,8295 __isl_take isl_basic_set *bset))8296{8297 unsigned flags = 0;8298 struct isl_map *result;8299 int i, j;8300 8301 if (isl_set_plain_is_universe(set)) {8302 isl_set_free(set);8303 return isl_map_reset_equal_dim_space(map, space);8304 }8305 8306 if (ISL_F_ISSET(map, ISL_MAP_DISJOINT) &&8307 ISL_F_ISSET(set, ISL_MAP_DISJOINT))8308 ISL_FL_SET(flags, ISL_MAP_DISJOINT);8309 8310 result = isl_map_alloc_space(space, map->n * set->n, flags);8311 for (i = 0; result && i < map->n; ++i)8312 for (j = 0; j < set->n; ++j) {8313 result = isl_map_add_basic_map(result,8314 fn(isl_basic_map_copy(map->p[i]),8315 isl_basic_set_copy(set->p[j])));8316 if (!result)8317 break;8318 }8319 8320 isl_map_free(map);8321 isl_set_free(set);8322 return result;8323}8324 8325__isl_give isl_map *isl_map_intersect_range(__isl_take isl_map *map,8326 __isl_take isl_set *set)8327{8328 isl_bool ok;8329 isl_space *space;8330 8331 isl_map_align_params_set(&map, &set);8332 ok = isl_map_compatible_range(map, set);8333 if (ok < 0)8334 goto error;8335 if (!ok)8336 isl_die(set->ctx, isl_error_invalid,8337 "incompatible spaces", goto error);8338 8339 space = isl_map_get_space(map);8340 return map_intersect_set(map, space, set,8341 &isl_basic_map_intersect_range);8342error:8343 isl_map_free(map);8344 isl_set_free(set);8345 return NULL;8346}8347 8348/* Intersect the domain of "map" with "set".8349 *8350 * If the domain dimensions of "map" do not have any identifiers,8351 * then copy them over from "set".8352 */8353__isl_give isl_map *isl_map_intersect_domain(__isl_take isl_map *map,8354 __isl_take isl_set *set)8355{8356 isl_bool ok;8357 isl_space *space;8358 8359 isl_map_align_params_set(&map, &set);8360 ok = isl_map_compatible_domain(map, set);8361 if (ok < 0)8362 goto error;8363 if (!ok)8364 isl_die(set->ctx, isl_error_invalid,8365 "incompatible spaces", goto error);8366 8367 space = isl_map_get_space(map);8368 space = isl_space_copy_ids_if_unset(space, isl_dim_in,8369 isl_set_peek_space(set), isl_dim_set);8370 return map_intersect_set(map, space, set,8371 &isl_basic_map_intersect_domain);8372error:8373 isl_map_free(map);8374 isl_set_free(set);8375 return NULL;8376}8377 8378#undef TYPE8379#define TYPE isl_map8380static8381#include "isl_copy_tuple_id_templ.c"8382 8383/* Data structure that specifies how isl_map_intersect_factor8384 * should operate.8385 *8386 * "preserve_type" is the tuple where the factor differs from8387 * the input map and of which the identifiers needs8388 * to be preserved explicitly.8389 * "other_factor" is used to extract the space of the other factor8390 * from the space of the product ("map").8391 * "product" is used to combine the given factor and a universe map8392 * in the space returned by "other_factor" to produce a map8393 * that lives in the same space as the input map.8394 */8395struct isl_intersect_factor_control {8396 enum isl_dim_type preserve_type;8397 __isl_give isl_space *(*other_factor)(__isl_take isl_space *space);8398 __isl_give isl_map *(*product)(__isl_take isl_map *factor,8399 __isl_take isl_map *other);8400};8401 8402/* Given a map "map" in some product space and a map "factor"8403 * living in some factor space, return the intersection.8404 *8405 * After aligning the parameters,8406 * the map "factor" is first extended to a map living in the same space8407 * as "map" and then a regular intersection is computed.8408 *8409 * Note that the extension is computed as a product, which is anonymous8410 * by default. If "map" has an identifier on the corresponding tuple,8411 * then this identifier needs to be set on the product8412 * before the intersection is computed.8413 */8414static __isl_give isl_map *isl_map_intersect_factor(8415 __isl_take isl_map *map, __isl_take isl_map *factor,8416 struct isl_intersect_factor_control *control)8417{8418 isl_bool equal;8419 isl_space *space;8420 isl_map *other, *product;8421 8422 equal = isl_map_has_equal_params(map, factor);8423 if (equal < 0)8424 goto error;8425 if (!equal) {8426 map = isl_map_align_params(map, isl_map_get_space(factor));8427 factor = isl_map_align_params(factor, isl_map_get_space(map));8428 }8429 8430 space = isl_map_get_space(map);8431 other = isl_map_universe(control->other_factor(space));8432 product = control->product(factor, other);8433 8434 space = isl_map_peek_space(map);8435 product = isl_map_copy_tuple_id(product, control->preserve_type,8436 space, control->preserve_type);8437 return map_intersect(map, product);8438error:8439 isl_map_free(map);8440 isl_map_free(factor);8441 return NULL;8442}8443 8444/* Return the domain product of "map2" and "map1".8445 */8446static __isl_give isl_map *isl_map_reverse_domain_product(8447 __isl_take isl_map *map1, __isl_take isl_map *map2)8448{8449 return isl_map_domain_product(map2, map1);8450}8451 8452/* Return the range product of "map2" and "map1".8453 */8454static __isl_give isl_map *isl_map_reverse_range_product(8455 __isl_take isl_map *map1, __isl_take isl_map *map2)8456{8457 return isl_map_range_product(map2, map1);8458}8459 8460/* Given a map "map" in a space [A -> B] -> C and a map "factor"8461 * in the space A -> C, return the intersection.8462 */8463__isl_give isl_map *isl_map_intersect_domain_factor_domain(8464 __isl_take isl_map *map, __isl_take isl_map *factor)8465{8466 struct isl_intersect_factor_control control = {8467 .preserve_type = isl_dim_in,8468 .other_factor = isl_space_domain_factor_range,8469 .product = isl_map_domain_product,8470 };8471 8472 return isl_map_intersect_factor(map, factor, &control);8473}8474 8475/* Given a map "map" in a space [A -> B] -> C and a map "factor"8476 * in the space B -> C, return the intersection.8477 */8478__isl_give isl_map *isl_map_intersect_domain_factor_range(8479 __isl_take isl_map *map, __isl_take isl_map *factor)8480{8481 struct isl_intersect_factor_control control = {8482 .preserve_type = isl_dim_in,8483 .other_factor = isl_space_domain_factor_domain,8484 .product = isl_map_reverse_domain_product,8485 };8486 8487 return isl_map_intersect_factor(map, factor, &control);8488}8489 8490/* Given a map "map" in a space A -> [B -> C] and a map "factor"8491 * in the space A -> B, return the intersection.8492 */8493__isl_give isl_map *isl_map_intersect_range_factor_domain(8494 __isl_take isl_map *map, __isl_take isl_map *factor)8495{8496 struct isl_intersect_factor_control control = {8497 .preserve_type = isl_dim_out,8498 .other_factor = isl_space_range_factor_range,8499 .product = isl_map_range_product,8500 };8501 8502 return isl_map_intersect_factor(map, factor, &control);8503}8504 8505/* Given a map "map" in a space A -> [B -> C] and a map "factor"8506 * in the space A -> C, return the intersection.8507 */8508__isl_give isl_map *isl_map_intersect_range_factor_range(8509 __isl_take isl_map *map, __isl_take isl_map *factor)8510{8511 struct isl_intersect_factor_control control = {8512 .preserve_type = isl_dim_out,8513 .other_factor = isl_space_range_factor_domain,8514 .product = isl_map_reverse_range_product,8515 };8516 8517 return isl_map_intersect_factor(map, factor, &control);8518}8519 8520/* Given a set "set" in a space [A -> B] and a set "domain"8521 * in the space A, return the intersection.8522 *8523 * The set "domain" is first extended to a set living in the space8524 * [A -> B] and then a regular intersection is computed.8525 */8526__isl_give isl_set *isl_set_intersect_factor_domain(__isl_take isl_set *set,8527 __isl_take isl_set *domain)8528{8529 struct isl_intersect_factor_control control = {8530 .preserve_type = isl_dim_set,8531 .other_factor = isl_space_factor_range,8532 .product = isl_map_range_product,8533 };8534 8535 return set_from_map(isl_map_intersect_factor(set_to_map(set),8536 set_to_map(domain), &control));8537}8538 8539/* Given a set "set" in a space [A -> B] and a set "range"8540 * in the space B, return the intersection.8541 *8542 * The set "range" is first extended to a set living in the space8543 * [A -> B] and then a regular intersection is computed.8544 */8545__isl_give isl_set *isl_set_intersect_factor_range(__isl_take isl_set *set,8546 __isl_take isl_set *range)8547{8548 struct isl_intersect_factor_control control = {8549 .preserve_type = isl_dim_set,8550 .other_factor = isl_space_factor_domain,8551 .product = isl_map_reverse_range_product,8552 };8553 8554 return set_from_map(isl_map_intersect_factor(set_to_map(set),8555 set_to_map(range), &control));8556}8557 8558/* Given a map "map" in a space [A -> B] -> C and a set "domain"8559 * in the space A, return the intersection.8560 *8561 * The set "domain" is extended to a set living in the space [A -> B] and8562 * the domain of "map" is intersected with this set.8563 */8564__isl_give isl_map *isl_map_intersect_domain_wrapped_domain(8565 __isl_take isl_map *map, __isl_take isl_set *domain)8566{8567 isl_space *space;8568 isl_set *factor;8569 8570 isl_map_align_params_set(&map, &domain);8571 space = isl_map_get_space(map);8572 space = isl_space_domain_wrapped_range(space);8573 factor = isl_set_universe(space);8574 domain = isl_set_product(domain, factor);8575 return isl_map_intersect_domain(map, domain);8576}8577 8578/* Given a map "map" in a space A -> [B -> C] and a set "domain"8579 * in the space B, return the intersection.8580 *8581 * The set "domain" is extended to a set living in the space [B -> C] and8582 * the range of "map" is intersected with this set.8583 */8584__isl_give isl_map *isl_map_intersect_range_wrapped_domain(8585 __isl_take isl_map *map, __isl_take isl_set *domain)8586{8587 isl_space *space;8588 isl_set *factor;8589 8590 isl_map_align_params_set(&map, &domain);8591 space = isl_map_get_space(map);8592 space = isl_space_range_wrapped_range(space);8593 factor = isl_set_universe(space);8594 domain = isl_set_product(domain, factor);8595 return isl_map_intersect_range(map, domain);8596}8597 8598__isl_give isl_map *isl_map_apply_domain(__isl_take isl_map *map1,8599 __isl_take isl_map *map2)8600{8601 if (isl_map_align_params_bin(&map1, &map2) < 0)8602 goto error;8603 map1 = isl_map_reverse(map1);8604 map1 = isl_map_apply_range(map1, map2);8605 return isl_map_reverse(map1);8606error:8607 isl_map_free(map1);8608 isl_map_free(map2);8609 return NULL;8610}8611 8612__isl_give isl_map *isl_map_apply_range(__isl_take isl_map *map1,8613 __isl_take isl_map *map2)8614{8615 isl_space *space;8616 struct isl_map *result;8617 int i, j;8618 8619 if (isl_map_align_params_bin(&map1, &map2) < 0)8620 goto error;8621 8622 space = isl_space_join(isl_space_copy(map1->dim),8623 isl_space_copy(map2->dim));8624 8625 result = isl_map_alloc_space(space, map1->n * map2->n, 0);8626 if (!result)8627 goto error;8628 for (i = 0; i < map1->n; ++i)8629 for (j = 0; j < map2->n; ++j) {8630 result = isl_map_add_basic_map(result,8631 isl_basic_map_apply_range(8632 isl_basic_map_copy(map1->p[i]),8633 isl_basic_map_copy(map2->p[j])));8634 if (!result)8635 goto error;8636 }8637 isl_map_free(map1);8638 isl_map_free(map2);8639 if (result && result->n <= 1)8640 ISL_F_SET(result, ISL_MAP_DISJOINT);8641 return result;8642error:8643 isl_map_free(map1);8644 isl_map_free(map2);8645 return NULL;8646}8647 8648/* Is "bmap" a transformation, i.e.,8649 * does it relate elements from the same space.8650 */8651isl_bool isl_basic_map_is_transformation(__isl_keep isl_basic_map *bmap)8652{8653 isl_space *space;8654 8655 space = isl_basic_map_peek_space(bmap);8656 return isl_space_tuple_is_equal(space, isl_dim_in, space, isl_dim_out);8657}8658 8659/* Check that "bmap" is a transformation, i.e.,8660 * that it relates elements from the same space.8661 */8662static isl_stat isl_basic_map_check_transformation(8663 __isl_keep isl_basic_map *bmap)8664{8665 isl_bool equal;8666 8667 equal = isl_basic_map_is_transformation(bmap);8668 if (equal < 0)8669 return isl_stat_error;8670 if (!equal)8671 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,8672 "domain and range don't match", return isl_stat_error);8673 return isl_stat_ok;8674}8675 8676/*8677 * returns range - domain8678 */8679__isl_give isl_basic_set *isl_basic_map_deltas(__isl_take isl_basic_map *bmap)8680{8681 isl_space *target_space;8682 struct isl_basic_set *bset;8683 isl_size dim;8684 isl_size nparam;8685 isl_size total;8686 int i;8687 8688 if (isl_basic_map_check_transformation(bmap) < 0)8689 return isl_basic_map_free(bmap);8690 dim = isl_basic_map_dim(bmap, isl_dim_in);8691 nparam = isl_basic_map_dim(bmap, isl_dim_param);8692 if (dim < 0 || nparam < 0)8693 goto error;8694 target_space = isl_space_domain(isl_basic_map_get_space(bmap));8695 bmap = isl_basic_map_from_range(isl_basic_map_wrap(bmap));8696 bmap = isl_basic_map_add_dims(bmap, isl_dim_in, dim);8697 total = isl_basic_map_dim(bmap, isl_dim_all);8698 if (total < 0)8699 bmap = isl_basic_map_free(bmap);8700 bmap = isl_basic_map_extend_constraints(bmap, dim, 0);8701 for (i = 0; i < dim; ++i) {8702 int j = isl_basic_map_alloc_equality(bmap);8703 if (j < 0) {8704 bmap = isl_basic_map_free(bmap);8705 break;8706 }8707 isl_seq_clr(bmap->eq[j], 1 + total);8708 isl_int_set_si(bmap->eq[j][1+nparam+i], 1);8709 isl_int_set_si(bmap->eq[j][1+nparam+dim+i], 1);8710 isl_int_set_si(bmap->eq[j][1+nparam+2*dim+i], -1);8711 }8712 bset = isl_basic_map_domain(bmap);8713 bset = isl_basic_set_reset_space(bset, target_space);8714 return bset;8715error:8716 isl_basic_map_free(bmap);8717 return NULL;8718}8719 8720/* Is the tuple of type "type1" of "map" the same as8721 * the tuple of type "type2" of "space"?8722 */8723isl_bool isl_map_space_tuple_is_equal(__isl_keep isl_map *map,8724 enum isl_dim_type type1, __isl_keep isl_space *space,8725 enum isl_dim_type type2)8726{8727 isl_space *map_space;8728 8729 map_space = isl_map_peek_space(map);8730 return isl_space_tuple_is_equal(map_space, type1, space, type2);8731}8732 8733/* Is the tuple of type "type1" of "map1" the same as8734 * the tuple of type "type2" of "map2"?8735 */8736isl_bool isl_map_tuple_is_equal(__isl_keep isl_map *map1,8737 enum isl_dim_type type1, __isl_keep isl_map *map2,8738 enum isl_dim_type type2)8739{8740 isl_space *space1, *space2;8741 8742 space1 = isl_map_peek_space(map1);8743 space2 = isl_map_peek_space(map2);8744 return isl_space_tuple_is_equal(space1, type1, space2, type2);8745}8746 8747/* Is the space of "obj" equal to "space", ignoring parameters?8748 */8749isl_bool isl_map_has_space_tuples(__isl_keep isl_map *map,8750 __isl_keep isl_space *space)8751{8752 isl_space *map_space;8753 8754 map_space = isl_map_peek_space(map);8755 return isl_space_has_equal_tuples(map_space, space);8756}8757 8758/* Check that "map" is a transformation, i.e.,8759 * that it relates elements from the same space.8760 */8761isl_stat isl_map_check_transformation(__isl_keep isl_map *map)8762{8763 isl_bool equal;8764 8765 equal = isl_map_tuple_is_equal(map, isl_dim_in, map, isl_dim_out);8766 if (equal < 0)8767 return isl_stat_error;8768 if (!equal)8769 isl_die(isl_map_get_ctx(map), isl_error_invalid,8770 "domain and range don't match", return isl_stat_error);8771 return isl_stat_ok;8772}8773 8774/*8775 * returns range - domain8776 */8777__isl_give isl_set *isl_map_deltas(__isl_take isl_map *map)8778{8779 int i;8780 isl_space *space;8781 struct isl_set *result;8782 8783 if (isl_map_check_transformation(map) < 0)8784 goto error;8785 space = isl_map_get_space(map);8786 space = isl_space_domain(space);8787 result = isl_set_alloc_space(space, map->n, 0);8788 if (!result)8789 goto error;8790 for (i = 0; i < map->n; ++i)8791 result = isl_set_add_basic_set(result,8792 isl_basic_map_deltas(isl_basic_map_copy(map->p[i])));8793 isl_map_free(map);8794 return result;8795error:8796 isl_map_free(map);8797 return NULL;8798}8799 8800/*8801 * returns [domain -> range] -> range - domain8802 */8803__isl_give isl_basic_map *isl_basic_map_deltas_map(8804 __isl_take isl_basic_map *bmap)8805{8806 int i, k;8807 isl_space *space;8808 isl_basic_map *domain;8809 isl_size nparam, n;8810 isl_size total;8811 8812 if (isl_basic_map_check_transformation(bmap) < 0)8813 return isl_basic_map_free(bmap);8814 8815 nparam = isl_basic_map_dim(bmap, isl_dim_param);8816 n = isl_basic_map_dim(bmap, isl_dim_in);8817 if (nparam < 0 || n < 0)8818 return isl_basic_map_free(bmap);8819 8820 space = isl_basic_map_get_space(bmap);8821 space = isl_space_from_range(isl_space_domain(space));8822 domain = isl_basic_map_universe(space);8823 8824 bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap));8825 bmap = isl_basic_map_apply_range(bmap, domain);8826 bmap = isl_basic_map_extend_constraints(bmap, n, 0);8827 8828 total = isl_basic_map_dim(bmap, isl_dim_all);8829 if (total < 0)8830 return isl_basic_map_free(bmap);8831 8832 for (i = 0; i < n; ++i) {8833 k = isl_basic_map_alloc_equality(bmap);8834 if (k < 0)8835 goto error;8836 isl_seq_clr(bmap->eq[k], 1 + total);8837 isl_int_set_si(bmap->eq[k][1 + nparam + i], 1);8838 isl_int_set_si(bmap->eq[k][1 + nparam + n + i], -1);8839 isl_int_set_si(bmap->eq[k][1 + nparam + n + n + i], 1);8840 }8841 8842 bmap = isl_basic_map_gauss(bmap, NULL);8843 return isl_basic_map_finalize(bmap);8844error:8845 isl_basic_map_free(bmap);8846 return NULL;8847}8848 8849/*8850 * returns [domain -> range] -> range - domain8851 */8852__isl_give isl_map *isl_map_deltas_map(__isl_take isl_map *map)8853{8854 if (isl_map_check_transformation(map) < 0)8855 return isl_map_free(map);8856 8857 return isl_map_transform(map, &isl_space_range_map,8858 &isl_basic_map_deltas_map);8859}8860 8861/* Return pairs of elements { x -> y } such that y - x is in "deltas".8862 */8863__isl_give isl_map *isl_set_translation(__isl_take isl_set *deltas)8864{8865 isl_space *space;8866 isl_map *map;8867 8868 space = isl_space_map_from_set(isl_set_get_space(deltas));8869 map = isl_map_deltas_map(isl_map_universe(space));8870 map = isl_map_intersect_range(map, deltas);8871 8872 return isl_set_unwrap(isl_map_domain(map));8873}8874 8875__isl_give isl_basic_map *isl_basic_map_identity(__isl_take isl_space *space)8876{8877 isl_size n_in, n_out;8878 8879 n_in = isl_space_dim(space, isl_dim_in);8880 n_out = isl_space_dim(space, isl_dim_out);8881 if (n_in < 0 || n_out < 0)8882 goto error;8883 if (n_in != n_out)8884 isl_die(space->ctx, isl_error_invalid,8885 "number of input and output dimensions needs to be "8886 "the same", goto error);8887 return isl_basic_map_equal(space, n_in);8888error:8889 isl_space_free(space);8890 return NULL;8891}8892 8893__isl_give isl_map *isl_map_identity(__isl_take isl_space *space)8894{8895 return isl_map_from_basic_map(isl_basic_map_identity(space));8896}8897 8898__isl_give isl_map *isl_set_identity(__isl_take isl_set *set)8899{8900 isl_space *space = isl_set_get_space(set);8901 isl_map *id;8902 id = isl_map_identity(isl_space_map_from_set(space));8903 return isl_map_intersect_range(id, set);8904}8905 8906/* Construct a basic set with all set dimensions having only non-negative8907 * values.8908 */8909__isl_give isl_basic_set *isl_basic_set_positive_orthant(8910 __isl_take isl_space *space)8911{8912 int i;8913 isl_size nparam;8914 isl_size dim;8915 isl_size total;8916 struct isl_basic_set *bset;8917 8918 nparam = isl_space_dim(space, isl_dim_param);8919 dim = isl_space_dim(space, isl_dim_set);8920 total = isl_space_dim(space, isl_dim_all);8921 if (nparam < 0 || dim < 0 || total < 0)8922 space = isl_space_free(space);8923 bset = isl_basic_set_alloc_space(space, 0, 0, dim);8924 if (!bset)8925 return NULL;8926 for (i = 0; i < dim; ++i) {8927 int k = isl_basic_set_alloc_inequality(bset);8928 if (k < 0)8929 goto error;8930 isl_seq_clr(bset->ineq[k], 1 + total);8931 isl_int_set_si(bset->ineq[k][1 + nparam + i], 1);8932 }8933 return bset;8934error:8935 isl_basic_set_free(bset);8936 return NULL;8937}8938 8939/* Construct the half-space x_pos >= 0.8940 */8941static __isl_give isl_basic_set *nonneg_halfspace(__isl_take isl_space *space,8942 int pos)8943{8944 int k;8945 isl_size total;8946 isl_basic_set *nonneg;8947 8948 total = isl_space_dim(space, isl_dim_all);8949 if (total < 0)8950 space = isl_space_free(space);8951 nonneg = isl_basic_set_alloc_space(space, 0, 0, 1);8952 k = isl_basic_set_alloc_inequality(nonneg);8953 if (k < 0)8954 goto error;8955 isl_seq_clr(nonneg->ineq[k], 1 + total);8956 isl_int_set_si(nonneg->ineq[k][pos], 1);8957 8958 return isl_basic_set_finalize(nonneg);8959error:8960 isl_basic_set_free(nonneg);8961 return NULL;8962}8963 8964/* Construct the half-space x_pos <= -1.8965 */8966static __isl_give isl_basic_set *neg_halfspace(__isl_take isl_space *space,8967 int pos)8968{8969 int k;8970 isl_size total;8971 isl_basic_set *neg;8972 8973 total = isl_space_dim(space, isl_dim_all);8974 if (total < 0)8975 space = isl_space_free(space);8976 neg = isl_basic_set_alloc_space(space, 0, 0, 1);8977 k = isl_basic_set_alloc_inequality(neg);8978 if (k < 0)8979 goto error;8980 isl_seq_clr(neg->ineq[k], 1 + total);8981 isl_int_set_si(neg->ineq[k][0], -1);8982 isl_int_set_si(neg->ineq[k][pos], -1);8983 8984 return isl_basic_set_finalize(neg);8985error:8986 isl_basic_set_free(neg);8987 return NULL;8988}8989 8990__isl_give isl_set *isl_set_split_dims(__isl_take isl_set *set,8991 enum isl_dim_type type, unsigned first, unsigned n)8992{8993 int i;8994 unsigned offset;8995 isl_basic_set *nonneg;8996 isl_basic_set *neg;8997 8998 if (n == 0)8999 return set;9000 9001 if (isl_set_check_range(set, type, first, n) < 0)9002 return isl_set_free(set);9003 9004 offset = pos(set->dim, type);9005 for (i = 0; i < n; ++i) {9006 nonneg = nonneg_halfspace(isl_set_get_space(set),9007 offset + first + i);9008 neg = neg_halfspace(isl_set_get_space(set), offset + first + i);9009 9010 set = isl_set_intersect(set, isl_basic_set_union(nonneg, neg));9011 }9012 9013 return set;9014}9015 9016static isl_stat foreach_orthant(__isl_take isl_set *set, int *signs, int first,9017 int len,9018 isl_stat (*fn)(__isl_take isl_set *orthant, int *signs, void *user),9019 void *user)9020{9021 isl_set *half;9022 9023 if (!set)9024 return isl_stat_error;9025 if (isl_set_plain_is_empty(set)) {9026 isl_set_free(set);9027 return isl_stat_ok;9028 }9029 if (first == len)9030 return fn(set, signs, user);9031 9032 signs[first] = 1;9033 half = isl_set_from_basic_set(nonneg_halfspace(isl_set_get_space(set),9034 1 + first));9035 half = isl_set_intersect(half, isl_set_copy(set));9036 if (foreach_orthant(half, signs, first + 1, len, fn, user) < 0)9037 goto error;9038 9039 signs[first] = -1;9040 half = isl_set_from_basic_set(neg_halfspace(isl_set_get_space(set),9041 1 + first));9042 half = isl_set_intersect(half, set);9043 return foreach_orthant(half, signs, first + 1, len, fn, user);9044error:9045 isl_set_free(set);9046 return isl_stat_error;9047}9048 9049/* Call "fn" on the intersections of "set" with each of the orthants9050 * (except for obviously empty intersections). The orthant is identified9051 * by the signs array, with each entry having value 1 or -1 according9052 * to the sign of the corresponding variable.9053 */9054isl_stat isl_set_foreach_orthant(__isl_keep isl_set *set,9055 isl_stat (*fn)(__isl_take isl_set *orthant, int *signs, void *user),9056 void *user)9057{9058 isl_size nparam;9059 isl_size nvar;9060 int *signs;9061 isl_stat r;9062 9063 if (!set)9064 return isl_stat_error;9065 if (isl_set_plain_is_empty(set))9066 return isl_stat_ok;9067 9068 nparam = isl_set_dim(set, isl_dim_param);9069 nvar = isl_set_dim(set, isl_dim_set);9070 if (nparam < 0 || nvar < 0)9071 return isl_stat_error;9072 9073 signs = isl_alloc_array(set->ctx, int, nparam + nvar);9074 9075 r = foreach_orthant(isl_set_copy(set), signs, 0, nparam + nvar,9076 fn, user);9077 9078 free(signs);9079 9080 return r;9081}9082 9083isl_bool isl_set_is_equal(__isl_keep isl_set *set1, __isl_keep isl_set *set2)9084{9085 return isl_map_is_equal(set_to_map(set1), set_to_map(set2));9086}9087 9088isl_bool isl_basic_map_is_subset(__isl_keep isl_basic_map *bmap1,9089 __isl_keep isl_basic_map *bmap2)9090{9091 isl_bool is_subset;9092 struct isl_map *map1;9093 struct isl_map *map2;9094 9095 if (!bmap1 || !bmap2)9096 return isl_bool_error;9097 9098 map1 = isl_map_from_basic_map(isl_basic_map_copy(bmap1));9099 map2 = isl_map_from_basic_map(isl_basic_map_copy(bmap2));9100 9101 is_subset = isl_map_is_subset(map1, map2);9102 9103 isl_map_free(map1);9104 isl_map_free(map2);9105 9106 return is_subset;9107}9108 9109isl_bool isl_basic_set_is_subset(__isl_keep isl_basic_set *bset1,9110 __isl_keep isl_basic_set *bset2)9111{9112 return isl_basic_map_is_subset(bset1, bset2);9113}9114 9115isl_bool isl_basic_map_is_equal(__isl_keep isl_basic_map *bmap1,9116 __isl_keep isl_basic_map *bmap2)9117{9118 isl_bool is_subset;9119 9120 if (!bmap1 || !bmap2)9121 return isl_bool_error;9122 is_subset = isl_basic_map_is_subset(bmap1, bmap2);9123 if (is_subset != isl_bool_true)9124 return is_subset;9125 is_subset = isl_basic_map_is_subset(bmap2, bmap1);9126 return is_subset;9127}9128 9129isl_bool isl_basic_set_is_equal(__isl_keep isl_basic_set *bset1,9130 __isl_keep isl_basic_set *bset2)9131{9132 return isl_basic_map_is_equal(9133 bset_to_bmap(bset1), bset_to_bmap(bset2));9134}9135 9136isl_bool isl_map_is_empty(__isl_keep isl_map *map)9137{9138 int i;9139 int is_empty;9140 9141 if (!map)9142 return isl_bool_error;9143 for (i = 0; i < map->n; ++i) {9144 is_empty = isl_basic_map_is_empty(map->p[i]);9145 if (is_empty < 0)9146 return isl_bool_error;9147 if (!is_empty)9148 return isl_bool_false;9149 }9150 return isl_bool_true;9151}9152 9153isl_bool isl_map_plain_is_empty(__isl_keep isl_map *map)9154{9155 return map ? map->n == 0 : isl_bool_error;9156}9157 9158isl_bool isl_set_plain_is_empty(__isl_keep isl_set *set)9159{9160 return set ? set->n == 0 : isl_bool_error;9161}9162 9163isl_bool isl_set_is_empty(__isl_keep isl_set *set)9164{9165 return isl_map_is_empty(set_to_map(set));9166}9167 9168#undef TYPE9169#define TYPE isl_basic_map9170 9171static9172#include "isl_type_has_equal_space_bin_templ.c"9173#include "isl_type_check_equal_space_templ.c"9174 9175/* Check that "bset1" and "bset2" live in the same space,9176 * reporting an error if they do not.9177 */9178isl_stat isl_basic_set_check_equal_space(__isl_keep isl_basic_set *bset1,9179 __isl_keep isl_basic_set *bset2)9180{9181 return isl_basic_map_check_equal_space(bset_to_bmap(bset1),9182 bset_to_bmap(bset1));9183}9184 9185#undef TYPE9186#define TYPE isl_map9187 9188#include "isl_type_has_equal_space_bin_templ.c"9189#include "isl_type_check_equal_space_templ.c"9190#include "isl_type_has_space_templ.c"9191 9192isl_bool isl_set_has_equal_space(__isl_keep isl_set *set1,9193 __isl_keep isl_set *set2)9194{9195 return isl_map_has_equal_space(set_to_map(set1), set_to_map(set2));9196}9197 9198#undef TYPE19199#define TYPE1 isl_map9200#undef TYPE29201#define TYPE2 isl_basic_map9202#undef TYPE_PAIR9203#define TYPE_PAIR isl_map_basic_map9204 9205static9206#include "isl_type_has_equal_space_templ.c"9207#include "isl_type_check_equal_space_templ.c"9208 9209/* Check that "set" and "bset" live in the same space,9210 * reporting an error if they do not.9211 */9212isl_stat isl_set_basic_set_check_equal_space(__isl_keep isl_set *set,9213 __isl_keep isl_basic_set *bset)9214{9215 return isl_map_basic_map_check_equal_space(set_to_map(set),9216 bset_to_bmap(bset));9217}9218 9219static isl_bool map_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2)9220{9221 isl_bool is_subset;9222 9223 if (!map1 || !map2)9224 return isl_bool_error;9225 is_subset = isl_map_is_subset(map1, map2);9226 if (is_subset != isl_bool_true)9227 return is_subset;9228 is_subset = isl_map_is_subset(map2, map1);9229 return is_subset;9230}9231 9232/* Is "map1" equal to "map2"?9233 *9234 * First check if they are obviously equal.9235 * If not, then perform a more detailed analysis.9236 */9237isl_bool isl_map_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2)9238{9239 isl_bool equal;9240 9241 equal = isl_map_plain_is_equal(map1, map2);9242 if (equal < 0 || equal)9243 return equal;9244 return isl_map_align_params_map_map_and_test(map1, map2, &map_is_equal);9245}9246 9247isl_bool isl_basic_map_is_strict_subset(__isl_keep isl_basic_map *bmap1,9248 __isl_keep isl_basic_map *bmap2)9249{9250 isl_bool is_subset;9251 9252 if (!bmap1 || !bmap2)9253 return isl_bool_error;9254 is_subset = isl_basic_map_is_subset(bmap1, bmap2);9255 if (is_subset != isl_bool_true)9256 return is_subset;9257 is_subset = isl_basic_map_is_subset(bmap2, bmap1);9258 return isl_bool_not(is_subset);9259}9260 9261isl_bool isl_map_is_strict_subset(__isl_keep isl_map *map1,9262 __isl_keep isl_map *map2)9263{9264 isl_bool is_subset;9265 9266 if (!map1 || !map2)9267 return isl_bool_error;9268 is_subset = isl_map_is_subset(map1, map2);9269 if (is_subset != isl_bool_true)9270 return is_subset;9271 is_subset = isl_map_is_subset(map2, map1);9272 return isl_bool_not(is_subset);9273}9274 9275isl_bool isl_set_is_strict_subset(__isl_keep isl_set *set1,9276 __isl_keep isl_set *set2)9277{9278 return isl_map_is_strict_subset(set_to_map(set1), set_to_map(set2));9279}9280 9281/* Is "bmap" obviously equal to the universe with the same space?9282 *9283 * That is, does it not have any constraints?9284 */9285isl_bool isl_basic_map_plain_is_universe(__isl_keep isl_basic_map *bmap)9286{9287 if (!bmap)9288 return isl_bool_error;9289 return bmap->n_eq == 0 && bmap->n_ineq == 0;9290}9291 9292/* Is "bset" obviously equal to the universe with the same space?9293 */9294isl_bool isl_basic_set_plain_is_universe(__isl_keep isl_basic_set *bset)9295{9296 return isl_basic_map_plain_is_universe(bset);9297}9298 9299/* If "c" does not involve any existentially quantified variables,9300 * then set *univ to false and abort9301 */9302static isl_stat involves_divs(__isl_take isl_constraint *c, void *user)9303{9304 isl_bool *univ = user;9305 isl_size n;9306 9307 n = isl_constraint_dim(c, isl_dim_div);9308 if (n < 0)9309 c = isl_constraint_free(c);9310 *univ = isl_constraint_involves_dims(c, isl_dim_div, 0, n);9311 isl_constraint_free(c);9312 if (*univ < 0 || !*univ)9313 return isl_stat_error;9314 return isl_stat_ok;9315}9316 9317/* Is "bmap" equal to the universe with the same space?9318 *9319 * First check if it is obviously equal to the universe.9320 * If not and if there are any constraints not involving9321 * existentially quantified variables, then it is certainly9322 * not equal to the universe.9323 * Otherwise, check if the universe is a subset of "bmap".9324 */9325isl_bool isl_basic_map_is_universe(__isl_keep isl_basic_map *bmap)9326{9327 isl_size n_div;9328 isl_bool univ;9329 isl_basic_map *test;9330 9331 univ = isl_basic_map_plain_is_universe(bmap);9332 if (univ < 0 || univ)9333 return univ;9334 n_div = isl_basic_map_dim(bmap, isl_dim_div);9335 if (n_div < 0)9336 return isl_bool_error;9337 if (n_div == 0)9338 return isl_bool_false;9339 univ = isl_bool_true;9340 if (isl_basic_map_foreach_constraint(bmap, &involves_divs, &univ) < 0 &&9341 univ)9342 return isl_bool_error;9343 if (univ < 0 || !univ)9344 return univ;9345 test = isl_basic_map_universe(isl_basic_map_get_space(bmap));9346 univ = isl_basic_map_is_subset(test, bmap);9347 isl_basic_map_free(test);9348 return univ;9349}9350 9351/* Is "bset" equal to the universe with the same space?9352 */9353isl_bool isl_basic_set_is_universe(__isl_keep isl_basic_set *bset)9354{9355 return isl_basic_map_is_universe(bset);9356}9357 9358isl_bool isl_map_plain_is_universe(__isl_keep isl_map *map)9359{9360 int i;9361 9362 if (!map)9363 return isl_bool_error;9364 9365 for (i = 0; i < map->n; ++i) {9366 isl_bool r = isl_basic_map_plain_is_universe(map->p[i]);9367 if (r < 0 || r)9368 return r;9369 }9370 9371 return isl_bool_false;9372}9373 9374isl_bool isl_set_plain_is_universe(__isl_keep isl_set *set)9375{9376 return isl_map_plain_is_universe(set_to_map(set));9377}9378 9379isl_bool isl_basic_map_is_empty(__isl_keep isl_basic_map *bmap)9380{9381 struct isl_basic_set *bset = NULL;9382 struct isl_vec *sample = NULL;9383 isl_bool empty, non_empty;9384 9385 if (!bmap)9386 return isl_bool_error;9387 9388 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY))9389 return isl_bool_true;9390 9391 if (isl_basic_map_plain_is_universe(bmap))9392 return isl_bool_false;9393 9394 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL)) {9395 struct isl_basic_map *copy = isl_basic_map_copy(bmap);9396 copy = isl_basic_map_remove_redundancies(copy);9397 empty = isl_basic_map_plain_is_empty(copy);9398 isl_basic_map_free(copy);9399 return empty;9400 }9401 9402 non_empty = isl_basic_map_plain_is_non_empty(bmap);9403 if (non_empty < 0)9404 return isl_bool_error;9405 if (non_empty)9406 return isl_bool_false;9407 isl_vec_free(bmap->sample);9408 bmap->sample = NULL;9409 bset = isl_basic_map_underlying_set(isl_basic_map_copy(bmap));9410 if (!bset)9411 return isl_bool_error;9412 sample = isl_basic_set_sample_vec(bset);9413 if (!sample)9414 return isl_bool_error;9415 empty = sample->size == 0;9416 isl_vec_free(bmap->sample);9417 bmap->sample = sample;9418 if (empty)9419 ISL_F_SET(bmap, ISL_BASIC_MAP_EMPTY);9420 9421 return empty;9422}9423 9424isl_bool isl_basic_map_plain_is_empty(__isl_keep isl_basic_map *bmap)9425{9426 if (!bmap)9427 return isl_bool_error;9428 return ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY);9429}9430 9431isl_bool isl_basic_set_plain_is_empty(__isl_keep isl_basic_set *bset)9432{9433 if (!bset)9434 return isl_bool_error;9435 return ISL_F_ISSET(bset, ISL_BASIC_SET_EMPTY);9436}9437 9438/* Is "bmap" known to be non-empty?9439 *9440 * That is, is the cached sample still valid?9441 */9442isl_bool isl_basic_map_plain_is_non_empty(__isl_keep isl_basic_map *bmap)9443{9444 isl_size total;9445 9446 if (!bmap)9447 return isl_bool_error;9448 if (!bmap->sample)9449 return isl_bool_false;9450 total = isl_basic_map_dim(bmap, isl_dim_all);9451 if (total < 0)9452 return isl_bool_error;9453 if (bmap->sample->size != 1 + total)9454 return isl_bool_false;9455 return isl_basic_map_contains(bmap, bmap->sample);9456}9457 9458isl_bool isl_basic_set_is_empty(__isl_keep isl_basic_set *bset)9459{9460 return isl_basic_map_is_empty(bset_to_bmap(bset));9461}9462 9463__isl_give isl_map *isl_basic_map_union(__isl_take isl_basic_map *bmap1,9464 __isl_take isl_basic_map *bmap2)9465{9466 struct isl_map *map;9467 9468 if (isl_basic_map_check_equal_space(bmap1, bmap2) < 0)9469 goto error;9470 9471 map = isl_map_alloc_space(isl_space_copy(bmap1->dim), 2, 0);9472 if (!map)9473 goto error;9474 map = isl_map_add_basic_map(map, bmap1);9475 map = isl_map_add_basic_map(map, bmap2);9476 return map;9477error:9478 isl_basic_map_free(bmap1);9479 isl_basic_map_free(bmap2);9480 return NULL;9481}9482 9483__isl_give isl_set *isl_basic_set_union(__isl_take isl_basic_set *bset1,9484 __isl_take isl_basic_set *bset2)9485{9486 return set_from_map(isl_basic_map_union(bset_to_bmap(bset1),9487 bset_to_bmap(bset2)));9488}9489 9490/* Order divs such that any div only depends on previous divs */9491__isl_give isl_basic_map *isl_basic_map_order_divs(9492 __isl_take isl_basic_map *bmap)9493{9494 int i;9495 isl_size off;9496 9497 off = isl_basic_map_var_offset(bmap, isl_dim_div);9498 if (off < 0)9499 return isl_basic_map_free(bmap);9500 9501 for (i = 0; i < bmap->n_div; ++i) {9502 int pos;9503 if (isl_int_is_zero(bmap->div[i][0]))9504 continue;9505 pos = isl_seq_first_non_zero(bmap->div[i]+1+1+off+i,9506 bmap->n_div-i);9507 if (pos == -1)9508 continue;9509 if (pos == 0)9510 isl_die(isl_basic_map_get_ctx(bmap), isl_error_internal,9511 "integer division depends on itself",9512 return isl_basic_map_free(bmap));9513 bmap = isl_basic_map_swap_div(bmap, i, i + pos);9514 if (!bmap)9515 return NULL;9516 --i;9517 }9518 return bmap;9519}9520 9521__isl_give isl_map *isl_map_order_divs(__isl_take isl_map *map)9522{9523 int i;9524 9525 if (!map)9526 return 0;9527 9528 for (i = 0; i < map->n; ++i) {9529 map->p[i] = isl_basic_map_order_divs(map->p[i]);9530 if (!map->p[i])9531 goto error;9532 }9533 9534 return map;9535error:9536 isl_map_free(map);9537 return NULL;9538}9539 9540/* Sort the local variables of "bset".9541 */9542__isl_give isl_basic_set *isl_basic_set_sort_divs(9543 __isl_take isl_basic_set *bset)9544{9545 return bset_from_bmap(isl_basic_map_sort_divs(bset_to_bmap(bset)));9546}9547 9548/* Apply the expansion computed by isl_merge_divs.9549 * The expansion itself is given by "exp" while the resulting9550 * list of divs is given by "div".9551 *9552 * Move the integer divisions of "bmap" into the right position9553 * according to "exp" and then introduce the additional integer9554 * divisions, adding div constraints.9555 * The moving should be done first to avoid moving coefficients9556 * in the definitions of the extra integer divisions.9557 */9558__isl_give isl_basic_map *isl_basic_map_expand_divs(9559 __isl_take isl_basic_map *bmap, __isl_take isl_mat *div, int *exp)9560{9561 int i, j;9562 int n_div;9563 9564 bmap = isl_basic_map_cow(bmap);9565 if (!bmap || !div)9566 goto error;9567 9568 if (div->n_row < bmap->n_div)9569 isl_die(isl_mat_get_ctx(div), isl_error_invalid,9570 "not an expansion", goto error);9571 9572 n_div = bmap->n_div;9573 bmap = isl_basic_map_extend(bmap, div->n_row - n_div, 0,9574 2 * (div->n_row - n_div));9575 9576 for (i = n_div; i < div->n_row; ++i)9577 if (isl_basic_map_alloc_div(bmap) < 0)9578 goto error;9579 9580 for (j = n_div - 1; j >= 0; --j) {9581 if (exp[j] == j)9582 break;9583 bmap = isl_basic_map_swap_div(bmap, j, exp[j]);9584 if (!bmap)9585 goto error;9586 }9587 j = 0;9588 for (i = 0; i < div->n_row; ++i) {9589 if (j < n_div && exp[j] == i) {9590 j++;9591 } else {9592 isl_seq_cpy(bmap->div[i], div->row[i], div->n_col);9593 if (isl_basic_map_div_is_marked_unknown(bmap, i))9594 continue;9595 bmap = isl_basic_map_add_div_constraints(bmap, i);9596 if (!bmap)9597 goto error;9598 }9599 }9600 9601 isl_mat_free(div);9602 return bmap;9603error:9604 isl_basic_map_free(bmap);9605 isl_mat_free(div);9606 return NULL;9607}9608 9609/* Apply the expansion computed by isl_merge_divs.9610 * The expansion itself is given by "exp" while the resulting9611 * list of divs is given by "div".9612 */9613__isl_give isl_basic_set *isl_basic_set_expand_divs(9614 __isl_take isl_basic_set *bset, __isl_take isl_mat *div, int *exp)9615{9616 return isl_basic_map_expand_divs(bset, div, exp);9617}9618 9619/* Look for a div in dst that corresponds to the div "div" in src.9620 * The divs before "div" in src and dst are assumed to be the same.9621 * 9622 * Return the position of the corresponding div in dst9623 * if there is one. Otherwise, return a position beyond the integer divisions.9624 * Return -1 on error.9625 */9626static int find_div(__isl_keep isl_basic_map *dst,9627 __isl_keep isl_basic_map *src, unsigned div)9628{9629 int i;9630 isl_size n_div;9631 isl_size v_div;9632 9633 v_div = isl_basic_map_var_offset(src, isl_dim_div);9634 n_div = isl_basic_map_dim(dst, isl_dim_div);9635 if (n_div < 0 || v_div < 0)9636 return -1;9637 isl_assert(dst->ctx, div <= n_div, return -1);9638 for (i = div; i < n_div; ++i)9639 if (isl_seq_eq(dst->div[i], src->div[div], 1+1+v_div+div) &&9640 isl_seq_first_non_zero(dst->div[i] + 1 + 1 + v_div + div,9641 n_div - div) == -1)9642 return i;9643 return n_div;9644}9645 9646/* Align the divs of "dst" to those of "src", adding divs from "src"9647 * if needed. That is, make sure that the first src->n_div divs9648 * of the result are equal to those of src.9649 * The integer division of "src" are assumed to be ordered.9650 *9651 * The integer divisions are swapped into the right position9652 * (possibly after adding them first). This may result9653 * in the remaining integer divisions appearing in the wrong order,9654 * i.e., with some integer division appearing before9655 * some other integer division on which it depends.9656 * The integer divisions therefore need to be ordered.9657 * This will not affect the integer divisions aligned to those of "src",9658 * since "src" is assumed to have ordered integer divisions.9659 *9660 * The result is not finalized as by design it will have redundant9661 * divs if any divs from "src" were copied.9662 */9663__isl_give isl_basic_map *isl_basic_map_align_divs(9664 __isl_take isl_basic_map *dst, __isl_keep isl_basic_map *src)9665{9666 int i;9667 isl_bool known;9668 int extended;9669 isl_size v_div;9670 isl_size dst_n_div;9671 9672 if (!dst || !src)9673 return isl_basic_map_free(dst);9674 9675 if (src->n_div == 0)9676 return dst;9677 9678 known = isl_basic_map_divs_known(src);9679 if (known < 0)9680 return isl_basic_map_free(dst);9681 if (!known)9682 isl_die(isl_basic_map_get_ctx(src), isl_error_invalid,9683 "some src divs are unknown",9684 return isl_basic_map_free(dst));9685 9686 v_div = isl_basic_map_var_offset(src, isl_dim_div);9687 if (v_div < 0)9688 return isl_basic_map_free(dst);9689 9690 extended = 0;9691 dst_n_div = isl_basic_map_dim(dst, isl_dim_div);9692 if (dst_n_div < 0)9693 dst = isl_basic_map_free(dst);9694 for (i = 0; i < src->n_div; ++i) {9695 int j = find_div(dst, src, i);9696 if (j < 0)9697 dst = isl_basic_map_free(dst);9698 if (j == dst_n_div) {9699 if (!extended) {9700 int extra = src->n_div - i;9701 dst = isl_basic_map_cow(dst);9702 if (!dst)9703 return isl_basic_map_free(dst);9704 dst = isl_basic_map_extend(dst,9705 extra, 0, 2 * extra);9706 extended = 1;9707 }9708 j = isl_basic_map_alloc_div(dst);9709 if (j < 0)9710 return isl_basic_map_free(dst);9711 isl_seq_cpy(dst->div[j], src->div[i], 1+1+v_div+i);9712 isl_seq_clr(dst->div[j]+1+1+v_div+i, dst->n_div - i);9713 dst_n_div++;9714 dst = isl_basic_map_add_div_constraints(dst, j);9715 if (!dst)9716 return isl_basic_map_free(dst);9717 }9718 if (j != i)9719 dst = isl_basic_map_swap_div(dst, i, j);9720 if (!dst)9721 return isl_basic_map_free(dst);9722 }9723 return isl_basic_map_order_divs(dst);9724}9725 9726__isl_give isl_map *isl_map_align_divs_internal(__isl_take isl_map *map)9727{9728 int i;9729 9730 if (!map)9731 return NULL;9732 if (map->n == 0)9733 return map;9734 map = isl_map_compute_divs(map);9735 map = isl_map_order_divs(map);9736 map = isl_map_cow(map);9737 if (!map)9738 return NULL;9739 9740 for (i = 1; i < map->n; ++i)9741 map->p[0] = isl_basic_map_align_divs(map->p[0], map->p[i]);9742 for (i = 1; i < map->n; ++i) {9743 map->p[i] = isl_basic_map_align_divs(map->p[i], map->p[0]);9744 if (!map->p[i])9745 return isl_map_free(map);9746 }9747 9748 map = isl_map_unmark_normalized(map);9749 return map;9750}9751 9752__isl_give isl_map *isl_map_align_divs(__isl_take isl_map *map)9753{9754 return isl_map_align_divs_internal(map);9755}9756 9757__isl_give isl_set *isl_set_align_divs(__isl_take isl_set *set)9758{9759 return set_from_map(isl_map_align_divs_internal(set_to_map(set)));9760}9761 9762/* Align the divs of the basic maps in "map" to those9763 * of the basic maps in "list", as well as to the other basic maps in "map".9764 * The elements in "list" are assumed to have known divs.9765 */9766__isl_give isl_map *isl_map_align_divs_to_basic_map_list(9767 __isl_take isl_map *map, __isl_keep isl_basic_map_list *list)9768{9769 int i;9770 isl_size n;9771 9772 n = isl_basic_map_list_n_basic_map(list);9773 map = isl_map_compute_divs(map);9774 map = isl_map_cow(map);9775 if (!map || n < 0)9776 return isl_map_free(map);9777 if (map->n == 0)9778 return map;9779 9780 for (i = 0; i < n; ++i) {9781 isl_basic_map *bmap;9782 9783 bmap = isl_basic_map_list_get_basic_map(list, i);9784 bmap = isl_basic_map_order_divs(bmap);9785 map->p[0] = isl_basic_map_align_divs(map->p[0], bmap);9786 isl_basic_map_free(bmap);9787 }9788 if (!map->p[0])9789 return isl_map_free(map);9790 9791 return isl_map_align_divs_internal(map);9792}9793 9794/* Align the divs of each element of "list" to those of "bmap".9795 * Both "bmap" and the elements of "list" are assumed to have known divs.9796 */9797__isl_give isl_basic_map_list *isl_basic_map_list_align_divs_to_basic_map(9798 __isl_take isl_basic_map_list *list, __isl_keep isl_basic_map *bmap)9799{9800 int i;9801 isl_size n;9802 9803 n = isl_basic_map_list_n_basic_map(list);9804 if (n < 0 || !bmap)9805 return isl_basic_map_list_free(list);9806 9807 for (i = 0; i < n; ++i) {9808 isl_basic_map *bmap_i;9809 9810 bmap_i = isl_basic_map_list_get_basic_map(list, i);9811 bmap_i = isl_basic_map_align_divs(bmap_i, bmap);9812 list = isl_basic_map_list_set_basic_map(list, i, bmap_i);9813 }9814 9815 return list;9816}9817 9818__isl_give isl_set *isl_set_apply( __isl_take isl_set *set,9819 __isl_take isl_map *map)9820{9821 isl_bool ok;9822 9823 isl_map_align_params_set(&map, &set);9824 ok = isl_map_compatible_domain(map, set);9825 if (ok < 0)9826 goto error;9827 if (!ok)9828 isl_die(isl_set_get_ctx(set), isl_error_invalid,9829 "incompatible spaces", goto error);9830 map = isl_map_intersect_domain(map, set);9831 set = isl_map_range(map);9832 return set;9833error:9834 isl_set_free(set);9835 isl_map_free(map);9836 return NULL;9837}9838 9839/* There is no need to cow as removing empty parts doesn't change9840 * the meaning of the set.9841 */9842__isl_give isl_map *isl_map_remove_empty_parts(__isl_take isl_map *map)9843{9844 int i;9845 9846 if (!map)9847 return NULL;9848 9849 for (i = map->n - 1; i >= 0; --i)9850 map = remove_if_empty(map, i);9851 9852 return map;9853}9854 9855__isl_give isl_set *isl_set_remove_empty_parts(__isl_take isl_set *set)9856{9857 return set_from_map(isl_map_remove_empty_parts(set_to_map(set)));9858}9859 9860/* Create a binary relation that maps the shared initial "pos" dimensions9861 * of "bset1" and "bset2" to the remaining dimensions of "bset1" and "bset2".9862 */9863static __isl_give isl_basic_map *join_initial(__isl_keep isl_basic_set *bset1,9864 __isl_keep isl_basic_set *bset2, int pos)9865{9866 isl_basic_map *bmap1;9867 isl_basic_map *bmap2;9868 9869 bmap1 = isl_basic_map_from_range(isl_basic_set_copy(bset1));9870 bmap2 = isl_basic_map_from_range(isl_basic_set_copy(bset2));9871 bmap1 = isl_basic_map_move_dims(bmap1, isl_dim_in, 0,9872 isl_dim_out, 0, pos);9873 bmap2 = isl_basic_map_move_dims(bmap2, isl_dim_in, 0,9874 isl_dim_out, 0, pos);9875 return isl_basic_map_range_product(bmap1, bmap2);9876}9877 9878/* Given two basic sets bset1 and bset2, compute the maximal difference9879 * between the values of dimension pos in bset1 and those in bset29880 * for any common value of the parameters and dimensions preceding pos.9881 */9882static enum isl_lp_result basic_set_maximal_difference_at(9883 __isl_keep isl_basic_set *bset1, __isl_keep isl_basic_set *bset2,9884 int pos, isl_int *opt)9885{9886 isl_basic_map *bmap1;9887 struct isl_ctx *ctx;9888 struct isl_vec *obj;9889 isl_size total;9890 isl_size nparam;9891 isl_size dim1;9892 enum isl_lp_result res;9893 9894 nparam = isl_basic_set_dim(bset1, isl_dim_param);9895 dim1 = isl_basic_set_dim(bset1, isl_dim_set);9896 if (nparam < 0 || dim1 < 0 || !bset2)9897 return isl_lp_error;9898 9899 bmap1 = join_initial(bset1, bset2, pos);9900 total = isl_basic_map_dim(bmap1, isl_dim_all);9901 if (total < 0)9902 return isl_lp_error;9903 9904 ctx = bmap1->ctx;9905 obj = isl_vec_alloc(ctx, 1 + total);9906 if (!obj)9907 goto error;9908 isl_seq_clr(obj->block.data, 1 + total);9909 isl_int_set_si(obj->block.data[1+nparam+pos], 1);9910 isl_int_set_si(obj->block.data[1+nparam+pos+(dim1-pos)], -1);9911 res = isl_basic_map_solve_lp(bmap1, 1, obj->block.data, ctx->one,9912 opt, NULL, NULL);9913 isl_basic_map_free(bmap1);9914 isl_vec_free(obj);9915 return res;9916error:9917 isl_basic_map_free(bmap1);9918 return isl_lp_error;9919}9920 9921/* Given two _disjoint_ basic sets bset1 and bset2, check whether9922 * for any common value of the parameters and dimensions preceding pos9923 * in both basic sets, the values of dimension pos in bset1 are9924 * smaller or larger than those in bset2.9925 *9926 * Returns9927 * 1 if bset1 follows bset29928 * -1 if bset1 precedes bset29929 * 0 if bset1 and bset2 are incomparable9930 * -2 if some error occurred.9931 */9932int isl_basic_set_compare_at(__isl_keep isl_basic_set *bset1,9933 __isl_keep isl_basic_set *bset2, int pos)9934{9935 isl_int opt;9936 enum isl_lp_result res;9937 int cmp;9938 9939 isl_int_init(opt);9940 9941 res = basic_set_maximal_difference_at(bset1, bset2, pos, &opt);9942 9943 if (res == isl_lp_empty)9944 cmp = 0;9945 else if ((res == isl_lp_ok && isl_int_is_pos(opt)) ||9946 res == isl_lp_unbounded)9947 cmp = 1;9948 else if (res == isl_lp_ok && isl_int_is_neg(opt))9949 cmp = -1;9950 else9951 cmp = -2;9952 9953 isl_int_clear(opt);9954 return cmp;9955}9956 9957/* Given two basic sets bset1 and bset2, check whether9958 * for any common value of the parameters and dimensions preceding pos9959 * there is a value of dimension pos in bset1 that is larger9960 * than a value of the same dimension in bset2.9961 *9962 * Return9963 * 1 if there exists such a pair9964 * 0 if there is no such pair, but there is a pair of equal values9965 * -1 otherwise9966 * -2 if some error occurred.9967 */9968int isl_basic_set_follows_at(__isl_keep isl_basic_set *bset1,9969 __isl_keep isl_basic_set *bset2, int pos)9970{9971 isl_bool empty;9972 isl_basic_map *bmap;9973 isl_size dim1;9974 9975 dim1 = isl_basic_set_dim(bset1, isl_dim_set);9976 if (dim1 < 0)9977 return -2;9978 bmap = join_initial(bset1, bset2, pos);9979 bmap = isl_basic_map_order_ge(bmap, isl_dim_out, 0,9980 isl_dim_out, dim1 - pos);9981 empty = isl_basic_map_is_empty(bmap);9982 if (empty < 0)9983 goto error;9984 if (empty) {9985 isl_basic_map_free(bmap);9986 return -1;9987 }9988 bmap = isl_basic_map_order_gt(bmap, isl_dim_out, 0,9989 isl_dim_out, dim1 - pos);9990 empty = isl_basic_map_is_empty(bmap);9991 if (empty < 0)9992 goto error;9993 isl_basic_map_free(bmap);9994 if (empty)9995 return 0;9996 return 1;9997error:9998 isl_basic_map_free(bmap);9999 return -2;10000}10001 10002/* Given two sets set1 and set2, check whether10003 * for any common value of the parameters and dimensions preceding pos10004 * there is a value of dimension pos in set1 that is larger10005 * than a value of the same dimension in set2.10006 *10007 * Return10008 * 1 if there exists such a pair10009 * 0 if there is no such pair, but there is a pair of equal values10010 * -1 otherwise10011 * -2 if some error occurred.10012 */10013int isl_set_follows_at(__isl_keep isl_set *set1,10014 __isl_keep isl_set *set2, int pos)10015{10016 int i, j;10017 int follows = -1;10018 10019 if (!set1 || !set2)10020 return -2;10021 10022 for (i = 0; i < set1->n; ++i)10023 for (j = 0; j < set2->n; ++j) {10024 int f;10025 f = isl_basic_set_follows_at(set1->p[i], set2->p[j], pos);10026 if (f == 1 || f == -2)10027 return f;10028 if (f > follows)10029 follows = f;10030 }10031 10032 return follows;10033}10034 10035static isl_bool isl_basic_map_plain_has_fixed_var(10036 __isl_keep isl_basic_map *bmap, unsigned pos, isl_int *val)10037{10038 int i;10039 int d;10040 isl_size total;10041 10042 total = isl_basic_map_dim(bmap, isl_dim_all);10043 if (total < 0)10044 return isl_bool_error;10045 for (i = 0, d = total-1; i < bmap->n_eq && d+1 > pos; ++i) {10046 for (; d+1 > pos; --d)10047 if (!isl_int_is_zero(bmap->eq[i][1+d]))10048 break;10049 if (d != pos)10050 continue;10051 if (isl_seq_first_non_zero(bmap->eq[i]+1, d) != -1)10052 return isl_bool_false;10053 if (isl_seq_first_non_zero(bmap->eq[i]+1+d+1, total-d-1) != -1)10054 return isl_bool_false;10055 if (!isl_int_is_one(bmap->eq[i][1+d]))10056 return isl_bool_false;10057 if (val)10058 isl_int_neg(*val, bmap->eq[i][0]);10059 return isl_bool_true;10060 }10061 return isl_bool_false;10062}10063 10064static isl_bool isl_map_plain_has_fixed_var(__isl_keep isl_map *map,10065 unsigned pos, isl_int *val)10066{10067 int i;10068 isl_int v;10069 isl_int tmp;10070 isl_bool fixed;10071 10072 if (!map)10073 return isl_bool_error;10074 if (map->n == 0)10075 return isl_bool_false;10076 if (map->n == 1)10077 return isl_basic_map_plain_has_fixed_var(map->p[0], pos, val); 10078 isl_int_init(v);10079 isl_int_init(tmp);10080 fixed = isl_basic_map_plain_has_fixed_var(map->p[0], pos, &v); 10081 for (i = 1; fixed == isl_bool_true && i < map->n; ++i) {10082 fixed = isl_basic_map_plain_has_fixed_var(map->p[i], pos, &tmp); 10083 if (fixed == isl_bool_true && isl_int_ne(tmp, v))10084 fixed = isl_bool_false;10085 }10086 if (val)10087 isl_int_set(*val, v);10088 isl_int_clear(tmp);10089 isl_int_clear(v);10090 return fixed;10091}10092 10093static isl_bool isl_basic_set_plain_has_fixed_var(10094 __isl_keep isl_basic_set *bset, unsigned pos, isl_int *val)10095{10096 return isl_basic_map_plain_has_fixed_var(bset_to_bmap(bset),10097 pos, val);10098}10099 10100isl_bool isl_basic_map_plain_is_fixed(__isl_keep isl_basic_map *bmap,10101 enum isl_dim_type type, unsigned pos, isl_int *val)10102{10103 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)10104 return isl_bool_error;10105 return isl_basic_map_plain_has_fixed_var(bmap,10106 isl_basic_map_offset(bmap, type) - 1 + pos, val);10107}10108 10109/* If "bmap" obviously lies on a hyperplane where the given dimension10110 * has a fixed value, then return that value.10111 * Otherwise return NaN.10112 */10113__isl_give isl_val *isl_basic_map_plain_get_val_if_fixed(10114 __isl_keep isl_basic_map *bmap,10115 enum isl_dim_type type, unsigned pos)10116{10117 isl_ctx *ctx;10118 isl_val *v;10119 isl_bool fixed;10120 10121 if (!bmap)10122 return NULL;10123 ctx = isl_basic_map_get_ctx(bmap);10124 v = isl_val_alloc(ctx);10125 if (!v)10126 return NULL;10127 fixed = isl_basic_map_plain_is_fixed(bmap, type, pos, &v->n);10128 if (fixed < 0)10129 return isl_val_free(v);10130 if (fixed) {10131 isl_int_set_si(v->d, 1);10132 return v;10133 }10134 isl_val_free(v);10135 return isl_val_nan(ctx);10136}10137 10138isl_bool isl_map_plain_is_fixed(__isl_keep isl_map *map,10139 enum isl_dim_type type, unsigned pos, isl_int *val)10140{10141 if (isl_map_check_range(map, type, pos, 1) < 0)10142 return isl_bool_error;10143 return isl_map_plain_has_fixed_var(map,10144 map_offset(map, type) - 1 + pos, val);10145}10146 10147/* If "map" obviously lies on a hyperplane where the given dimension10148 * has a fixed value, then return that value.10149 * Otherwise return NaN.10150 */10151__isl_give isl_val *isl_map_plain_get_val_if_fixed(__isl_keep isl_map *map,10152 enum isl_dim_type type, unsigned pos)10153{10154 isl_ctx *ctx;10155 isl_val *v;10156 isl_bool fixed;10157 10158 if (!map)10159 return NULL;10160 ctx = isl_map_get_ctx(map);10161 v = isl_val_alloc(ctx);10162 if (!v)10163 return NULL;10164 fixed = isl_map_plain_is_fixed(map, type, pos, &v->n);10165 if (fixed < 0)10166 return isl_val_free(v);10167 if (fixed) {10168 isl_int_set_si(v->d, 1);10169 return v;10170 }10171 isl_val_free(v);10172 return isl_val_nan(ctx);10173}10174 10175/* If "set" obviously lies on a hyperplane where the given dimension10176 * has a fixed value, then return that value.10177 * Otherwise return NaN.10178 */10179__isl_give isl_val *isl_set_plain_get_val_if_fixed(__isl_keep isl_set *set,10180 enum isl_dim_type type, unsigned pos)10181{10182 return isl_map_plain_get_val_if_fixed(set, type, pos);10183}10184 10185/* Return a sequence of values in the same space as "set"10186 * that are equal to the corresponding set dimensions of "set"10187 * for those set dimensions that obviously lie on a hyperplane10188 * where the dimension has a fixed value.10189 * The other elements are set to NaN.10190 */10191__isl_give isl_multi_val *isl_set_get_plain_multi_val_if_fixed(10192 __isl_keep isl_set *set)10193{10194 int i;10195 isl_size n;10196 isl_space *space;10197 isl_multi_val *mv;10198 10199 space = isl_space_drop_all_params(isl_set_get_space(set));10200 mv = isl_multi_val_alloc(space);10201 n = isl_multi_val_size(mv);10202 if (n < 0)10203 return isl_multi_val_free(mv);10204 10205 for (i = 0; i < n; ++i) {10206 isl_val *v;10207 10208 v = isl_set_plain_get_val_if_fixed(set, isl_dim_set, i);10209 mv = isl_multi_val_set_val(mv, i, v);10210 }10211 10212 return mv;10213}10214 10215/* Check if dimension dim has fixed value and if so and if val is not NULL,10216 * then return this fixed value in *val.10217 */10218isl_bool isl_basic_set_plain_dim_is_fixed(__isl_keep isl_basic_set *bset,10219 unsigned dim, isl_int *val)10220{10221 isl_size nparam;10222 10223 nparam = isl_basic_set_dim(bset, isl_dim_param);10224 if (nparam < 0)10225 return isl_bool_error;10226 return isl_basic_set_plain_has_fixed_var(bset, nparam + dim, val);10227}10228 10229/* Return -1 if the constraint "c1" should be sorted before "c2"10230 * and 1 if it should be sorted after "c2".10231 * Return 0 if the two constraints are the same (up to the constant term).10232 *10233 * In particular, if a constraint involves later variables than another10234 * then it is sorted after this other constraint.10235 * uset_gist depends on constraints without existentially quantified10236 * variables sorting first.10237 *10238 * For constraints that have the same latest variable, those10239 * with the same coefficient for this latest variable (first in absolute value10240 * and then in actual value) are grouped together.10241 * This is useful for detecting pairs of constraints that can10242 * be chained in their printed representation.10243 *10244 * Finally, within a group, constraints are sorted according to10245 * their coefficients (excluding the constant term).10246 */10247static int sort_constraint_cmp(const void *p1, const void *p2, void *arg)10248{10249 isl_int **c1 = (isl_int **) p1;10250 isl_int **c2 = (isl_int **) p2;10251 int l1, l2;10252 unsigned size = *(unsigned *) arg;10253 int cmp;10254 10255 l1 = isl_seq_last_non_zero(*c1 + 1, size);10256 l2 = isl_seq_last_non_zero(*c2 + 1, size);10257 10258 if (l1 != l2)10259 return l1 - l2;10260 10261 cmp = isl_int_abs_cmp((*c1)[1 + l1], (*c2)[1 + l1]);10262 if (cmp != 0)10263 return cmp;10264 cmp = isl_int_cmp((*c1)[1 + l1], (*c2)[1 + l1]);10265 if (cmp != 0)10266 return -cmp;10267 10268 return isl_seq_cmp(*c1 + 1, *c2 + 1, size);10269}10270 10271/* Return -1 if the constraint "c1" of "bmap" is sorted before "c2"10272 * by isl_basic_map_sort_constraints, 1 if it is sorted after "c2"10273 * and 0 if the two constraints are the same (up to the constant term).10274 */10275int isl_basic_map_constraint_cmp(__isl_keep isl_basic_map *bmap,10276 isl_int *c1, isl_int *c2)10277{10278 isl_size total;10279 unsigned size;10280 10281 total = isl_basic_map_dim(bmap, isl_dim_all);10282 if (total < 0)10283 return -2;10284 size = total;10285 return sort_constraint_cmp(&c1, &c2, &size);10286}10287 10288__isl_give isl_basic_map *isl_basic_map_sort_constraints(10289 __isl_take isl_basic_map *bmap)10290{10291 isl_size total;10292 unsigned size;10293 10294 if (!bmap)10295 return NULL;10296 if (bmap->n_ineq == 0)10297 return bmap;10298 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_SORTED))10299 return bmap;10300 total = isl_basic_map_dim(bmap, isl_dim_all);10301 if (total < 0)10302 return isl_basic_map_free(bmap);10303 size = total;10304 if (isl_sort(bmap->ineq, bmap->n_ineq, sizeof(isl_int *),10305 &sort_constraint_cmp, &size) < 0)10306 return isl_basic_map_free(bmap);10307 ISL_F_SET(bmap, ISL_BASIC_MAP_SORTED);10308 return bmap;10309}10310 10311__isl_give isl_basic_set *isl_basic_set_sort_constraints(10312 __isl_take isl_basic_set *bset)10313{10314 isl_basic_map *bmap = bset_to_bmap(bset);10315 return bset_from_bmap(isl_basic_map_sort_constraints(bmap));10316}10317 10318__isl_give isl_basic_map *isl_basic_map_normalize(10319 __isl_take isl_basic_map *bmap)10320{10321 bmap = isl_basic_map_remove_redundancies(bmap);10322 bmap = isl_basic_map_sort_constraints(bmap);10323 return bmap;10324}10325int isl_basic_map_plain_cmp(__isl_keep isl_basic_map *bmap1,10326 __isl_keep isl_basic_map *bmap2)10327{10328 int i, cmp;10329 isl_size total;10330 isl_space *space1, *space2;10331 10332 if (!bmap1 || !bmap2)10333 return -1;10334 10335 if (bmap1 == bmap2)10336 return 0;10337 space1 = isl_basic_map_peek_space(bmap1);10338 space2 = isl_basic_map_peek_space(bmap2);10339 cmp = isl_space_cmp(space1, space2);10340 if (cmp)10341 return cmp;10342 if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_RATIONAL) !=10343 ISL_F_ISSET(bmap2, ISL_BASIC_MAP_RATIONAL))10344 return ISL_F_ISSET(bmap1, ISL_BASIC_MAP_RATIONAL) ? -1 : 1;10345 if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_EMPTY) &&10346 ISL_F_ISSET(bmap2, ISL_BASIC_MAP_EMPTY))10347 return 0;10348 if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_EMPTY))10349 return 1;10350 if (ISL_F_ISSET(bmap2, ISL_BASIC_MAP_EMPTY))10351 return -1;10352 if (bmap1->n_eq != bmap2->n_eq)10353 return bmap1->n_eq - bmap2->n_eq;10354 if (bmap1->n_ineq != bmap2->n_ineq)10355 return bmap1->n_ineq - bmap2->n_ineq;10356 if (bmap1->n_div != bmap2->n_div)10357 return bmap1->n_div - bmap2->n_div;10358 total = isl_basic_map_dim(bmap1, isl_dim_all);10359 if (total < 0)10360 return -1;10361 for (i = 0; i < bmap1->n_eq; ++i) {10362 cmp = isl_seq_cmp(bmap1->eq[i], bmap2->eq[i], 1+total);10363 if (cmp)10364 return cmp;10365 }10366 for (i = 0; i < bmap1->n_ineq; ++i) {10367 cmp = isl_seq_cmp(bmap1->ineq[i], bmap2->ineq[i], 1+total);10368 if (cmp)10369 return cmp;10370 }10371 for (i = 0; i < bmap1->n_div; ++i) {10372 isl_bool unknown1, unknown2;10373 10374 unknown1 = isl_basic_map_div_is_marked_unknown(bmap1, i);10375 unknown2 = isl_basic_map_div_is_marked_unknown(bmap2, i);10376 if (unknown1 < 0 || unknown2 < 0)10377 return -1;10378 if (unknown1 && unknown2)10379 continue;10380 if (unknown1)10381 return 1;10382 if (unknown2)10383 return -1;10384 cmp = isl_seq_cmp(bmap1->div[i], bmap2->div[i], 1+1+total);10385 if (cmp)10386 return cmp;10387 }10388 return 0;10389}10390 10391int isl_basic_set_plain_cmp(__isl_keep isl_basic_set *bset1,10392 __isl_keep isl_basic_set *bset2)10393{10394 return isl_basic_map_plain_cmp(bset1, bset2);10395}10396 10397int isl_set_plain_cmp(__isl_keep isl_set *set1, __isl_keep isl_set *set2)10398{10399 int i, cmp;10400 10401 if (set1 == set2)10402 return 0;10403 if (set1->n != set2->n)10404 return set1->n - set2->n;10405 10406 for (i = 0; i < set1->n; ++i) {10407 cmp = isl_basic_set_plain_cmp(set1->p[i], set2->p[i]);10408 if (cmp)10409 return cmp;10410 }10411 10412 return 0;10413}10414 10415isl_bool isl_basic_map_plain_is_equal(__isl_keep isl_basic_map *bmap1,10416 __isl_keep isl_basic_map *bmap2)10417{10418 if (!bmap1 || !bmap2)10419 return isl_bool_error;10420 return isl_basic_map_plain_cmp(bmap1, bmap2) == 0;10421}10422 10423isl_bool isl_basic_set_plain_is_equal(__isl_keep isl_basic_set *bset1,10424 __isl_keep isl_basic_set *bset2)10425{10426 return isl_basic_map_plain_is_equal(bset_to_bmap(bset1),10427 bset_to_bmap(bset2));10428}10429 10430static int qsort_bmap_cmp(const void *p1, const void *p2)10431{10432 isl_basic_map *bmap1 = *(isl_basic_map **) p1;10433 isl_basic_map *bmap2 = *(isl_basic_map **) p2;10434 10435 return isl_basic_map_plain_cmp(bmap1, bmap2);10436}10437 10438/* Sort the basic maps of "map" and remove duplicate basic maps.10439 *10440 * While removing basic maps, we make sure that the basic maps remain10441 * sorted because isl_map_normalize expects the basic maps of the result10442 * to be sorted.10443 */10444static __isl_give isl_map *sort_and_remove_duplicates(__isl_take isl_map *map)10445{10446 int i, j;10447 10448 map = isl_map_remove_empty_parts(map);10449 if (!map)10450 return NULL;10451 qsort(map->p, map->n, sizeof(struct isl_basic_map *), qsort_bmap_cmp);10452 for (i = map->n - 1; i >= 1; --i) {10453 if (!isl_basic_map_plain_is_equal(map->p[i - 1], map->p[i]))10454 continue;10455 isl_basic_map_free(map->p[i-1]);10456 for (j = i; j < map->n; ++j)10457 map->p[j - 1] = map->p[j];10458 map->n--;10459 }10460 10461 return map;10462}10463 10464/* Remove obvious duplicates among the basic maps of "map".10465 *10466 * Unlike isl_map_normalize, this function does not remove redundant10467 * constraints and only removes duplicates that have exactly the same10468 * constraints in the input. It does sort the constraints and10469 * the basic maps to ease the detection of duplicates.10470 *10471 * If "map" has already been normalized or if the basic maps are10472 * disjoint, then there can be no duplicates.10473 */10474__isl_give isl_map *isl_map_remove_obvious_duplicates(__isl_take isl_map *map)10475{10476 int i;10477 isl_basic_map *bmap;10478 10479 if (!map)10480 return NULL;10481 if (map->n <= 1)10482 return map;10483 if (ISL_F_ISSET(map, ISL_MAP_NORMALIZED | ISL_MAP_DISJOINT))10484 return map;10485 for (i = 0; i < map->n; ++i) {10486 bmap = isl_basic_map_copy(map->p[i]);10487 bmap = isl_basic_map_sort_constraints(bmap);10488 if (!bmap)10489 return isl_map_free(map);10490 isl_basic_map_free(map->p[i]);10491 map->p[i] = bmap;10492 }10493 10494 map = sort_and_remove_duplicates(map);10495 return map;10496}10497 10498/* We normalize in place, but if anything goes wrong we need10499 * to return NULL, so we need to make sure we don't change the10500 * meaning of any possible other copies of map.10501 */10502__isl_give isl_map *isl_map_normalize(__isl_take isl_map *map)10503{10504 int i;10505 struct isl_basic_map *bmap;10506 10507 if (!map)10508 return NULL;10509 if (ISL_F_ISSET(map, ISL_MAP_NORMALIZED))10510 return map;10511 for (i = 0; i < map->n; ++i) {10512 bmap = isl_basic_map_normalize(isl_basic_map_copy(map->p[i]));10513 if (!bmap)10514 goto error;10515 isl_basic_map_free(map->p[i]);10516 map->p[i] = bmap;10517 }10518 10519 map = sort_and_remove_duplicates(map);10520 if (map)10521 ISL_F_SET(map, ISL_MAP_NORMALIZED);10522 return map;10523error:10524 isl_map_free(map);10525 return NULL;10526}10527 10528__isl_give isl_set *isl_set_normalize(__isl_take isl_set *set)10529{10530 return set_from_map(isl_map_normalize(set_to_map(set)));10531}10532 10533isl_bool isl_map_plain_is_equal(__isl_keep isl_map *map1,10534 __isl_keep isl_map *map2)10535{10536 int i;10537 isl_bool equal;10538 10539 if (!map1 || !map2)10540 return isl_bool_error;10541 10542 if (map1 == map2)10543 return isl_bool_true;10544 equal = isl_map_has_equal_space(map1, map2);10545 if (equal < 0 || !equal)10546 return equal;10547 10548 map1 = isl_map_copy(map1);10549 map2 = isl_map_copy(map2);10550 map1 = isl_map_normalize(map1);10551 map2 = isl_map_normalize(map2);10552 if (!map1 || !map2)10553 goto error;10554 equal = map1->n == map2->n;10555 for (i = 0; equal && i < map1->n; ++i) {10556 equal = isl_basic_map_plain_is_equal(map1->p[i], map2->p[i]);10557 if (equal < 0)10558 goto error;10559 }10560 isl_map_free(map1);10561 isl_map_free(map2);10562 return equal;10563error:10564 isl_map_free(map1);10565 isl_map_free(map2);10566 return isl_bool_error;10567}10568 10569isl_bool isl_set_plain_is_equal(__isl_keep isl_set *set1,10570 __isl_keep isl_set *set2)10571{10572 return isl_map_plain_is_equal(set_to_map(set1), set_to_map(set2));10573}10574 10575/* Return the basic maps in "map" as a list.10576 */10577__isl_give isl_basic_map_list *isl_map_get_basic_map_list(10578 __isl_keep isl_map *map)10579{10580 int i;10581 isl_ctx *ctx;10582 isl_basic_map_list *list;10583 10584 if (!map)10585 return NULL;10586 ctx = isl_map_get_ctx(map);10587 list = isl_basic_map_list_alloc(ctx, map->n);10588 10589 for (i = 0; i < map->n; ++i) {10590 isl_basic_map *bmap;10591 10592 bmap = isl_basic_map_copy(map->p[i]);10593 list = isl_basic_map_list_add(list, bmap);10594 }10595 10596 return list;10597}10598 10599/* Return the intersection of the elements in the non-empty list "list".10600 * All elements are assumed to live in the same space.10601 */10602__isl_give isl_basic_map *isl_basic_map_list_intersect(10603 __isl_take isl_basic_map_list *list)10604{10605 int i;10606 isl_size n;10607 isl_basic_map *bmap;10608 10609 n = isl_basic_map_list_n_basic_map(list);10610 if (n < 0)10611 goto error;10612 if (n < 1)10613 isl_die(isl_basic_map_list_get_ctx(list), isl_error_invalid,10614 "expecting non-empty list", goto error);10615 10616 bmap = isl_basic_map_list_get_basic_map(list, 0);10617 for (i = 1; i < n; ++i) {10618 isl_basic_map *bmap_i;10619 10620 bmap_i = isl_basic_map_list_get_basic_map(list, i);10621 bmap = isl_basic_map_intersect(bmap, bmap_i);10622 }10623 10624 isl_basic_map_list_free(list);10625 return bmap;10626error:10627 isl_basic_map_list_free(list);10628 return NULL;10629}10630 10631/* Return the intersection of the elements in the non-empty list "list".10632 * All elements are assumed to live in the same space.10633 */10634__isl_give isl_basic_set *isl_basic_set_list_intersect(10635 __isl_take isl_basic_set_list *list)10636{10637 return isl_basic_map_list_intersect(list);10638}10639 10640/* Return the union of the elements of "list".10641 * The list is required to have at least one element.10642 */10643__isl_give isl_set *isl_basic_set_list_union(10644 __isl_take isl_basic_set_list *list)10645{10646 int i;10647 isl_size n;10648 isl_space *space;10649 isl_basic_set *bset;10650 isl_set *set;10651 10652 n = isl_basic_set_list_n_basic_set(list);10653 if (n < 0)10654 goto error;10655 if (n < 1)10656 isl_die(isl_basic_set_list_get_ctx(list), isl_error_invalid,10657 "expecting non-empty list", goto error);10658 10659 bset = isl_basic_set_list_get_basic_set(list, 0);10660 space = isl_basic_set_get_space(bset);10661 isl_basic_set_free(bset);10662 10663 set = isl_set_alloc_space(space, n, 0);10664 for (i = 0; i < n; ++i) {10665 bset = isl_basic_set_list_get_basic_set(list, i);10666 set = isl_set_add_basic_set(set, bset);10667 }10668 10669 isl_basic_set_list_free(list);10670 return set;10671error:10672 isl_basic_set_list_free(list);10673 return NULL;10674}10675 10676/* Return the union of the elements in the non-empty list "list".10677 * All elements are assumed to live in the same space.10678 */10679__isl_give isl_set *isl_set_list_union(__isl_take isl_set_list *list)10680{10681 int i;10682 isl_size n;10683 isl_set *set;10684 10685 n = isl_set_list_n_set(list);10686 if (n < 0)10687 goto error;10688 if (n < 1)10689 isl_die(isl_set_list_get_ctx(list), isl_error_invalid,10690 "expecting non-empty list", goto error);10691 10692 set = isl_set_list_get_set(list, 0);10693 for (i = 1; i < n; ++i) {10694 isl_set *set_i;10695 10696 set_i = isl_set_list_get_set(list, i);10697 set = isl_set_union(set, set_i);10698 }10699 10700 isl_set_list_free(list);10701 return set;10702error:10703 isl_set_list_free(list);10704 return NULL;10705}10706 10707__isl_give isl_basic_map *isl_basic_map_product(10708 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)10709{10710 isl_space *space_result = NULL;10711 struct isl_basic_map *bmap;10712 unsigned in1, in2, out1, out2, nparam, total, pos;10713 struct isl_dim_map *dim_map1, *dim_map2;10714 10715 if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)10716 goto error;10717 space_result = isl_space_product(isl_space_copy(bmap1->dim),10718 isl_space_copy(bmap2->dim));10719 10720 in1 = isl_basic_map_dim(bmap1, isl_dim_in);10721 in2 = isl_basic_map_dim(bmap2, isl_dim_in);10722 out1 = isl_basic_map_dim(bmap1, isl_dim_out);10723 out2 = isl_basic_map_dim(bmap2, isl_dim_out);10724 nparam = isl_basic_map_dim(bmap1, isl_dim_param);10725 10726 total = nparam + in1 + in2 + out1 + out2 + bmap1->n_div + bmap2->n_div;10727 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);10728 dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);10729 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);10730 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);10731 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);10732 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos += in1);10733 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in2);10734 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += out1);10735 isl_dim_map_div(dim_map1, bmap1, pos += out2);10736 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);10737 10738 bmap = isl_basic_map_alloc_space(space_result,10739 bmap1->n_div + bmap2->n_div,10740 bmap1->n_eq + bmap2->n_eq,10741 bmap1->n_ineq + bmap2->n_ineq);10742 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);10743 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);10744 bmap = isl_basic_map_simplify(bmap);10745 return isl_basic_map_finalize(bmap);10746error:10747 isl_basic_map_free(bmap1);10748 isl_basic_map_free(bmap2);10749 return NULL;10750}10751 10752__isl_give isl_basic_map *isl_basic_map_flat_product(10753 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)10754{10755 isl_basic_map *prod;10756 10757 prod = isl_basic_map_product(bmap1, bmap2);10758 prod = isl_basic_map_flatten(prod);10759 return prod;10760}10761 10762__isl_give isl_basic_set *isl_basic_set_flat_product(10763 __isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2)10764{10765 return isl_basic_map_flat_range_product(bset1, bset2);10766}10767 10768__isl_give isl_basic_map *isl_basic_map_domain_product(10769 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)10770{10771 isl_space *space1, *space2;10772 isl_space *space_result = NULL;10773 isl_basic_map *bmap;10774 isl_size in1, in2, out, nparam;10775 unsigned total, pos;10776 struct isl_dim_map *dim_map1, *dim_map2;10777 10778 in1 = isl_basic_map_dim(bmap1, isl_dim_in);10779 in2 = isl_basic_map_dim(bmap2, isl_dim_in);10780 out = isl_basic_map_dim(bmap1, isl_dim_out);10781 nparam = isl_basic_map_dim(bmap1, isl_dim_param);10782 if (in1 < 0 || in2 < 0 || out < 0 || nparam < 0)10783 goto error;10784 10785 space1 = isl_basic_map_get_space(bmap1);10786 space2 = isl_basic_map_get_space(bmap2);10787 space_result = isl_space_domain_product(space1, space2);10788 10789 total = nparam + in1 + in2 + out + bmap1->n_div + bmap2->n_div;10790 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);10791 dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);10792 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);10793 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);10794 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);10795 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos += in1);10796 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in2);10797 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos);10798 isl_dim_map_div(dim_map1, bmap1, pos += out);10799 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);10800 10801 bmap = isl_basic_map_alloc_space(space_result,10802 bmap1->n_div + bmap2->n_div,10803 bmap1->n_eq + bmap2->n_eq,10804 bmap1->n_ineq + bmap2->n_ineq);10805 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);10806 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);10807 bmap = isl_basic_map_simplify(bmap);10808 return isl_basic_map_finalize(bmap);10809error:10810 isl_basic_map_free(bmap1);10811 isl_basic_map_free(bmap2);10812 return NULL;10813}10814 10815__isl_give isl_basic_map *isl_basic_map_range_product(10816 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)10817{10818 isl_bool rational;10819 isl_space *space_result = NULL;10820 isl_basic_map *bmap;10821 isl_size in, out1, out2, nparam;10822 unsigned total, pos;10823 struct isl_dim_map *dim_map1, *dim_map2;10824 10825 rational = isl_basic_map_is_rational(bmap1);10826 if (rational >= 0 && rational)10827 rational = isl_basic_map_is_rational(bmap2);10828 in = isl_basic_map_dim(bmap1, isl_dim_in);10829 out1 = isl_basic_map_dim(bmap1, isl_dim_out);10830 out2 = isl_basic_map_dim(bmap2, isl_dim_out);10831 nparam = isl_basic_map_dim(bmap1, isl_dim_param);10832 if (in < 0 || out1 < 0 || out2 < 0 || nparam < 0 || rational < 0)10833 goto error;10834 10835 if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)10836 goto error;10837 10838 space_result = isl_space_range_product(isl_space_copy(bmap1->dim),10839 isl_space_copy(bmap2->dim));10840 10841 total = nparam + in + out1 + out2 + bmap1->n_div + bmap2->n_div;10842 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);10843 dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);10844 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);10845 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);10846 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);10847 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos);10848 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in);10849 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += out1);10850 isl_dim_map_div(dim_map1, bmap1, pos += out2);10851 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);10852 10853 bmap = isl_basic_map_alloc_space(space_result,10854 bmap1->n_div + bmap2->n_div,10855 bmap1->n_eq + bmap2->n_eq,10856 bmap1->n_ineq + bmap2->n_ineq);10857 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);10858 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);10859 if (rational)10860 bmap = isl_basic_map_set_rational(bmap);10861 bmap = isl_basic_map_simplify(bmap);10862 return isl_basic_map_finalize(bmap);10863error:10864 isl_basic_map_free(bmap1);10865 isl_basic_map_free(bmap2);10866 return NULL;10867}10868 10869__isl_give isl_basic_map *isl_basic_map_flat_range_product(10870 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)10871{10872 isl_basic_map *prod;10873 10874 prod = isl_basic_map_range_product(bmap1, bmap2);10875 prod = isl_basic_map_flatten_range(prod);10876 return prod;10877}10878 10879/* Apply "basic_map_product" to each pair of basic maps in "map1" and "map2"10880 * and collect the results.10881 * The result live in the space obtained by calling "space_product"10882 * on the spaces of "map1" and "map2".10883 * If "remove_duplicates" is set then the result may contain duplicates10884 * (even if the inputs do not) and so we try and remove the obvious10885 * duplicates.10886 */10887static __isl_give isl_map *map_product(__isl_take isl_map *map1,10888 __isl_take isl_map *map2,10889 __isl_give isl_space *(*space_product)(__isl_take isl_space *left,10890 __isl_take isl_space *right),10891 __isl_give isl_basic_map *(*basic_map_product)(10892 __isl_take isl_basic_map *left,10893 __isl_take isl_basic_map *right),10894 int remove_duplicates)10895{10896 unsigned flags = 0;10897 struct isl_map *result;10898 int i, j;10899 isl_bool m;10900 10901 m = isl_map_has_equal_params(map1, map2);10902 if (m < 0)10903 goto error;10904 if (!m)10905 isl_die(isl_map_get_ctx(map1), isl_error_invalid,10906 "parameters don't match", goto error);10907 10908 if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) &&10909 ISL_F_ISSET(map2, ISL_MAP_DISJOINT))10910 ISL_FL_SET(flags, ISL_MAP_DISJOINT);10911 10912 result = isl_map_alloc_space(space_product(isl_space_copy(map1->dim),10913 isl_space_copy(map2->dim)),10914 map1->n * map2->n, flags);10915 if (!result)10916 goto error;10917 for (i = 0; i < map1->n; ++i)10918 for (j = 0; j < map2->n; ++j) {10919 struct isl_basic_map *part;10920 part = basic_map_product(isl_basic_map_copy(map1->p[i]),10921 isl_basic_map_copy(map2->p[j]));10922 if (isl_basic_map_is_empty(part))10923 isl_basic_map_free(part);10924 else10925 result = isl_map_add_basic_map(result, part);10926 if (!result)10927 goto error;10928 }10929 if (remove_duplicates)10930 result = isl_map_remove_obvious_duplicates(result);10931 isl_map_free(map1);10932 isl_map_free(map2);10933 return result;10934error:10935 isl_map_free(map1);10936 isl_map_free(map2);10937 return NULL;10938}10939 10940/* Given two maps A -> B and C -> D, construct a map [A -> C] -> [B -> D]10941 */10942__isl_give isl_map *isl_map_product(__isl_take isl_map *map1,10943 __isl_take isl_map *map2)10944{10945 isl_map_align_params_bin(&map1, &map2);10946 return map_product(map1, map2, &isl_space_product,10947 &isl_basic_map_product, 0);10948}10949 10950/* Given two maps A -> B and C -> D, construct a map (A, C) -> (B, D)10951 */10952__isl_give isl_map *isl_map_flat_product(__isl_take isl_map *map1,10953 __isl_take isl_map *map2)10954{10955 isl_map *prod;10956 10957 prod = isl_map_product(map1, map2);10958 prod = isl_map_flatten(prod);10959 return prod;10960}10961 10962/* Given two set A and B, construct its Cartesian product A x B.10963 */10964__isl_give isl_set *isl_set_product(__isl_take isl_set *set1,10965 __isl_take isl_set *set2)10966{10967 return isl_map_range_product(set1, set2);10968}10969 10970__isl_give isl_set *isl_set_flat_product(__isl_take isl_set *set1,10971 __isl_take isl_set *set2)10972{10973 return isl_map_flat_range_product(set1, set2);10974}10975 10976/* Given two maps A -> B and C -> D, construct a map [A -> C] -> (B * D)10977 */10978__isl_give isl_map *isl_map_domain_product(__isl_take isl_map *map1,10979 __isl_take isl_map *map2)10980{10981 isl_map_align_params_bin(&map1, &map2);10982 return map_product(map1, map2, &isl_space_domain_product,10983 &isl_basic_map_domain_product, 1);10984}10985 10986/* Given two maps A -> B and C -> D, construct a map (A * C) -> [B -> D]10987 */10988__isl_give isl_map *isl_map_range_product(__isl_take isl_map *map1,10989 __isl_take isl_map *map2)10990{10991 isl_map_align_params_bin(&map1, &map2);10992 return map_product(map1, map2, &isl_space_range_product,10993 &isl_basic_map_range_product, 1);10994}10995 10996/* Given a map of the form [A -> B] -> [C -> D], return the map A -> C.10997 */10998__isl_give isl_map *isl_map_factor_domain(__isl_take isl_map *map)10999{11000 isl_space *space;11001 isl_size total1, keep1, total2, keep2;11002 11003 total1 = isl_map_dim(map, isl_dim_in);11004 total2 = isl_map_dim(map, isl_dim_out);11005 if (total1 < 0 || total2 < 0)11006 return isl_map_free(map);11007 if (!isl_space_domain_is_wrapping(map->dim) ||11008 !isl_space_range_is_wrapping(map->dim))11009 isl_die(isl_map_get_ctx(map), isl_error_invalid,11010 "not a product", return isl_map_free(map));11011 11012 space = isl_map_get_space(map);11013 space = isl_space_factor_domain(space);11014 keep1 = isl_space_dim(space, isl_dim_in);11015 keep2 = isl_space_dim(space, isl_dim_out);11016 if (keep1 < 0 || keep2 < 0)11017 map = isl_map_free(map);11018 map = isl_map_project_out(map, isl_dim_in, keep1, total1 - keep1);11019 map = isl_map_project_out(map, isl_dim_out, keep2, total2 - keep2);11020 map = isl_map_reset_space(map, space);11021 11022 return map;11023}11024 11025/* Given a map of the form [A -> B] -> [C -> D], return the map B -> D.11026 */11027__isl_give isl_map *isl_map_factor_range(__isl_take isl_map *map)11028{11029 isl_space *space;11030 isl_size total1, keep1, total2, keep2;11031 11032 total1 = isl_map_dim(map, isl_dim_in);11033 total2 = isl_map_dim(map, isl_dim_out);11034 if (total1 < 0 || total2 < 0)11035 return isl_map_free(map);11036 if (!isl_space_domain_is_wrapping(map->dim) ||11037 !isl_space_range_is_wrapping(map->dim))11038 isl_die(isl_map_get_ctx(map), isl_error_invalid,11039 "not a product", return isl_map_free(map));11040 11041 space = isl_map_get_space(map);11042 space = isl_space_factor_range(space);11043 keep1 = isl_space_dim(space, isl_dim_in);11044 keep2 = isl_space_dim(space, isl_dim_out);11045 if (keep1 < 0 || keep2 < 0)11046 map = isl_map_free(map);11047 map = isl_map_project_out(map, isl_dim_in, 0, total1 - keep1);11048 map = isl_map_project_out(map, isl_dim_out, 0, total2 - keep2);11049 map = isl_map_reset_space(map, space);11050 11051 return map;11052}11053 11054/* Given a map of the form [A -> B] -> C, return the map A -> C.11055 */11056__isl_give isl_map *isl_map_domain_factor_domain(__isl_take isl_map *map)11057{11058 isl_space *space;11059 isl_size total, keep;11060 11061 total = isl_map_dim(map, isl_dim_in);11062 if (total < 0)11063 return isl_map_free(map);11064 if (!isl_space_domain_is_wrapping(map->dim))11065 isl_die(isl_map_get_ctx(map), isl_error_invalid,11066 "domain is not a product", return isl_map_free(map));11067 11068 space = isl_map_get_space(map);11069 space = isl_space_domain_factor_domain(space);11070 keep = isl_space_dim(space, isl_dim_in);11071 if (keep < 0)11072 map = isl_map_free(map);11073 map = isl_map_project_out(map, isl_dim_in, keep, total - keep);11074 map = isl_map_reset_space(map, space);11075 11076 return map;11077}11078 11079/* Given a map of the form [A -> B] -> C, return the map B -> C.11080 */11081__isl_give isl_map *isl_map_domain_factor_range(__isl_take isl_map *map)11082{11083 isl_space *space;11084 isl_size total, keep;11085 11086 total = isl_map_dim(map, isl_dim_in);11087 if (total < 0)11088 return isl_map_free(map);11089 if (!isl_space_domain_is_wrapping(map->dim))11090 isl_die(isl_map_get_ctx(map), isl_error_invalid,11091 "domain is not a product", return isl_map_free(map));11092 11093 space = isl_map_get_space(map);11094 space = isl_space_domain_factor_range(space);11095 keep = isl_space_dim(space, isl_dim_in);11096 if (keep < 0)11097 map = isl_map_free(map);11098 map = isl_map_project_out(map, isl_dim_in, 0, total - keep);11099 map = isl_map_reset_space(map, space);11100 11101 return map;11102}11103 11104/* Given a map A -> [B -> C], extract the map A -> B.11105 */11106__isl_give isl_map *isl_map_range_factor_domain(__isl_take isl_map *map)11107{11108 isl_space *space;11109 isl_size total, keep;11110 11111 total = isl_map_dim(map, isl_dim_out);11112 if (total < 0)11113 return isl_map_free(map);11114 if (!isl_space_range_is_wrapping(map->dim))11115 isl_die(isl_map_get_ctx(map), isl_error_invalid,11116 "range is not a product", return isl_map_free(map));11117 11118 space = isl_map_get_space(map);11119 space = isl_space_range_factor_domain(space);11120 keep = isl_space_dim(space, isl_dim_out);11121 if (keep < 0)11122 map = isl_map_free(map);11123 map = isl_map_project_out(map, isl_dim_out, keep, total - keep);11124 map = isl_map_reset_space(map, space);11125 11126 return map;11127}11128 11129/* Given a map A -> [B -> C], extract the map A -> C.11130 */11131__isl_give isl_map *isl_map_range_factor_range(__isl_take isl_map *map)11132{11133 isl_space *space;11134 isl_size total, keep;11135 11136 total = isl_map_dim(map, isl_dim_out);11137 if (total < 0)11138 return isl_map_free(map);11139 if (!isl_space_range_is_wrapping(map->dim))11140 isl_die(isl_map_get_ctx(map), isl_error_invalid,11141 "range is not a product", return isl_map_free(map));11142 11143 space = isl_map_get_space(map);11144 space = isl_space_range_factor_range(space);11145 keep = isl_space_dim(space, isl_dim_out);11146 if (keep < 0)11147 map = isl_map_free(map);11148 map = isl_map_project_out(map, isl_dim_out, 0, total - keep);11149 map = isl_map_reset_space(map, space);11150 11151 return map;11152}11153 11154/* Given two maps A -> B and C -> D, construct a map (A, C) -> (B * D)11155 */11156__isl_give isl_map *isl_map_flat_domain_product(__isl_take isl_map *map1,11157 __isl_take isl_map *map2)11158{11159 isl_map *prod;11160 11161 prod = isl_map_domain_product(map1, map2);11162 prod = isl_map_flatten_domain(prod);11163 return prod;11164}11165 11166/* Given two maps A -> B and C -> D, construct a map (A * C) -> (B, D)11167 */11168__isl_give isl_map *isl_map_flat_range_product(__isl_take isl_map *map1,11169 __isl_take isl_map *map2)11170{11171 isl_map *prod;11172 11173 prod = isl_map_range_product(map1, map2);11174 prod = isl_map_flatten_range(prod);11175 return prod;11176}11177 11178uint32_t isl_basic_map_get_hash(__isl_keep isl_basic_map *bmap)11179{11180 int i;11181 uint32_t hash = isl_hash_init();11182 isl_size total;11183 11184 if (!bmap)11185 return 0;11186 bmap = isl_basic_map_copy(bmap);11187 bmap = isl_basic_map_normalize(bmap);11188 total = isl_basic_map_dim(bmap, isl_dim_all);11189 if (total < 0)11190 return 0;11191 isl_hash_byte(hash, bmap->n_eq & 0xFF);11192 for (i = 0; i < bmap->n_eq; ++i) {11193 uint32_t c_hash;11194 c_hash = isl_seq_get_hash(bmap->eq[i], 1 + total);11195 isl_hash_hash(hash, c_hash);11196 }11197 isl_hash_byte(hash, bmap->n_ineq & 0xFF);11198 for (i = 0; i < bmap->n_ineq; ++i) {11199 uint32_t c_hash;11200 c_hash = isl_seq_get_hash(bmap->ineq[i], 1 + total);11201 isl_hash_hash(hash, c_hash);11202 }11203 isl_hash_byte(hash, bmap->n_div & 0xFF);11204 for (i = 0; i < bmap->n_div; ++i) {11205 uint32_t c_hash;11206 if (isl_int_is_zero(bmap->div[i][0]))11207 continue;11208 isl_hash_byte(hash, i & 0xFF);11209 c_hash = isl_seq_get_hash(bmap->div[i], 1 + 1 + total);11210 isl_hash_hash(hash, c_hash);11211 }11212 isl_basic_map_free(bmap);11213 return hash;11214}11215 11216uint32_t isl_basic_set_get_hash(__isl_keep isl_basic_set *bset)11217{11218 return isl_basic_map_get_hash(bset_to_bmap(bset));11219}11220 11221uint32_t isl_map_get_hash(__isl_keep isl_map *map)11222{11223 int i;11224 uint32_t hash;11225 11226 if (!map)11227 return 0;11228 map = isl_map_copy(map);11229 map = isl_map_normalize(map);11230 if (!map)11231 return 0;11232 11233 hash = isl_hash_init();11234 for (i = 0; i < map->n; ++i) {11235 uint32_t bmap_hash;11236 bmap_hash = isl_basic_map_get_hash(map->p[i]);11237 isl_hash_hash(hash, bmap_hash);11238 }11239 11240 isl_map_free(map);11241 11242 return hash;11243}11244 11245uint32_t isl_set_get_hash(__isl_keep isl_set *set)11246{11247 return isl_map_get_hash(set_to_map(set));11248}11249 11250/* Return the number of basic maps in the (current) representation of "map".11251 */11252isl_size isl_map_n_basic_map(__isl_keep isl_map *map)11253{11254 return map ? map->n : isl_size_error;11255}11256 11257isl_size isl_set_n_basic_set(__isl_keep isl_set *set)11258{11259 return set ? set->n : isl_size_error;11260}11261 11262isl_stat isl_map_foreach_basic_map(__isl_keep isl_map *map,11263 isl_stat (*fn)(__isl_take isl_basic_map *bmap, void *user), void *user)11264{11265 int i;11266 11267 if (!map)11268 return isl_stat_error;11269 11270 for (i = 0; i < map->n; ++i)11271 if (fn(isl_basic_map_copy(map->p[i]), user) < 0)11272 return isl_stat_error;11273 11274 return isl_stat_ok;11275}11276 11277isl_stat isl_set_foreach_basic_set(__isl_keep isl_set *set,11278 isl_stat (*fn)(__isl_take isl_basic_set *bset, void *user), void *user)11279{11280 int i;11281 11282 if (!set)11283 return isl_stat_error;11284 11285 for (i = 0; i < set->n; ++i)11286 if (fn(isl_basic_set_copy(set->p[i]), user) < 0)11287 return isl_stat_error;11288 11289 return isl_stat_ok;11290}11291 11292/* Does "test" succeed on every basic set in "set"?11293 */11294isl_bool isl_set_every_basic_set(__isl_keep isl_set *set,11295 isl_bool (*test)(__isl_keep isl_basic_set *bset, void *user),11296 void *user)11297{11298 int i;11299 11300 if (!set)11301 return isl_bool_error;11302 11303 for (i = 0; i < set->n; ++i) {11304 isl_bool r;11305 11306 r = test(set->p[i], user);11307 if (r < 0 || !r)11308 return r;11309 }11310 11311 return isl_bool_true;11312}11313 11314/* Return a list of basic sets, the union of which is equal to "set".11315 */11316__isl_give isl_basic_set_list *isl_set_get_basic_set_list(11317 __isl_keep isl_set *set)11318{11319 int i;11320 isl_basic_set_list *list;11321 11322 if (!set)11323 return NULL;11324 11325 list = isl_basic_set_list_alloc(isl_set_get_ctx(set), set->n);11326 for (i = 0; i < set->n; ++i) {11327 isl_basic_set *bset;11328 11329 bset = isl_basic_set_copy(set->p[i]);11330 list = isl_basic_set_list_add(list, bset);11331 }11332 11333 return list;11334}11335 11336__isl_give isl_basic_set *isl_basic_set_lift(__isl_take isl_basic_set *bset)11337{11338 isl_space *space;11339 11340 if (!bset)11341 return NULL;11342 11343 bset = isl_basic_set_cow(bset);11344 if (!bset)11345 return NULL;11346 11347 space = isl_basic_set_get_space(bset);11348 space = isl_space_lift(space, bset->n_div);11349 if (!space)11350 goto error;11351 isl_space_free(bset->dim);11352 bset->dim = space;11353 bset->extra -= bset->n_div;11354 bset->n_div = 0;11355 11356 bset = isl_basic_set_finalize(bset);11357 11358 return bset;11359error:11360 isl_basic_set_free(bset);11361 return NULL;11362}11363 11364__isl_give isl_set *isl_set_lift(__isl_take isl_set *set)11365{11366 int i;11367 isl_space *space;11368 unsigned n_div;11369 11370 set = set_from_map(isl_map_align_divs_internal(set_to_map(set)));11371 11372 if (!set)11373 return NULL;11374 11375 set = isl_set_cow(set);11376 if (!set)11377 return NULL;11378 11379 n_div = set->p[0]->n_div;11380 space = isl_set_get_space(set);11381 space = isl_space_lift(space, n_div);11382 if (!space)11383 goto error;11384 isl_space_free(set->dim);11385 set->dim = space;11386 11387 for (i = 0; i < set->n; ++i) {11388 set->p[i] = isl_basic_set_lift(set->p[i]);11389 if (!set->p[i])11390 goto error;11391 }11392 11393 return set;11394error:11395 isl_set_free(set);11396 return NULL;11397}11398 11399int isl_basic_set_size(__isl_keep isl_basic_set *bset)11400{11401 isl_size dim;11402 int size = 0;11403 11404 dim = isl_basic_set_dim(bset, isl_dim_all);11405 if (dim < 0)11406 return -1;11407 size += bset->n_eq * (1 + dim);11408 size += bset->n_ineq * (1 + dim);11409 size += bset->n_div * (2 + dim);11410 11411 return size;11412}11413 11414int isl_set_size(__isl_keep isl_set *set)11415{11416 int i;11417 int size = 0;11418 11419 if (!set)11420 return -1;11421 11422 for (i = 0; i < set->n; ++i)11423 size += isl_basic_set_size(set->p[i]);11424 11425 return size;11426}11427 11428/* Check if there is any lower bound (if lower == 0) and/or upper11429 * bound (if upper == 0) on the specified dim.11430 */11431static isl_bool basic_map_dim_is_bounded(__isl_keep isl_basic_map *bmap,11432 enum isl_dim_type type, unsigned pos, int lower, int upper)11433{11434 int i;11435 11436 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)11437 return isl_bool_error;11438 11439 pos += isl_basic_map_offset(bmap, type);11440 11441 for (i = 0; i < bmap->n_div; ++i) {11442 if (isl_int_is_zero(bmap->div[i][0]))11443 continue;11444 if (!isl_int_is_zero(bmap->div[i][1 + pos]))11445 return isl_bool_true;11446 }11447 11448 for (i = 0; i < bmap->n_eq; ++i)11449 if (!isl_int_is_zero(bmap->eq[i][pos]))11450 return isl_bool_true;11451 11452 for (i = 0; i < bmap->n_ineq; ++i) {11453 int sgn = isl_int_sgn(bmap->ineq[i][pos]);11454 if (sgn > 0)11455 lower = 1;11456 if (sgn < 0)11457 upper = 1;11458 }11459 11460 return lower && upper;11461}11462 11463isl_bool isl_basic_map_dim_is_bounded(__isl_keep isl_basic_map *bmap,11464 enum isl_dim_type type, unsigned pos)11465{11466 return basic_map_dim_is_bounded(bmap, type, pos, 0, 0);11467}11468 11469isl_bool isl_basic_map_dim_has_lower_bound(__isl_keep isl_basic_map *bmap,11470 enum isl_dim_type type, unsigned pos)11471{11472 return basic_map_dim_is_bounded(bmap, type, pos, 0, 1);11473}11474 11475isl_bool isl_basic_map_dim_has_upper_bound(__isl_keep isl_basic_map *bmap,11476 enum isl_dim_type type, unsigned pos)11477{11478 return basic_map_dim_is_bounded(bmap, type, pos, 1, 0);11479}11480 11481isl_bool isl_map_dim_is_bounded(__isl_keep isl_map *map,11482 enum isl_dim_type type, unsigned pos)11483{11484 int i;11485 11486 if (!map)11487 return isl_bool_error;11488 11489 for (i = 0; i < map->n; ++i) {11490 isl_bool bounded;11491 bounded = isl_basic_map_dim_is_bounded(map->p[i], type, pos);11492 if (bounded < 0 || !bounded)11493 return bounded;11494 }11495 11496 return isl_bool_true;11497}11498 11499/* Return true if the specified dim is involved in both an upper bound11500 * and a lower bound.11501 */11502isl_bool isl_set_dim_is_bounded(__isl_keep isl_set *set,11503 enum isl_dim_type type, unsigned pos)11504{11505 return isl_map_dim_is_bounded(set_to_map(set), type, pos);11506}11507 11508/* Does "map" have a bound (according to "fn") for any of its basic maps?11509 */11510static isl_bool has_any_bound(__isl_keep isl_map *map,11511 enum isl_dim_type type, unsigned pos,11512 isl_bool (*fn)(__isl_keep isl_basic_map *bmap,11513 enum isl_dim_type type, unsigned pos))11514{11515 int i;11516 11517 if (!map)11518 return isl_bool_error;11519 11520 for (i = 0; i < map->n; ++i) {11521 isl_bool bounded;11522 bounded = fn(map->p[i], type, pos);11523 if (bounded < 0 || bounded)11524 return bounded;11525 }11526 11527 return isl_bool_false;11528}11529 11530/* Return 1 if the specified dim is involved in any lower bound.11531 */11532isl_bool isl_set_dim_has_any_lower_bound(__isl_keep isl_set *set,11533 enum isl_dim_type type, unsigned pos)11534{11535 return has_any_bound(set, type, pos,11536 &isl_basic_map_dim_has_lower_bound);11537}11538 11539/* Return 1 if the specified dim is involved in any upper bound.11540 */11541isl_bool isl_set_dim_has_any_upper_bound(__isl_keep isl_set *set,11542 enum isl_dim_type type, unsigned pos)11543{11544 return has_any_bound(set, type, pos,11545 &isl_basic_map_dim_has_upper_bound);11546}11547 11548/* Does "map" have a bound (according to "fn") for all of its basic maps?11549 */11550static isl_bool has_bound(__isl_keep isl_map *map,11551 enum isl_dim_type type, unsigned pos,11552 isl_bool (*fn)(__isl_keep isl_basic_map *bmap,11553 enum isl_dim_type type, unsigned pos))11554{11555 int i;11556 11557 if (!map)11558 return isl_bool_error;11559 11560 for (i = 0; i < map->n; ++i) {11561 isl_bool bounded;11562 bounded = fn(map->p[i], type, pos);11563 if (bounded < 0 || !bounded)11564 return bounded;11565 }11566 11567 return isl_bool_true;11568}11569 11570/* Return 1 if the specified dim has a lower bound (in each of its basic sets).11571 */11572isl_bool isl_set_dim_has_lower_bound(__isl_keep isl_set *set,11573 enum isl_dim_type type, unsigned pos)11574{11575 return has_bound(set, type, pos, &isl_basic_map_dim_has_lower_bound);11576}11577 11578/* Return 1 if the specified dim has an upper bound (in each of its basic sets).11579 */11580isl_bool isl_set_dim_has_upper_bound(__isl_keep isl_set *set,11581 enum isl_dim_type type, unsigned pos)11582{11583 return has_bound(set, type, pos, &isl_basic_map_dim_has_upper_bound);11584}11585 11586/* For each of the "n" variables starting at "first", determine11587 * the sign of the variable and put the results in the first "n"11588 * elements of the array "signs".11589 * Sign11590 * 1 means that the variable is non-negative11591 * -1 means that the variable is non-positive11592 * 0 means the variable attains both positive and negative values.11593 */11594isl_stat isl_basic_set_vars_get_sign(__isl_keep isl_basic_set *bset,11595 unsigned first, unsigned n, int *signs)11596{11597 isl_vec *bound = NULL;11598 struct isl_tab *tab = NULL;11599 struct isl_tab_undo *snap;11600 int i;11601 isl_size total;11602 11603 total = isl_basic_set_dim(bset, isl_dim_all);11604 if (total < 0 || !signs)11605 return isl_stat_error;11606 11607 bound = isl_vec_alloc(bset->ctx, 1 + total);11608 tab = isl_tab_from_basic_set(bset, 0);11609 if (!bound || !tab)11610 goto error;11611 11612 isl_seq_clr(bound->el, bound->size);11613 isl_int_set_si(bound->el[0], -1);11614 11615 snap = isl_tab_snap(tab);11616 for (i = 0; i < n; ++i) {11617 int empty;11618 11619 isl_int_set_si(bound->el[1 + first + i], -1);11620 if (isl_tab_add_ineq(tab, bound->el) < 0)11621 goto error;11622 empty = tab->empty;11623 isl_int_set_si(bound->el[1 + first + i], 0);11624 if (isl_tab_rollback(tab, snap) < 0)11625 goto error;11626 11627 if (empty) {11628 signs[i] = 1;11629 continue;11630 }11631 11632 isl_int_set_si(bound->el[1 + first + i], 1);11633 if (isl_tab_add_ineq(tab, bound->el) < 0)11634 goto error;11635 empty = tab->empty;11636 isl_int_set_si(bound->el[1 + first + i], 0);11637 if (isl_tab_rollback(tab, snap) < 0)11638 goto error;11639 11640 signs[i] = empty ? -1 : 0;11641 }11642 11643 isl_tab_free(tab);11644 isl_vec_free(bound);11645 return isl_stat_ok;11646error:11647 isl_tab_free(tab);11648 isl_vec_free(bound);11649 return isl_stat_error;11650}11651 11652isl_stat isl_basic_set_dims_get_sign(__isl_keep isl_basic_set *bset,11653 enum isl_dim_type type, unsigned first, unsigned n, int *signs)11654{11655 if (!bset || !signs)11656 return isl_stat_error;11657 if (isl_basic_set_check_range(bset, type, first, n) < 0)11658 return isl_stat_error;11659 11660 first += pos(bset->dim, type) - 1;11661 return isl_basic_set_vars_get_sign(bset, first, n, signs);11662}11663 11664/* Is it possible for the integer division "div" to depend (possibly11665 * indirectly) on any output dimensions?11666 *11667 * If the div is undefined, then we conservatively assume that it11668 * may depend on them.11669 * Otherwise, we check if it actually depends on them or on any integer11670 * divisions that may depend on them.11671 */11672static isl_bool div_may_involve_output(__isl_keep isl_basic_map *bmap, int div)11673{11674 int i;11675 isl_size n_out, n_div;11676 unsigned o_out, o_div;11677 11678 if (isl_int_is_zero(bmap->div[div][0]))11679 return isl_bool_true;11680 11681 n_out = isl_basic_map_dim(bmap, isl_dim_out);11682 if (n_out < 0)11683 return isl_bool_error;11684 o_out = isl_basic_map_offset(bmap, isl_dim_out);11685 11686 if (isl_seq_first_non_zero(bmap->div[div] + 1 + o_out, n_out) != -1)11687 return isl_bool_true;11688 11689 n_div = isl_basic_map_dim(bmap, isl_dim_div);11690 if (n_div < 0)11691 return isl_bool_error;11692 o_div = isl_basic_map_offset(bmap, isl_dim_div);11693 11694 for (i = 0; i < n_div; ++i) {11695 isl_bool may_involve;11696 11697 if (isl_int_is_zero(bmap->div[div][1 + o_div + i]))11698 continue;11699 may_involve = div_may_involve_output(bmap, i);11700 if (may_involve < 0 || may_involve)11701 return may_involve;11702 }11703 11704 return isl_bool_false;11705}11706 11707/* Return the first integer division of "bmap" in the range11708 * [first, first + n[ that may depend on any output dimensions and11709 * that has a non-zero coefficient in "c" (where the first coefficient11710 * in "c" corresponds to integer division "first").11711 */11712static int first_div_may_involve_output(__isl_keep isl_basic_map *bmap,11713 isl_int *c, int first, int n)11714{11715 int k;11716 11717 if (!bmap)11718 return -1;11719 11720 for (k = first; k < first + n; ++k) {11721 isl_bool may_involve;11722 11723 if (isl_int_is_zero(c[k]))11724 continue;11725 may_involve = div_may_involve_output(bmap, k);11726 if (may_involve < 0)11727 return -1;11728 if (may_involve)11729 return k;11730 }11731 11732 return first + n;11733}11734 11735/* Look for a pair of inequality constraints in "bmap" of the form11736 *11737 * -l + i >= 0 or i >= l11738 * and11739 * n + l - i >= 0 or i <= l + n11740 *11741 * with n < "m" and i the output dimension at position "pos".11742 * (Note that n >= 0 as otherwise the two constraints would conflict.)11743 * Furthermore, "l" is only allowed to involve parameters, input dimensions11744 * and earlier output dimensions, as well as integer divisions that do11745 * not involve any of the output dimensions.11746 *11747 * Return the index of the first inequality constraint or bmap->n_ineq11748 * if no such pair can be found.11749 */11750static int find_modulo_constraint_pair(__isl_keep isl_basic_map *bmap,11751 int pos, isl_int m)11752{11753 int i, j;11754 isl_ctx *ctx;11755 isl_size total;11756 isl_size n_div, n_out;11757 unsigned o_div, o_out;11758 int less;11759 11760 total = isl_basic_map_dim(bmap, isl_dim_all);11761 n_out = isl_basic_map_dim(bmap, isl_dim_out);11762 n_div = isl_basic_map_dim(bmap, isl_dim_div);11763 if (total < 0 || n_out < 0 || n_div < 0)11764 return -1;11765 11766 ctx = isl_basic_map_get_ctx(bmap);11767 o_out = isl_basic_map_offset(bmap, isl_dim_out);11768 o_div = isl_basic_map_offset(bmap, isl_dim_div);11769 for (i = 0; i < bmap->n_ineq; ++i) {11770 if (!isl_int_abs_eq(bmap->ineq[i][o_out + pos], ctx->one))11771 continue;11772 if (isl_seq_first_non_zero(bmap->ineq[i] + o_out + pos + 1,11773 n_out - (pos + 1)) != -1)11774 continue;11775 if (first_div_may_involve_output(bmap, bmap->ineq[i] + o_div,11776 0, n_div) < n_div)11777 continue;11778 for (j = i + 1; j < bmap->n_ineq; ++j) {11779 if (!isl_int_abs_eq(bmap->ineq[j][o_out + pos],11780 ctx->one))11781 continue;11782 if (!isl_seq_is_neg(bmap->ineq[i] + 1,11783 bmap->ineq[j] + 1, total))11784 continue;11785 break;11786 }11787 if (j >= bmap->n_ineq)11788 continue;11789 isl_int_add(bmap->ineq[i][0],11790 bmap->ineq[i][0], bmap->ineq[j][0]);11791 less = isl_int_abs_lt(bmap->ineq[i][0], m);11792 isl_int_sub(bmap->ineq[i][0],11793 bmap->ineq[i][0], bmap->ineq[j][0]);11794 if (!less)11795 continue;11796 if (isl_int_is_one(bmap->ineq[i][o_out + pos]))11797 return i;11798 else11799 return j;11800 }11801 11802 return bmap->n_ineq;11803}11804 11805/* Return the index of the equality of "bmap" that defines11806 * the output dimension "pos" in terms of earlier dimensions.11807 * The equality may also involve integer divisions, as long11808 * as those integer divisions are defined in terms of11809 * parameters or input dimensions.11810 * In this case, *div is set to the number of integer divisions and11811 * *ineq is set to the number of inequality constraints (provided11812 * div and ineq are not NULL).11813 *11814 * The equality may also involve a single integer division involving11815 * the output dimensions (typically only output dimension "pos") as11816 * long as the coefficient of output dimension "pos" is 1 or -1 and11817 * there is a pair of constraints i >= l and i <= l + n, with i referring11818 * to output dimension "pos", l an expression involving only earlier11819 * dimensions and n smaller than the coefficient of the integer division11820 * in the equality. In this case, the output dimension can be defined11821 * in terms of a modulo expression that does not involve the integer division.11822 * *div is then set to this single integer division and11823 * *ineq is set to the index of constraint i >= l.11824 *11825 * Return bmap->n_eq if there is no such equality.11826 * Return -1 on error.11827 */11828int isl_basic_map_output_defining_equality(__isl_keep isl_basic_map *bmap,11829 int pos, int *div, int *ineq)11830{11831 int j, k, l;11832 isl_size n_div, n_out;11833 unsigned o_div, o_out;11834 11835 n_out = isl_basic_map_dim(bmap, isl_dim_out);11836 n_div = isl_basic_map_dim(bmap, isl_dim_div);11837 if (n_out < 0 || n_div < 0)11838 return -1;11839 11840 o_out = isl_basic_map_offset(bmap, isl_dim_out);11841 o_div = isl_basic_map_offset(bmap, isl_dim_div);11842 11843 if (ineq)11844 *ineq = bmap->n_ineq;11845 if (div)11846 *div = n_div;11847 for (j = 0; j < bmap->n_eq; ++j) {11848 if (isl_int_is_zero(bmap->eq[j][o_out + pos]))11849 continue;11850 if (isl_seq_first_non_zero(bmap->eq[j] + o_out + pos + 1,11851 n_out - (pos + 1)) != -1)11852 continue;11853 k = first_div_may_involve_output(bmap, bmap->eq[j] + o_div,11854 0, n_div);11855 if (k >= n_div)11856 return j;11857 if (!isl_int_is_one(bmap->eq[j][o_out + pos]) &&11858 !isl_int_is_negone(bmap->eq[j][o_out + pos]))11859 continue;11860 if (first_div_may_involve_output(bmap, bmap->eq[j] + o_div,11861 k + 1, n_div - (k+1)) < n_div)11862 continue;11863 l = find_modulo_constraint_pair(bmap, pos,11864 bmap->eq[j][o_div + k]);11865 if (l < 0)11866 return -1;11867 if (l >= bmap->n_ineq)11868 continue;11869 if (div)11870 *div = k;11871 if (ineq)11872 *ineq = l;11873 return j;11874 }11875 11876 return bmap->n_eq;11877}11878 11879/* Check if the given basic map is obviously single-valued.11880 * In particular, for each output dimension, check that there is11881 * an equality that defines the output dimension in terms of11882 * earlier dimensions.11883 */11884isl_bool isl_basic_map_plain_is_single_valued(__isl_keep isl_basic_map *bmap)11885{11886 int i;11887 isl_size n_out;11888 11889 n_out = isl_basic_map_dim(bmap, isl_dim_out);11890 if (n_out < 0)11891 return isl_bool_error;11892 11893 for (i = 0; i < n_out; ++i) {11894 int eq;11895 11896 eq = isl_basic_map_output_defining_equality(bmap, i,11897 NULL, NULL);11898 if (eq < 0)11899 return isl_bool_error;11900 if (eq >= bmap->n_eq)11901 return isl_bool_false;11902 }11903 11904 return isl_bool_true;11905}11906 11907/* Check if the given basic map is single-valued.11908 * We simply compute11909 *11910 * M \circ M^-111911 *11912 * and check if the result is a subset of the identity mapping.11913 */11914isl_bool isl_basic_map_is_single_valued(__isl_keep isl_basic_map *bmap)11915{11916 isl_space *space;11917 isl_basic_map *test;11918 isl_basic_map *id;11919 isl_bool sv;11920 11921 sv = isl_basic_map_plain_is_single_valued(bmap);11922 if (sv < 0 || sv)11923 return sv;11924 11925 test = isl_basic_map_reverse(isl_basic_map_copy(bmap));11926 test = isl_basic_map_apply_range(test, isl_basic_map_copy(bmap));11927 11928 space = isl_basic_map_get_space(bmap);11929 space = isl_space_map_from_set(isl_space_range(space));11930 id = isl_basic_map_identity(space);11931 11932 sv = isl_basic_map_is_subset(test, id);11933 11934 isl_basic_map_free(test);11935 isl_basic_map_free(id);11936 11937 return sv;11938}11939 11940/* Check if the given map is obviously single-valued.11941 */11942isl_bool isl_map_plain_is_single_valued(__isl_keep isl_map *map)11943{11944 if (!map)11945 return isl_bool_error;11946 if (map->n == 0)11947 return isl_bool_true;11948 if (map->n >= 2)11949 return isl_bool_false;11950 11951 return isl_basic_map_plain_is_single_valued(map->p[0]);11952}11953 11954/* Check if the given map is single-valued.11955 * We simply compute11956 *11957 * M \circ M^-111958 *11959 * and check if the result is a subset of the identity mapping.11960 */11961isl_bool isl_map_is_single_valued(__isl_keep isl_map *map)11962{11963 isl_space *space;11964 isl_map *test;11965 isl_map *id;11966 isl_bool sv;11967 11968 sv = isl_map_plain_is_single_valued(map);11969 if (sv < 0 || sv)11970 return sv;11971 11972 test = isl_map_reverse(isl_map_copy(map));11973 test = isl_map_apply_range(test, isl_map_copy(map));11974 11975 space = isl_space_map_from_set(isl_space_range(isl_map_get_space(map)));11976 id = isl_map_identity(space);11977 11978 sv = isl_map_is_subset(test, id);11979 11980 isl_map_free(test);11981 isl_map_free(id);11982 11983 return sv;11984}11985 11986isl_bool isl_map_is_injective(__isl_keep isl_map *map)11987{11988 isl_bool in;11989 11990 map = isl_map_copy(map);11991 map = isl_map_reverse(map);11992 in = isl_map_is_single_valued(map);11993 isl_map_free(map);11994 11995 return in;11996}11997 11998/* Check if the given map is obviously injective.11999 */12000isl_bool isl_map_plain_is_injective(__isl_keep isl_map *map)12001{12002 isl_bool in;12003 12004 map = isl_map_copy(map);12005 map = isl_map_reverse(map);12006 in = isl_map_plain_is_single_valued(map);12007 isl_map_free(map);12008 12009 return in;12010}12011 12012isl_bool isl_map_is_bijective(__isl_keep isl_map *map)12013{12014 isl_bool sv;12015 12016 sv = isl_map_is_single_valued(map);12017 if (sv < 0 || !sv)12018 return sv;12019 12020 return isl_map_is_injective(map);12021}12022 12023isl_bool isl_set_is_singleton(__isl_keep isl_set *set)12024{12025 return isl_map_is_single_valued(set_to_map(set));12026}12027 12028/* Does "map" only map elements to themselves?12029 *12030 * If the domain and range spaces are different, then "map"12031 * is considered not to be an identity relation, even if it is empty.12032 * Otherwise, construct the maximal identity relation and12033 * check whether "map" is a subset of this relation.12034 */12035isl_bool isl_map_is_identity(__isl_keep isl_map *map)12036{12037 isl_map *id;12038 isl_bool equal, is_identity;12039 12040 equal = isl_map_tuple_is_equal(map, isl_dim_in, map, isl_dim_out);12041 if (equal < 0 || !equal)12042 return equal;12043 12044 id = isl_map_identity(isl_map_get_space(map));12045 is_identity = isl_map_is_subset(map, id);12046 isl_map_free(id);12047 12048 return is_identity;12049}12050 12051int isl_map_is_translation(__isl_keep isl_map *map)12052{12053 int ok;12054 isl_set *delta;12055 12056 delta = isl_map_deltas(isl_map_copy(map));12057 ok = isl_set_is_singleton(delta);12058 isl_set_free(delta);12059 12060 return ok;12061}12062 12063static int unique(isl_int *p, unsigned pos, unsigned len)12064{12065 if (isl_seq_first_non_zero(p, pos) != -1)12066 return 0;12067 if (isl_seq_first_non_zero(p + pos + 1, len - pos - 1) != -1)12068 return 0;12069 return 1;12070}12071 12072isl_bool isl_basic_set_is_box(__isl_keep isl_basic_set *bset)12073{12074 int i, j;12075 isl_size nvar, n_div;12076 unsigned ovar;12077 12078 n_div = isl_basic_set_dim(bset, isl_dim_div);12079 if (n_div < 0)12080 return isl_bool_error;12081 if (n_div != 0)12082 return isl_bool_false;12083 12084 nvar = isl_basic_set_dim(bset, isl_dim_set);12085 if (nvar < 0)12086 return isl_bool_error;12087 ovar = isl_space_offset(bset->dim, isl_dim_set);12088 for (j = 0; j < nvar; ++j) {12089 int lower = 0, upper = 0;12090 for (i = 0; i < bset->n_eq; ++i) {12091 if (isl_int_is_zero(bset->eq[i][1 + ovar + j]))12092 continue;12093 if (!unique(bset->eq[i] + 1 + ovar, j, nvar))12094 return isl_bool_false;12095 break;12096 }12097 if (i < bset->n_eq)12098 continue;12099 for (i = 0; i < bset->n_ineq; ++i) {12100 if (isl_int_is_zero(bset->ineq[i][1 + ovar + j]))12101 continue;12102 if (!unique(bset->ineq[i] + 1 + ovar, j, nvar))12103 return isl_bool_false;12104 if (isl_int_is_pos(bset->ineq[i][1 + ovar + j]))12105 lower = 1;12106 else12107 upper = 1;12108 }12109 if (!lower || !upper)12110 return isl_bool_false;12111 }12112 12113 return isl_bool_true;12114}12115 12116isl_bool isl_set_is_box(__isl_keep isl_set *set)12117{12118 if (!set)12119 return isl_bool_error;12120 if (set->n != 1)12121 return isl_bool_false;12122 12123 return isl_basic_set_is_box(set->p[0]);12124}12125 12126isl_bool isl_basic_set_is_wrapping(__isl_keep isl_basic_set *bset)12127{12128 if (!bset)12129 return isl_bool_error;12130 12131 return isl_space_is_wrapping(bset->dim);12132}12133 12134isl_bool isl_set_is_wrapping(__isl_keep isl_set *set)12135{12136 if (!set)12137 return isl_bool_error;12138 12139 return isl_space_is_wrapping(set->dim);12140}12141 12142/* Modify the space of "map" through a call to "change".12143 * If "can_change" is set (not NULL), then first call it to check12144 * if the modification is allowed, printing the error message "cannot_change"12145 * if it is not.12146 */12147static __isl_give isl_map *isl_map_change_space(__isl_take isl_map *map,12148 isl_bool (*can_change)(__isl_keep isl_map *map),12149 const char *cannot_change,12150 __isl_give isl_space *(*change)(__isl_take isl_space *space))12151{12152 isl_bool ok;12153 isl_space *space;12154 12155 if (!map)12156 return NULL;12157 12158 ok = can_change ? can_change(map) : isl_bool_true;12159 if (ok < 0)12160 return isl_map_free(map);12161 if (!ok)12162 isl_die(isl_map_get_ctx(map), isl_error_invalid, cannot_change,12163 return isl_map_free(map));12164 12165 space = change(isl_map_get_space(map));12166 map = isl_map_reset_space(map, space);12167 12168 return map;12169}12170 12171/* Is the domain of "map" a wrapped relation?12172 */12173isl_bool isl_map_domain_is_wrapping(__isl_keep isl_map *map)12174{12175 if (!map)12176 return isl_bool_error;12177 12178 return isl_space_domain_is_wrapping(map->dim);12179}12180 12181/* Does "map" have a wrapped relation in both domain and range?12182 */12183isl_bool isl_map_is_product(__isl_keep isl_map *map)12184{12185 return isl_space_is_product(isl_map_peek_space(map));12186}12187 12188/* Is the range of "map" a wrapped relation?12189 */12190isl_bool isl_map_range_is_wrapping(__isl_keep isl_map *map)12191{12192 if (!map)12193 return isl_bool_error;12194 12195 return isl_space_range_is_wrapping(map->dim);12196}12197 12198__isl_give isl_basic_set *isl_basic_map_wrap(__isl_take isl_basic_map *bmap)12199{12200 isl_space *space;12201 12202 space = isl_basic_map_take_space(bmap);12203 space = isl_space_wrap(space);12204 bmap = isl_basic_map_restore_space(bmap, space);12205 12206 bmap = isl_basic_map_finalize(bmap);12207 12208 return bset_from_bmap(bmap);12209}12210 12211/* Given a map A -> B, return the set (A -> B).12212 */12213__isl_give isl_set *isl_map_wrap(__isl_take isl_map *map)12214{12215 return isl_map_change_space(map, NULL, NULL, &isl_space_wrap);12216}12217 12218__isl_give isl_basic_map *isl_basic_set_unwrap(__isl_take isl_basic_set *bset)12219{12220 bset = isl_basic_set_cow(bset);12221 if (!bset)12222 return NULL;12223 12224 bset->dim = isl_space_unwrap(bset->dim);12225 if (!bset->dim)12226 goto error;12227 12228 bset = isl_basic_set_finalize(bset);12229 12230 return bset_to_bmap(bset);12231error:12232 isl_basic_set_free(bset);12233 return NULL;12234}12235 12236/* Given a set (A -> B), return the map A -> B.12237 * Error out if "set" is not of the form (A -> B).12238 */12239__isl_give isl_map *isl_set_unwrap(__isl_take isl_set *set)12240{12241 return isl_map_change_space(set, &isl_set_is_wrapping,12242 "not a wrapping set", &isl_space_unwrap);12243}12244 12245__isl_give isl_basic_map *isl_basic_map_reset(__isl_take isl_basic_map *bmap,12246 enum isl_dim_type type)12247{12248 isl_space *space;12249 12250 space = isl_basic_map_take_space(bmap);12251 space = isl_space_reset(space, type);12252 bmap = isl_basic_map_restore_space(bmap, space);12253 12254 bmap = isl_basic_map_mark_final(bmap);12255 12256 return bmap;12257}12258 12259__isl_give isl_map *isl_map_reset(__isl_take isl_map *map,12260 enum isl_dim_type type)12261{12262 int i;12263 isl_space *space;12264 12265 if (!map)12266 return NULL;12267 12268 if (!isl_space_is_named_or_nested(map->dim, type))12269 return map;12270 12271 map = isl_map_cow(map);12272 if (!map)12273 return NULL;12274 12275 for (i = 0; i < map->n; ++i) {12276 map->p[i] = isl_basic_map_reset(map->p[i], type);12277 if (!map->p[i])12278 goto error;12279 }12280 12281 space = isl_map_take_space(map);12282 space = isl_space_reset(space, type);12283 map = isl_map_restore_space(map, space);12284 12285 return map;12286error:12287 isl_map_free(map);12288 return NULL;12289}12290 12291__isl_give isl_basic_map *isl_basic_map_flatten(__isl_take isl_basic_map *bmap)12292{12293 isl_space *space;12294 12295 space = isl_basic_map_take_space(bmap);12296 space = isl_space_flatten(space);12297 bmap = isl_basic_map_restore_space(bmap, space);12298 12299 bmap = isl_basic_map_mark_final(bmap);12300 12301 return bmap;12302}12303 12304__isl_give isl_basic_set *isl_basic_set_flatten(__isl_take isl_basic_set *bset)12305{12306 return bset_from_bmap(isl_basic_map_flatten(bset_to_bmap(bset)));12307}12308 12309__isl_give isl_basic_map *isl_basic_map_flatten_domain(12310 __isl_take isl_basic_map *bmap)12311{12312 isl_space *space;12313 12314 space = isl_basic_map_take_space(bmap);12315 space = isl_space_flatten_domain(space);12316 bmap = isl_basic_map_restore_space(bmap, space);12317 12318 bmap = isl_basic_map_mark_final(bmap);12319 12320 return bmap;12321}12322 12323__isl_give isl_basic_map *isl_basic_map_flatten_range(12324 __isl_take isl_basic_map *bmap)12325{12326 isl_space *space;12327 12328 space = isl_basic_map_take_space(bmap);12329 space = isl_space_flatten_range(space);12330 bmap = isl_basic_map_restore_space(bmap, space);12331 12332 bmap = isl_basic_map_mark_final(bmap);12333 12334 return bmap;12335}12336 12337/* Remove any internal structure from the spaces of domain and range of "map".12338 */12339__isl_give isl_map *isl_map_flatten(__isl_take isl_map *map)12340{12341 if (!map)12342 return NULL;12343 12344 if (!map->dim->nested[0] && !map->dim->nested[1])12345 return map;12346 12347 return isl_map_change_space(map, NULL, NULL, &isl_space_flatten);12348}12349 12350__isl_give isl_set *isl_set_flatten(__isl_take isl_set *set)12351{12352 return set_from_map(isl_map_flatten(set_to_map(set)));12353}12354 12355__isl_give isl_map *isl_set_flatten_map(__isl_take isl_set *set)12356{12357 isl_space *space, *flat_space;12358 isl_map *map;12359 12360 space = isl_set_get_space(set);12361 flat_space = isl_space_flatten(isl_space_copy(space));12362 map = isl_map_identity(isl_space_join(isl_space_reverse(space),12363 flat_space));12364 map = isl_map_intersect_domain(map, set);12365 12366 return map;12367}12368 12369/* Remove any internal structure from the space of the domain of "map".12370 */12371__isl_give isl_map *isl_map_flatten_domain(__isl_take isl_map *map)12372{12373 if (!map)12374 return NULL;12375 12376 if (!map->dim->nested[0])12377 return map;12378 12379 return isl_map_change_space(map, NULL, NULL, &isl_space_flatten_domain);12380}12381 12382/* Remove any internal structure from the space of the range of "map".12383 */12384__isl_give isl_map *isl_map_flatten_range(__isl_take isl_map *map)12385{12386 if (!map)12387 return NULL;12388 12389 if (!map->dim->nested[1])12390 return map;12391 12392 return isl_map_change_space(map, NULL, NULL, &isl_space_flatten_range);12393}12394 12395/* Reorder the dimensions of "bmap" according to the given dim_map12396 * and set the dimension specification to "space" and12397 * perform Gaussian elimination on the result.12398 */12399__isl_give isl_basic_map *isl_basic_map_realign(__isl_take isl_basic_map *bmap,12400 __isl_take isl_space *space, __isl_take struct isl_dim_map *dim_map)12401{12402 isl_basic_map *res;12403 unsigned flags;12404 isl_size n_div;12405 12406 n_div = isl_basic_map_dim(bmap, isl_dim_div);12407 if (n_div < 0 || !space || !dim_map)12408 goto error;12409 12410 flags = bmap->flags;12411 ISL_FL_CLR(flags, ISL_BASIC_MAP_FINAL);12412 ISL_FL_CLR(flags, ISL_BASIC_MAP_SORTED);12413 ISL_FL_CLR(flags, ISL_BASIC_MAP_NORMALIZED_DIVS);12414 res = isl_basic_map_alloc_space(space, n_div, bmap->n_eq, bmap->n_ineq);12415 res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);12416 if (res)12417 res->flags = flags;12418 res = isl_basic_map_gauss(res, NULL);12419 res = isl_basic_map_finalize(res);12420 return res;12421error:12422 isl_dim_map_free(dim_map);12423 isl_basic_map_free(bmap);12424 isl_space_free(space);12425 return NULL;12426}12427 12428/* Reorder the dimensions of "map" according to given reordering.12429 */12430__isl_give isl_map *isl_map_realign(__isl_take isl_map *map,12431 __isl_take isl_reordering *r)12432{12433 int i;12434 struct isl_dim_map *dim_map;12435 12436 map = isl_map_cow(map);12437 dim_map = isl_dim_map_from_reordering(r);12438 if (!map || !r || !dim_map)12439 goto error;12440 12441 for (i = 0; i < map->n; ++i) {12442 struct isl_dim_map *dim_map_i;12443 isl_space *space;12444 12445 dim_map_i = isl_dim_map_extend(dim_map, map->p[i]);12446 12447 space = isl_reordering_get_space(r);12448 map->p[i] = isl_basic_map_realign(map->p[i], space, dim_map_i);12449 12450 if (!map->p[i])12451 goto error;12452 }12453 12454 map = isl_map_reset_space(map, isl_reordering_get_space(r));12455 map = isl_map_unmark_normalized(map);12456 12457 isl_reordering_free(r);12458 isl_dim_map_free(dim_map);12459 return map;12460error:12461 isl_dim_map_free(dim_map);12462 isl_map_free(map);12463 isl_reordering_free(r);12464 return NULL;12465}12466 12467__isl_give isl_set *isl_set_realign(__isl_take isl_set *set,12468 __isl_take isl_reordering *r)12469{12470 return set_from_map(isl_map_realign(set_to_map(set), r));12471}12472 12473__isl_give isl_map *isl_map_align_params(__isl_take isl_map *map,12474 __isl_take isl_space *model)12475{12476 isl_ctx *ctx;12477 isl_bool aligned;12478 12479 if (!map || !model)12480 goto error;12481 12482 ctx = isl_space_get_ctx(model);12483 if (!isl_space_has_named_params(model))12484 isl_die(ctx, isl_error_invalid,12485 "model has unnamed parameters", goto error);12486 if (isl_map_check_named_params(map) < 0)12487 goto error;12488 aligned = isl_map_space_has_equal_params(map, model);12489 if (aligned < 0)12490 goto error;12491 if (!aligned) {12492 isl_space *space;12493 isl_reordering *exp;12494 12495 space = isl_map_peek_space(map);12496 exp = isl_parameter_alignment_reordering(space, model);12497 map = isl_map_realign(map, exp);12498 }12499 12500 isl_space_free(model);12501 return map;12502error:12503 isl_space_free(model);12504 isl_map_free(map);12505 return NULL;12506}12507 12508__isl_give isl_set *isl_set_align_params(__isl_take isl_set *set,12509 __isl_take isl_space *model)12510{12511 return isl_map_align_params(set, model);12512}12513 12514/* Align the parameters of "bmap" to those of "model", introducing12515 * additional parameters if needed.12516 */12517__isl_give isl_basic_map *isl_basic_map_align_params(12518 __isl_take isl_basic_map *bmap, __isl_take isl_space *model)12519{12520 isl_ctx *ctx;12521 isl_bool equal_params;12522 isl_space *bmap_space;12523 12524 if (!bmap || !model)12525 goto error;12526 12527 ctx = isl_space_get_ctx(model);12528 if (!isl_space_has_named_params(model))12529 isl_die(ctx, isl_error_invalid,12530 "model has unnamed parameters", goto error);12531 if (isl_basic_map_check_named_params(bmap) < 0)12532 goto error;12533 bmap_space = isl_basic_map_peek_space(bmap);12534 equal_params = isl_space_has_equal_params(bmap_space, model);12535 if (equal_params < 0)12536 goto error;12537 if (!equal_params) {12538 isl_reordering *exp;12539 struct isl_dim_map *dim_map;12540 12541 exp = isl_parameter_alignment_reordering(bmap_space, model);12542 dim_map = isl_dim_map_from_reordering(exp);12543 bmap = isl_basic_map_realign(bmap,12544 isl_reordering_get_space(exp),12545 isl_dim_map_extend(dim_map, bmap));12546 isl_reordering_free(exp);12547 isl_dim_map_free(dim_map);12548 }12549 12550 isl_space_free(model);12551 return bmap;12552error:12553 isl_space_free(model);12554 isl_basic_map_free(bmap);12555 return NULL;12556}12557 12558/* Do "bset" and "space" have the same parameters?12559 */12560isl_bool isl_basic_set_space_has_equal_params(__isl_keep isl_basic_set *bset,12561 __isl_keep isl_space *space)12562{12563 isl_space *bset_space;12564 12565 bset_space = isl_basic_set_peek_space(bset);12566 return isl_space_has_equal_params(bset_space, space);12567}12568 12569/* Do "map" and "space" have the same parameters?12570 */12571isl_bool isl_map_space_has_equal_params(__isl_keep isl_map *map,12572 __isl_keep isl_space *space)12573{12574 isl_space *map_space;12575 12576 map_space = isl_map_peek_space(map);12577 return isl_space_has_equal_params(map_space, space);12578}12579 12580/* Do "set" and "space" have the same parameters?12581 */12582isl_bool isl_set_space_has_equal_params(__isl_keep isl_set *set,12583 __isl_keep isl_space *space)12584{12585 return isl_map_space_has_equal_params(set_to_map(set), space);12586}12587 12588/* Align the parameters of "bset" to those of "model", introducing12589 * additional parameters if needed.12590 */12591__isl_give isl_basic_set *isl_basic_set_align_params(12592 __isl_take isl_basic_set *bset, __isl_take isl_space *model)12593{12594 return isl_basic_map_align_params(bset, model);12595}12596 12597/* Drop all parameters not referenced by "map".12598 */12599__isl_give isl_map *isl_map_drop_unused_params(__isl_take isl_map *map)12600{12601 int i;12602 isl_size n;12603 12604 n = isl_map_dim(map, isl_dim_param);12605 if (isl_map_check_named_params(map) < 0 || n < 0)12606 return isl_map_free(map);12607 12608 for (i = n - 1; i >= 0; i--) {12609 isl_bool involves;12610 12611 involves = isl_map_involves_dims(map, isl_dim_param, i, 1);12612 if (involves < 0)12613 return isl_map_free(map);12614 if (!involves)12615 map = isl_map_project_out(map, isl_dim_param, i, 1);12616 }12617 12618 return map;12619}12620 12621/* Drop all parameters not referenced by "set".12622 */12623__isl_give isl_set *isl_set_drop_unused_params(12624 __isl_take isl_set *set)12625{12626 return set_from_map(isl_map_drop_unused_params(set_to_map(set)));12627}12628 12629/* Drop all parameters not referenced by "bmap".12630 */12631__isl_give isl_basic_map *isl_basic_map_drop_unused_params(12632 __isl_take isl_basic_map *bmap)12633{12634 isl_size nparam;12635 int i;12636 12637 nparam = isl_basic_map_dim(bmap, isl_dim_param);12638 if (nparam < 0 || isl_basic_map_check_named_params(bmap) < 0)12639 return isl_basic_map_free(bmap);12640 12641 for (i = nparam - 1; i >= 0; i--) {12642 isl_bool involves;12643 12644 involves = isl_basic_map_involves_dims(bmap,12645 isl_dim_param, i, 1);12646 if (involves < 0)12647 return isl_basic_map_free(bmap);12648 if (!involves)12649 bmap = isl_basic_map_drop(bmap, isl_dim_param, i, 1);12650 }12651 12652 return bmap;12653}12654 12655/* Drop all parameters not referenced by "bset".12656 */12657__isl_give isl_basic_set *isl_basic_set_drop_unused_params(12658 __isl_take isl_basic_set *bset)12659{12660 return bset_from_bmap(isl_basic_map_drop_unused_params(12661 bset_to_bmap(bset)));12662}12663 12664/* Given a tuple of identifiers "tuple" in a space that corresponds12665 * to that of "set", if any of those identifiers appear as parameters12666 * in "set", then equate those parameters with the corresponding12667 * set dimensions and project out the parameters.12668 * The result therefore has no such parameters.12669 */12670static __isl_give isl_set *equate_params(__isl_take isl_set *set,12671 __isl_keep isl_multi_id *tuple)12672{12673 int i;12674 isl_size n;12675 isl_space *set_space, *tuple_space;12676 12677 set_space = isl_set_peek_space(set);12678 tuple_space = isl_multi_id_peek_space(tuple);12679 if (isl_space_check_equal_tuples(tuple_space, set_space) < 0)12680 return isl_set_free(set);12681 n = isl_multi_id_size(tuple);12682 if (n < 0)12683 return isl_set_free(set);12684 for (i = 0; i < n; ++i) {12685 isl_id *id;12686 int pos;12687 12688 id = isl_multi_id_get_at(tuple, i);12689 if (!id)12690 return isl_set_free(set);12691 pos = isl_set_find_dim_by_id(set, isl_dim_param, id);12692 isl_id_free(id);12693 if (pos < 0)12694 continue;12695 set = isl_set_equate(set, isl_dim_param, pos, isl_dim_set, i);12696 set = isl_set_project_out(set, isl_dim_param, pos, 1);12697 }12698 return set;12699}12700 12701/* Bind the set dimensions of "set" to parameters with identifiers12702 * specified by "tuple", living in the same space as "set".12703 *12704 * If no parameters with these identifiers appear in "set" already,12705 * then the set dimensions are simply reinterpreted as parameters.12706 * Otherwise, the parameters are first equated to the corresponding12707 * set dimensions.12708 */12709__isl_give isl_set *isl_set_bind(__isl_take isl_set *set,12710 __isl_take isl_multi_id *tuple)12711{12712 isl_space *space;12713 12714 set = equate_params(set, tuple);12715 space = isl_set_get_space(set);12716 space = isl_space_bind_set(space, tuple);12717 isl_multi_id_free(tuple);12718 set = isl_set_reset_space(set, space);12719 12720 return set;12721}12722 12723/* Given a tuple of identifiers "tuple" in a space that corresponds12724 * to the domain of "map", if any of those identifiers appear as parameters12725 * in "map", then equate those parameters with the corresponding12726 * input dimensions and project out the parameters.12727 * The result therefore has no such parameters.12728 */12729static __isl_give isl_map *map_equate_params(__isl_take isl_map *map,12730 __isl_keep isl_multi_id *tuple)12731{12732 int i;12733 isl_size n;12734 isl_space *map_space, *tuple_space;12735 12736 map_space = isl_map_peek_space(map);12737 tuple_space = isl_multi_id_peek_space(tuple);12738 if (isl_space_check_domain_tuples(tuple_space, map_space) < 0)12739 return isl_map_free(map);12740 n = isl_multi_id_size(tuple);12741 if (n < 0)12742 return isl_map_free(map);12743 for (i = 0; i < n; ++i) {12744 isl_id *id;12745 int pos;12746 12747 id = isl_multi_id_get_at(tuple, i);12748 if (!id)12749 return isl_map_free(map);12750 pos = isl_map_find_dim_by_id(map, isl_dim_param, id);12751 isl_id_free(id);12752 if (pos < 0)12753 continue;12754 map = isl_map_equate(map, isl_dim_param, pos, isl_dim_in, i);12755 map = isl_map_project_out(map, isl_dim_param, pos, 1);12756 }12757 return map;12758}12759 12760/* Bind the input dimensions of "map" to parameters with identifiers12761 * specified by "tuple", living in the domain space of "map".12762 *12763 * If no parameters with these identifiers appear in "map" already,12764 * then the input dimensions are simply reinterpreted as parameters.12765 * Otherwise, the parameters are first equated to the corresponding12766 * input dimensions.12767 */12768__isl_give isl_set *isl_map_bind_domain(__isl_take isl_map *map,12769 __isl_take isl_multi_id *tuple)12770{12771 isl_space *space;12772 isl_set *set;12773 12774 map = map_equate_params(map, tuple);12775 space = isl_map_get_space(map);12776 space = isl_space_bind_map_domain(space, tuple);12777 isl_multi_id_free(tuple);12778 set = set_from_map(isl_map_reset_space(map, space));12779 12780 return set;12781}12782 12783/* Bind the output dimensions of "map" to parameters with identifiers12784 * specified by "tuple", living in the range space of "map".12785 *12786 * Since binding is more easily implemented on the domain,12787 * bind the input dimensions of the inverse of "map".12788 */12789__isl_give isl_set *isl_map_bind_range(__isl_take isl_map *map,12790 __isl_take isl_multi_id *tuple)12791{12792 return isl_map_bind_domain(isl_map_reverse(map), tuple);12793}12794 12795/* Insert a domain corresponding to "tuple"12796 * into the nullary or unary relation "set".12797 * The result has an extra initial tuple and is therefore12798 * either a unary or binary relation.12799 * Any parameters with identifiers in "tuple" are reinterpreted12800 * as the corresponding domain dimensions.12801 */12802static __isl_give isl_map *unbind_params_insert_domain(12803 __isl_take isl_set *set, __isl_take isl_multi_id *tuple)12804{12805 isl_space *space;12806 isl_reordering *r;12807 12808 space = isl_set_peek_space(set);12809 r = isl_reordering_unbind_params_insert_domain(space, tuple);12810 isl_multi_id_free(tuple);12811 12812 return isl_map_realign(set_to_map(set), r);12813}12814 12815/* Construct a set with "tuple" as domain from the parameter domain "set".12816 * Any parameters with identifiers in "tuple" are reinterpreted12817 * as the corresponding set dimensions.12818 */12819__isl_give isl_set *isl_set_unbind_params(__isl_take isl_set *set,12820 __isl_take isl_multi_id *tuple)12821{12822 isl_bool is_params;12823 12824 is_params = isl_set_is_params(set);12825 if (is_params < 0)12826 set = isl_set_free(set);12827 else if (!is_params)12828 isl_die(isl_set_get_ctx(set), isl_error_invalid,12829 "expecting parameter domain", set = isl_set_free(set));12830 return set_from_map(unbind_params_insert_domain(set, tuple));12831}12832 12833/* Check that "set" is a proper set, i.e., that it is not a parameter domain.12834 */12835static isl_stat isl_set_check_is_set(__isl_keep isl_set *set)12836{12837 isl_bool is_params;12838 12839 is_params = isl_set_is_params(set);12840 if (is_params < 0)12841 return isl_stat_error;12842 else if (is_params)12843 isl_die(isl_set_get_ctx(set), isl_error_invalid,12844 "expecting proper set", return isl_stat_error);12845 12846 return isl_stat_ok;12847}12848 12849/* Construct a map with "domain" as domain and "set" as range.12850 * Any parameters with identifiers in "domain" are reinterpreted12851 * as the corresponding domain dimensions.12852 */12853__isl_give isl_map *isl_set_unbind_params_insert_domain(12854 __isl_take isl_set *set, __isl_take isl_multi_id *domain)12855{12856 if (isl_set_check_is_set(set) < 0)12857 set = isl_set_free(set);12858 return unbind_params_insert_domain(set, domain);12859}12860 12861/* Construct a map with "domain" as domain and "set" as range.12862 */12863__isl_give isl_map *isl_set_insert_domain(__isl_take isl_set *set,12864 __isl_take isl_space *domain)12865{12866 isl_size dim;12867 isl_space *space;12868 isl_map *map;12869 12870 if (isl_set_check_is_set(set) < 0 || isl_space_check_is_set(domain) < 0)12871 domain = isl_space_free(domain);12872 dim = isl_space_dim(domain, isl_dim_set);12873 if (dim < 0)12874 domain = isl_space_free(domain);12875 space = isl_set_get_space(set);12876 domain = isl_space_replace_params(domain, space);12877 space = isl_space_map_from_domain_and_range(domain, space);12878 12879 map = isl_map_from_range(set);12880 map = isl_map_add_dims(map, isl_dim_in, dim);12881 map = isl_map_reset_space(map, space);12882 12883 return map;12884}12885 12886__isl_give isl_mat *isl_basic_map_equalities_matrix(12887 __isl_keep isl_basic_map *bmap, enum isl_dim_type c1,12888 enum isl_dim_type c2, enum isl_dim_type c3,12889 enum isl_dim_type c4, enum isl_dim_type c5)12890{12891 enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 };12892 struct isl_mat *mat;12893 int i, j, k;12894 int pos;12895 isl_size total;12896 12897 total = isl_basic_map_dim(bmap, isl_dim_all);12898 if (total < 0)12899 return NULL;12900 mat = isl_mat_alloc(bmap->ctx, bmap->n_eq, total + 1);12901 if (!mat)12902 return NULL;12903 for (i = 0; i < bmap->n_eq; ++i)12904 for (j = 0, pos = 0; j < 5; ++j) {12905 int off = isl_basic_map_offset(bmap, c[j]);12906 isl_size dim = isl_basic_map_dim(bmap, c[j]);12907 if (dim < 0)12908 return isl_mat_free(mat);12909 for (k = 0; k < dim; ++k) {12910 isl_int_set(mat->row[i][pos],12911 bmap->eq[i][off + k]);12912 ++pos;12913 }12914 }12915 12916 return mat;12917}12918 12919__isl_give isl_mat *isl_basic_map_inequalities_matrix(12920 __isl_keep isl_basic_map *bmap, enum isl_dim_type c1,12921 enum isl_dim_type c2, enum isl_dim_type c3,12922 enum isl_dim_type c4, enum isl_dim_type c5)12923{12924 enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 };12925 struct isl_mat *mat;12926 int i, j, k;12927 int pos;12928 isl_size total;12929 12930 total = isl_basic_map_dim(bmap, isl_dim_all);12931 if (total < 0)12932 return NULL;12933 mat = isl_mat_alloc(bmap->ctx, bmap->n_ineq, total + 1);12934 if (!mat)12935 return NULL;12936 for (i = 0; i < bmap->n_ineq; ++i)12937 for (j = 0, pos = 0; j < 5; ++j) {12938 int off = isl_basic_map_offset(bmap, c[j]);12939 isl_size dim = isl_basic_map_dim(bmap, c[j]);12940 if (dim < 0)12941 return isl_mat_free(mat);12942 for (k = 0; k < dim; ++k) {12943 isl_int_set(mat->row[i][pos],12944 bmap->ineq[i][off + k]);12945 ++pos;12946 }12947 }12948 12949 return mat;12950}12951 12952__isl_give isl_basic_map *isl_basic_map_from_constraint_matrices(12953 __isl_take isl_space *space,12954 __isl_take isl_mat *eq, __isl_take isl_mat *ineq, enum isl_dim_type c1,12955 enum isl_dim_type c2, enum isl_dim_type c3,12956 enum isl_dim_type c4, enum isl_dim_type c5)12957{12958 enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 };12959 isl_basic_map *bmap = NULL;12960 isl_size dim;12961 unsigned total;12962 unsigned extra;12963 int i, j, k, l;12964 int pos;12965 12966 dim = isl_space_dim(space, isl_dim_all);12967 if (dim < 0 || !eq || !ineq)12968 goto error;12969 12970 if (eq->n_col != ineq->n_col)12971 isl_die(space->ctx, isl_error_invalid,12972 "equalities and inequalities matrices should have "12973 "same number of columns", goto error);12974 12975 total = 1 + dim;12976 12977 if (eq->n_col < total)12978 isl_die(space->ctx, isl_error_invalid,12979 "number of columns too small", goto error);12980 12981 extra = eq->n_col - total;12982 12983 bmap = isl_basic_map_alloc_space(isl_space_copy(space), extra,12984 eq->n_row, ineq->n_row);12985 if (!bmap)12986 goto error;12987 for (i = 0; i < extra; ++i) {12988 k = isl_basic_map_alloc_div(bmap);12989 if (k < 0)12990 goto error;12991 isl_int_set_si(bmap->div[k][0], 0);12992 }12993 for (i = 0; i < eq->n_row; ++i) {12994 l = isl_basic_map_alloc_equality(bmap);12995 if (l < 0)12996 goto error;12997 for (j = 0, pos = 0; j < 5; ++j) {12998 int off = isl_basic_map_offset(bmap, c[j]);12999 isl_size dim = isl_basic_map_dim(bmap, c[j]);13000 if (dim < 0)13001 goto error;13002 for (k = 0; k < dim; ++k) {13003 isl_int_set(bmap->eq[l][off + k], 13004 eq->row[i][pos]);13005 ++pos;13006 }13007 }13008 }13009 for (i = 0; i < ineq->n_row; ++i) {13010 l = isl_basic_map_alloc_inequality(bmap);13011 if (l < 0)13012 goto error;13013 for (j = 0, pos = 0; j < 5; ++j) {13014 int off = isl_basic_map_offset(bmap, c[j]);13015 isl_size dim = isl_basic_map_dim(bmap, c[j]);13016 if (dim < 0)13017 goto error;13018 for (k = 0; k < dim; ++k) {13019 isl_int_set(bmap->ineq[l][off + k], 13020 ineq->row[i][pos]);13021 ++pos;13022 }13023 }13024 }13025 13026 isl_space_free(space);13027 isl_mat_free(eq);13028 isl_mat_free(ineq);13029 13030 bmap = isl_basic_map_simplify(bmap);13031 return isl_basic_map_finalize(bmap);13032error:13033 isl_space_free(space);13034 isl_mat_free(eq);13035 isl_mat_free(ineq);13036 isl_basic_map_free(bmap);13037 return NULL;13038}13039 13040__isl_give isl_mat *isl_basic_set_equalities_matrix(13041 __isl_keep isl_basic_set *bset, enum isl_dim_type c1,13042 enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4)13043{13044 return isl_basic_map_equalities_matrix(bset_to_bmap(bset),13045 c1, c2, c3, c4, isl_dim_in);13046}13047 13048__isl_give isl_mat *isl_basic_set_inequalities_matrix(13049 __isl_keep isl_basic_set *bset, enum isl_dim_type c1,13050 enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4)13051{13052 return isl_basic_map_inequalities_matrix(bset_to_bmap(bset),13053 c1, c2, c3, c4, isl_dim_in);13054}13055 13056__isl_give isl_basic_set *isl_basic_set_from_constraint_matrices(13057 __isl_take isl_space *space,13058 __isl_take isl_mat *eq, __isl_take isl_mat *ineq, enum isl_dim_type c1,13059 enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4)13060{13061 isl_basic_map *bmap;13062 bmap = isl_basic_map_from_constraint_matrices(space, eq, ineq,13063 c1, c2, c3, c4, isl_dim_in);13064 return bset_from_bmap(bmap);13065}13066 13067isl_bool isl_basic_map_can_zip(__isl_keep isl_basic_map *bmap)13068{13069 if (!bmap)13070 return isl_bool_error;13071 13072 return isl_space_can_zip(bmap->dim);13073}13074 13075isl_bool isl_map_can_zip(__isl_keep isl_map *map)13076{13077 if (!map)13078 return isl_bool_error;13079 13080 return isl_space_can_zip(map->dim);13081}13082 13083/* Given a basic map (A -> B) -> (C -> D), return the corresponding basic map13084 * (A -> C) -> (B -> D).13085 */13086__isl_give isl_basic_map *isl_basic_map_zip(__isl_take isl_basic_map *bmap)13087{13088 unsigned pos;13089 isl_size n_in;13090 isl_size n1;13091 isl_size n2;13092 13093 if (!bmap)13094 return NULL;13095 13096 if (!isl_basic_map_can_zip(bmap))13097 isl_die(bmap->ctx, isl_error_invalid,13098 "basic map cannot be zipped", goto error);13099 n_in = isl_space_dim(bmap->dim->nested[0], isl_dim_in);13100 n1 = isl_space_dim(bmap->dim->nested[0], isl_dim_out);13101 n2 = isl_space_dim(bmap->dim->nested[1], isl_dim_in);13102 if (n_in < 0 || n1 < 0 || n2 < 0)13103 return isl_basic_map_free(bmap);13104 pos = isl_basic_map_offset(bmap, isl_dim_in) + n_in;13105 bmap = isl_basic_map_cow(bmap);13106 bmap = isl_basic_map_swap_vars(bmap, pos, n1, n2);13107 if (!bmap)13108 return NULL;13109 bmap->dim = isl_space_zip(bmap->dim);13110 if (!bmap->dim)13111 goto error;13112 bmap = isl_basic_map_mark_final(bmap);13113 return bmap;13114error:13115 isl_basic_map_free(bmap);13116 return NULL;13117}13118 13119/* Given a map (A -> B) -> (C -> D), return the corresponding map13120 * (A -> C) -> (B -> D).13121 */13122__isl_give isl_map *isl_map_zip(__isl_take isl_map *map)13123{13124 if (!map)13125 return NULL;13126 13127 if (!isl_map_can_zip(map))13128 isl_die(map->ctx, isl_error_invalid, "map cannot be zipped",13129 goto error);13130 13131 return isl_map_transform(map, &isl_space_zip, &isl_basic_map_zip);13132error:13133 isl_map_free(map);13134 return NULL;13135}13136 13137/* Can we apply isl_basic_map_curry to "bmap"?13138 * That is, does it have a nested relation in its domain?13139 */13140isl_bool isl_basic_map_can_curry(__isl_keep isl_basic_map *bmap)13141{13142 if (!bmap)13143 return isl_bool_error;13144 13145 return isl_space_can_curry(bmap->dim);13146}13147 13148/* Can we apply isl_map_curry to "map"?13149 * That is, does it have a nested relation in its domain?13150 */13151isl_bool isl_map_can_curry(__isl_keep isl_map *map)13152{13153 if (!map)13154 return isl_bool_error;13155 13156 return isl_space_can_curry(map->dim);13157}13158 13159/* Given a basic map (A -> B) -> C, return the corresponding basic map13160 * A -> (B -> C).13161 */13162__isl_give isl_basic_map *isl_basic_map_curry(__isl_take isl_basic_map *bmap)13163{13164 13165 if (!bmap)13166 return NULL;13167 13168 if (!isl_basic_map_can_curry(bmap))13169 isl_die(bmap->ctx, isl_error_invalid,13170 "basic map cannot be curried", goto error);13171 bmap = isl_basic_map_cow(bmap);13172 if (!bmap)13173 return NULL;13174 bmap->dim = isl_space_curry(bmap->dim);13175 if (!bmap->dim)13176 goto error;13177 bmap = isl_basic_map_mark_final(bmap);13178 return bmap;13179error:13180 isl_basic_map_free(bmap);13181 return NULL;13182}13183 13184/* Given a map (A -> B) -> C, return the corresponding map13185 * A -> (B -> C).13186 */13187__isl_give isl_map *isl_map_curry(__isl_take isl_map *map)13188{13189 return isl_map_change_space(map, &isl_map_can_curry,13190 "map cannot be curried", &isl_space_curry);13191}13192 13193/* Can isl_map_range_curry be applied to "map"?13194 * That is, does it have a nested relation in its range,13195 * the domain of which is itself a nested relation?13196 */13197isl_bool isl_map_can_range_curry(__isl_keep isl_map *map)13198{13199 if (!map)13200 return isl_bool_error;13201 13202 return isl_space_can_range_curry(map->dim);13203}13204 13205/* Given a map A -> ((B -> C) -> D), return the corresponding map13206 * A -> (B -> (C -> D)).13207 */13208__isl_give isl_map *isl_map_range_curry(__isl_take isl_map *map)13209{13210 return isl_map_change_space(map, &isl_map_can_range_curry,13211 "map range cannot be curried",13212 &isl_space_range_curry);13213}13214 13215/* Can we apply isl_basic_map_uncurry to "bmap"?13216 * That is, does it have a nested relation in its domain?13217 */13218isl_bool isl_basic_map_can_uncurry(__isl_keep isl_basic_map *bmap)13219{13220 if (!bmap)13221 return isl_bool_error;13222 13223 return isl_space_can_uncurry(bmap->dim);13224}13225 13226/* Can we apply isl_map_uncurry to "map"?13227 * That is, does it have a nested relation in its domain?13228 */13229isl_bool isl_map_can_uncurry(__isl_keep isl_map *map)13230{13231 if (!map)13232 return isl_bool_error;13233 13234 return isl_space_can_uncurry(map->dim);13235}13236 13237/* Given a basic map A -> (B -> C), return the corresponding basic map13238 * (A -> B) -> C.13239 */13240__isl_give isl_basic_map *isl_basic_map_uncurry(__isl_take isl_basic_map *bmap)13241{13242 13243 if (!bmap)13244 return NULL;13245 13246 if (!isl_basic_map_can_uncurry(bmap))13247 isl_die(bmap->ctx, isl_error_invalid,13248 "basic map cannot be uncurried",13249 return isl_basic_map_free(bmap));13250 bmap = isl_basic_map_cow(bmap);13251 if (!bmap)13252 return NULL;13253 bmap->dim = isl_space_uncurry(bmap->dim);13254 if (!bmap->dim)13255 return isl_basic_map_free(bmap);13256 bmap = isl_basic_map_mark_final(bmap);13257 return bmap;13258}13259 13260/* Given a map A -> (B -> C), return the corresponding map13261 * (A -> B) -> C.13262 */13263__isl_give isl_map *isl_map_uncurry(__isl_take isl_map *map)13264{13265 return isl_map_change_space(map, &isl_map_can_uncurry,13266 "map cannot be uncurried", &isl_space_uncurry);13267}13268 13269__isl_give isl_set *isl_set_equate(__isl_take isl_set *set,13270 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)13271{13272 return isl_map_equate(set, type1, pos1, type2, pos2);13273}13274 13275/* Construct a basic map where the given dimensions are equal to each other.13276 */13277static __isl_give isl_basic_map *equator(__isl_take isl_space *space,13278 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)13279{13280 isl_basic_map *bmap = NULL;13281 int i;13282 isl_size total;13283 13284 total = isl_space_dim(space, isl_dim_all);13285 if (total < 0 ||13286 isl_space_check_range(space, type1, pos1, 1) < 0 ||13287 isl_space_check_range(space, type2, pos2, 1) < 0)13288 goto error;13289 13290 if (type1 == type2 && pos1 == pos2)13291 return isl_basic_map_universe(space);13292 13293 bmap = isl_basic_map_alloc_space(isl_space_copy(space), 0, 1, 0);13294 i = isl_basic_map_alloc_equality(bmap);13295 if (i < 0)13296 goto error;13297 isl_seq_clr(bmap->eq[i], 1 + total);13298 pos1 += isl_basic_map_offset(bmap, type1);13299 pos2 += isl_basic_map_offset(bmap, type2);13300 isl_int_set_si(bmap->eq[i][pos1], -1);13301 isl_int_set_si(bmap->eq[i][pos2], 1);13302 bmap = isl_basic_map_finalize(bmap);13303 isl_space_free(space);13304 return bmap;13305error:13306 isl_space_free(space);13307 isl_basic_map_free(bmap);13308 return NULL;13309}13310 13311/* Add a constraint imposing that the given two dimensions are equal.13312 */13313__isl_give isl_basic_map *isl_basic_map_equate(__isl_take isl_basic_map *bmap,13314 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)13315{13316 isl_basic_map *eq;13317 13318 eq = equator(isl_basic_map_get_space(bmap), type1, pos1, type2, pos2);13319 13320 bmap = isl_basic_map_intersect(bmap, eq);13321 13322 return bmap;13323}13324 13325/* Add a constraint imposing that the given two dimensions are equal.13326 */13327__isl_give isl_map *isl_map_equate(__isl_take isl_map *map,13328 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)13329{13330 isl_basic_map *bmap;13331 13332 bmap = equator(isl_map_get_space(map), type1, pos1, type2, pos2);13333 13334 map = isl_map_intersect(map, isl_map_from_basic_map(bmap));13335 13336 return map;13337}13338 13339/* Add a constraint imposing that the given two dimensions have opposite values.13340 */13341__isl_give isl_map *isl_map_oppose(__isl_take isl_map *map,13342 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)13343{13344 isl_basic_map *bmap = NULL;13345 int i;13346 isl_size total;13347 13348 if (isl_map_check_range(map, type1, pos1, 1) < 0)13349 return isl_map_free(map);13350 if (isl_map_check_range(map, type2, pos2, 1) < 0)13351 return isl_map_free(map);13352 13353 total = isl_map_dim(map, isl_dim_all);13354 if (total < 0)13355 return isl_map_free(map);13356 bmap = isl_basic_map_alloc_space(isl_map_get_space(map), 0, 1, 0);13357 i = isl_basic_map_alloc_equality(bmap);13358 if (i < 0)13359 goto error;13360 isl_seq_clr(bmap->eq[i], 1 + total);13361 pos1 += isl_basic_map_offset(bmap, type1);13362 pos2 += isl_basic_map_offset(bmap, type2);13363 isl_int_set_si(bmap->eq[i][pos1], 1);13364 isl_int_set_si(bmap->eq[i][pos2], 1);13365 bmap = isl_basic_map_finalize(bmap);13366 13367 map = isl_map_intersect(map, isl_map_from_basic_map(bmap));13368 13369 return map;13370error:13371 isl_basic_map_free(bmap);13372 isl_map_free(map);13373 return NULL;13374}13375 13376/* Construct a constraint imposing that the value of the first dimension is13377 * greater than or equal to that of the second.13378 */13379static __isl_give isl_constraint *constraint_order_ge(13380 __isl_take isl_space *space, enum isl_dim_type type1, int pos1,13381 enum isl_dim_type type2, int pos2)13382{13383 isl_constraint *c;13384 13385 if (isl_space_check_range(space, type1, pos1, 1) < 0 ||13386 isl_space_check_range(space, type2, pos2, 1) < 0)13387 space = isl_space_free(space);13388 if (!space)13389 return NULL;13390 13391 c = isl_constraint_alloc_inequality(isl_local_space_from_space(space));13392 13393 if (type1 == type2 && pos1 == pos2)13394 return c;13395 13396 c = isl_constraint_set_coefficient_si(c, type1, pos1, 1);13397 c = isl_constraint_set_coefficient_si(c, type2, pos2, -1);13398 13399 return c;13400}13401 13402/* Add a constraint imposing that the value of the first dimension is13403 * greater than or equal to that of the second.13404 */13405__isl_give isl_basic_map *isl_basic_map_order_ge(__isl_take isl_basic_map *bmap,13406 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)13407{13408 isl_constraint *c;13409 isl_space *space;13410 13411 if (type1 == type2 && pos1 == pos2)13412 return bmap;13413 space = isl_basic_map_get_space(bmap);13414 c = constraint_order_ge(space, type1, pos1, type2, pos2);13415 bmap = isl_basic_map_add_constraint(bmap, c);13416 13417 return bmap;13418}13419 13420/* Add a constraint imposing that the value of the first dimension is13421 * greater than or equal to that of the second.13422 */13423__isl_give isl_map *isl_map_order_ge(__isl_take isl_map *map,13424 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)13425{13426 isl_constraint *c;13427 isl_space *space;13428 13429 if (type1 == type2 && pos1 == pos2)13430 return map;13431 space = isl_map_get_space(map);13432 c = constraint_order_ge(space, type1, pos1, type2, pos2);13433 map = isl_map_add_constraint(map, c);13434 13435 return map;13436}13437 13438/* Add a constraint imposing that the value of the first dimension is13439 * less than or equal to that of the second.13440 */13441__isl_give isl_map *isl_map_order_le(__isl_take isl_map *map,13442 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)13443{13444 return isl_map_order_ge(map, type2, pos2, type1, pos1);13445}13446 13447/* Construct a basic map where the value of the first dimension is13448 * greater than that of the second.13449 */13450static __isl_give isl_basic_map *greator(__isl_take isl_space *space,13451 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)13452{13453 isl_basic_map *bmap = NULL;13454 int i;13455 isl_size total;13456 13457 if (isl_space_check_range(space, type1, pos1, 1) < 0 ||13458 isl_space_check_range(space, type2, pos2, 1) < 0)13459 goto error;13460 13461 if (type1 == type2 && pos1 == pos2)13462 return isl_basic_map_empty(space);13463 13464 bmap = isl_basic_map_alloc_space(space, 0, 0, 1);13465 total = isl_basic_map_dim(bmap, isl_dim_all);13466 i = isl_basic_map_alloc_inequality(bmap);13467 if (total < 0 || i < 0)13468 return isl_basic_map_free(bmap);13469 isl_seq_clr(bmap->ineq[i], 1 + total);13470 pos1 += isl_basic_map_offset(bmap, type1);13471 pos2 += isl_basic_map_offset(bmap, type2);13472 isl_int_set_si(bmap->ineq[i][pos1], 1);13473 isl_int_set_si(bmap->ineq[i][pos2], -1);13474 isl_int_set_si(bmap->ineq[i][0], -1);13475 bmap = isl_basic_map_finalize(bmap);13476 13477 return bmap;13478error:13479 isl_space_free(space);13480 isl_basic_map_free(bmap);13481 return NULL;13482}13483 13484/* Add a constraint imposing that the value of the first dimension is13485 * greater than that of the second.13486 */13487__isl_give isl_basic_map *isl_basic_map_order_gt(__isl_take isl_basic_map *bmap,13488 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)13489{13490 isl_basic_map *gt;13491 13492 gt = greator(isl_basic_map_get_space(bmap), type1, pos1, type2, pos2);13493 13494 bmap = isl_basic_map_intersect(bmap, gt);13495 13496 return bmap;13497}13498 13499/* Add a constraint imposing that the value of the first dimension is13500 * greater than that of the second.13501 */13502__isl_give isl_map *isl_map_order_gt(__isl_take isl_map *map,13503 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)13504{13505 isl_basic_map *bmap;13506 13507 bmap = greator(isl_map_get_space(map), type1, pos1, type2, pos2);13508 13509 map = isl_map_intersect(map, isl_map_from_basic_map(bmap));13510 13511 return map;13512}13513 13514/* Add a constraint imposing that the value of the first dimension is13515 * smaller than that of the second.13516 */13517__isl_give isl_map *isl_map_order_lt(__isl_take isl_map *map,13518 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)13519{13520 return isl_map_order_gt(map, type2, pos2, type1, pos1);13521}13522 13523__isl_give isl_aff *isl_basic_map_get_div(__isl_keep isl_basic_map *bmap,13524 int pos)13525{13526 isl_aff *div;13527 isl_local_space *ls;13528 13529 if (!bmap)13530 return NULL;13531 13532 if (!isl_basic_map_divs_known(bmap))13533 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,13534 "some divs are unknown", return NULL);13535 13536 ls = isl_basic_map_get_local_space(bmap);13537 div = isl_local_space_get_div(ls, pos);13538 isl_local_space_free(ls);13539 13540 return div;13541}13542 13543__isl_give isl_aff *isl_basic_set_get_div(__isl_keep isl_basic_set *bset,13544 int pos)13545{13546 return isl_basic_map_get_div(bset, pos);13547}13548 13549/* Plug in "subs" for set dimension "pos" of "set".13550 */13551__isl_give isl_set *isl_set_substitute(__isl_take isl_set *set,13552 unsigned pos, __isl_keep isl_aff *subs)13553{13554 isl_multi_aff *ma;13555 13556 if (set && isl_set_plain_is_empty(set))13557 return set;13558 13559 ma = isl_multi_aff_identity_on_domain_space(isl_set_get_space(set));13560 ma = isl_multi_aff_set_aff(ma, pos, isl_aff_copy(subs));13561 return isl_set_preimage_multi_aff(set, ma);13562}13563 13564/* Check if the range of "ma" is compatible with the domain or range13565 * (depending on "type") of "bmap".13566 */13567static isl_stat check_basic_map_compatible_range_multi_aff(13568 __isl_keep isl_basic_map *bmap, enum isl_dim_type type,13569 __isl_keep isl_multi_aff *ma)13570{13571 isl_bool m;13572 isl_space *ma_space;13573 13574 ma_space = isl_multi_aff_get_space(ma);13575 13576 m = isl_space_has_equal_params(bmap->dim, ma_space);13577 if (m < 0)13578 goto error;13579 if (!m)13580 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,13581 "parameters don't match", goto error);13582 m = isl_space_tuple_is_equal(bmap->dim, type, ma_space, isl_dim_out);13583 if (m < 0)13584 goto error;13585 if (!m)13586 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,13587 "spaces don't match", goto error);13588 13589 isl_space_free(ma_space);13590 return isl_stat_ok;13591error:13592 isl_space_free(ma_space);13593 return isl_stat_error;13594}13595 13596/* Copy the divs from "ma" to "bmap", adding zeros for the "n_before"13597 * coefficients before the transformed range of dimensions,13598 * the "n_after" coefficients after the transformed range of dimensions13599 * and the coefficients of the other divs in "bmap".13600 */13601static __isl_give isl_basic_map *set_ma_divs(__isl_take isl_basic_map *bmap,13602 __isl_keep isl_multi_aff *ma, int n_before, int n_after, int n_div)13603{13604 int i;13605 isl_size n_param;13606 isl_size n_set;13607 isl_local_space *ls;13608 13609 if (n_div == 0)13610 return bmap;13611 13612 ls = isl_aff_get_domain_local_space(ma->u.p[0]);13613 n_param = isl_local_space_dim(ls, isl_dim_param);13614 n_set = isl_local_space_dim(ls, isl_dim_set);13615 if (n_param < 0 || n_set < 0)13616 return isl_basic_map_free(bmap);13617 13618 for (i = 0; i < n_div; ++i) {13619 int o_bmap = 0, o_ls = 0;13620 13621 isl_seq_cpy(bmap->div[i], ls->div->row[i], 1 + 1 + n_param);13622 o_bmap += 1 + 1 + n_param;13623 o_ls += 1 + 1 + n_param;13624 isl_seq_clr(bmap->div[i] + o_bmap, n_before);13625 o_bmap += n_before;13626 isl_seq_cpy(bmap->div[i] + o_bmap,13627 ls->div->row[i] + o_ls, n_set);13628 o_bmap += n_set;13629 o_ls += n_set;13630 isl_seq_clr(bmap->div[i] + o_bmap, n_after);13631 o_bmap += n_after;13632 isl_seq_cpy(bmap->div[i] + o_bmap,13633 ls->div->row[i] + o_ls, n_div);13634 o_bmap += n_div;13635 o_ls += n_div;13636 isl_seq_clr(bmap->div[i] + o_bmap, bmap->n_div - n_div);13637 bmap = isl_basic_map_add_div_constraints(bmap, i);13638 if (!bmap)13639 goto error;13640 }13641 13642 isl_local_space_free(ls);13643 return bmap;13644error:13645 isl_local_space_free(ls);13646 return isl_basic_map_free(bmap);13647}13648 13649/* How many stride constraints does "ma" enforce?13650 * That is, how many of the affine expressions have a denominator13651 * different from one?13652 */13653static int multi_aff_strides(__isl_keep isl_multi_aff *ma)13654{13655 int i;13656 int strides = 0;13657 13658 for (i = 0; i < ma->n; ++i)13659 if (!isl_int_is_one(ma->u.p[i]->v->el[0]))13660 strides++;13661 13662 return strides;13663}13664 13665/* For each affine expression in ma of the form13666 *13667 * x_i = (f_i y + h_i)/m_i13668 *13669 * with m_i different from one, add a constraint to "bmap"13670 * of the form13671 *13672 * f_i y + h_i = m_i alpha_i13673 *13674 * with alpha_i an additional existentially quantified variable.13675 *13676 * The input variables of "ma" correspond to a subset of the variables13677 * of "bmap". There are "n_before" variables in "bmap" before this13678 * subset and "n_after" variables after this subset.13679 * The integer divisions of the affine expressions in "ma" are assumed13680 * to have been aligned. There are "n_div_ma" of them and13681 * they appear first in "bmap", straight after the "n_after" variables.13682 */13683static __isl_give isl_basic_map *add_ma_strides(13684 __isl_take isl_basic_map *bmap, __isl_keep isl_multi_aff *ma,13685 int n_before, int n_after, int n_div_ma)13686{13687 int i, k;13688 int div;13689 isl_size total;13690 isl_size n_param;13691 isl_size n_in;13692 13693 total = isl_basic_map_dim(bmap, isl_dim_all);13694 n_param = isl_multi_aff_dim(ma, isl_dim_param);13695 n_in = isl_multi_aff_dim(ma, isl_dim_in);13696 if (total < 0 || n_param < 0 || n_in < 0)13697 return isl_basic_map_free(bmap);13698 for (i = 0; i < ma->n; ++i) {13699 int o_bmap = 0, o_ma = 1;13700 13701 if (isl_int_is_one(ma->u.p[i]->v->el[0]))13702 continue;13703 div = isl_basic_map_alloc_div(bmap);13704 k = isl_basic_map_alloc_equality(bmap);13705 if (div < 0 || k < 0)13706 goto error;13707 isl_int_set_si(bmap->div[div][0], 0);13708 isl_seq_cpy(bmap->eq[k] + o_bmap,13709 ma->u.p[i]->v->el + o_ma, 1 + n_param);13710 o_bmap += 1 + n_param;13711 o_ma += 1 + n_param;13712 isl_seq_clr(bmap->eq[k] + o_bmap, n_before);13713 o_bmap += n_before;13714 isl_seq_cpy(bmap->eq[k] + o_bmap,13715 ma->u.p[i]->v->el + o_ma, n_in);13716 o_bmap += n_in;13717 o_ma += n_in;13718 isl_seq_clr(bmap->eq[k] + o_bmap, n_after);13719 o_bmap += n_after;13720 isl_seq_cpy(bmap->eq[k] + o_bmap,13721 ma->u.p[i]->v->el + o_ma, n_div_ma);13722 o_bmap += n_div_ma;13723 o_ma += n_div_ma;13724 isl_seq_clr(bmap->eq[k] + o_bmap, 1 + total - o_bmap);13725 isl_int_neg(bmap->eq[k][1 + total], ma->u.p[i]->v->el[0]);13726 total++;13727 }13728 13729 return bmap;13730error:13731 isl_basic_map_free(bmap);13732 return NULL;13733}13734 13735/* Replace the domain or range space (depending on "type) of "space" by "set".13736 */13737static __isl_give isl_space *isl_space_set(__isl_take isl_space *space,13738 enum isl_dim_type type, __isl_take isl_space *set)13739{13740 if (type == isl_dim_in) {13741 space = isl_space_range(space);13742 space = isl_space_map_from_domain_and_range(set, space);13743 } else {13744 space = isl_space_domain(space);13745 space = isl_space_map_from_domain_and_range(space, set);13746 }13747 13748 return space;13749}13750 13751/* Compute the preimage of the domain or range (depending on "type")13752 * of "bmap" under the function represented by "ma".13753 * In other words, plug in "ma" in the domain or range of "bmap".13754 * The result is a basic map that lives in the same space as "bmap"13755 * except that the domain or range has been replaced by13756 * the domain space of "ma".13757 *13758 * If bmap is represented by13759 *13760 * A(p) + S u + B x + T v + C(divs) >= 0,13761 *13762 * where u and x are input and output dimensions if type == isl_dim_out13763 * while x and v are input and output dimensions if type == isl_dim_in,13764 * and ma is represented by13765 *13766 * x = D(p) + F(y) + G(divs')13767 *13768 * then the result is13769 *13770 * A(p) + B D(p) + S u + B F(y) + T v + B G(divs') + C(divs) >= 013771 *13772 * The divs in the input set are similarly adjusted.13773 * In particular13774 *13775 * floor((a_i(p) + s u + b_i x + t v + c_i(divs))/n_i)13776 *13777 * becomes13778 *13779 * floor((a_i(p) + b_i D(p) + s u + b_i F(y) + t v +13780 * B_i G(divs') + c_i(divs))/n_i)13781 *13782 * If bmap is not a rational map and if F(y) involves any denominators13783 *13784 * x_i = (f_i y + h_i)/m_i13785 *13786 * then additional constraints are added to ensure that we only13787 * map back integer points. That is we enforce13788 *13789 * f_i y + h_i = m_i alpha_i13790 *13791 * with alpha_i an additional existentially quantified variable.13792 *13793 * We first copy over the divs from "ma".13794 * Then we add the modified constraints and divs from "bmap".13795 * Finally, we add the stride constraints, if needed.13796 */13797__isl_give isl_basic_map *isl_basic_map_preimage_multi_aff(13798 __isl_take isl_basic_map *bmap, enum isl_dim_type type,13799 __isl_take isl_multi_aff *ma)13800{13801 int i, k;13802 isl_space *space;13803 isl_basic_map *res = NULL;13804 isl_size n_before, n_after, n_div_bmap, n_div_ma;13805 isl_int f, c1, c2, g;13806 isl_bool rational;13807 int strides;13808 13809 isl_int_init(f);13810 isl_int_init(c1);13811 isl_int_init(c2);13812 isl_int_init(g);13813 13814 ma = isl_multi_aff_align_divs(ma);13815 if (!bmap || !ma)13816 goto error;13817 if (check_basic_map_compatible_range_multi_aff(bmap, type, ma) < 0)13818 goto error;13819 13820 if (type == isl_dim_in) {13821 n_before = 0;13822 n_after = isl_basic_map_dim(bmap, isl_dim_out);13823 } else {13824 n_before = isl_basic_map_dim(bmap, isl_dim_in);13825 n_after = 0;13826 }13827 n_div_bmap = isl_basic_map_dim(bmap, isl_dim_div);13828 n_div_ma = ma->n ? isl_aff_dim(ma->u.p[0], isl_dim_div) : 0;13829 if (n_before < 0 || n_after < 0 || n_div_bmap < 0 || n_div_ma < 0)13830 goto error;13831 13832 space = isl_multi_aff_get_domain_space(ma);13833 space = isl_space_set(isl_basic_map_get_space(bmap), type, space);13834 rational = isl_basic_map_is_rational(bmap);13835 strides = rational ? 0 : multi_aff_strides(ma);13836 res = isl_basic_map_alloc_space(space, n_div_ma + n_div_bmap + strides,13837 bmap->n_eq + strides, bmap->n_ineq + 2 * n_div_ma);13838 if (rational)13839 res = isl_basic_map_set_rational(res);13840 13841 for (i = 0; i < n_div_ma + n_div_bmap; ++i)13842 if (isl_basic_map_alloc_div(res) < 0)13843 goto error;13844 13845 res = set_ma_divs(res, ma, n_before, n_after, n_div_ma);13846 if (!res)13847 goto error;13848 13849 for (i = 0; i < bmap->n_eq; ++i) {13850 k = isl_basic_map_alloc_equality(res);13851 if (k < 0)13852 goto error;13853 if (isl_seq_preimage(res->eq[k], bmap->eq[i], ma, n_before,13854 n_after, n_div_ma, n_div_bmap,13855 f, c1, c2, g, 0) < 0)13856 goto error;13857 }13858 13859 for (i = 0; i < bmap->n_ineq; ++i) {13860 k = isl_basic_map_alloc_inequality(res);13861 if (k < 0)13862 goto error;13863 if (isl_seq_preimage(res->ineq[k], bmap->ineq[i], ma, n_before,13864 n_after, n_div_ma, n_div_bmap,13865 f, c1, c2, g, 0) < 0)13866 goto error;13867 }13868 13869 for (i = 0; i < bmap->n_div; ++i) {13870 if (isl_int_is_zero(bmap->div[i][0])) {13871 isl_int_set_si(res->div[n_div_ma + i][0], 0);13872 continue;13873 }13874 if (isl_seq_preimage(res->div[n_div_ma + i], bmap->div[i], ma,13875 n_before, n_after, n_div_ma, n_div_bmap,13876 f, c1, c2, g, 1) < 0)13877 goto error;13878 }13879 13880 if (strides)13881 res = add_ma_strides(res, ma, n_before, n_after, n_div_ma);13882 13883 isl_int_clear(f);13884 isl_int_clear(c1);13885 isl_int_clear(c2);13886 isl_int_clear(g);13887 isl_basic_map_free(bmap);13888 isl_multi_aff_free(ma);13889 res = isl_basic_map_simplify(res);13890 return isl_basic_map_finalize(res);13891error:13892 isl_int_clear(f);13893 isl_int_clear(c1);13894 isl_int_clear(c2);13895 isl_int_clear(g);13896 isl_basic_map_free(bmap);13897 isl_multi_aff_free(ma);13898 isl_basic_map_free(res);13899 return NULL;13900}13901 13902/* Compute the preimage of "bset" under the function represented by "ma".13903 * In other words, plug in "ma" in "bset". The result is a basic set13904 * that lives in the domain space of "ma".13905 */13906__isl_give isl_basic_set *isl_basic_set_preimage_multi_aff(13907 __isl_take isl_basic_set *bset, __isl_take isl_multi_aff *ma)13908{13909 return isl_basic_map_preimage_multi_aff(bset, isl_dim_set, ma);13910}13911 13912/* Compute the preimage of the domain of "bmap" under the function13913 * represented by "ma".13914 * In other words, plug in "ma" in the domain of "bmap".13915 * The result is a basic map that lives in the same space as "bmap"13916 * except that the domain has been replaced by the domain space of "ma".13917 */13918__isl_give isl_basic_map *isl_basic_map_preimage_domain_multi_aff(13919 __isl_take isl_basic_map *bmap, __isl_take isl_multi_aff *ma)13920{13921 return isl_basic_map_preimage_multi_aff(bmap, isl_dim_in, ma);13922}13923 13924/* Compute the preimage of the range of "bmap" under the function13925 * represented by "ma".13926 * In other words, plug in "ma" in the range of "bmap".13927 * The result is a basic map that lives in the same space as "bmap"13928 * except that the range has been replaced by the domain space of "ma".13929 */13930__isl_give isl_basic_map *isl_basic_map_preimage_range_multi_aff(13931 __isl_take isl_basic_map *bmap, __isl_take isl_multi_aff *ma)13932{13933 return isl_basic_map_preimage_multi_aff(bmap, isl_dim_out, ma);13934}13935 13936/* Check if the range of "ma" is compatible with the domain or range13937 * (depending on "type") of "map".13938 * Return isl_stat_error if anything is wrong.13939 */13940static isl_stat check_map_compatible_range_multi_aff(13941 __isl_keep isl_map *map, enum isl_dim_type type,13942 __isl_keep isl_multi_aff *ma)13943{13944 isl_bool m;13945 isl_space *ma_space;13946 13947 ma_space = isl_multi_aff_get_space(ma);13948 m = isl_map_space_tuple_is_equal(map, type, ma_space, isl_dim_out);13949 isl_space_free(ma_space);13950 if (m < 0)13951 return isl_stat_error;13952 if (!m)13953 isl_die(isl_map_get_ctx(map), isl_error_invalid,13954 "spaces don't match", return isl_stat_error);13955 return isl_stat_ok;13956}13957 13958/* Compute the preimage of the domain or range (depending on "type")13959 * of "map" under the function represented by "ma".13960 * In other words, plug in "ma" in the domain or range of "map".13961 * The result is a map that lives in the same space as "map"13962 * except that the domain or range has been replaced by13963 * the domain space of "ma".13964 *13965 * The parameters are assumed to have been aligned.13966 */13967static __isl_give isl_map *map_preimage_multi_aff(__isl_take isl_map *map,13968 enum isl_dim_type type, __isl_take isl_multi_aff *ma)13969{13970 int i;13971 isl_space *space;13972 13973 map = isl_map_cow(map);13974 ma = isl_multi_aff_align_divs(ma);13975 if (!map || !ma)13976 goto error;13977 if (check_map_compatible_range_multi_aff(map, type, ma) < 0)13978 goto error;13979 13980 for (i = 0; i < map->n; ++i) {13981 map->p[i] = isl_basic_map_preimage_multi_aff(map->p[i], type,13982 isl_multi_aff_copy(ma));13983 if (!map->p[i])13984 goto error;13985 }13986 13987 space = isl_multi_aff_get_domain_space(ma);13988 space = isl_space_set(isl_map_get_space(map), type, space);13989 13990 isl_space_free(isl_map_take_space(map));13991 map = isl_map_restore_space(map, space);13992 if (!map)13993 goto error;13994 13995 isl_multi_aff_free(ma);13996 if (map->n > 1)13997 ISL_F_CLR(map, ISL_MAP_DISJOINT);13998 ISL_F_CLR(map, ISL_SET_NORMALIZED);13999 return map;14000error:14001 isl_multi_aff_free(ma);14002 isl_map_free(map);14003 return NULL;14004}14005 14006/* Compute the preimage of the domain or range (depending on "type")14007 * of "map" under the function represented by "ma".14008 * In other words, plug in "ma" in the domain or range of "map".14009 * The result is a map that lives in the same space as "map"14010 * except that the domain or range has been replaced by14011 * the domain space of "ma".14012 */14013__isl_give isl_map *isl_map_preimage_multi_aff(__isl_take isl_map *map,14014 enum isl_dim_type type, __isl_take isl_multi_aff *ma)14015{14016 isl_bool aligned;14017 14018 if (!map || !ma)14019 goto error;14020 14021 aligned = isl_map_space_has_equal_params(map, ma->space);14022 if (aligned < 0)14023 goto error;14024 if (aligned)14025 return map_preimage_multi_aff(map, type, ma);14026 14027 if (isl_map_check_named_params(map) < 0)14028 goto error;14029 if (!isl_space_has_named_params(ma->space))14030 isl_die(map->ctx, isl_error_invalid,14031 "unaligned unnamed parameters", goto error);14032 map = isl_map_align_params(map, isl_multi_aff_get_space(ma));14033 ma = isl_multi_aff_align_params(ma, isl_map_get_space(map));14034 14035 return map_preimage_multi_aff(map, type, ma);14036error:14037 isl_multi_aff_free(ma);14038 return isl_map_free(map);14039}14040 14041/* Compute the preimage of "set" under the function represented by "ma".14042 * In other words, plug in "ma" in "set". The result is a set14043 * that lives in the domain space of "ma".14044 */14045__isl_give isl_set *isl_set_preimage_multi_aff(__isl_take isl_set *set,14046 __isl_take isl_multi_aff *ma)14047{14048 return isl_map_preimage_multi_aff(set, isl_dim_set, ma);14049}14050 14051/* Compute the preimage of the domain of "map" under the function14052 * represented by "ma".14053 * In other words, plug in "ma" in the domain of "map".14054 * The result is a map that lives in the same space as "map"14055 * except that the domain has been replaced by the domain space of "ma".14056 */14057__isl_give isl_map *isl_map_preimage_domain_multi_aff(__isl_take isl_map *map,14058 __isl_take isl_multi_aff *ma)14059{14060 return isl_map_preimage_multi_aff(map, isl_dim_in, ma);14061}14062 14063/* Compute the preimage of the range of "map" under the function14064 * represented by "ma".14065 * In other words, plug in "ma" in the range of "map".14066 * The result is a map that lives in the same space as "map"14067 * except that the range has been replaced by the domain space of "ma".14068 */14069__isl_give isl_map *isl_map_preimage_range_multi_aff(__isl_take isl_map *map,14070 __isl_take isl_multi_aff *ma)14071{14072 return isl_map_preimage_multi_aff(map, isl_dim_out, ma);14073}14074 14075/* Compute the preimage of "map" under the function represented by "pma".14076 * In other words, plug in "pma" in the domain or range of "map".14077 * The result is a map that lives in the same space as "map",14078 * except that the space of type "type" has been replaced by14079 * the domain space of "pma".14080 *14081 * The parameters of "map" and "pma" are assumed to have been aligned.14082 */14083static __isl_give isl_map *isl_map_preimage_pw_multi_aff_aligned(14084 __isl_take isl_map *map, enum isl_dim_type type,14085 __isl_take isl_pw_multi_aff *pma)14086{14087 int i;14088 isl_map *res;14089 14090 if (!pma)14091 goto error;14092 14093 if (pma->n == 0) {14094 isl_pw_multi_aff_free(pma);14095 res = isl_map_empty(isl_map_get_space(map));14096 isl_map_free(map);14097 return res;14098 }14099 14100 res = isl_map_preimage_multi_aff(isl_map_copy(map), type,14101 isl_multi_aff_copy(pma->p[0].maff));14102 if (type == isl_dim_in)14103 res = isl_map_intersect_domain(res,14104 isl_map_copy(pma->p[0].set));14105 else14106 res = isl_map_intersect_range(res,14107 isl_map_copy(pma->p[0].set));14108 14109 for (i = 1; i < pma->n; ++i) {14110 isl_map *res_i;14111 14112 res_i = isl_map_preimage_multi_aff(isl_map_copy(map), type,14113 isl_multi_aff_copy(pma->p[i].maff));14114 if (type == isl_dim_in)14115 res_i = isl_map_intersect_domain(res_i,14116 isl_map_copy(pma->p[i].set));14117 else14118 res_i = isl_map_intersect_range(res_i,14119 isl_map_copy(pma->p[i].set));14120 res = isl_map_union(res, res_i);14121 }14122 14123 isl_pw_multi_aff_free(pma);14124 isl_map_free(map);14125 return res;14126error:14127 isl_pw_multi_aff_free(pma);14128 isl_map_free(map);14129 return NULL;14130}14131 14132/* Compute the preimage of "map" under the function represented by "pma".14133 * In other words, plug in "pma" in the domain or range of "map".14134 * The result is a map that lives in the same space as "map",14135 * except that the space of type "type" has been replaced by14136 * the domain space of "pma".14137 */14138__isl_give isl_map *isl_map_preimage_pw_multi_aff(__isl_take isl_map *map,14139 enum isl_dim_type type, __isl_take isl_pw_multi_aff *pma)14140{14141 isl_bool aligned;14142 14143 if (!map || !pma)14144 goto error;14145 14146 aligned = isl_map_space_has_equal_params(map, pma->dim);14147 if (aligned < 0)14148 goto error;14149 if (aligned)14150 return isl_map_preimage_pw_multi_aff_aligned(map, type, pma);14151 14152 if (isl_map_check_named_params(map) < 0)14153 goto error;14154 if (isl_pw_multi_aff_check_named_params(pma) < 0)14155 goto error;14156 map = isl_map_align_params(map, isl_pw_multi_aff_get_space(pma));14157 pma = isl_pw_multi_aff_align_params(pma, isl_map_get_space(map));14158 14159 return isl_map_preimage_pw_multi_aff_aligned(map, type, pma);14160error:14161 isl_pw_multi_aff_free(pma);14162 return isl_map_free(map);14163}14164 14165/* Compute the preimage of "set" under the function represented by "pma".14166 * In other words, plug in "pma" in "set". The result is a set14167 * that lives in the domain space of "pma".14168 */14169__isl_give isl_set *isl_set_preimage_pw_multi_aff(__isl_take isl_set *set,14170 __isl_take isl_pw_multi_aff *pma)14171{14172 return isl_map_preimage_pw_multi_aff(set, isl_dim_set, pma);14173}14174 14175/* Compute the preimage of the domain of "map" under the function14176 * represented by "pma".14177 * In other words, plug in "pma" in the domain of "map".14178 * The result is a map that lives in the same space as "map",14179 * except that domain space has been replaced by the domain space of "pma".14180 */14181__isl_give isl_map *isl_map_preimage_domain_pw_multi_aff(14182 __isl_take isl_map *map, __isl_take isl_pw_multi_aff *pma)14183{14184 return isl_map_preimage_pw_multi_aff(map, isl_dim_in, pma);14185}14186 14187/* Compute the preimage of the range of "map" under the function14188 * represented by "pma".14189 * In other words, plug in "pma" in the range of "map".14190 * The result is a map that lives in the same space as "map",14191 * except that range space has been replaced by the domain space of "pma".14192 */14193__isl_give isl_map *isl_map_preimage_range_pw_multi_aff(14194 __isl_take isl_map *map, __isl_take isl_pw_multi_aff *pma)14195{14196 return isl_map_preimage_pw_multi_aff(map, isl_dim_out, pma);14197}14198 14199/* Compute the preimage of "map" under the function represented by "mpa".14200 * In other words, plug in "mpa" in the domain or range of "map".14201 * The result is a map that lives in the same space as "map",14202 * except that the space of type "type" has been replaced by14203 * the domain space of "mpa".14204 *14205 * If the map does not involve any constraints that refer to the14206 * dimensions of the substituted space, then the only possible14207 * effect of "mpa" on the map is to map the space to a different space.14208 * We create a separate isl_multi_aff to effectuate this change14209 * in order to avoid spurious splitting of the map along the pieces14210 * of "mpa".14211 * If "mpa" has a non-trivial explicit domain, however,14212 * then the full substitution should be performed.14213 */14214__isl_give isl_map *isl_map_preimage_multi_pw_aff(__isl_take isl_map *map,14215 enum isl_dim_type type, __isl_take isl_multi_pw_aff *mpa)14216{14217 isl_size n;14218 isl_bool full;14219 isl_pw_multi_aff *pma;14220 14221 n = isl_map_dim(map, type);14222 if (n < 0 || !mpa)14223 goto error;14224 14225 full = isl_map_involves_dims(map, type, 0, n);14226 if (full >= 0 && !full)14227 full = isl_multi_pw_aff_has_non_trivial_domain(mpa);14228 if (full < 0)14229 goto error;14230 if (!full) {14231 isl_space *space;14232 isl_multi_aff *ma;14233 14234 space = isl_multi_pw_aff_get_space(mpa);14235 isl_multi_pw_aff_free(mpa);14236 ma = isl_multi_aff_zero(space);14237 return isl_map_preimage_multi_aff(map, type, ma);14238 }14239 14240 pma = isl_pw_multi_aff_from_multi_pw_aff(mpa);14241 return isl_map_preimage_pw_multi_aff(map, type, pma);14242error:14243 isl_map_free(map);14244 isl_multi_pw_aff_free(mpa);14245 return NULL;14246}14247 14248/* Compute the preimage of "map" under the function represented by "mpa".14249 * In other words, plug in "mpa" in the domain "map".14250 * The result is a map that lives in the same space as "map",14251 * except that domain space has been replaced by the domain space of "mpa".14252 */14253__isl_give isl_map *isl_map_preimage_domain_multi_pw_aff(14254 __isl_take isl_map *map, __isl_take isl_multi_pw_aff *mpa)14255{14256 return isl_map_preimage_multi_pw_aff(map, isl_dim_in, mpa);14257}14258 14259/* Compute the preimage of "set" by the function represented by "mpa".14260 * In other words, plug in "mpa" in "set".14261 */14262__isl_give isl_set *isl_set_preimage_multi_pw_aff(__isl_take isl_set *set,14263 __isl_take isl_multi_pw_aff *mpa)14264{14265 return isl_map_preimage_multi_pw_aff(set, isl_dim_set, mpa);14266}14267 14268/* Return a copy of the equality constraints of "bset" as a matrix.14269 */14270__isl_give isl_mat *isl_basic_set_extract_equalities(14271 __isl_keep isl_basic_set *bset)14272{14273 isl_ctx *ctx;14274 isl_size total;14275 14276 total = isl_basic_set_dim(bset, isl_dim_all);14277 if (total < 0)14278 return NULL;14279 14280 ctx = isl_basic_set_get_ctx(bset);14281 return isl_mat_sub_alloc6(ctx, bset->eq, 0, bset->n_eq, 0, 1 + total);14282}14283 14284/* Are the "n" "coefficients" starting at "first" of the integer division14285 * expressions at position "pos1" in "bmap1" and "pos2" in "bmap2" equal14286 * to each other?14287 * The "coefficient" at position 0 is the denominator.14288 * The "coefficient" at position 1 is the constant term.14289 */14290isl_bool isl_basic_map_equal_div_expr_part(__isl_keep isl_basic_map *bmap1,14291 int pos1, __isl_keep isl_basic_map *bmap2, int pos2,14292 unsigned first, unsigned n)14293{14294 if (isl_basic_map_check_range(bmap1, isl_dim_div, pos1, 1) < 0)14295 return isl_bool_error;14296 if (isl_basic_map_check_range(bmap2, isl_dim_div, pos2, 1) < 0)14297 return isl_bool_error;14298 return isl_seq_eq(bmap1->div[pos1] + first,14299 bmap2->div[pos2] + first, n);14300}14301 14302/* Are the integer division expressions at position "pos1" in "bmap1" and14303 * "pos2" in "bmap2" equal to each other, except that the constant terms14304 * are different?14305 */14306isl_bool isl_basic_map_equal_div_expr_except_constant(14307 __isl_keep isl_basic_map *bmap1, int pos1,14308 __isl_keep isl_basic_map *bmap2, int pos2)14309{14310 isl_bool equal;14311 isl_size total, total2;14312 14313 total = isl_basic_map_dim(bmap1, isl_dim_all);14314 total2 = isl_basic_map_dim(bmap2, isl_dim_all);14315 if (total < 0 || total2 < 0)14316 return isl_bool_error;14317 if (total != total2)14318 isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,14319 "incomparable div expressions", return isl_bool_error);14320 equal = isl_basic_map_equal_div_expr_part(bmap1, pos1, bmap2, pos2,14321 0, 1);14322 if (equal < 0 || !equal)14323 return equal;14324 equal = isl_basic_map_equal_div_expr_part(bmap1, pos1, bmap2, pos2,14325 1, 1);14326 if (equal < 0 || equal)14327 return isl_bool_not(equal);14328 return isl_basic_map_equal_div_expr_part(bmap1, pos1, bmap2, pos2,14329 2, total);14330}14331 14332/* Replace the numerator of the constant term of the integer division14333 * expression at position "div" in "bmap" by "value".14334 * The caller guarantees that this does not change the meaning14335 * of the input.14336 */14337__isl_give isl_basic_map *isl_basic_map_set_div_expr_constant_num_si_inplace(14338 __isl_take isl_basic_map *bmap, int div, int value)14339{14340 if (isl_basic_map_check_range(bmap, isl_dim_div, div, 1) < 0)14341 return isl_basic_map_free(bmap);14342 14343 isl_int_set_si(bmap->div[div][1], value);14344 14345 return bmap;14346}14347 14348/* Is the point "inner" internal to inequality constraint "ineq"14349 * of "bset"?14350 * The point is considered to be internal to the inequality constraint,14351 * if it strictly lies on the positive side of the inequality constraint,14352 * or if it lies on the constraint and the constraint is lexico-positive.14353 */14354static isl_bool is_internal(__isl_keep isl_vec *inner,14355 __isl_keep isl_basic_set *bset, int ineq)14356{14357 isl_ctx *ctx;14358 int pos;14359 isl_size total;14360 14361 if (!inner || !bset)14362 return isl_bool_error;14363 14364 ctx = isl_basic_set_get_ctx(bset);14365 isl_seq_inner_product(inner->el, bset->ineq[ineq], inner->size,14366 &ctx->normalize_gcd);14367 if (!isl_int_is_zero(ctx->normalize_gcd))14368 return isl_int_is_nonneg(ctx->normalize_gcd);14369 14370 total = isl_basic_set_dim(bset, isl_dim_all);14371 if (total < 0)14372 return isl_bool_error;14373 pos = isl_seq_first_non_zero(bset->ineq[ineq] + 1, total);14374 return isl_int_is_pos(bset->ineq[ineq][1 + pos]);14375}14376 14377/* Tighten the inequality constraints of "bset" that are outward with respect14378 * to the point "vec".14379 * That is, tighten the constraints that are not satisfied by "vec".14380 *14381 * "vec" is a point internal to some superset S of "bset" that is used14382 * to make the subsets of S disjoint, by tightening one half of the constraints14383 * that separate two subsets. In particular, the constraints of S14384 * are all satisfied by "vec" and should not be tightened.14385 * Of the internal constraints, those that have "vec" on the outside14386 * are tightened. The shared facet is included in the adjacent subset14387 * with the opposite constraint.14388 * For constraints that saturate "vec", this criterion cannot be used14389 * to determine which of the two sides should be tightened.14390 * Instead, the sign of the first non-zero coefficient is used14391 * to make this choice. Note that this second criterion is never used14392 * on the constraints of S since "vec" is interior to "S".14393 */14394__isl_give isl_basic_set *isl_basic_set_tighten_outward(14395 __isl_take isl_basic_set *bset, __isl_keep isl_vec *vec)14396{14397 int j;14398 14399 bset = isl_basic_set_cow(bset);14400 if (!bset)14401 return NULL;14402 for (j = 0; j < bset->n_ineq; ++j) {14403 isl_bool internal;14404 14405 internal = is_internal(vec, bset, j);14406 if (internal < 0)14407 return isl_basic_set_free(bset);14408 if (internal)14409 continue;14410 isl_int_sub_ui(bset->ineq[j][0], bset->ineq[j][0], 1);14411 }14412 14413 return bset;14414}14415 14416/* Replace the variables x of type "type" starting at "first" in "bmap"14417 * by x' with x = M x' with M the matrix trans.14418 * That is, replace the corresponding coefficients c by c M.14419 *14420 * The transformation matrix should be a square matrix.14421 */14422__isl_give isl_basic_map *isl_basic_map_transform_dims(14423 __isl_take isl_basic_map *bmap, enum isl_dim_type type, unsigned first,14424 __isl_take isl_mat *trans)14425{14426 unsigned pos;14427 14428 bmap = isl_basic_map_cow(bmap);14429 if (!bmap || !trans)14430 goto error;14431 14432 if (trans->n_row != trans->n_col)14433 isl_die(trans->ctx, isl_error_invalid,14434 "expecting square transformation matrix", goto error);14435 if (isl_basic_map_check_range(bmap, type, first, trans->n_row) < 0)14436 goto error;14437 14438 pos = isl_basic_map_offset(bmap, type) + first;14439 14440 if (isl_mat_sub_transform(bmap->eq, bmap->n_eq, pos,14441 isl_mat_copy(trans)) < 0)14442 goto error;14443 if (isl_mat_sub_transform(bmap->ineq, bmap->n_ineq, pos,14444 isl_mat_copy(trans)) < 0)14445 goto error;14446 if (isl_mat_sub_transform(bmap->div, bmap->n_div, 1 + pos,14447 isl_mat_copy(trans)) < 0)14448 goto error;14449 14450 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);14451 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);14452 14453 isl_mat_free(trans);14454 return bmap;14455error:14456 isl_mat_free(trans);14457 isl_basic_map_free(bmap);14458 return NULL;14459}14460 14461/* Replace the variables x of type "type" starting at "first" in "bset"14462 * by x' with x = M x' with M the matrix trans.14463 * That is, replace the corresponding coefficients c by c M.14464 *14465 * The transformation matrix should be a square matrix.14466 */14467__isl_give isl_basic_set *isl_basic_set_transform_dims(14468 __isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned first,14469 __isl_take isl_mat *trans)14470{14471 return isl_basic_map_transform_dims(bset, type, first, trans);14472}14473