brintos

brintos / llvm-project-archived public Read only

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