@@ -344,8 +344,15 @@ EXTRA_DIST = \
isl_map_lexopt_templ.c \
isl_maybe_map.h \
isl_multi_macro.h \
+ isl_multi_explicit_domain.c \
+ isl_multi_pw_aff_explicit_domain.c \
+ isl_multi_union_pw_aff_explicit_domain.c \
+ isl_multi_no_explicit_domain.c \
isl_multi_templ.c \
isl_multi_templ.h \
+ isl_multi_align_templ.c \
+ isl_multi_align_set.c \
+ isl_multi_align_union_set.c \
isl_multi_apply_templ.c \
isl_multi_apply_set.c \
isl_multi_apply_union_set.c \
@@ -270,6 +270,17 @@ be used as an alternative.
=back
+=head3 Changes since isl-0.19
+
+=over
+
+=item * Zero-dimensional objects of type C<isl_multi_pw_aff> or
+C<isl_multi_union_pw_aff> can now keep track of an explicit domain.
+This explicit domain, if present, is taken into account
+by various operations that take such objects as input.
+
+=back
+
=head1 License
C<isl> is released under the MIT license.
@@ -2749,6 +2760,10 @@ Objects of the value type do not have an associated space.
The space of a multiple value is therefore always a set space.
Similarly, the space of a multiple union piecewise
affine expression is always a set space.
+If the base expressions are not total, then
+a corresponding zero-dimensional multiple expression may
+have an explicit domain that keeps track of the domain
+outside of any base expressions.
The multiple expression types defined by C<isl>
are C<isl_multi_val>, C<isl_multi_aff>, C<isl_multi_pw_aff>,
@@ -2969,10 +2984,7 @@ while there is only a single multiple expression in
an C<isl_multi_union_pw_aff>, which can therefore only live
in a single space. This means that not every
C<isl_union_pw_multi_aff> can be converted to
-an C<isl_multi_union_pw_aff>. Conversely, a zero-dimensional
-C<isl_multi_union_pw_aff> carries no information
-about any possible domain and therefore cannot be converted
-to an C<isl_union_pw_multi_aff>. Moreover, the elements
+an C<isl_multi_union_pw_aff>. Conversely, the elements
of an C<isl_multi_union_pw_aff> may be defined over different domains,
while each multiple expression inside an C<isl_union_pw_multi_aff>
has a single domain. The conversion of an C<isl_union_pw_multi_aff>
@@ -4569,8 +4581,9 @@ parameters.
__isl_give isl_set *isl_pw_aff_params(
__isl_take isl_pw_aff *pwa);
-The function C<isl_multi_union_pw_aff_domain> requires its
-input to have at least one set dimension.
+If no explicit domain was set on a zero-dimensional input to
+C<isl_multi_union_pw_aff_domain>, then this function will
+return a parameter set.
#include <isl/polynomial.h>
__isl_give isl_qpolynomial *
@@ -3830,6 +3830,7 @@ error:
#define DOMBASE set
#define NO_DOMAIN
+#include <isl_multi_no_explicit_domain.c>
#include <isl_multi_templ.c>
#include <isl_multi_apply_set.c>
#include <isl_multi_cmp.c>
#undef DOMBASE
#define DOMBASE set
+#include <isl_multi_explicit_domain.c>
+#include <isl_multi_pw_aff_explicit_domain.c>
#include <isl_multi_templ.c>
#include <isl_multi_apply_set.c>
#include <isl_multi_coalesce.c>
#include <isl_multi_dims.c>
#include <isl_multi_gist.c>
#include <isl_multi_hash.c>
+#include <isl_multi_align_set.c>
#include <isl_multi_intersect.c>
+/* Does "mpa" have a non-trivial explicit domain?
+ *
+ * The explicit domain, if present, is trivial if it represents
+ * an (obviously) universe set.
+ */
+isl_bool isl_multi_pw_aff_has_non_trivial_domain(
+ __isl_keep isl_multi_pw_aff *mpa)
+{
+ if (!mpa)
+ return isl_bool_error;
+ if (!isl_multi_pw_aff_has_explicit_domain(mpa))
+ return isl_bool_false;
+ return isl_bool_not(isl_set_plain_is_universe(mpa->u.dom));
+}
+
/* Scale the elements of "pma" by the corresponding elements of "mv".
*/
__isl_give isl_pw_multi_aff *isl_pw_multi_aff_scale_multi_val(
* on the shared domain of the piecewise affine expressions,
* in the special case of a 0D multi piecewise affine expression.
*
- * A 0D multi piecewise affine expression does not carry any domain
- * information, so create a piecewise multi affine expression
- * with a universe domain.
+ * Create a piecewise multi affine expression with the explicit domain of
+ * the 0D multi piecewise affine expression as domain.
*/
static __isl_give isl_pw_multi_aff *isl_pw_multi_aff_from_multi_pw_aff_0D(
__isl_take isl_multi_pw_aff *mpa)
{
isl_space *space;
+ isl_set *dom;
+ isl_multi_aff *ma;
space = isl_multi_pw_aff_get_space(mpa);
+ dom = isl_multi_pw_aff_get_explicit_domain(mpa);
isl_multi_pw_aff_free(mpa);
- return isl_pw_multi_aff_zero(space);
+
+ ma = isl_multi_aff_zero(space);
+ return isl_pw_multi_aff_alloc(dom, ma);
}
/* Construct and return a piecewise multi affine expression
@@ -6571,6 +6594,10 @@ __isl_give isl_multi_pw_aff *isl_multi_pw_aff_from_multi_aff(
/* Construct and return a multi piecewise affine expression
* that is equal to the given piecewise multi affine expression.
+ *
+ * If the resulting multi piecewise affine expression has
+ * an explicit domain, then assign it the domain of the input.
+ * In other cases, the domain is stored in the individual elements.
*/
__isl_give isl_multi_pw_aff *isl_multi_pw_aff_from_pw_multi_aff(
__isl_take isl_pw_multi_aff *pma)
@@ -6592,6 +6619,12 @@ __isl_give isl_multi_pw_aff *isl_multi_pw_aff_from_pw_multi_aff(
pa = isl_pw_multi_aff_get_pw_aff(pma, i);
mpa = isl_multi_pw_aff_set_pw_aff(mpa, i, pa);
}
+ if (isl_multi_pw_aff_has_explicit_domain(mpa)) {
+ isl_set *dom;
+
+ dom = isl_pw_multi_aff_domain(isl_pw_multi_aff_copy(pma));
+ mpa = isl_multi_pw_aff_intersect_domain(mpa, dom);
+ }
isl_pw_multi_aff_free(pma);
return mpa;
@@ -6723,6 +6756,9 @@ isl_bool isl_pw_multi_aff_is_equal(__isl_keep isl_pw_multi_aff *pma1,
* In other words, plug in "ma" in "mpa".
*
* The parameters of "mpa" and "ma" are assumed to have been aligned.
+ *
+ * If "mpa" has an explicit domain, then it is this domain
+ * that needs to undergo a pullback, i.e., a preimage.
*/
static __isl_give isl_multi_pw_aff *isl_multi_pw_aff_pullback_multi_aff_aligned(
__isl_take isl_multi_pw_aff *mpa, __isl_take isl_multi_aff *ma)
@@ -6745,6 +6781,12 @@ static __isl_give isl_multi_pw_aff *isl_multi_pw_aff_pullback_multi_aff_aligned(
if (!mpa->u.p[i])
goto error;
}
+ if (isl_multi_pw_aff_has_explicit_domain(mpa)) {
+ mpa->u.dom = isl_set_preimage_multi_aff(mpa->u.dom,
+ isl_multi_aff_copy(ma));
+ if (!mpa->u.dom)
+ goto error;
+ }
isl_multi_aff_free(ma);
isl_space_free(mpa->space);
@@ -6785,6 +6827,9 @@ error:
* In other words, plug in "pma" in "mpa".
*
* The parameters of "mpa" and "mpa" are assumed to have been aligned.
+ *
+ * If "mpa" has an explicit domain, then it is this domain
+ * that needs to undergo a pullback, i.e., a preimage.
*/
static __isl_give isl_multi_pw_aff *
isl_multi_pw_aff_pullback_pw_multi_aff_aligned(
@@ -6806,6 +6851,12 @@ isl_multi_pw_aff_pullback_pw_multi_aff_aligned(
if (!mpa->u.p[i])
goto error;
}
+ if (isl_multi_pw_aff_has_explicit_domain(mpa)) {
+ mpa->u.dom = isl_set_preimage_pw_multi_aff(mpa->u.dom,
+ isl_pw_multi_aff_copy(pma));
+ if (!mpa->u.dom)
+ goto error;
+ }
isl_pw_multi_aff_free(pma);
isl_space_free(mpa->space);
@@ -7036,6 +7087,9 @@ __isl_give isl_pw_aff *isl_pw_aff_pullback_multi_pw_aff(
* The parameters of "mpa1" and "mpa2" are assumed to have been aligned.
*
* We pullback each member of "mpa1" in turn.
+ *
+ * If "mpa1" has an explicit domain, then it is this domain
+ * that needs to undergo a pullback instead, i.e., a preimage.
*/
static __isl_give isl_multi_pw_aff *
isl_multi_pw_aff_pullback_multi_pw_aff_aligned(
@@ -7058,6 +7112,12 @@ isl_multi_pw_aff_pullback_multi_pw_aff_aligned(
goto error;
}
+ if (isl_multi_pw_aff_has_explicit_domain(mpa1)) {
+ mpa1->u.dom = isl_set_preimage_multi_pw_aff(mpa1->u.dom,
+ isl_multi_pw_aff_copy(mpa2));
+ if (!mpa1->u.dom)
+ goto error;
+ }
mpa1 = isl_multi_pw_aff_reset_space(mpa1, space);
isl_multi_pw_aff_free(mpa2);
#define NO_IDENTITY
#define NO_GIST
+#include <isl_multi_explicit_domain.c>
+#include <isl_multi_union_pw_aff_explicit_domain.c>
#include <isl_multi_templ.c>
#include <isl_multi_apply_set.c>
#include <isl_multi_apply_union_set.c>
#include <isl_multi_coalesce.c>
#include <isl_multi_floor.c>
#include <isl_multi_gist.c>
+#include <isl_multi_align_set.c>
+#include <isl_multi_align_union_set.c>
#include <isl_multi_intersect.c>
+/* Does "mupa" have a non-trivial explicit domain?
+ *
+ * The explicit domain, if present, is trivial if it represents
+ * an (obviously) universe parameter set.
+ */
+isl_bool isl_multi_union_pw_aff_has_non_trivial_domain(
+ __isl_keep isl_multi_union_pw_aff *mupa)
+{
+ isl_bool is_params, trivial;
+ isl_set *set;
+
+ if (!mupa)
+ return isl_bool_error;
+ if (!isl_multi_union_pw_aff_has_explicit_domain(mupa))
+ return isl_bool_false;
+ is_params = isl_union_set_is_params(mupa->u.dom);
+ if (is_params < 0 || !is_params)
+ return isl_bool_not(is_params);
+ set = isl_set_from_union_set(isl_union_set_copy(mupa->u.dom));
+ trivial = isl_set_plain_is_universe(set);
+ isl_set_free(set);
+ return isl_bool_not(trivial);
+}
+
/* Construct a multiple union piecewise affine expression
* in the given space with value zero in each of the output dimensions.
*
* the defined expression on the symmetric difference of the domains.
*
* We simply iterate over the elements in both arguments and
- * call isl_union_pw_aff_union_add on each of them.
+ * call isl_union_pw_aff_union_add on each of them, if there is
+ * at least one element.
+ *
+ * Otherwise, the two expressions have an explicit domain and
+ * the union of these explicit domains is computed.
+ * This assumes that the explicit domains are either both in terms
+ * of specific domains elements or both in terms of parameters.
+ * However, if one of the expressions does not have any constraints
+ * on its explicit domain, then this is allowed as well and the result
+ * is the expression with no constraints on its explicit domain.
*/
static __isl_give isl_multi_union_pw_aff *
isl_multi_union_pw_aff_union_add_aligned(
__isl_take isl_multi_union_pw_aff *mupa1,
__isl_take isl_multi_union_pw_aff *mupa2)
{
- return isl_multi_union_pw_aff_bin_op(mupa1, mupa2,
+ isl_bool has_domain, is_params1, is_params2;
+
+ if (isl_multi_union_pw_aff_check_equal_space(mupa1, mupa2) < 0)
+ goto error;
+ if (mupa1->n > 0)
+ return isl_multi_union_pw_aff_bin_op(mupa1, mupa2,
&isl_union_pw_aff_union_add);
+ if (isl_multi_union_pw_aff_check_has_explicit_domain(mupa1) < 0 ||
+ isl_multi_union_pw_aff_check_has_explicit_domain(mupa2) < 0)
+ goto error;
+
+ has_domain = isl_multi_union_pw_aff_has_non_trivial_domain(mupa1);
+ if (has_domain < 0)
+ goto error;
+ if (!has_domain) {
+ isl_multi_union_pw_aff_free(mupa2);
+ return mupa1;
+ }
+ has_domain = isl_multi_union_pw_aff_has_non_trivial_domain(mupa2);
+ if (has_domain < 0)
+ goto error;
+ if (!has_domain) {
+ isl_multi_union_pw_aff_free(mupa1);
+ return mupa2;
+ }
+
+ is_params1 = isl_union_set_is_params(mupa1->u.dom);
+ is_params2 = isl_union_set_is_params(mupa2->u.dom);
+ if (is_params1 < 0 || is_params2 < 0)
+ goto error;
+ if (is_params1 != is_params2)
+ isl_die(isl_multi_union_pw_aff_get_ctx(mupa1),
+ isl_error_invalid,
+ "cannot compute union of concrete domain and "
+ "parameter constraints", goto error);
+ mupa1 = isl_multi_union_pw_aff_cow(mupa1);
+ if (!mupa1)
+ goto error;
+ mupa1->u.dom = isl_union_set_union(mupa1->u.dom,
+ isl_union_set_copy(mupa2->u.dom));
+ if (!mupa1->u.dom)
+ goto error;
+ isl_multi_union_pw_aff_free(mupa2);
+ return mupa1;
+error:
+ isl_multi_union_pw_aff_free(mupa1);
+ isl_multi_union_pw_aff_free(mupa2);
+ return NULL;
}
/* Compute the sum of "mupa1" and "mupa2" on the union of their domains,
@@ -8239,6 +8382,10 @@ static isl_stat extract_space(__isl_take isl_pw_multi_aff *pma, void *user)
*
* In order to be able to perform the conversion, the input
* needs to be non-empty and may only involve a single range space.
+ *
+ * If the resulting multi union piecewise affine expression has
+ * an explicit domain, then assign it the domain of the input.
+ * In other cases, the domain is stored in the individual elements.
*/
__isl_give isl_multi_union_pw_aff *
isl_multi_union_pw_aff_from_union_pw_multi_aff(
@@ -8270,6 +8417,14 @@ isl_multi_union_pw_aff_from_union_pw_multi_aff(
upa = isl_union_pw_multi_aff_get_union_pw_aff(upma, i);
mupa = isl_multi_union_pw_aff_set_union_pw_aff(mupa, i, upa);
}
+ if (isl_multi_union_pw_aff_has_explicit_domain(mupa)) {
+ isl_union_set *dom;
+ isl_union_pw_multi_aff *copy;
+
+ copy = isl_union_pw_multi_aff_copy(upma);
+ dom = isl_union_pw_multi_aff_domain(copy);
+ mupa = isl_multi_union_pw_aff_intersect_domain(mupa, dom);
+ }
isl_union_pw_multi_aff_free(upma);
return mupa;
@@ -8372,6 +8527,10 @@ __isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_multi_aff_on_domain(
/* Return a multiple union piecewise affine expression
* that is equal to "pma" on "domain", assuming "domain" and "pma"
* have been aligned.
+ *
+ * If the resulting multi union piecewise affine expression has
+ * an explicit domain, then assign it the input domain.
+ * In other cases, the domain is stored in the individual elements.
*/
static __isl_give isl_multi_union_pw_aff *
isl_multi_union_pw_aff_pw_multi_aff_on_domain_aligned(
@@ -8396,6 +8555,9 @@ isl_multi_union_pw_aff_pw_multi_aff_on_domain_aligned(
isl_union_set_copy(domain), pa);
mupa = isl_multi_union_pw_aff_set_union_pw_aff(mupa, i, upa);
}
+ if (isl_multi_union_pw_aff_has_explicit_domain(mupa))
+ mupa = isl_multi_union_pw_aff_intersect_domain(mupa,
+ isl_union_set_copy(domain));
isl_union_set_free(domain);
isl_pw_multi_aff_free(pma);
@@ -8437,6 +8599,8 @@ error:
/* Return a union set containing those elements in the domains
* of the elements of "mupa" where they are all zero.
+ *
+ * If there are no elements, then simply return the entire domain.
*/
__isl_give isl_union_set *isl_multi_union_pw_aff_zero_union_set(
__isl_take isl_multi_union_pw_aff *mupa)
@@ -8450,9 +8614,7 @@ __isl_give isl_union_set *isl_multi_union_pw_aff_zero_union_set(
n = isl_multi_union_pw_aff_dim(mupa, isl_dim_set);
if (n == 0)
- isl_die(isl_multi_union_pw_aff_get_ctx(mupa), isl_error_invalid,
- "cannot determine zero set "
- "of zero-dimensional function", goto error);
+ return isl_multi_union_pw_aff_domain(mupa);
upa = isl_multi_union_pw_aff_get_union_pw_aff(mupa, 0);
zero = isl_union_pw_aff_zero_union_set(upa);
@@ -8468,27 +8630,37 @@ __isl_give isl_union_set *isl_multi_union_pw_aff_zero_union_set(
isl_multi_union_pw_aff_free(mupa);
return zero;
-error:
- isl_multi_union_pw_aff_free(mupa);
- return NULL;
}
/* Construct a union map mapping the shared domain
* of the union piecewise affine expressions to the range of "mupa"
* in the special case of a 0D multi union piecewise affine expression.
*
- * There is no way to extract a domain from a zero-dimensional
- * isl_multi_union_pw_aff.
+ * Construct a map between the explicit domain of "mupa" and
+ * the range space.
+ * Note that this assumes that the domain consists of explicit elements.
*/
static __isl_give isl_union_map *isl_union_map_from_multi_union_pw_aff_0D(
__isl_take isl_multi_union_pw_aff *mupa)
{
- isl_die(isl_multi_union_pw_aff_get_ctx(mupa), isl_error_invalid,
- "cannot determine domain of zero-dimensional "
- "isl_multi_union_pw_aff", goto error);
-error:
- isl_multi_union_pw_aff_free(mupa);
- return NULL;
+ isl_bool is_params;
+ isl_space *space;
+ isl_union_set *dom, *ran;
+
+ space = isl_multi_union_pw_aff_get_space(mupa);
+ dom = isl_multi_union_pw_aff_domain(mupa);
+ ran = isl_union_set_from_set(isl_set_universe(space));
+
+ is_params = isl_union_set_is_params(dom);
+ if (is_params < 0)
+ dom = isl_union_set_free(dom);
+ else if (is_params)
+ isl_die(isl_union_set_get_ctx(dom), isl_error_invalid,
+ "cannot create union map from expression without "
+ "explicit domain elements",
+ dom = isl_union_set_free(dom));
+
+ return isl_union_map_from_domain_and_range(dom, ran);
}
/* Construct a union map mapping the shared domain
@@ -8496,8 +8668,8 @@ error:
* with each dimension in the range equated to the
* corresponding union piecewise affine expression.
*
- * The input cannot be zero-dimensional as there is
- * no way to extract a domain from a zero-dimensional isl_multi_union_pw_aff.
+ * If the input is zero-dimensional, then construct a mapping
+ * from its explicit domain.
*/
__isl_give isl_union_map *isl_union_map_from_multi_union_pw_aff(
__isl_take isl_multi_union_pw_aff *mupa)
@@ -8592,26 +8764,29 @@ isl_union_pw_multi_aff_reset_range_space(
* that is equal to the given multi union piecewise affine expression,
* in the special case of a 0D multi union piecewise affine expression.
*
- * There is no way to extract a domain from a zero-dimensional
- * isl_multi_union_pw_aff.
+ * Construct a union piecewise multi affine expression
+ * on top of the explicit domain of the input.
*/
__isl_give isl_union_pw_multi_aff *
isl_union_pw_multi_aff_from_multi_union_pw_aff_0D(
__isl_take isl_multi_union_pw_aff *mupa)
{
- isl_die(isl_multi_union_pw_aff_get_ctx(mupa), isl_error_invalid,
- "cannot determine domain of zero-dimensional "
- "isl_multi_union_pw_aff", goto error);
-error:
- isl_multi_union_pw_aff_free(mupa);
- return NULL;
+ isl_space *space;
+ isl_multi_val *mv;
+ isl_union_set *domain;
+
+ space = isl_multi_union_pw_aff_get_space(mupa);
+ mv = isl_multi_val_zero(space);
+ domain = isl_multi_union_pw_aff_domain(mupa);
+ return isl_union_pw_multi_aff_multi_val_on_domain(domain, mv);
}
/* Construct and return a union piecewise multi affine expression
* that is equal to the given multi union piecewise affine expression.
*
- * In order to be able to perform the conversion, the input
- * needs to have a least one output dimension.
+ * If the input is zero-dimensional, then
+ * construct a union piecewise multi affine expression
+ * on top of the explicit domain of the input.
*/
__isl_give isl_union_pw_multi_aff *
isl_union_pw_multi_aff_from_multi_union_pw_aff(
@@ -8650,19 +8825,15 @@ isl_union_pw_multi_aff_from_multi_union_pw_aff(
/* Intersect the range of "mupa" with "range",
* in the special case where "mupa" is 0D.
*
- * A 0D isl_multi_union_pw_aff does not carry any domain information,
- * so the information in "range" cannot be included.
+ * Intersect the domain of "mupa" with the constraints on the parameters
+ * of "range".
*/
static __isl_give isl_multi_union_pw_aff *mupa_intersect_range_0D(
__isl_take isl_multi_union_pw_aff *mupa, __isl_take isl_set *range)
{
- isl_die(isl_multi_union_pw_aff_get_ctx(mupa), isl_error_invalid,
- "cannot intersect range of zero-dimensional "
- "isl_multi_union_pw_aff", goto error);
-error:
- isl_multi_union_pw_aff_free(mupa);
- isl_set_free(range);
- return NULL;
+ range = isl_set_params(range);
+ mupa = isl_multi_union_pw_aff_intersect_params(mupa, range);
+ return mupa;
}
/* Intersect the range of "mupa" with "range".
/* Return the shared domain of the elements of "mupa",
* in the special case where "mupa" is zero-dimensional.
*
- * There is no way to extract a domain from a zero-dimensional
- * isl_multi_union_pw_aff.
+ * Return the explicit domain of "mupa".
+ * Note that this domain may be a parameter set, either
+ * because "mupa" is meant to live in a set space or
+ * because no explicit domain has been set.
*/
__isl_give isl_union_set *isl_multi_union_pw_aff_domain_0D(
__isl_take isl_multi_union_pw_aff *mupa)
{
- isl_die(isl_multi_union_pw_aff_get_ctx(mupa), isl_error_invalid,
- "cannot determine domain", goto error);
-error:
+ isl_union_set *dom;
+
+ dom = isl_multi_union_pw_aff_get_explicit_domain(mupa);
isl_multi_union_pw_aff_free(mupa);
- return NULL;
+
+ return dom;
}
/* Return the shared domain of the elements of "mupa".
+ *
+ * If "mupa" is zero-dimensional, then return its explicit domain.
*/
__isl_give isl_union_set *isl_multi_union_pw_aff_domain(
__isl_take isl_multi_union_pw_aff *mupa)
/* Apply "ma" to "mupa", in the special case where "mupa" is 0D.
* The space of "mupa" is known to be compatible with the domain of "ma".
*
- * This function is currently only called when the number of output
- * dimensions of "ma" is greater than zero, in which case no result
- * can be computed because a 0D isl_multi_union_pw_aff
- * does not carry any domain information.
+ * Construct an isl_multi_union_pw_aff that is equal to "ma"
+ * on the domain of "mupa".
*/
static __isl_give isl_multi_union_pw_aff *mupa_apply_multi_aff_0D(
__isl_take isl_multi_union_pw_aff *mupa, __isl_take isl_multi_aff *ma)
{
- isl_die(isl_multi_aff_get_ctx(ma), isl_error_invalid,
- "cannot determine domains", goto error);
-error:
- isl_multi_union_pw_aff_free(mupa);
- isl_multi_aff_free(ma);
- return NULL;
+ isl_union_set *dom;
+
+ dom = isl_multi_union_pw_aff_domain(mupa);
+ ma = isl_multi_aff_project_domain_on_params(ma);
+
+ return isl_multi_union_pw_aff_multi_aff_on_domain(dom, ma);
}
/* Apply "ma" to "mupa". The space of "mupa" needs to be compatible
* with the domain of "ma".
- * Furthermore, the dimension of this space needs to be greater than zero,
- * unless the dimension of the target space of "ma" is also zero.
* The result is defined over the shared domain of the elements of "mupa"
*/
__isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_apply_multi_aff(
@@ -8908,7 +9080,7 @@ __isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_apply_multi_aff(
isl_die(isl_multi_aff_get_ctx(ma), isl_error_invalid,
"spaces don't match", goto error);
n_out = isl_multi_aff_dim(ma, isl_dim_out);
- if (isl_multi_aff_dim(ma, isl_dim_in) == 0 && n_out != 0)
+ if (isl_multi_aff_dim(ma, isl_dim_in) == 0)
return mupa_apply_multi_aff_0D(mupa, ma);
space1 = isl_space_range(isl_multi_aff_get_space(ma));
/* Apply "pa" to "mupa", in the special case where "mupa" is 0D.
* The space of "mupa" is known to be compatible with the domain of "pa".
*
- * The result cannot be computed because a 0D isl_multi_union_pw_aff
- * does not carry any domain information.
+ * Construct an isl_multi_union_pw_aff that is equal to "pa"
+ * on the domain of "mupa".
*/
static __isl_give isl_union_pw_aff *isl_multi_union_pw_aff_apply_pw_aff_0D(
__isl_take isl_multi_union_pw_aff *mupa, __isl_take isl_pw_aff *pa)
{
- isl_die(isl_pw_aff_get_ctx(pa), isl_error_invalid,
- "cannot determine domains", goto error);
-error:
- isl_multi_union_pw_aff_free(mupa);
- isl_pw_aff_free(pa);
- return NULL;
+ isl_union_set *dom;
+
+ dom = isl_multi_union_pw_aff_domain(mupa);
+ pa = isl_pw_aff_project_domain_on_params(pa);
+
+ return isl_union_pw_aff_pw_aff_on_domain(dom, pa);
}
/* Apply "pa" to "mupa". The space of "mupa" needs to be compatible
/* Apply "pma" to "mupa", in the special case where "mupa" is 0D.
* The space of "mupa" is known to be compatible with the domain of "pma".
*
- * This function is currently only called when the number of output
- * dimensions of "pma" is greater than zero, in which case no result
- * can be computed because a 0D isl_multi_union_pw_aff
- * does not carry any domain information.
+ * Construct an isl_multi_union_pw_aff that is equal to "pma"
+ * on the domain of "mupa".
*/
static __isl_give isl_multi_union_pw_aff *mupa_apply_pw_multi_aff_0D(
__isl_take isl_multi_union_pw_aff *mupa,
__isl_take isl_pw_multi_aff *pma)
{
- isl_die(isl_pw_multi_aff_get_ctx(pma), isl_error_invalid,
- "cannot determine domains", goto error);
-error:
- isl_multi_union_pw_aff_free(mupa);
- isl_pw_multi_aff_free(pma);
- return NULL;
+ isl_union_set *dom;
+
+ dom = isl_multi_union_pw_aff_domain(mupa);
+ pma = isl_pw_multi_aff_project_domain_on_params(pma);
+
+ return isl_multi_union_pw_aff_pw_multi_aff_on_domain(dom, pma);
}
/* Apply "pma" to "mupa". The space of "mupa" needs to be compatible
* with the domain of "pma".
- * Furthermore, the dimension of this space needs to be greater than zero,
- * unless the dimension of the target space of "pma" is also zero.
* The result is defined over the shared domain of the elements of "mupa"
*/
__isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_apply_pw_multi_aff(
@@ -9062,7 +9230,7 @@ __isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_apply_pw_multi_aff(
isl_die(isl_pw_multi_aff_get_ctx(pma), isl_error_invalid,
"spaces don't match", goto error);
n_out = isl_pw_multi_aff_dim(pma, isl_dim_out);
- if (isl_pw_multi_aff_dim(pma, isl_dim_in) == 0 && n_out != 0)
+ if (isl_pw_multi_aff_dim(pma, isl_dim_in) == 0)
return mupa_apply_pw_multi_aff_0D(mupa, pma);
space1 = isl_space_range(isl_pw_multi_aff_get_space(pma));
return NULL;
}
+/* Replace the explicit domain of "mupa" by its preimage under "upma".
+ * If the explicit domain only keeps track of constraints on the parameters,
+ * then only update those constraints.
+ */
+static __isl_give isl_multi_union_pw_aff *preimage_explicit_domain(
+ __isl_take isl_multi_union_pw_aff *mupa,
+ __isl_keep isl_union_pw_multi_aff *upma)
+{
+ isl_bool is_params;
+
+ if (isl_multi_union_pw_aff_check_has_explicit_domain(mupa) < 0)
+ return isl_multi_union_pw_aff_free(mupa);
+
+ mupa = isl_multi_union_pw_aff_cow(mupa);
+ if (!mupa)
+ return NULL;
+
+ is_params = isl_union_set_is_params(mupa->u.dom);
+ if (is_params < 0)
+ return isl_multi_union_pw_aff_free(mupa);
+
+ upma = isl_union_pw_multi_aff_copy(upma);
+ if (is_params)
+ mupa->u.dom = isl_union_set_intersect_params(mupa->u.dom,
+ isl_union_set_params(isl_union_pw_multi_aff_domain(upma)));
+ else
+ mupa->u.dom = isl_union_set_preimage_union_pw_multi_aff(
+ mupa->u.dom, upma);
+ if (!mupa->u.dom)
+ return isl_multi_union_pw_aff_free(mupa);
+ return mupa;
+}
+
/* Compute the pullback of "mupa" by the function represented by "upma".
* In other words, plug in "upma" in "mupa". The result contains
* expressions defined over the domain space of "upma".
*
* Run over all elements of "mupa" and plug in "upma" in each of them.
+ *
+ * If "mupa" has an explicit domain, then it is this domain
+ * that needs to undergo a pullback instead, i.e., a preimage.
*/
__isl_give isl_multi_union_pw_aff *
isl_multi_union_pw_aff_pullback_union_pw_multi_aff(
@@ -9104,6 +9308,7 @@ isl_multi_union_pw_aff_pullback_union_pw_multi_aff(
isl_union_pw_multi_aff_get_space(upma));
upma = isl_union_pw_multi_aff_align_params(upma,
isl_multi_union_pw_aff_get_space(mupa));
+ mupa = isl_multi_union_pw_aff_cow(mupa);
if (!mupa || !upma)
goto error;
@@ -9117,6 +9322,9 @@ isl_multi_union_pw_aff_pullback_union_pw_multi_aff(
mupa = isl_multi_union_pw_aff_set_union_pw_aff(mupa, i, upa);
}
+ if (isl_multi_union_pw_aff_has_explicit_domain(mupa))
+ mupa = preimage_explicit_domain(mupa, upma);
+
isl_union_pw_multi_aff_free(upma);
return mupa;
error:
@@ -159,9 +159,14 @@ __isl_give isl_basic_set *isl_aff_pos_basic_set(__isl_take isl_aff *aff);
#undef BASE
#define BASE pw_aff
+#undef DOMBASE
+#define DOMBASE set
+#define EXPLICIT_DOMAIN
#include <isl_multi_templ.h>
+#undef EXPLICIT_DOMAIN
+
#undef EL
#define EL isl_union_pw_aff
@@ -169,9 +174,14 @@ __isl_give isl_basic_set *isl_aff_pos_basic_set(__isl_take isl_aff *aff);
#undef BASE
#define BASE union_pw_aff
+#undef DOMBASE
+#define DOMBASE union_set
+#define EXPLICIT_DOMAIN
#include <isl_multi_templ.h>
+#undef EXPLICIT_DOMAIN
+
#undef EL
#define EL isl_union_pw_multi_aff
@@ -3723,6 +3723,9 @@ __isl_give isl_multi_aff *isl_multi_aff_read_from_str(isl_ctx *ctx,
* The input format is similar to that of map, except that any conditions
* on the domains should be specified inside the tuple since each
* piecewise affine expression may have a different domain.
+ * However, additional, shared conditions can also be specified.
+ * This is especially useful for setting the explicit domain
+ * of a zero-dimensional isl_multi_pw_aff.
*
* Since we do not know in advance if the isl_multi_pw_aff lives
* in a set or a map space, we first read the first tuple and check
@@ -3765,6 +3768,9 @@ __isl_give isl_multi_pw_aff *isl_stream_read_multi_pw_aff(
goto error;
}
+ if (isl_stream_eat_if_available(s, ':'))
+ dom = read_formula(s, v, dom, 0);
+
if (isl_stream_eat(s, '}'))
goto error;
@@ -3970,8 +3976,9 @@ static int next_is_param_tuple(__isl_keep isl_stream *s)
return is_tuple;
}
-/* Read the body of an isl_multi_union_pw_aff from "s",
- * i.e., everything except the parameter specification.
+/* Read the core of a body of an isl_multi_union_pw_aff from "s",
+ * i.e., everything except the parameter specification and
+ * without shared domain constraints.
* "v" contains a description of the identifiers parsed so far.
* The parameters, if any, are specified by "space".
*
@@ -3983,7 +3990,7 @@ static int next_is_param_tuple(__isl_keep isl_stream *s)
* elements in a list and construct the result from the tuple space and
* the list.
*/
-static __isl_give isl_multi_union_pw_aff *read_multi_union_pw_aff_body(
+static __isl_give isl_multi_union_pw_aff *read_multi_union_pw_aff_body_core(
__isl_keep isl_stream *s, struct vars *v, __isl_take isl_space *space)
{
isl_union_pw_aff_list *list;
@@ -3997,6 +4004,78 @@ static __isl_give isl_multi_union_pw_aff *read_multi_union_pw_aff_body(
return mupa;
}
+/* Read the body of an isl_union_set from "s",
+ * i.e., everything except the parameter specification.
+ * "v" contains a description of the identifiers parsed so far.
+ * The parameters, if any, are specified by "space".
+ *
+ * First read a generic disjunction of object bodies and then try and extract
+ * an isl_union_set from that.
+ */
+static __isl_give isl_union_set *read_union_set_body(__isl_keep isl_stream *s,
+ struct vars *v, __isl_take isl_space *space)
+{
+ struct isl_obj obj = { isl_obj_set, NULL };
+ isl_map *map;
+
+ map = isl_set_universe(space);
+ if (isl_stream_eat(s, '{') < 0)
+ goto error;
+ obj = obj_read_disjuncts(s, v, map);
+ if (isl_stream_eat(s, '}') < 0)
+ goto error;
+ isl_map_free(map);
+
+ return extract_union_set(s->ctx, obj);
+error:
+ obj.type->free(obj.v);
+ isl_map_free(map);
+ return NULL;
+}
+
+/* Read the body of an isl_multi_union_pw_aff from "s",
+ * i.e., everything except the parameter specification.
+ * "v" contains a description of the identifiers parsed so far.
+ * The parameters, if any, are specified by "space".
+ *
+ * In particular, handle the special case with shared domain constraints.
+ * These are specified as
+ *
+ * ([...] : ...)
+ *
+ * and are especially useful for setting the explicit domain
+ * of a zero-dimensional isl_multi_union_pw_aff.
+ * The core isl_multi_union_pw_aff body ([...]) is read by
+ * read_multi_union_pw_aff_body_core.
+ */
+static __isl_give isl_multi_union_pw_aff *read_multi_union_pw_aff_body(
+ __isl_keep isl_stream *s, struct vars *v, __isl_take isl_space *space)
+{
+ isl_multi_union_pw_aff *mupa;
+
+ if (!isl_stream_next_token_is(s, '('))
+ return read_multi_union_pw_aff_body_core(s, v, space);
+
+ if (isl_stream_eat(s, '(') < 0)
+ goto error;
+ mupa = read_multi_union_pw_aff_body_core(s, v, isl_space_copy(space));
+ if (isl_stream_eat_if_available(s, ':')) {
+ isl_union_set *dom;
+
+ dom = read_union_set_body(s, v, space);
+ mupa = isl_multi_union_pw_aff_intersect_domain(mupa, dom);
+ } else {
+ isl_space_free(space);
+ }
+ if (isl_stream_eat(s, ')') < 0)
+ return isl_multi_union_pw_aff_free(mupa);
+
+ return mupa;
+error:
+ isl_space_free(space);
+ return NULL;
+}
+
/* Read an isl_multi_union_pw_aff from "s".
*
* The input has the form
@@ -4007,11 +4086,22 @@ static __isl_give isl_multi_union_pw_aff *read_multi_union_pw_aff_body(
*
* [..] -> [{ [..] : ... ; [..] : ... }, { [..] : ... ; [..] : ... }]
*
+ * Additionally, a shared domain may be specified as
+ *
+ * ([..] : ...)
+ *
+ * or
+ *
+ * [..] -> ([..] : ...)
+ *
+ * The first case is handled by the caller, the second case
+ * is handled by read_multi_union_pw_aff_body.
+ *
* We first check for the special case of an empty tuple "[]".
* Then we check if there are any parameters.
* Finally, read the tuple and construct the result.
*/
-__isl_give isl_multi_union_pw_aff *isl_stream_read_multi_union_pw_aff(
+static __isl_give isl_multi_union_pw_aff *read_multi_union_pw_aff_core(
__isl_keep isl_stream *s)
{
struct vars *v;
return NULL;
}
+/* Read an isl_multi_union_pw_aff from "s".
+ *
+ * In particular, handle the special case with shared domain constraints.
+ * These are specified as
+ *
+ * ([...] : ...)
+ *
+ * and are especially useful for setting the explicit domain
+ * of a zero-dimensional isl_multi_union_pw_aff.
+ * The core isl_multi_union_pw_aff ([...]) is read by
+ * read_multi_union_pw_aff_core.
+ */
+__isl_give isl_multi_union_pw_aff *isl_stream_read_multi_union_pw_aff(
+ __isl_keep isl_stream *s)
+{
+ isl_multi_union_pw_aff *mupa;
+
+ if (!isl_stream_next_token_is(s, '('))
+ return read_multi_union_pw_aff_core(s);
+
+ if (isl_stream_eat(s, '(') < 0)
+ return NULL;
+ mupa = read_multi_union_pw_aff_core(s);
+ if (isl_stream_eat_if_available(s, ':')) {
+ isl_union_set *dom;
+
+ dom = isl_stream_read_union_set(s);
+ mupa = isl_multi_union_pw_aff_intersect_domain(mupa, dom);
+ }
+ if (isl_stream_eat(s, ')') < 0)
+ return isl_multi_union_pw_aff_free(mupa);
+ return mupa;
+}
+
/* Read an isl_multi_union_pw_aff from "str".
*/
__isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_read_from_str(
@@ -13399,18 +13399,26 @@ __isl_give isl_map *isl_map_preimage_range_pw_multi_aff(
* We create a separate isl_multi_aff to effectuate this change
* in order to avoid spurious splitting of the map along the pieces
* of "mpa".
+ * If "mpa" has a non-trivial explicit domain, however,
+ * then the full substitution should be performed.
*/
__isl_give isl_map *isl_map_preimage_multi_pw_aff(__isl_take isl_map *map,
enum isl_dim_type type, __isl_take isl_multi_pw_aff *mpa)
{
int n;
+ isl_bool full;
isl_pw_multi_aff *pma;
if (!map || !mpa)
goto error;
n = isl_map_dim(map, type);
- if (!isl_map_involves_dims(map, type, 0, n)) {
+ full = isl_map_involves_dims(map, type, 0, n);
+ if (full >= 0 && !full)
+ full = isl_multi_pw_aff_has_non_trivial_domain(mpa);
+ if (full < 0)
+ goto error;
+ if (!full) {
isl_space *space;
isl_multi_aff *ma;
--- /dev/null
+#define ALIGN_DOMBASE set
+#define ALIGN_DOM isl_set
+
+#include <isl_multi_align_templ.c>
+
+#undef ALIGN_DOMBASE
+#undef ALIGN_DOM
--- /dev/null
+/*
+ * Copyright 2017 Sven Verdoolaege
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege,
+ */
+
+/* Align the parameters of "multi" and "domain" (if needed) and
+ * call "fn".
+ */
+static __isl_give MULTI(BASE) *FN(FN(MULTI(BASE),align_params),ALIGN_DOMBASE)(
+ __isl_take MULTI(BASE) *multi, __isl_take ALIGN_DOM *domain,
+ __isl_give MULTI(BASE) *fn(__isl_take MULTI(BASE) *multi,
+ __isl_take ALIGN_DOM *domain))
+{
+ isl_bool aligned;
+ isl_bool named;
+ isl_space *dom_space;
+
+ aligned = FN(ALIGN_DOM,space_has_equal_params)(domain, multi->space);
+ if (aligned < 0)
+ goto error;
+ if (aligned)
+ return fn(multi, domain);
+
+ dom_space = FN(ALIGN_DOM,peek_space)(domain);
+ named = isl_space_has_named_params(multi->space);
+ if (named >= 0 && named)
+ named = isl_space_has_named_params(dom_space);
+ if (named < 0)
+ goto error;
+ if (!named)
+ isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_invalid,
+ "unaligned unnamed parameters", goto error);
+ multi = FN(MULTI(BASE),align_params)(multi,
+ FN(ALIGN_DOM,get_space)(domain));
+ domain = FN(ALIGN_DOM,align_params)(domain,
+ FN(MULTI(BASE),get_space)(multi));
+ return fn(multi, domain);
+error:
+ FN(MULTI(BASE),free)(multi);
+ FN(ALIGN_DOM,free)(domain);
+ return NULL;
+}
--- /dev/null
+#define ALIGN_DOMBASE union_set
+#define ALIGN_DOM isl_union_set
+
+#include <isl_multi_align_templ.c>
+
+#undef ALIGN_DOMBASE
+#undef ALIGN_DOM
@@ -23,7 +23,7 @@ isl_bool FN(MULTI(BASE),involves_dims)(__isl_keep MULTI(BASE) *multi,
if (!multi)
return isl_bool_error;
- if (multi->n == 0 || n == 0)
+ if (n == 0)
return isl_bool_false;
for (i = 0; i < multi->n; ++i) {
@@ -34,6 +34,10 @@ isl_bool FN(MULTI(BASE),involves_dims)(__isl_keep MULTI(BASE) *multi,
return involves;
}
+ if (FN(MULTI(BASE),has_explicit_domain)(multi))
+ return FN(MULTI(BASE),involves_explicit_domain_dims)(multi,
+ type, first, n);
+
return isl_bool_false;
}
@@ -59,6 +63,11 @@ __isl_give MULTI(BASE) *FN(MULTI(BASE),insert_dims)(
multi->space = isl_space_insert_dims(multi->space, type, first, n);
if (!multi->space)
return FN(MULTI(BASE),free)(multi);
+ if (FN(MULTI(BASE),has_explicit_domain)(multi))
+ multi = FN(MULTI(BASE),insert_explicit_domain_dims)(multi,
+ type, first, n);
+ if (!multi)
+ return NULL;
for (i = 0; i < multi->n; ++i) {
multi->u.p[i] = FN(EL,insert_dims)(multi->u.p[i],
--- /dev/null
+/*
+ * Copyright 2017 Sven Verdoolaege
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege.
+ */
+
+/* These versions of the explicit domain functions are used
+ * when the multi expression may have an explicit domain.
+ */
+
+#include <isl_multi_macro.h>
+
+__isl_give MULTI(BASE) *FN(MULTI(BASE),cow)(__isl_take MULTI(BASE) *multi);
+
+/* Does "multi" have an explicit domain?
+ *
+ * An explicit domain is only available if "multi" is zero-dimensional.
+ */
+static int FN(MULTI(BASE),has_explicit_domain)(__isl_keep MULTI(BASE) *multi)
+{
+ return multi && multi->n == 0;
+}
+
+/* Check that "multi" has an explicit domain.
+ */
+static isl_stat FN(MULTI(BASE),check_has_explicit_domain)(
+ __isl_keep MULTI(BASE) *multi)
+{
+ if (!multi)
+ return isl_stat_error;
+ if (!FN(MULTI(BASE),has_explicit_domain)(multi))
+ isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_internal,
+ "expression does not have an explicit domain",
+ return isl_stat_error);
+ return isl_stat_ok;
+}
+
+/* Return the explicit domain of "multi", assuming it has one.
+ */
+static __isl_give DOM *FN(MULTI(BASE),get_explicit_domain)(
+ __isl_keep MULTI(BASE) *multi)
+{
+ if (FN(MULTI(BASE),check_has_explicit_domain)(multi) < 0)
+ return NULL;
+ return FN(DOM,copy)(multi->u.dom);
+}
+
+/* Replace the explicit domain of "multi" by "dom", assuming it has one.
+ */
+static __isl_give MULTI(BASE) *FN(MULTI(BASE),set_explicit_domain)(
+ __isl_take MULTI(BASE) *multi, __isl_take DOM *dom)
+{
+ if (FN(MULTI(BASE),check_has_explicit_domain)(multi) < 0)
+ goto error;
+ multi = FN(MULTI(BASE),cow)(multi);
+ if (!multi || !dom)
+ goto error;
+ FN(DOM,free)(multi->u.dom);
+ multi->u.dom = dom;
+ if (!multi->u.dom)
+ return FN(MULTI(BASE),free)(multi);
+ return multi;
+error:
+ FN(MULTI(BASE),free)(multi);
+ FN(DOM,free)(dom);
+ return NULL;
+}
+
+/* Intersect the domain of "dst" with the explicit domain of "src".
+ */
+static __isl_give MULTI(BASE) *FN(MULTI(BASE),intersect_explicit_domain)(
+ __isl_take MULTI(BASE) *dst, __isl_keep MULTI(BASE) *src)
+{
+ DOM *dom;
+
+ dom = FN(MULTI(BASE),get_explicit_domain)(src);
+ dst = FN(MULTI(BASE),intersect_domain)(dst, dom);
+
+ return dst;
+}
+
+/* Set the explicit domain of "dst" to that of "src".
+ */
+static __isl_give MULTI(BASE) *FN(MULTI(BASE),copy_explicit_domain)(
+ __isl_take MULTI(BASE) *dst, __isl_keep MULTI(BASE) *src)
+{
+ DOM *dom;
+
+ dom = FN(MULTI(BASE),get_explicit_domain)(src);
+ dst = FN(MULTI(BASE),set_explicit_domain)(dst, dom);
+
+ return dst;
+}
+
+/* Align the parameters of the explicit domain of "multi" to those of "space".
+ */
+static __isl_give MULTI(BASE) *FN(MULTI(BASE),align_explicit_domain_params)(
+ __isl_take MULTI(BASE) *multi, __isl_take isl_space *space)
+{
+ DOM *dom;
+
+ dom = FN(MULTI(BASE),get_explicit_domain)(multi);
+ dom = FN(DOM,align_params)(dom, space);
+ multi = FN(MULTI(BASE),set_explicit_domain)(multi, dom);
+
+ return multi;
+}
+
+/* Replace the space of the explicit domain of "multi" by "space",
+ * without modifying its dimension.
+ */
+static __isl_give MULTI(BASE) *FN(MULTI(BASE),reset_explicit_domain_space)(
+ __isl_take MULTI(BASE) *multi, __isl_take isl_space *space)
+{
+ DOM *dom;
+
+ dom = FN(MULTI(BASE),get_explicit_domain)(multi);
+ dom = FN(DOM,reset_equal_dim_space)(dom, space);
+ multi = FN(MULTI(BASE),set_explicit_domain)(multi, dom);
+
+ return multi;
+}
+
+/* Free the explicit domain of "multi".
+ */
+static void FN(MULTI(BASE),free_explicit_domain)(__isl_keep MULTI(BASE) *multi)
+{
+ if (FN(MULTI(BASE),check_has_explicit_domain)(multi) < 0)
+ return;
+ FN(DOM,free)(multi->u.dom);
+}
+
+/* Do "multi1" and "multi2" have the same explicit domain?
+ */
+static isl_bool FN(MULTI(BASE),equal_explicit_domain)(
+ __isl_keep MULTI(BASE) *multi1, __isl_keep MULTI(BASE) *multi2)
+{
+ DOM *dom1, *dom2;
+ isl_bool equal;
+
+ if (FN(MULTI(BASE),check_has_explicit_domain)(multi1) < 0 ||
+ FN(MULTI(BASE),check_has_explicit_domain)(multi2) < 0)
+ return isl_bool_error;
+ dom1 = FN(MULTI(BASE),get_explicit_domain)(multi1);
+ dom2 = FN(MULTI(BASE),get_explicit_domain)(multi2);
+ equal = FN(DOM,is_equal)(dom1, dom2);
+ FN(DOM,free)(dom1);
+ FN(DOM,free)(dom2);
+
+ return equal;
+}
+
+static isl_stat FN(MULTI(BASE),check_explicit_domain)(
+ __isl_keep MULTI(BASE) *multi) __attribute__ ((unused));
+
+/* Debugging function to check that the explicit domain of "multi"
+ * has the correct space.
+ */
+isl_stat FN(MULTI(BASE),check_explicit_domain)(__isl_keep MULTI(BASE) *multi)
+{
+ isl_space *space1, *space2;
+ isl_bool equal;
+
+ if (FN(MULTI(BASE),check_has_explicit_domain)(multi) < 0)
+ return isl_stat_error;
+ space1 = isl_space_domain(isl_space_copy(multi->space));
+ space2 = FN(DOM,get_space)(multi->u.dom);
+ equal = isl_space_is_equal(space1, space2);
+ isl_space_free(space1);
+ isl_space_free(space2);
+ if (equal < 0)
+ return isl_stat_error;
+ if (!equal)
+ isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_internal,
+ "check failed", return isl_stat_error);
+ return isl_stat_ok;
+}
#include <isl_multi_macro.h>
+/* Does the space of "domain" correspond to that of the domain of "multi"?
+ * The parameters do not need to be aligned.
+ */
+static isl_bool FN(MULTI(BASE),compatible_domain)(
+ __isl_keep MULTI(BASE) *multi, __isl_keep DOM *domain)
+{
+ isl_bool ok;
+ isl_space *space, *domain_space;
+
+ domain_space = FN(DOM,get_space)(domain);
+ space = FN(MULTI(BASE),get_space)(multi);
+ ok = isl_space_has_domain_tuples(domain_space, space);
+ isl_space_free(space);
+ isl_space_free(domain_space);
+
+ return ok;
+}
+
+/* Check that the space of "domain" corresponds to
+ * that of the domain of "multi", ignoring parameters.
+ */
+static isl_stat FN(MULTI(BASE),check_compatible_domain)(
+ __isl_keep MULTI(BASE) *multi, __isl_keep DOM *domain)
+{
+ isl_bool ok;
+
+ ok = FN(MULTI(BASE),compatible_domain)(multi, domain);
+ if (ok < 0)
+ return isl_stat_error;
+ if (!ok)
+ isl_die(FN(DOM,get_ctx)(domain), isl_error_invalid,
+ "incompatible spaces", return isl_stat_error);
+
+ return isl_stat_ok;
+}
+
+/* Intersect the explicit domain of "multi" with "domain".
+ *
+ * The parameters of "multi" and "domain" are assumed to have been aligned.
+ *
+ * In the case of an isl_multi_union_pw_aff object, the explicit domain
+ * is allowed to have only constraints on the parameters, while
+ * "domain" contains actual domain elements. In this case,
+ * "domain" is intersected with those parameter constraints and
+ * then used as the explicit domain of "multi".
+ */
+static __isl_give MULTI(BASE) *FN(MULTI(BASE),domain_intersect_aligned)(
+ __isl_take MULTI(BASE) *multi, __isl_take DOM *domain)
+{
+ isl_bool is_params;
+ DOM *multi_dom;
+
+ if (FN(MULTI(BASE),check_compatible_domain)(multi, domain) < 0)
+ goto error;
+ if (FN(MULTI(BASE),check_has_explicit_domain)(multi) < 0)
+ goto error;
+ is_params = FN(DOM,is_params)(multi->u.dom);
+ if (is_params < 0)
+ goto error;
+ multi_dom = FN(MULTI(BASE),get_explicit_domain)(multi);
+ if (!is_params) {
+ domain = FN(DOM,intersect)(multi_dom, domain);
+ } else {
+ isl_set *params;
+
+ params = FN(DOM,params)(multi_dom);
+ domain = FN(DOM,intersect_params)(domain, params);
+ }
+ multi = FN(MULTI(BASE),set_explicit_domain)(multi, domain);
+ return multi;
+error:
+ FN(MULTI(BASE),free)(multi);
+ FN(DOM,free)(domain);
+ return NULL;
+}
+
+/* Intersect the explicit domain of "multi" with "domain".
+ * First align the parameters, if needed.
+ */
+static __isl_give MULTI(BASE) *FN(MULTI(BASE),domain_intersect)(
+ __isl_take MULTI(BASE) *multi, __isl_take DOM *domain)
+{
+ return FN(FN(MULTI(BASE),align_params),DOMBASE)(multi, domain,
+ FN(MULTI(BASE),domain_intersect_aligned));
+}
+
/* Intersect the domain of "multi" with "domain".
+ *
+ * If "multi" has an explicit domain, then only this domain
+ * needs to be intersected.
*/
__isl_give MULTI(BASE) *FN(MULTI(BASE),intersect_domain)(
__isl_take MULTI(BASE) *multi, __isl_take DOM *domain)
{
+ if (FN(MULTI(BASE),has_explicit_domain)(multi))
+ return FN(MULTI(BASE),domain_intersect)(multi, domain);
return FN(FN(MULTI(BASE),apply),DOMBASE)(multi, domain,
&FN(EL,intersect_domain));
}
+/* Intersect the parameter domain of the explicit domain of "multi"
+ * with "domain".
+ */
+static __isl_give MULTI(BASE) *FN(MULTI(BASE),domain_intersect_params_aligned)(
+ __isl_take MULTI(BASE) *multi, __isl_take isl_set *domain)
+{
+ DOM *multi_dom;
+
+ multi_dom = FN(MULTI(BASE),get_explicit_domain)(multi);
+ multi_dom = FN(DOM,intersect_params)(multi_dom, domain);
+ multi = FN(MULTI(BASE),set_explicit_domain)(multi, multi_dom);
+
+ return multi;
+}
+
+/* Intersect the parameter domain of the explicit domain of "multi"
+ * with "domain".
+ * First align the parameters, if needed.
+ */
+static __isl_give MULTI(BASE) *FN(MULTI(BASE),domain_intersect_params)(
+ __isl_take MULTI(BASE) *multi, __isl_take isl_set *domain)
+{
+ return FN(FN(MULTI(BASE),align_params),set)(multi, domain,
+ FN(MULTI(BASE),domain_intersect_params_aligned));
+}
+
/* Intersect the parameter domain of "multi" with "domain".
+ *
+ * If "multi" has an explicit domain, then only this domain
+ * needs to be intersected.
*/
__isl_give MULTI(BASE) *FN(MULTI(BASE),intersect_params)(
__isl_take MULTI(BASE) *multi, __isl_take isl_set *domain)
{
+ if (FN(MULTI(BASE),has_explicit_domain)(multi))
+ return FN(MULTI(BASE),domain_intersect_params)(multi, domain);
return FN(MULTI(BASE),apply_set)(multi, domain,
&FN(EL,intersect_params));
}
--- /dev/null
+/*
+ * Copyright 2017 Sven Verdoolaege
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege.
+ */
+
+/* These versions of the explicit domain functions are used
+ * when the multi expression cannot have an explicit domain.
+ */
+
+#include <isl_multi_macro.h>
+
+/* Does "multi" have an explicit domain?
+ *
+ * No.
+ */
+static int FN(MULTI(BASE),has_explicit_domain)(__isl_keep MULTI(BASE) *multi)
+{
+ return 0;
+}
+
+/* Initialize the explicit domain of "multi".
+ * "multi" cannot have an explicit domain, so this function is never called.
+ */
+static __isl_give MULTI(BASE) *FN(MULTI(BASE),init_explicit_domain)(
+ __isl_take MULTI(BASE) *multi)
+{
+ return multi;
+}
+
+/* Intersect the domain of "dst" with the explicit domain of "src".
+ * "src" cannot have an explicit domain, so this function is never called.
+ */
+static __isl_give MULTI(BASE) *FN(MULTI(BASE),intersect_explicit_domain)(
+ __isl_take MULTI(BASE) *dst, __isl_keep MULTI(BASE) *src)
+{
+ return dst;
+}
+
+/* Set the explicit domain of "dst" to that of "src".
+ * "src" and "dst" cannot have an explicit domain,
+ * so this function is never called.
+ */
+static __isl_give MULTI(BASE) *FN(MULTI(BASE),copy_explicit_domain)(
+ __isl_take MULTI(BASE) *dst, __isl_keep MULTI(BASE) *src)
+{
+ return dst;
+}
+
+/* Intersect the domain of "dst" with the domain product
+ * of the explicit domains of "src1" and "src2".
+ * This function is only called if at least one of "src1" or "src2"
+ * has an explicit domain.
+ * "src1", "src2" and "dst" cannot have an explicit domain,
+ * so this function is never called.
+ */
+static __isl_give MULTI(BASE) *
+FN(MULTI(BASE),intersect_explicit_domain_product)(
+ __isl_take MULTI(BASE) *dst, __isl_keep MULTI(BASE) *src1,
+ __isl_keep MULTI(BASE) *src2)
+{
+ return dst;
+}
+
+/* Align the parameters of the explicit domain of "multi" to those of "space".
+ * "multi" cannot have an explicit domain, so this function is never called.
+ */
+static __isl_give MULTI(BASE) *FN(MULTI(BASE),align_explicit_domain_params)(
+ __isl_take MULTI(BASE) *multi, __isl_take isl_space *space)
+{
+ isl_space_free(space);
+ return multi;
+}
+
+/* Replace the space of the explicit domain of "multi" by "space",
+ * without modifying its dimension.
+ * "multi" cannot have an explicit domain, so this function is never called.
+ */
+static __isl_give MULTI(BASE) *FN(MULTI(BASE),reset_explicit_domain_space)(
+ __isl_take MULTI(BASE) *multi, __isl_take isl_space *space)
+{
+ isl_space_free(space);
+ return multi;
+}
+
+/* Check whether the explicit domain of "multi" has non-zero coefficients
+ * for any dimension in the given range or if any of these dimensions appear
+ * with non-zero coefficients in any of the integer divisions involved.
+ * "multi" cannot have an explicit domain, so this function is never called.
+ */
+isl_bool FN(MULTI(BASE),involves_explicit_domain_dims)(
+ __isl_keep MULTI(BASE) *multi,
+ enum isl_dim_type type, unsigned pos, unsigned n)
+{
+ return isl_bool_false;
+}
+
+/* Insert "n" dimensions of type "type" at position "pos"
+ * of the explicit domain of "multi".
+ * "multi" cannot have an explicit domain, so this function is never called.
+ */
+__isl_give MULTI(BASE) *FN(MULTI(BASE),insert_explicit_domain_dims)(
+ __isl_take MULTI(BASE) *multi,
+ enum isl_dim_type type, unsigned pos, unsigned n)
+{
+ return multi;
+}
+
+/* Drop the "n" dimensions of type "type" starting at position "pos"
+ * of the explicit domain of "multi".
+ * "multi" cannot have an explicit domain, so this function is never called.
+ */
+__isl_give MULTI(BASE) *FN(MULTI(BASE),drop_explicit_domain_dims)(
+ __isl_take MULTI(BASE) *multi,
+ enum isl_dim_type type, unsigned pos, unsigned n)
+{
+ return multi;
+}
+
+/* Move the "n" dimensions of "src_type" starting at "src_pos" of
+ * of the explicit domain of "multi" to dimensions of "dst_type" at "dst_pos".
+ * "multi" cannot have an explicit domain, so this function is never called.
+ */
+__isl_give MULTI(BASE) *FN(MULTI(BASE),move_explicit_domain_dims)(
+ __isl_take MULTI(BASE) *multi,
+ enum isl_dim_type dst_type, unsigned dst_pos,
+ enum isl_dim_type src_type, unsigned src_pos, unsigned n)
+{
+ return multi;
+}
+
+/* Free the explicit domain of "multi".
+ * "multi" cannot have an explicit domain, so this function is never called.
+ */
+static void FN(MULTI(BASE),free_explicit_domain)(__isl_keep MULTI(BASE) *multi)
+{
+}
+
+/* Do "multi1" and "multi2" have the same explicit domain?
+ * "multi1" and "multi2" cannot have an explicit domain,
+ * so this function is never called.
+ */
+static isl_bool FN(MULTI(BASE),equal_explicit_domain)(
+ __isl_keep MULTI(BASE) *multi1, __isl_keep MULTI(BASE) *multi2)
+{
+ return isl_bool_true;
+}
+
+static isl_stat FN(MULTI(BASE),check_explicit_domain)(
+ __isl_keep MULTI(BASE) *multi) __attribute__ ((unused));
+
+/* Debugging function to check that the explicit domain of "multi"
+ * has the correct space.
+ * "multi" cannot have an explicit domain,
+ * so this function should never be called.
+ */
+static isl_stat FN(MULTI(BASE),check_explicit_domain)(
+ __isl_keep MULTI(BASE) *multi)
+{
+ return isl_stat_ok;
+}
--- /dev/null
+/*
+ * Copyright 2017 Sven Verdoolaege
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege.
+ */
+
+/* Initialize the explicit domain of "mpa".
+ *
+ * The explicit domain is initialized to a universe set
+ * in the domain space.
+ */
+static __isl_give isl_multi_pw_aff *isl_multi_pw_aff_init_explicit_domain(
+ __isl_take isl_multi_pw_aff *mpa)
+{
+ if (isl_multi_pw_aff_check_has_explicit_domain(mpa) < 0)
+ return isl_multi_pw_aff_free(mpa);
+ mpa->u.dom = isl_set_universe(isl_multi_pw_aff_get_domain_space(mpa));
+ if (!mpa->u.dom)
+ return isl_multi_pw_aff_free(mpa);
+ return mpa;
+}
+
+/* Intersect the domain of "dst" with the domain product
+ * of the explicit domains of "src1" and "src2".
+ * This function is only called if at least one of "src1" or "src2"
+ * has an explicit domain.
+ */
+static __isl_give isl_multi_pw_aff *
+isl_multi_pw_aff_intersect_explicit_domain_product(
+ __isl_take isl_multi_pw_aff *dst, __isl_keep isl_multi_pw_aff *src1,
+ __isl_keep isl_multi_pw_aff *src2)
+{
+ isl_space *space;
+ isl_set *dom;
+ isl_map *map;
+
+ if (!src1 || !src2)
+ return FN(isl_multi_pw_aff,free)(dst);
+ space = isl_multi_pw_aff_get_domain_space(dst);
+ dom = isl_set_universe(space);
+ map = isl_set_unwrap(dom);
+ if (isl_multi_pw_aff_has_explicit_domain(src1)) {
+ dom = isl_set_copy(src1->u.dom);
+ map = isl_map_intersect_domain(map, dom);
+ }
+ if (isl_multi_pw_aff_has_explicit_domain(src2)) {
+ dom = isl_set_copy(src2->u.dom);
+ map = isl_map_intersect_range(map, dom);
+ }
+ dom = isl_map_wrap(map);
+ dst = isl_multi_pw_aff_intersect_domain(dst, dom);
+ return dst;
+}
+
+/* Check whether the explicit domain of "mpa" has non-zero coefficients
+ * for any dimension in the given range or if any of these dimensions appear
+ * with non-zero coefficients in any of the integer divisions involved.
+ */
+isl_bool isl_multi_pw_aff_involves_explicit_domain_dims(
+ __isl_keep isl_multi_pw_aff *mpa,
+ enum isl_dim_type type, unsigned pos, unsigned n)
+{
+ if (isl_multi_pw_aff_check_has_explicit_domain(mpa) < 0)
+ return isl_bool_error;
+ if (type == isl_dim_in)
+ type = isl_dim_set;
+ return isl_set_involves_dims(mpa->u.dom, type, pos, n);
+}
+
+/* Insert "n" dimensions of type "type" at position "pos"
+ * of the explicit domain of "mpa".
+ */
+static __isl_give isl_multi_pw_aff *
+isl_multi_pw_aff_insert_explicit_domain_dims(__isl_take isl_multi_pw_aff *mpa,
+ enum isl_dim_type type, unsigned pos, unsigned n)
+{
+ if (isl_multi_pw_aff_check_has_explicit_domain(mpa) < 0)
+ return isl_multi_pw_aff_free(mpa);
+ mpa = isl_multi_pw_aff_cow(mpa);
+ if (!mpa)
+ return NULL;
+ if (type == isl_dim_in)
+ type = isl_dim_set;
+ mpa->u.dom = isl_set_insert_dims(mpa->u.dom, type, pos, n);
+ if (!mpa->u.dom)
+ return isl_multi_pw_aff_free(mpa);
+ return mpa;
+}
+
+/* Drop the "n" dimensions of type "type" starting at position "pos"
+ * of the explicit domain of "mpa".
+ */
+static __isl_give isl_multi_pw_aff *
+isl_multi_pw_aff_drop_explicit_domain_dims(__isl_take isl_multi_pw_aff *mpa,
+ enum isl_dim_type type, unsigned pos, unsigned n)
+{
+ if (isl_multi_pw_aff_check_has_explicit_domain(mpa) < 0)
+ return isl_multi_pw_aff_free(mpa);
+ mpa = isl_multi_pw_aff_cow(mpa);
+ if (!mpa)
+ return NULL;
+ if (type == isl_dim_in)
+ type = isl_dim_set;
+ mpa->u.dom = isl_set_drop(mpa->u.dom, type, pos, n);
+ if (!mpa->u.dom)
+ return isl_multi_pw_aff_free(mpa);
+ return mpa;
+}
+
+/* Move the "n" dimensions of "src_type" starting at "src_pos" of
+ * of the explicit domain of "mpa" to dimensions of "dst_type" at "dst_pos".
+ */
+static __isl_give isl_multi_pw_aff *isl_multi_pw_aff_move_explicit_domain_dims(
+ __isl_take isl_multi_pw_aff *mpa,
+ enum isl_dim_type dst_type, unsigned dst_pos,
+ enum isl_dim_type src_type, unsigned src_pos, unsigned n)
+{
+ if (isl_multi_pw_aff_check_has_explicit_domain(mpa) < 0)
+ return isl_multi_pw_aff_free(mpa);
+ mpa = isl_multi_pw_aff_cow(mpa);
+ if (!mpa)
+ return NULL;
+ if (dst_type == isl_dim_in)
+ dst_type = isl_dim_set;
+ if (src_type == isl_dim_in)
+ src_type = isl_dim_set;
+ mpa->u.dom = isl_set_move_dims(mpa->u.dom, dst_type, dst_pos,
+ src_type, src_pos, n);
+ if (!mpa->u.dom)
+ return isl_multi_pw_aff_free(mpa);
+ return mpa;
+}
@@ -46,6 +46,12 @@ __isl_give isl_space *FN(MULTI(BASE),get_domain_space)(
return multi ? isl_space_domain(isl_space_copy(multi->space)) : NULL;
}
+/* Allocate a multi expression living in "space".
+ *
+ * If the number of base expressions is zero, then make sure
+ * there is enough room in the structure for the explicit domain,
+ * in case the type supports such an explicit domain.
+ */
__isl_give MULTI(BASE) *FN(MULTI(BASE),alloc)(__isl_take isl_space *space)
{
isl_ctx *ctx;
@@ -57,14 +63,19 @@ __isl_give MULTI(BASE) *FN(MULTI(BASE),alloc)(__isl_take isl_space *space)
ctx = isl_space_get_ctx(space);
n = isl_space_dim(space, isl_dim_out);
- multi = isl_calloc(ctx, MULTI(BASE),
+ if (n > 0)
+ multi = isl_calloc(ctx, MULTI(BASE),
sizeof(MULTI(BASE)) + (n - 1) * sizeof(struct EL *));
+ else
+ multi = isl_calloc(ctx, MULTI(BASE), sizeof(MULTI(BASE)));
if (!multi)
goto error;
multi->space = space;
multi->n = n;
multi->ref = 1;
+ if (FN(MULTI(BASE),has_explicit_domain)(multi))
+ multi = FN(MULTI(BASE),init_explicit_domain)(multi);
return multi;
error:
isl_space_free(space);
@@ -86,6 +97,8 @@ __isl_give MULTI(BASE) *FN(MULTI(BASE),dup)(__isl_keep MULTI(BASE) *multi)
for (i = 0; i < multi->n; ++i)
dup = FN(FN(MULTI(BASE),set),BASE)(dup, i,
FN(EL,copy)(multi->u.p[i]));
+ if (FN(MULTI(BASE),has_explicit_domain)(multi))
+ dup = FN(MULTI(BASE),copy_explicit_domain)(dup, multi);
return dup;
}
@@ -124,6 +137,8 @@ __isl_null MULTI(BASE) *FN(MULTI(BASE),free)(__isl_take MULTI(BASE) *multi)
isl_space_free(multi->space);
for (i = 0; i < multi->n; ++i)
FN(EL,free)(multi->u.p[i]);
+ if (FN(MULTI(BASE),has_explicit_domain)(multi))
+ FN(MULTI(BASE),free_explicit_domain)(multi);
free(multi);
return NULL;
@@ -267,6 +282,10 @@ error:
* directly or through its domain. It therefore passes along both,
* which we pass along to the element function since we don't know how
* that is represented either.
+ *
+ * If "multi" has an explicit domain, then the caller is expected
+ * to make sure that any modification that would change the dimensions
+ * of the explicit domain has bee applied before this function is called.
*/
__isl_give MULTI(BASE) *FN(MULTI(BASE),reset_space_and_domain)(
__isl_take MULTI(BASE) *multi, __isl_take isl_space *space,
@@ -284,6 +303,12 @@ __isl_give MULTI(BASE) *FN(MULTI(BASE),reset_space_and_domain)(
if (!multi->u.p[i])
goto error;
}
+ if (FN(MULTI(BASE),has_explicit_domain)(multi)) {
+ multi = FN(MULTI(BASE),reset_explicit_domain_space)(multi,
+ isl_space_copy(domain));
+ if (!multi)
+ goto error;
+ }
isl_space_free(domain);
isl_space_free(multi->space);
multi->space = space;
@@ -436,6 +461,9 @@ error:
}
/* Align the parameters of "multi" to those of "model".
+ *
+ * If "multi" has an explicit domain, then align the parameters
+ * of the domain first.
*/
__isl_give MULTI(BASE) *FN(MULTI(BASE),align_params)(
__isl_take MULTI(BASE) *multi, __isl_take isl_space *model)
@@ -463,6 +491,12 @@ __isl_give MULTI(BASE) *FN(MULTI(BASE),align_params)(
isl_die(ctx, isl_error_invalid,
"input has unnamed parameters", goto error);
+ if (FN(MULTI(BASE),has_explicit_domain)(multi)) {
+ multi = FN(MULTI(BASE),align_explicit_domain_params)(multi,
+ isl_space_copy(model));
+ if (!multi)
+ goto error;
+ }
model = isl_space_params(model);
exp = isl_parameter_alignment_reordering(multi->space, model);
exp = isl_reordering_extend_space(exp,
@@ -649,10 +683,18 @@ __isl_give MULTI(BASE) *FN(MULTI(BASE),drop_dims)(
for (i = first; i + n < multi->n; ++i)
multi->u.p[i] = multi->u.p[i + n];
multi->n -= n;
+ if (n > 0 && FN(MULTI(BASE),has_explicit_domain)(multi))
+ multi = FN(MULTI(BASE),init_explicit_domain)(multi);
return multi;
}
+ if (FN(MULTI(BASE),has_explicit_domain)(multi))
+ multi = FN(MULTI(BASE),drop_explicit_domain_dims)(multi,
+ type, first, n);
+ if (!multi)
+ return NULL;
+
for (i = 0; i < multi->n; ++i) {
multi->u.p[i] = FN(EL,drop_dims)(multi->u.p[i], type, first, n);
if (!multi->u.p[i])
@@ -699,6 +741,9 @@ error:
* construct a MULTI(BASE) (A * C) -> [B -> D].
*
* The parameters are assumed to have been aligned.
+ *
+ * If "multi1" and/or "multi2" has an explicit domain, then
+ * intersect the domain of the result with these explicit domains.
*/
static __isl_give MULTI(BASE) *FN(MULTI(BASE),range_product_aligned)(
__isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2)
@@ -728,6 +773,11 @@ static __isl_give MULTI(BASE) *FN(MULTI(BASE),range_product_aligned)(
res = FN(FN(MULTI(BASE),set),BASE)(res, n1 + i, el);
}
+ if (FN(MULTI(BASE),has_explicit_domain)(multi1))
+ res = FN(MULTI(BASE),intersect_explicit_domain)(res, multi1);
+ if (FN(MULTI(BASE),has_explicit_domain)(multi2))
+ res = FN(MULTI(BASE),intersect_explicit_domain)(res, multi2);
+
FN(MULTI(BASE),free)(multi1);
FN(MULTI(BASE),free)(multi2);
return res;
@@ -836,6 +886,9 @@ __isl_give MULTI(BASE) *FN(MULTI(BASE),factor_range)(
* construct a MULTI(BASE) [A -> C] -> [B -> D].
*
* The parameters are assumed to have been aligned.
+ *
+ * If "multi1" and/or "multi2" has an explicit domain, then
+ * intersect the domain of the result with these explicit domains.
*/
__isl_give MULTI(BASE) *FN(MULTI(BASE),product_aligned)(
__isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2)
@@ -869,6 +922,11 @@ __isl_give MULTI(BASE) *FN(MULTI(BASE),product_aligned)(
res = FN(FN(MULTI(BASE),set),BASE)(res, out1 + i, el);
}
+ if (FN(MULTI(BASE),has_explicit_domain)(multi1) ||
+ FN(MULTI(BASE),has_explicit_domain)(multi2))
+ res = FN(MULTI(BASE),intersect_explicit_domain_product)(res,
+ multi1, multi2);
+
isl_space_free(space);
FN(MULTI(BASE),free)(multi1);
FN(MULTI(BASE),free)(multi2);
@@ -1044,6 +1102,9 @@ static __isl_give MULTI(BASE) *FN(MULTI(BASE),bin_op)(
/* Pairwise perform "fn" to the elements of "multi1" and "multi2" and
* return the result.
+ *
+ * If "multi2" has an explicit domain, then
+ * intersect the domain of the result with this explicit domain.
*/
static __isl_give MULTI(BASE) *FN(MULTI(BASE),bin_op)(
__isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2,
@@ -1062,6 +1123,10 @@ static __isl_give MULTI(BASE) *FN(MULTI(BASE),bin_op)(
goto error;
}
+ if (FN(MULTI(BASE),has_explicit_domain)(multi2))
+ multi1 = FN(MULTI(BASE),intersect_explicit_domain)(multi1,
+ multi2);
+
FN(MULTI(BASE),free)(multi2);
return multi1;
error:
@@ -1338,6 +1403,11 @@ __isl_give MULTI(BASE) *FN(MULTI(BASE),move_dims)(__isl_take MULTI(BASE) *multi,
src_type, src_pos, n);
if (!multi->space)
return FN(MULTI(BASE),free)(multi);
+ if (FN(MULTI(BASE),has_explicit_domain)(multi))
+ multi = FN(MULTI(BASE),move_explicit_domain_dims)(multi,
+ dst_type, dst_pos, src_type, src_pos, n);
+ if (!multi)
+ return NULL;
for (i = 0; i < multi->n; ++i) {
multi->u.p[i] = FN(EL,move_dims)(multi->u.p[i],
@@ -1395,6 +1465,13 @@ isl_bool FN(MULTI(BASE),plain_is_equal)(__isl_keep MULTI(BASE) *multi1,
return equal;
}
+ if (FN(MULTI(BASE),has_explicit_domain)(multi1) ||
+ FN(MULTI(BASE),has_explicit_domain)(multi2)) {
+ equal = FN(MULTI(BASE),equal_explicit_domain)(multi1, multi2);
+ if (equal < 0 || !equal)
+ return equal;
+ }
+
return isl_bool_true;
}
@@ -1420,6 +1497,8 @@ isl_bool FN(MULTI(BASE),involves_nan)(__isl_keep MULTI(BASE) *multi)
#ifndef NO_DOMAIN
/* Return the shared domain of the elements of "multi".
+ *
+ * If "multi" has an explicit domain, then return this domain.
*/
__isl_give isl_set *FN(MULTI(BASE),domain)(__isl_take MULTI(BASE) *multi)
{
@@ -1429,6 +1508,12 @@ __isl_give isl_set *FN(MULTI(BASE),domain)(__isl_take MULTI(BASE) *multi)
if (!multi)
return NULL;
+ if (FN(MULTI(BASE),has_explicit_domain)(multi)) {
+ dom = FN(MULTI(BASE),get_explicit_domain)(multi);
+ FN(MULTI(BASE),free)(multi);
+ return dom;
+ }
+
dom = isl_set_universe(FN(MULTI(BASE),get_domain_space)(multi));
for (i = 0; i < multi->n; ++i) {
isl_set *dom_i;
* to the output or set dimension of "space".
* "p" is an array of size "n" of base expressions.
* The array is only accessible when n > 0.
+ * "dom" is the explicit domain, if present
+ * The explicit domain is only accessible when n == 0.
*/
struct MULTI(BASE) {
int ref;
@@ -16,8 +18,16 @@ struct MULTI(BASE) {
int n;
struct {
+#ifdef EXPLICIT_DOMAIN
+ DOM *dom;
+#endif
EL *p[1];
} u;
};
__isl_give MULTI(BASE) *CAT(MULTI(BASE),_alloc)(__isl_take isl_space *space);
+
+#ifdef EXPLICIT_DOMAIN
+isl_bool CAT(MULTI(BASE),_has_non_trivial_domain)(
+ __isl_keep MULTI(BASE) *multi);
+#endif
--- /dev/null
+/*
+ * Copyright 2017 Sven Verdoolaege
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege.
+ */
+
+/* Initialize the explicit domain of "mupa".
+ *
+ * The explicit domain is initialized to a universe parameter set.
+ * It may later be specialized with constraints on the parameter or
+ * specific domain instances.
+ */
+static __isl_give isl_multi_union_pw_aff *
+isl_multi_union_pw_aff_init_explicit_domain(
+ __isl_take isl_multi_union_pw_aff *mupa)
+{
+ isl_space *space;
+
+ if (isl_multi_union_pw_aff_check_has_explicit_domain(mupa) < 0)
+ return isl_multi_union_pw_aff_free(mupa);
+ space = isl_space_params(isl_multi_union_pw_aff_get_space(mupa));
+ mupa->u.dom = isl_union_set_from_set(isl_set_universe(space));
+ if (!mupa->u.dom)
+ return isl_multi_union_pw_aff_free(mupa);
+ return mupa;
+}
+
+/* Drop the "n" dimensions of type "type" starting at position "pos"
+ * of the explicit domain of "mupa".
+ */
+static __isl_give isl_multi_union_pw_aff *
+isl_multi_union_pw_aff_drop_explicit_domain_dims(
+ __isl_take isl_multi_union_pw_aff *mupa,
+ enum isl_dim_type type, unsigned pos, unsigned n)
+{
+ if (isl_multi_union_pw_aff_check_has_explicit_domain(mupa) < 0)
+ return isl_multi_union_pw_aff_free(mupa);
+ if (type != isl_dim_param)
+ isl_die(isl_multi_union_pw_aff_get_ctx(mupa), isl_error_invalid,
+ "can only drop parameters",
+ return isl_multi_union_pw_aff_free(mupa));
+ mupa = isl_multi_union_pw_aff_cow(mupa);
+ if (!mupa)
+ return NULL;
+ mupa->u.dom = isl_union_set_project_out(mupa->u.dom, type, pos, n);
+ if (!mupa->u.dom)
+ return isl_multi_union_pw_aff_free(mupa);
+ return mupa;
+}
#include <isl_space_private.h>
#include <isl_mat_private.h>
#include <isl_vec_private.h>
+#include <isl/union_set.h>
#include <isl/union_map.h>
#include <isl/constraint.h>
#include <isl_local_space_private.h>
@@ -1175,6 +1176,16 @@ static __isl_give isl_printer *print_disjuncts_map(__isl_keep isl_map *map,
return print_disjuncts(map, space, p, latex);
}
+/* Print the disjuncts of a set.
+ * The names of the variables are taken from "space".
+ * "latex" is set if the constraints should be printed in LaTeX format.
+ */
+static __isl_give isl_printer *print_disjuncts_set(__isl_keep isl_set *set,
+ __isl_keep isl_space *space, __isl_take isl_printer *p, int latex)
+{
+ return print_disjuncts_map(set_to_map(set), space, p, latex);
+}
+
struct isl_aff_split {
isl_basic_map *aff;
isl_map *map;
@@ -1584,6 +1595,15 @@ static __isl_give isl_printer *isl_printer_print_union_map_isl_body(
return p;
}
+/* Print the body of "uset" (everything except the parameter declarations)
+ * to "p" in isl format.
+ */
+static __isl_give isl_printer *isl_printer_print_union_set_isl_body(
+ __isl_take isl_printer *p, __isl_keep isl_union_set *uset)
+{
+ return isl_printer_print_union_map_isl_body(p, uset_to_umap(uset));
+}
+
/* Print the isl_union_map "umap" to "p" in isl format.
*/
static __isl_give isl_printer *isl_union_map_print_isl(
@@ -3169,11 +3189,15 @@ static __isl_give isl_printer *print_dim_mpa(__isl_take isl_printer *p,
}
/* Print "mpa" to "p" in isl format.
+ *
+ * If "mpa" is zero-dimensional and has a non-trivial explicit domain,
+ * then it is printed after the tuple of affine expressions.
*/
static __isl_give isl_printer *print_multi_pw_aff_isl(__isl_take isl_printer *p,
__isl_keep isl_multi_pw_aff *mpa)
{
struct isl_print_space_data data = { 0 };
+ isl_bool has_domain;
if (!mpa)
return isl_printer_free(p);
@@ -3183,6 +3207,16 @@ static __isl_give isl_printer *print_multi_pw_aff_isl(__isl_take isl_printer *p,
data.print_dim = &print_dim_mpa;
data.user = mpa;
p = isl_print_space(mpa->space, p, 0, &data);
+ has_domain = isl_multi_pw_aff_has_non_trivial_domain(mpa);
+ if (has_domain < 0)
+ return isl_printer_free(p);
+ if (has_domain) {
+ isl_space *space;
+
+ space = isl_space_domain(isl_space_copy(mpa->space));
+ p = print_disjuncts_set(mpa->u.dom, space, p, 0);
+ isl_space_free(space);
+ }
p = isl_printer_print_str(p, " }");
return p;
}
@@ -3274,22 +3308,45 @@ static __isl_give isl_printer *print_union_pw_aff_dim(__isl_take isl_printer *p,
}
/* Print the isl_multi_union_pw_aff "mupa" to "p" in isl format.
+ *
+ * If "mupa" is zero-dimensional and has a non-trivial explicit domain,
+ * then it is printed after the tuple of affine expressions.
+ * In order to clarify that this domain belongs to the expression,
+ * the tuple along with the domain are placed inside parentheses.
+ * If "mupa" has any parameters, then the opening parenthesis
+ * appears after the parameter declarations.
*/
static __isl_give isl_printer *print_multi_union_pw_aff_isl(
__isl_take isl_printer *p, __isl_keep isl_multi_union_pw_aff *mupa)
{
struct isl_print_space_data data = { 0 };
+ isl_bool has_domain;
isl_space *space;
+ if (!mupa)
+ return isl_printer_free(p);
+ has_domain = isl_multi_union_pw_aff_has_non_trivial_domain(mupa);
+ if (has_domain < 0)
+ return isl_printer_free(p);
+
space = isl_multi_union_pw_aff_get_space(mupa);
p = print_param_tuple(p, space, &data);
+ if (has_domain)
+ p = isl_printer_print_str(p, "(");
+
data.print_dim = &print_union_pw_aff_dim;
data.user = mupa;
p = isl_print_space(space, p, 0, &data);
isl_space_free(space);
+ if (has_domain) {
+ p = isl_printer_print_str(p, " : ");
+ p = isl_printer_print_union_set_isl_body(p, mupa->u.dom);
+ p = isl_printer_print_str(p, ")");
+ }
+
return p;
}
@@ -119,6 +119,200 @@ static int test_parse_multi_val(isl_ctx *ctx, const char *str)
return mv ? 0 : -1;
}
+/* Check that printing "mpa" and parsing the output results
+ * in the same expression.
+ */
+static isl_stat check_reparse_mpa(isl_ctx *ctx,
+ __isl_take isl_multi_pw_aff *mpa)
+{
+ char *str;
+ isl_bool equal;
+ isl_multi_pw_aff *mpa2;
+
+ str = isl_multi_pw_aff_to_str(mpa);
+ mpa2 = isl_multi_pw_aff_read_from_str(ctx, str);
+ free(str);
+ equal = isl_multi_pw_aff_plain_is_equal(mpa, mpa2);
+ isl_multi_pw_aff_free(mpa);
+ isl_multi_pw_aff_free(mpa2);
+ if (equal < 0)
+ return isl_stat_error;
+ if (!equal)
+ isl_die(ctx, isl_error_unknown,
+ "parsed function not equal to original",
+ return isl_stat_error);
+
+ return isl_stat_ok;
+}
+
+/* String descriptions of multi piecewise affine expressions
+ * that are used for testing printing and parsing.
+ */
+const char *parse_multi_mpa_tests[] = {
+ "{ A[x, y] -> [] : x + y >= 0 }",
+ "{ A[x, y] -> B[] : x + y >= 0 }",
+ "{ A[x, y] -> [x] : x + y >= 0 }",
+ "[N] -> { A[x, y] -> [x] : x + y <= N }",
+ "{ A[x, y] -> [x, y] : x + y >= 0 }",
+ "{ A[x, y] -> [(x : x >= 0), (y : y >= 0)] : x + y >= 0 }",
+ "[N] -> { [] : N >= 0 }",
+ "[N] -> { [] : N >= 0 }",
+ "[N] -> { [N] : N >= 0 }",
+ "[N] -> { [N, N + 1] : N >= 0 }",
+ "[N, M] -> { [(N : N >= 0), (M : M >= 0)] : N + M >= 0 }",
+};
+
+/* Test parsing of multi piecewise affine expressions by printing
+ * the expressions and checking that parsing the output results
+ * in the same expression.
+ * Do this for a couple of manually constructed expressions and
+ * a set of expressions parsed from strings.
+ */
+static int test_parse_mpa(isl_ctx *ctx)
+{
+ int i;
+ isl_space *space;
+ isl_set *dom;
+ isl_multi_pw_aff *mpa;
+ isl_stat r;
+
+ space = isl_space_set_alloc(ctx, 0, 0);
+ space = isl_space_set_tuple_name(space, isl_dim_set, "A");
+ mpa = isl_multi_pw_aff_zero(space);
+ r = check_reparse_mpa(ctx, mpa);
+ if (r < 0)
+ return -1;
+
+ space = isl_space_set_alloc(ctx, 1, 0);
+ space = isl_space_set_dim_name(space, isl_dim_param, 0, "N");
+ space = isl_space_set_tuple_name(space, isl_dim_set, "A");
+ dom = isl_set_universe(isl_space_params(isl_space_copy(space)));
+ dom = isl_set_lower_bound_si(dom, isl_dim_param, 0, 5);
+ mpa = isl_multi_pw_aff_zero(space);
+ mpa = isl_multi_pw_aff_intersect_domain(mpa, dom);
+ r = check_reparse_mpa(ctx, mpa);
+ if (r < 0)
+ return -1;
+
+ for (i = 0; i < ARRAY_SIZE(parse_multi_mpa_tests); ++i) {
+ const char *str;
+
+ str = parse_multi_mpa_tests[i];
+ mpa = isl_multi_pw_aff_read_from_str(ctx, str);
+ r = check_reparse_mpa(ctx, mpa);
+ if (r < 0)
+ return -1;
+ }
+
+ return 0;
+}
+
+/* Check that printing "mupa" and parsing the output results
+ * in the same expression.
+ */
+static isl_stat check_reparse_mupa(isl_ctx *ctx,
+ __isl_take isl_multi_union_pw_aff *mupa)
+{
+ char *str;
+ isl_bool equal;
+ isl_multi_union_pw_aff *mupa2;
+
+ str = isl_multi_union_pw_aff_to_str(mupa);
+ mupa2 = isl_multi_union_pw_aff_read_from_str(ctx, str);
+ free(str);
+ equal = isl_multi_union_pw_aff_plain_is_equal(mupa, mupa2);
+ isl_multi_union_pw_aff_free(mupa);
+ isl_multi_union_pw_aff_free(mupa2);
+ if (equal < 0)
+ return isl_stat_error;
+ if (!equal)
+ isl_die(ctx, isl_error_unknown,
+ "parsed function not equal to original",
+ return isl_stat_error);
+
+ return isl_stat_ok;
+}
+
+/* String descriptions of multi union piecewise affine expressions
+ * that are used for testing printing and parsing.
+ */
+const char *parse_multi_mupa_tests[] = {
+ "[]",
+ "A[]",
+ "A[B[] -> C[]]",
+ "(A[] : { S[x] : x > 0; T[y] : y >= 0 })",
+ "(A[] : { })",
+ "[N] -> (A[] : { })",
+ "[N] -> (A[] : { : N >= 0 })",
+ "[N] -> (A[] : { S[x] : x > N; T[y] : y >= 0 })",
+ "(A[] : [N] -> { S[x] : x > N; T[y] : y >= 0 })",
+ "A[{ S[x] -> [x + 1]; T[x] -> [x] }]",
+ "(A[{ S[x] -> [x + 1]; T[x] -> [x] }] : "
+ "{ S[x] : x > 0; T[y] : y >= 0 })",
+};
+
+/* Test parsing of multi union piecewise affine expressions by printing
+ * the expressions and checking that parsing the output results
+ * in the same expression.
+ * Do this for a couple of manually constructed expressions and
+ * a set of expressions parsed from strings.
+ */
+static int test_parse_mupa(isl_ctx *ctx)
+{
+ int i;
+ isl_space *space;
+ isl_multi_union_pw_aff *mupa;
+ isl_set *dom;
+ isl_union_set *uset;
+ isl_stat r;
+
+ space = isl_space_set_alloc(ctx, 0, 0);
+ space = isl_space_set_tuple_name(space, isl_dim_set, "A");
+ mupa = isl_multi_union_pw_aff_zero(space);
+ r = check_reparse_mupa(ctx, mupa);
+ if (r < 0)
+ return -1;
+
+ space = isl_space_set_alloc(ctx, 1, 0);
+ space = isl_space_set_dim_name(space, isl_dim_param, 0, "N");
+ space = isl_space_set_tuple_name(space, isl_dim_set, "A");
+ dom = isl_set_universe(space);
+ dom = isl_set_lower_bound_si(dom, isl_dim_param, 0, 5);
+ uset = isl_union_set_from_set(dom);
+ space = isl_space_set_alloc(ctx, 1, 0);
+ space = isl_space_set_dim_name(space, isl_dim_param, 0, "N");
+ space = isl_space_set_tuple_name(space, isl_dim_set, "B");
+ mupa = isl_multi_union_pw_aff_zero(space);
+ mupa = isl_multi_union_pw_aff_intersect_domain(mupa, uset);
+ r = check_reparse_mupa(ctx, mupa);
+ if (r < 0)
+ return -1;
+
+ for (i = 0; i < ARRAY_SIZE(parse_multi_mupa_tests); ++i) {
+ const char *str;
+
+ str = parse_multi_mupa_tests[i];
+ mupa = isl_multi_union_pw_aff_read_from_str(ctx, str);
+ r = check_reparse_mupa(ctx, mupa);
+ if (r < 0)
+ return -1;
+ }
+
+ return 0;
+}
+
+/* Test parsing of multi expressions.
+ */
+static int test_parse_multi(isl_ctx *ctx)
+{
+ if (test_parse_mpa(ctx) < 0)
+ return -1;
+ if (test_parse_mupa(ctx) < 0)
+ return -1;
+
+ return 0;
+}
+
/* Pairs of binary relation representations that should represent
* the same binary relations.
*/
@@ -206,6 +400,8 @@ int test_parse(struct isl_ctx *ctx)
return -1;
if (test_parse_multi_val(ctx, "{ A[4, infty, NaN, -1/2, 2/3] }") < 0)
return -1;
+ if (test_parse_multi(ctx) < 0)
+ return -1;
str = "{ [i] -> [-i] }";
map = isl_map_read_from_str(ctx, str);
@@ -4879,6 +5075,15 @@ struct {
{ &isl_multi_pw_aff_factor_range,
"{ [B[] -> C[]] }",
"{ C[] }" },
+ { &isl_multi_pw_aff_range_factor_domain,
+ "{ A[x] -> [B[] -> C[]] : x >= 0 }",
+ "{ A[x] -> B[] : x >= 0 }" },
+ { &isl_multi_pw_aff_range_factor_range,
+ "{ A[x] -> [B[] -> C[]] : x >= 0 }",
+ "{ A[y] -> C[] : y >= 0 }" },
+ { &isl_multi_pw_aff_factor_range,
+ "[N] -> { [B[] -> C[]] : N >= 0 }",
+ "[N] -> { C[] : N >= 0 }" },
};
/* Perform some basic tests of unary operations on isl_multi_pw_aff objects.
@@ -4924,16 +5129,56 @@ struct {
{ &isl_multi_pw_aff_add, "{ A[x] -> [(1 : x >= 5)] }",
"{ A[x] -> [(x : x <= 10)] }",
"{ A[x] -> [(1 + x : 5 <= x <= 10)] }" },
+ { &isl_multi_pw_aff_add, "{ A[x] -> [] : x >= 5 }",
+ "{ A[x] -> [] : x <= 10 }",
+ "{ A[x] -> [] : 5 <= x <= 10 }" },
+ { &isl_multi_pw_aff_add, "{ A[x] -> [] : x >= 5 }",
+ "[N] -> { A[x] -> [] : x <= N }",
+ "[N] -> { A[x] -> [] : 5 <= x <= N }" },
+ { &isl_multi_pw_aff_add,
+ "[N] -> { A[x] -> [] : x <= N }",
+ "{ A[x] -> [] : x >= 5 }",
+ "[N] -> { A[x] -> [] : 5 <= x <= N }" },
{ &isl_multi_pw_aff_range_product, "{ A[x] -> B[(1 : x >= 5)] }",
"{ A[y] -> C[(2 : y <= 10)] }",
"{ A[x] -> [B[(1 : x >= 5)] -> C[(2 : x <= 10)]] }" },
+ { &isl_multi_pw_aff_range_product, "{ A[x] -> B[1] : x >= 5 }",
+ "{ A[y] -> C[2] : y <= 10 }",
+ "{ A[x] -> [B[(1 : x >= 5)] -> C[(2 : x <= 10)]] }" },
+ { &isl_multi_pw_aff_range_product, "{ A[x] -> B[1] : x >= 5 }",
+ "[N] -> { A[y] -> C[2] : y <= N }",
+ "[N] -> { A[x] -> [B[(1 : x >= 5)] -> C[(2 : x <= N)]] }" },
+ { &isl_multi_pw_aff_range_product, "[N] -> { A[x] -> B[1] : x >= N }",
+ "{ A[y] -> C[2] : y <= 10 }",
+ "[N] -> { A[x] -> [B[(1 : x >= N)] -> C[(2 : x <= 10)]] }" },
{ &isl_multi_pw_aff_range_product, "{ A[] -> B[1] }", "{ A[] -> C[2] }",
"{ A[] -> [B[1] -> C[2]] }" },
{ &isl_multi_pw_aff_range_product, "{ A[] -> B[] }", "{ A[] -> C[] }",
"{ A[] -> [B[] -> C[]] }" },
+ { &isl_multi_pw_aff_range_product, "{ A[x] -> B[(1 : x >= 5)] }",
+ "{ A[y] -> C[] : y <= 10 }",
+ "{ A[x] -> [B[(1 : x >= 5)] -> C[]] : x <= 10 }" },
+ { &isl_multi_pw_aff_range_product, "{ A[y] -> C[] : y <= 10 }",
+ "{ A[x] -> B[(1 : x >= 5)] }",
+ "{ A[x] -> [C[] -> B[(1 : x >= 5)]] : x <= 10 }" },
{ &isl_multi_pw_aff_product, "{ A[x] -> B[(1 : x >= 5)] }",
"{ A[y] -> C[(2 : y <= 10)] }",
"{ [A[x] -> A[y]] -> [B[(1 : x >= 5)] -> C[(2 : y <= 10)]] }" },
+ { &isl_multi_pw_aff_product, "{ A[x] -> B[(1 : x >= 5)] }",
+ "{ A[y] -> C[] : y <= 10 }",
+ "{ [A[x] -> A[y]] -> [B[(1 : x >= 5)] -> C[]] : y <= 10 }" },
+ { &isl_multi_pw_aff_product, "{ A[y] -> C[] : y <= 10 }",
+ "{ A[x] -> B[(1 : x >= 5)] }",
+ "{ [A[y] -> A[x]] -> [C[] -> B[(1 : x >= 5)]] : y <= 10 }" },
+ { &isl_multi_pw_aff_product, "{ A[x] -> B[(1 : x >= 5)] }",
+ "[N] -> { A[y] -> C[] : y <= N }",
+ "[N] -> { [A[x] -> A[y]] -> [B[(1 : x >= 5)] -> C[]] : y <= N }" },
+ { &isl_multi_pw_aff_product, "[N] -> { A[y] -> C[] : y <= N }",
+ "{ A[x] -> B[(1 : x >= 5)] }",
+ "[N] -> { [A[y] -> A[x]] -> [C[] -> B[(1 : x >= 5)]] : y <= N }" },
+ { &isl_multi_pw_aff_product, "{ A[x] -> B[] : x >= 5 }",
+ "{ A[y] -> C[] : y <= 10 }",
+ "{ [A[x] -> A[y]] -> [B[] -> C[]] : x >= 5 and y <= 10 }" },
{ &isl_multi_pw_aff_product, "{ A[] -> B[1] }", "{ A[] -> C[2] }",
"{ [A[] -> A[]] -> [B[1] -> C[2]] }" },
{ &isl_multi_pw_aff_product, "{ A[] -> B[] }", "{ A[] -> C[] }",
@@ -4949,6 +5194,26 @@ struct {
"{ B[i,j] -> C[(i + 2j : j > 4)] }",
"{ A[a,b] -> B[(b : b > a),(a : b > a)] }",
"{ A[a,b] -> C[(b + 2a : b > a > 4)] }" },
+ { &isl_multi_pw_aff_pullback_multi_pw_aff,
+ "{ B[i,j] -> C[] }",
+ "{ A[a,b] -> B[(b : b > a),(a : b > a)] }",
+ "{ A[a,b] -> C[] }" },
+ { &isl_multi_pw_aff_pullback_multi_pw_aff,
+ "{ B[i,j] -> C[] : i > j }",
+ "{ A[a,b] -> B[b,a] }",
+ "{ A[a,b] -> C[] : b > a }" },
+ { &isl_multi_pw_aff_pullback_multi_pw_aff,
+ "{ B[i,j] -> C[] : j > 5 }",
+ "{ A[a,b] -> B[(b : b > a),(a : b > a)] }",
+ "{ A[a,b] -> C[] : b > a > 5 }" },
+ { &isl_multi_pw_aff_pullback_multi_pw_aff,
+ "[N] -> { B[i,j] -> C[] : j > N }",
+ "{ A[a,b] -> B[(b : b > a),(a : b > a)] }",
+ "[N] -> { A[a,b] -> C[] : b > a > N }" },
+ { &isl_multi_pw_aff_pullback_multi_pw_aff,
+ "[M,N] -> { B[] -> C[] : N > 5 }",
+ "[M,N] -> { A[] -> B[] : M > N }",
+ "[M,N] -> { A[] -> C[] : M > N > 5 }" },
};
/* Perform some basic tests of binary operations on isl_multi_pw_aff objects.
@@ -5004,6 +5269,15 @@ struct {
{ &isl_multi_union_pw_aff_factor_range,
"[B[] -> C[]]",
"C[]" },
+ { &isl_multi_union_pw_aff_factor_range,
+ "([B[] -> C[]] : { A[x] : x >= 0 })",
+ "(C[] : { A[x] : x >= 0 })" },
+ { &isl_multi_union_pw_aff_factor_range,
+ "[N] -> ([B[] -> C[]] : { A[x] : x <= N })",
+ "[N] -> (C[] : { A[x] : x <= N })" },
+ { &isl_multi_union_pw_aff_factor_range,
+ "[N] -> ([B[] -> C[]] : { : N >= 0 })",
+ "[N] -> (C[] : { : N >= 0 })" },
};
/* Perform some basic tests of unary operations on
@@ -5063,15 +5337,66 @@ struct {
{ &isl_multi_union_pw_aff_add, "[{ A[x] -> [(1)] : x >= 5 }]",
"[{ A[x] -> [(x)] : x <= 10 }]",
"[{ A[x] -> [(1 + x)] : 5 <= x <= 10 }]" },
+ { &isl_multi_union_pw_aff_add, "([] : { A[x] : x >= 5 })",
+ "([] : { A[x] : x <= 10 })",
+ "([] : { A[x] : 5 <= x <= 10 })" },
+ { &isl_multi_union_pw_aff_add, "([] : { A[x] : x >= 5 })",
+ "[N] -> ([] : { A[x] : x <= N })",
+ "[N] -> ([] : { A[x] : 5 <= x <= N })" },
+ { &isl_multi_union_pw_aff_add, "[N] -> ([] : { A[x] : x >= N })",
+ "([] : { A[x] : x <= 10 })",
+ "[N] -> ([] : { A[x] : N <= x <= 10 })" },
{ &isl_multi_union_pw_aff_union_add, "[{ A[x] -> [(1)] : x >= 5 }]",
"[{ A[x] -> [(x)] : x <= 10 }]",
"[{ A[x] -> [(1 + x)] : 5 <= x <= 10; "
"A[x] -> [(1)] : x > 10; A[x] -> [(x)] : x < 5 }]" },
+ { &isl_multi_union_pw_aff_union_add, "([] : { A[x] : x >= 5 })",
+ "([] : { A[x] : x <= 10 })",
+ "([] : { A[x] })" },
+ { &isl_multi_union_pw_aff_union_add, "([] : { A[x] : x >= 0 })",
+ "[N] -> ([] : { A[x] : x >= N })",
+ "[N] -> ([] : { A[x] : x >= 0 or x >= N })" },
+ { &isl_multi_union_pw_aff_union_add,
+ "[N] -> ([] : { A[] : N >= 0})",
+ "[N] -> ([] : { A[] : N <= 0})",
+ "[N] -> ([] : { A[] })" },
+ { &isl_multi_union_pw_aff_union_add,
+ "[N] -> ([] : { A[] })",
+ "[N] -> ([] : { : })",
+ "[N] -> ([] : { : })" },
+ { &isl_multi_union_pw_aff_union_add,
+ "[N] -> ([] : { : })",
+ "[N] -> ([] : { A[] })",
+ "[N] -> ([] : { : })" },
+ { &isl_multi_union_pw_aff_union_add,
+ "[N] -> ([] : { : N >= 0})",
+ "[N] -> ([] : { : N <= 0})",
+ "[N] -> ([] : { : })" },
{ &isl_multi_union_pw_aff_range_product,
"B[{ A[] -> [1] }]",
"C[{ A[] -> [2] }]",
"[B[{ A[] -> [1] }] -> C[{ A[] -> [2] }]]" },
{ &isl_multi_union_pw_aff_range_product,
+ "(B[] : { A[x] : x >= 5 })",
+ "(C[] : { A[x] : x <= 10 })",
+ "([B[] -> C[]] : { A[x] : 5 <= x <= 10 })" },
+ { &isl_multi_union_pw_aff_range_product,
+ "B[{ A[x] -> [x + 1] : x >= 5 }]",
+ "(C[] : { A[x] : x <= 10 })",
+ "[B[{ A[x] -> [x + 1] : 5 <= x <= 10 }] -> C[]]" },
+ { &isl_multi_union_pw_aff_range_product,
+ "(C[] : { A[x] : x <= 10 })",
+ "B[{ A[x] -> [x + 1] : x >= 5 }]",
+ "[C[] -> B[{ A[x] -> [x + 1] : 5 <= x <= 10 }]]" },
+ { &isl_multi_union_pw_aff_range_product,
+ "B[{ A[x] -> [x + 1] : x >= 5 }]",
+ "[N] -> (C[] : { A[x] : x <= N })",
+ "[N] -> [B[{ A[x] -> [x + 1] : 5 <= x <= N }] -> C[]]" },
+ { &isl_multi_union_pw_aff_range_product,
+ "[N] -> (C[] : { A[x] : x <= N })",
+ "B[{ A[x] -> [x + 1] : x >= 5 }]",
+ "[N] -> [C[] -> B[{ A[x] -> [x + 1] : 5 <= x <= N }]]" },
+ { &isl_multi_union_pw_aff_range_product,
"B[{ A[] -> [1]; D[] -> [3] }]",
"C[{ A[] -> [2] }]",
"[B[{ A[] -> [1]; D[] -> [3] }] -> C[{ A[] -> [2] }]]" },
@@ -5133,6 +5458,32 @@ struct {
{ &isl_multi_union_pw_aff_intersect_range,
"C[{ B[i,j] -> [i + 2j] }]", "[N] -> { C[x] : N >= 0 }",
"[N] -> C[{ B[i,j] -> [i + 2j] : N >= 0 }]" },
+ { &isl_multi_union_pw_aff_intersect_range,
+ "C[]", "{ C[] }", "C[]" },
+ { &isl_multi_union_pw_aff_intersect_range,
+ "[N] -> (C[] : { : N >= 0 })",
+ "{ C[] }",
+ "[N] -> (C[] : { : N >= 0 })" },
+ { &isl_multi_union_pw_aff_intersect_range,
+ "(C[] : { A[a,b] })",
+ "{ C[] }",
+ "(C[] : { A[a,b] })" },
+ { &isl_multi_union_pw_aff_intersect_range,
+ "[N] -> (C[] : { A[a,b] : a,b <= N })",
+ "{ C[] }",
+ "[N] -> (C[] : { A[a,b] : a,b <= N })" },
+ { &isl_multi_union_pw_aff_intersect_range,
+ "C[]",
+ "[N] -> { C[] : N >= 0 }",
+ "[N] -> (C[] : { : N >= 0 })" },
+ { &isl_multi_union_pw_aff_intersect_range,
+ "(C[] : { A[a,b] })",
+ "[N] -> { C[] : N >= 0 }",
+ "[N] -> (C[] : { A[a,b] : N >= 0 })" },
+ { &isl_multi_union_pw_aff_intersect_range,
+ "[N] -> (C[] : { : N >= 0 })",
+ "[N] -> { C[] : N < 1024 }",
+ "[N] -> (C[] : { : 0 <= N < 1024 })" },
{ &isl_multi_union_pw_aff_intersect_params,
"C[{ B[i,j] -> [i + 2j] }]", "[N] -> { : N >= 0 }",
"[N] -> C[{ B[i,j] -> [i + 2j] : N >= 0}]" },
@@ -5142,6 +5493,18 @@ struct {
{ &isl_multi_union_pw_aff_intersect_params,
"[N] -> C[{ B[i,j] -> [i + 2j] : N <= 256 }]", "{ : }",
"[N] -> C[{ B[i,j] -> [i + 2j] : N <= 256 }]" },
+ { &isl_multi_union_pw_aff_intersect_params,
+ "C[]", "[N] -> { : N >= 0 }",
+ "[N] -> (C[] : { : N >= 0 })" },
+ { &isl_multi_union_pw_aff_intersect_params,
+ "(C[] : { A[a,b] })", "[N] -> { : N >= 0 }",
+ "[N] -> (C[] : { A[a,b] : N >= 0 })" },
+ { &isl_multi_union_pw_aff_intersect_params,
+ "[N] -> (C[] : { A[a,N] })", "{ : }",
+ "[N] -> (C[] : { A[a,N] })" },
+ { &isl_multi_union_pw_aff_intersect_params,
+ "[N] -> (C[] : { A[a,b] : N <= 256 })", "[N] -> { : N >= 0 }",
+ "[N] -> (C[] : { A[a,b] : 0 <= N <= 256 })" },
};
/* Perform some basic tests of binary operations on
@@ -5191,6 +5554,18 @@ struct {
{ &isl_multi_union_pw_aff_intersect_domain,
"C[{ B[i,j] -> [i + 2j] }]", "{ B[i,i] }",
"C[{ B[i,i] -> [3i] }]" },
+ { &isl_multi_union_pw_aff_intersect_domain,
+ "(C[] : { B[i,j] })", "{ B[i,i] }",
+ "(C[] : { B[i,i] })" },
+ { &isl_multi_union_pw_aff_intersect_domain,
+ "(C[] : { B[i,j] })", "[N] -> { B[N,N] }",
+ "[N] -> (C[] : { B[N,N] })" },
+ { &isl_multi_union_pw_aff_intersect_domain,
+ "C[]", "{ B[i,i] }",
+ "(C[] : { B[i,i] })" },
+ { &isl_multi_union_pw_aff_intersect_domain,
+ "[N] -> (C[] : { : N >= 0 })", "{ B[i,i] }",
+ "[N] -> (C[] : { B[i,i] : N >= 0 })" },
};
/* Perform some basic tests of binary operations on
@@ -5258,6 +5633,26 @@ struct {
"C[]",
"{ C[] -> D[] }",
"D[]" },
+ { &isl_multi_union_pw_aff_apply_multi_aff,
+ "[N] -> (C[] : { : N >= 0 })",
+ "{ C[] -> D[] }",
+ "[N] -> (D[] : { : N >= 0 })" },
+ { &isl_multi_union_pw_aff_apply_multi_aff,
+ "C[]",
+ "[N] -> { C[] -> D[N] }",
+ "[N] -> D[{ [N] }]" },
+ { &isl_multi_union_pw_aff_apply_multi_aff,
+ "(C[] : { A[i,j] : i >= j })",
+ "{ C[] -> D[] }",
+ "(D[] : { A[i,j] : i >= j })" },
+ { &isl_multi_union_pw_aff_apply_multi_aff,
+ "[N] -> (C[] : { A[i,j] : N >= 0 })",
+ "{ C[] -> D[] }",
+ "[N] -> (D[] : { A[i,j] : N >= 0 })" },
+ { &isl_multi_union_pw_aff_apply_multi_aff,
+ "(C[] : { A[i,j] : i >= j })",
+ "[N] -> { C[] -> D[N] }",
+ "[N] -> (D[{ A[i,j] -> [N] : i >= j }])" },
};
/* Perform some basic tests of binary operations on
@@ -5313,6 +5708,34 @@ struct {
"{ C[a] -> [a] : a >= 0; C[a] -> [-a] : a < 0 }",
"{ A[i,j] -> [i] : i >= 0; A[i,j] -> [-i] : i < 0; "
"B[i,j] -> [j] : j >= 0; B[i,j] -> [-j] : j < 0 }" },
+ { &isl_multi_union_pw_aff_apply_pw_aff,
+ "C[]",
+ "[N] -> { C[] -> [N] }",
+ "[N] -> { [N] }" },
+ { &isl_multi_union_pw_aff_apply_pw_aff,
+ "C[]",
+ "[N] -> { C[] -> [N] : N >= 0; C[] -> [-N] : N < 0 }",
+ "[N] -> { [N] : N >= 0; [-N] : N < 0 }" },
+ { &isl_multi_union_pw_aff_apply_pw_aff,
+ "[N] -> (C[] : { : N >= 0 })",
+ "[N] -> { C[] -> [N] }",
+ "[N] -> { [N] : N >= 0 }" },
+ { &isl_multi_union_pw_aff_apply_pw_aff,
+ "[N] -> (C[] : { : N >= 0 })",
+ "[N] -> { C[] -> [N] : N >= 0; C[] -> [-N] : N < 0 }",
+ "[N] -> { [N] : N >= 0 }" },
+ { &isl_multi_union_pw_aff_apply_pw_aff,
+ "[N] -> (C[] : { : N >= 0 })",
+ "{ C[] -> [0] }",
+ "[N] -> { [0] : N >= 0 }" },
+ { &isl_multi_union_pw_aff_apply_pw_aff,
+ "(C[] : { A[i,j] : i >= j })",
+ "[N] -> { C[] -> [N] }",
+ "[N] -> { A[i,j] -> [N] : i >= j }" },
+ { &isl_multi_union_pw_aff_apply_pw_aff,
+ "(C[] : { A[i,j] : i >= j })",
+ "[N] -> { C[] -> [N] : N >= 0 }",
+ "[N] -> { A[i,j] -> [N] : i >= j and N >= 0 }" },
};
/* Perform some basic tests of binary operations on
@@ -5393,6 +5816,46 @@ struct {
"C[]",
"{ C[] -> D[] }",
"D[]" },
+ { &isl_multi_union_pw_aff_apply_pw_multi_aff,
+ "[N] -> (C[] : { : N >= 0 })",
+ "{ C[] -> D[] }",
+ "[N] -> (D[] : { : N >= 0 })" },
+ { &isl_multi_union_pw_aff_apply_pw_multi_aff,
+ "C[]",
+ "[N] -> { C[] -> D[N] }",
+ "[N] -> D[{ [N] }]" },
+ { &isl_multi_union_pw_aff_apply_pw_multi_aff,
+ "(C[] : { A[i,j] : i >= j })",
+ "{ C[] -> D[] }",
+ "(D[] : { A[i,j] : i >= j })" },
+ { &isl_multi_union_pw_aff_apply_pw_multi_aff,
+ "[N] -> (C[] : { A[i,j] : N >= 0 })",
+ "{ C[] -> D[] }",
+ "[N] -> (D[] : { A[i,j] : N >= 0 })" },
+ { &isl_multi_union_pw_aff_apply_pw_multi_aff,
+ "(C[] : { A[i,j] : i >= j })",
+ "[N] -> { C[] -> D[N] }",
+ "[N] -> (D[{ A[i,j] -> [N] : i >= j }])" },
+ { &isl_multi_union_pw_aff_apply_pw_multi_aff,
+ "C[]",
+ "[N] -> { C[] -> D[N] : N >= 0; C[] -> D[-N] : N < 0 }",
+ "[N] -> D[{ [N] : N >= 0; [-N] : N < 0 }]" },
+ { &isl_multi_union_pw_aff_apply_pw_multi_aff,
+ "[N] -> (C[] : { : N >= 0 })",
+ "[N] -> { C[] -> D[N] }",
+ "[N] -> D[{ [N] : N >= 0 }]" },
+ { &isl_multi_union_pw_aff_apply_pw_multi_aff,
+ "[N] -> (C[] : { : N >= 0 })",
+ "[N] -> { C[] -> D[N] : N >= 0; C[] -> D[-N] : N < 0 }",
+ "[N] -> D[{ [N] : N >= 0 }]" },
+ { &isl_multi_union_pw_aff_apply_pw_multi_aff,
+ "[N] -> (C[] : { : N >= 0 })",
+ "{ C[] -> D[0] }",
+ "[N] -> D[{ [0] : N >= 0 }]" },
+ { &isl_multi_union_pw_aff_apply_pw_multi_aff,
+ "(C[] : { A[i,j] : i >= j })",
+ "[N] -> { C[] -> D[N] : N >= 0 }",
+ "[N] -> D[{ A[i,j] -> [N] : i >= j and N >= 0 }]" },
};
/* Perform some basic tests of binary operations on
@@ -5455,6 +5918,42 @@ struct {
"C[{ B[i,j] -> [i + 2j] }]",
"{ A[a,b] -> B[b,a] : a > b; A[a,b] -> B[a,b] : a <= b }",
"C[{ A[a,b] -> [b + 2a] : a > b; A[a,b] -> [a + 2b] : a <= b }]" },
+ { &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
+ "(C[] : { B[a,b] })",
+ "{ A[a,b] -> B[b,a] }",
+ "(C[] : { A[a,b] })" },
+ { &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
+ "(C[] : { B[a,b] })",
+ "{ B[a,b] -> A[b,a] }",
+ "(C[] : { })" },
+ { &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
+ "(C[] : { B[a,b] })",
+ "{ A[a,b] -> B[b,a] : a > b }",
+ "(C[] : { A[a,b] : a > b })" },
+ { &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
+ "(C[] : { B[a,b] : a > b })",
+ "{ A[a,b] -> B[b,a] }",
+ "(C[] : { A[a,b] : b > a })" },
+ { &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
+ "[N] -> (C[] : { B[a,b] : a > N })",
+ "{ A[a,b] -> B[b,a] : a > b }",
+ "[N] -> (C[] : { A[a,b] : a > b > N })" },
+ { &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
+ "(C[] : { B[a,b] : a > b })",
+ "[N] -> { A[a,b] -> B[b,a] : a > N }",
+ "[N] -> (C[] : { A[a,b] : b > a > N })" },
+ { &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
+ "C[]",
+ "{ A[a,b] -> B[b,a] }",
+ "C[]" },
+ { &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
+ "[N] -> (C[] : { : N >= 0 })",
+ "{ A[a,b] -> B[b,a] }",
+ "[N] -> (C[] : { : N >= 0 })" },
+ { &isl_multi_union_pw_aff_pullback_union_pw_multi_aff,
+ "C[]",
+ "[N] -> { A[a,b] -> B[b,a] : N >= 0 }",
+ "[N] -> (C[] : { : N >= 0 })" },
};
/* Perform some basic tests of binary operations on
@@ -6098,6 +6597,9 @@ struct {
{ &isl_multi_union_pw_aff_zero_union_set,
"F[{ A[i,j] -> [i-j]; B[i,j] -> [i-j] : i >= 0 }]",
"{ A[i,i]; B[i,i] : i >= 0 }" },
+ { &isl_multi_union_pw_aff_zero_union_set,
+ "(F[] : { A[i,j]; B[i,i] : i >= 0 })",
+ "{ A[i,j]; B[i,i] : i >= 0 }" },
};
/* Perform some basic tests of functions that select
@@ -6174,6 +6676,26 @@ struct {
"F[{ A[i,j] -> [i]; B[i,j] -> [i] }, "
"{ A[i,j] -> [j]; B[i,j] -> [j] }]",
"{ A[i,j] -> B[i',j'] : i,j >> i',j' }" },
+ { &isl_union_map_eq_at_multi_union_pw_aff,
+ "{ A[i,j] -> B[i',j']; A[i,j] -> C[i',j'] }",
+ "(F[] : { A[i,j]; B[i,j] })",
+ "{ A[i,j] -> B[i',j'] }" },
+ { &isl_union_map_eq_at_multi_union_pw_aff,
+ "{ A[i,j] -> B[i',j'] }",
+ "(F[] : { A[i,j] : i > j; B[i,j] : i < j })",
+ "{ A[i,j] -> B[i',j'] : i > j and i' < j' }" },
+ { &isl_union_map_eq_at_multi_union_pw_aff,
+ "[N] -> { A[i,j] -> B[i',j'] : i,i' <= N }",
+ "(F[] : { A[i,j] : i > j; B[i,j] : i < j })",
+ "[N] -> { A[i,j] -> B[i',j'] : i > j and i' < j' and i,i' <= N }" },
+ { &isl_union_map_eq_at_multi_union_pw_aff,
+ "{ A[i,j] -> B[i',j'] }",
+ "[N] -> (F[] : { A[i,j] : i < N; B[i,j] : i < N })",
+ "[N] -> { A[i,j] -> B[i',j'] : i,i' < N }" },
+ { &isl_union_map_eq_at_multi_union_pw_aff,
+ "{ A[i,j] -> B[i',j'] }",
+ "[N] -> (F[] : { : N >= 0 })",
+ "[N] -> { A[i,j] -> B[i',j'] : N >= 0 }" },
};
/* Perform some basic tests of functions that select
@@ -6697,6 +7219,7 @@ const char *mpa_conversion_tests[] = {
"{ [x] -> A[x] : x >= 0; [x] -> A[-x] : x < 0 }",
"{ [x] -> A[x, x + 1] }",
"{ [x] -> A[] }",
+ "{ [x] -> A[] : x >= 0 }",
};
/* Check that conversion from isl_pw_multi_aff to isl_multi_pw_aff and
@@ -6743,6 +7266,7 @@ const char *umap_mupa_conversion_tests[] = {
"5e0 = -a - b + c and c >= -a and c <= 4 - a) }",
"{ [a, b] -> [c] : exists d : 18 * d = -3 - a + 2c and 1 <= c <= 3 }",
"{ A[] -> B[0]; C[] -> B[1] }",
+ "{ A[] -> B[]; C[] -> B[] }",
};
/* Check that converting from isl_union_map to isl_multi_union_pw_aff and back
@@ -7518,7 +8042,7 @@ static int test_pw_multi_aff(isl_ctx *ctx)
/* Check that we can properly parse multi piecewise affine expressions
* where the piecewise affine expressions have different domains.
*/
-static int test_multi_pw_aff(isl_ctx *ctx)
+static int test_multi_pw_aff_1(isl_ctx *ctx)
{
const char *str;
isl_set *dom, *dom2;
@@ -7563,6 +8087,61 @@ static int test_multi_pw_aff(isl_ctx *ctx)
return 0;
}
+/* Check that the dimensions in the explicit domain
+ * of a multi piecewise affine expression are properly
+ * taken into account.
+ */
+static int test_multi_pw_aff_2(isl_ctx *ctx)
+{
+ const char *str;
+ isl_bool involves1, involves2, involves3, equal;
+ isl_multi_pw_aff *mpa, *mpa1, *mpa2;
+
+ str = "{ A[x,y] -> B[] : x >= y }";
+ mpa = isl_multi_pw_aff_read_from_str(ctx, str);
+ involves1 = isl_multi_pw_aff_involves_dims(mpa, isl_dim_in, 0, 2);
+ mpa1 = isl_multi_pw_aff_copy(mpa);
+
+ mpa = isl_multi_pw_aff_insert_dims(mpa, isl_dim_in, 0, 1);
+ involves2 = isl_multi_pw_aff_involves_dims(mpa, isl_dim_in, 0, 1);
+ involves3 = isl_multi_pw_aff_involves_dims(mpa, isl_dim_in, 1, 2);
+ str = "{ [a,x,y] -> B[] : x >= y }";
+ mpa2 = isl_multi_pw_aff_read_from_str(ctx, str);
+ equal = isl_multi_pw_aff_plain_is_equal(mpa, mpa2);
+ isl_multi_pw_aff_free(mpa2);
+
+ mpa = isl_multi_pw_aff_drop_dims(mpa, isl_dim_in, 0, 1);
+ mpa = isl_multi_pw_aff_set_tuple_name(mpa, isl_dim_in, "A");
+ if (equal >= 0 && equal)
+ equal = isl_multi_pw_aff_plain_is_equal(mpa, mpa1);
+ isl_multi_pw_aff_free(mpa1);
+ isl_multi_pw_aff_free(mpa);
+
+ if (involves1 < 0 || involves2 < 0 || involves3 < 0 || equal < 0)
+ return -1;
+ if (!equal)
+ isl_die(ctx, isl_error_unknown,
+ "incorrect result of dimension insertion/removal",
+ return isl_stat_error);
+ if (!involves1 || involves2 || !involves3)
+ isl_die(ctx, isl_error_unknown,
+ "incorrect characterization of involved dimensions",
+ return isl_stat_error);
+
+ return 0;
+}
+
+/* Perform some tests on multi piecewise affine expressions.
+ */
+static int test_multi_pw_aff(isl_ctx *ctx)
+{
+ if (test_multi_pw_aff_1(ctx) < 0)
+ return -1;
+ if (test_multi_pw_aff_2(ctx) < 0)
+ return -1;
+ return 0;
+}
+
/* This is a regression test for a bug where isl_basic_map_simplify
* would end up in an infinite loop. In particular, we construct
* an empty basic set that is not obviously empty.
@@ -7705,6 +8284,50 @@ static int test_schedule_tree(isl_ctx *ctx)
return 0;
}
+/* Check that a zero-dimensional prefix schedule keeps track
+ * of the domain and outer filters.
+ */
+static int test_schedule_tree_prefix(isl_ctx *ctx)
+{
+ const char *str;
+ isl_bool equal;
+ isl_union_set *uset;
+ isl_union_set_list *filters;
+ isl_multi_union_pw_aff *mupa, *mupa2;
+ isl_schedule_node *node;
+
+ str = "{ S1[i,j] : 0 <= i,j < 10; S2[i,j] : 0 <= i,j < 10 }";
+ uset = isl_union_set_read_from_str(ctx, str);
+ node = isl_schedule_node_from_domain(uset);
+ node = isl_schedule_node_child(node, 0);
+
+ str = "{ S1[i,j] : i > j }";
+ uset = isl_union_set_read_from_str(ctx, str);
+ filters = isl_union_set_list_from_union_set(uset);
+ str = "{ S1[i,j] : i <= j; S2[i,j] }";
+ uset = isl_union_set_read_from_str(ctx, str);
+ filters = isl_union_set_list_add(filters, uset);
+ node = isl_schedule_node_insert_sequence(node, filters);
+
+ node = isl_schedule_node_child(node, 0);
+ node = isl_schedule_node_child(node, 0);
+ mupa = isl_schedule_node_get_prefix_schedule_multi_union_pw_aff(node);
+ str = "([] : { S1[i,j] : i > j })";
+ mupa2 = isl_multi_union_pw_aff_read_from_str(ctx, str);
+ equal = isl_multi_union_pw_aff_plain_is_equal(mupa, mupa2);
+ isl_multi_union_pw_aff_free(mupa2);
+ isl_multi_union_pw_aff_free(mupa);
+ isl_schedule_node_free(node);
+
+ if (equal < 0)
+ return -1;
+ if (!equal)
+ isl_die(ctx, isl_error_unknown, "unexpected prefix schedule",
+ return -1);
+
+ return 0;
+}
+
/* Check that the reaching domain elements and the prefix schedule
* at a leaf node are the same before and after grouping.
*/
@@ -8226,6 +8849,7 @@ struct {
{ "schedule (whole component)", &test_schedule_whole },
{ "schedule (incremental)", &test_schedule_incremental },
{ "schedule tree", &test_schedule_tree },
+ { "schedule tree prefix", &test_schedule_tree_prefix },
{ "schedule tree grouping", &test_schedule_tree_group },
{ "tile", &test_tile },
{ "union_pw", &test_union_pw },
#include <isl_union_map_private.h>
#include <isl/ctx.h>
#include <isl/hash.h>
-#include <isl/aff.h>
+#include <isl_aff_private.h>
#include <isl/map.h>
#include <isl/set.h>
#include <isl_space_private.h>
@@ -3907,6 +3907,41 @@ static isl_stat order_at(__isl_take isl_map *map, void *user)
return data->res ? isl_stat_ok : isl_stat_error;
}
+/* If "mupa" has a non-trivial explicit domain, then intersect
+ * domain and range of "umap" with this explicit domain.
+ * If the explicit domain only describes constraints on the parameters,
+ * then the intersection only needs to be performed once.
+ */
+static __isl_give isl_union_map *intersect_explicit_domain(
+ __isl_take isl_union_map *umap, __isl_keep isl_multi_union_pw_aff *mupa)
+{
+ isl_bool non_trivial, is_params;
+ isl_union_set *dom;
+
+ non_trivial = isl_multi_union_pw_aff_has_non_trivial_domain(mupa);
+ if (non_trivial < 0)
+ return isl_union_map_free(umap);
+ if (!non_trivial)
+ return umap;
+ mupa = isl_multi_union_pw_aff_copy(mupa);
+ dom = isl_multi_union_pw_aff_domain(mupa);
+ is_params = isl_union_set_is_params(dom);
+ if (is_params < 0) {
+ isl_union_set_free(dom);
+ return isl_union_map_free(umap);
+ }
+ if (is_params) {
+ isl_set *set;
+
+ set = isl_union_set_params(dom);
+ umap = isl_union_map_intersect_params(umap, set);
+ return umap;
+ }
+ umap = isl_union_map_intersect_domain(umap, isl_union_set_copy(dom));
+ umap = isl_union_map_intersect_range(umap, dom);
+ return umap;
+}
+
/* Intersect each map in "umap" with the result of calling "order"
* on the functions is "mupa" that apply to the domain and the range
* of the map.
@@ -3922,6 +3957,7 @@ static __isl_give isl_union_map *isl_union_map_order_at_multi_union_pw_aff(
isl_multi_union_pw_aff_get_space(mupa));
mupa = isl_multi_union_pw_aff_align_params(mupa,
isl_union_map_get_space(umap));
+ umap = intersect_explicit_domain(umap, mupa);
data.mupa = mupa;
data.order = order;
data.res = isl_union_map_empty(isl_union_map_get_space(umap));
@@ -1640,6 +1640,7 @@ isl_stat isl_val_check_match_domain_space(__isl_keep isl_val *v,
#define NO_IDENTITY
#define NO_FROM_BASE
#define NO_MOVE_DIMS
+#include <isl_multi_no_explicit_domain.c>
#include <isl_multi_templ.c>
#include <isl_multi_dims.c>