brintos

brintos / llvm-project-archived public Read only

0
0
Text · 375.4 KiB · 5cb7a56 Raw
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, &params);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