#include <stdlib.h>
#include <isl_dim_private.h>
#include "isl_name.h"
+#include <isl_reordering.h>
isl_ctx *isl_dim_get_ctx(__isl_keep isl_dim *dim)
{
goto error;
pos = global_pos(dim, type, pos);
- isl_assert(ctx, pos != isl_dim_total(dim), goto error);
+ if (pos == isl_dim_total(dim))
+ goto error;
if (pos >= dim->n_name) {
if (!name)
case isl_dim_param: return dim->nparam;
case isl_dim_in: return dim->n_in;
case isl_dim_out: return dim->n_out;
+ case isl_dim_all: return dim->nparam + dim->n_in + dim->n_out;
default: return 0;
}
}
return NULL;
if (!name_ok(dim->ctx, s))
goto error;
+ isl_name_free(dim->ctx, get_name(dim, type, pos));
name = isl_name_get(dim->ctx, s);
if (!name)
goto error;
dim = isl_dim_reset(dim, type);
switch (type) {
case isl_dim_param:
- return isl_dim_extend(dim,
+ dim = isl_dim_extend(dim,
dim->nparam + n, dim->n_in, dim->n_out);
+ if (dim && dim->nested[0] &&
+ !(dim->nested[0] = isl_dim_add(dim->nested[0],
+ isl_dim_param, n)))
+ goto error;
+ if (dim && dim->nested[1] &&
+ !(dim->nested[1] = isl_dim_add(dim->nested[1],
+ isl_dim_param, n)))
+ goto error;
+ return dim;
case isl_dim_in:
return isl_dim_extend(dim,
dim->nparam, dim->n_in + n, dim->n_out);
case isl_dim_out:
return isl_dim_extend(dim,
dim->nparam, dim->n_in, dim->n_out + n);
+ default:
+ isl_die(dim->ctx, isl_error_invalid,
+ "cannot add dimensions of specified type", goto error);
+ }
+error:
+ isl_dim_free(dim);
+ return NULL;
+}
+
+static int valid_dim_type(enum isl_dim_type type)
+{
+ switch (type) {
+ case isl_dim_param:
+ case isl_dim_in:
+ case isl_dim_out:
+ return 1;
+ default:
+ return 0;
}
- return dim;
}
__isl_give isl_dim *isl_dim_insert(__isl_take isl_dim *dim,
if (n == 0)
return isl_dim_reset(dim, type);
+ if (!valid_dim_type(type))
+ isl_die(dim->ctx, isl_error_invalid,
+ "cannot insert dimensions of specified type",
+ goto error);
+
isl_assert(dim->ctx, pos <= isl_dim_size(dim, type), goto error);
dim = isl_dim_cow(dim);
case isl_dim_param: dim->nparam += n; break;
case isl_dim_in: dim->n_in += n; break;
case isl_dim_out: dim->n_out += n; break;
+ default: ;
}
dim = isl_dim_reset(dim, type);
enum isl_dim_type dst_type, unsigned dst_pos,
enum isl_dim_type src_type, unsigned src_pos, unsigned n)
{
+ int i;
+
if (!dim)
return NULL;
if (n == 0)
case isl_dim_param: dim->nparam += n; break;
case isl_dim_in: dim->n_in += n; break;
case isl_dim_out: dim->n_out += n; break;
+ default: ;
}
switch (src_type) {
case isl_dim_param: dim->nparam -= n; break;
case isl_dim_in: dim->n_in -= n; break;
case isl_dim_out: dim->n_out -= n; break;
+ default: ;
+ }
+
+ if (dst_type != isl_dim_param && src_type != isl_dim_param)
+ return dim;
+
+ for (i = 0; i < 2; ++i) {
+ if (!dim->nested[i])
+ continue;
+ dim->nested[i] = isl_dim_replace(dim->nested[i],
+ isl_dim_param, dim);
+ if (!dim->nested[i])
+ goto error;
}
return dim;
return NULL;
}
-struct isl_dim *isl_dim_map(struct isl_dim *dim)
+__isl_give isl_dim *isl_dim_range_product(__isl_take isl_dim *left,
+ __isl_take isl_dim *right)
+{
+ isl_dim *dom, *ran1, *ran2, *nest;
+
+ if (!left || !right)
+ goto error;
+
+ isl_assert(left->ctx, match(left, isl_dim_param, right, isl_dim_param),
+ goto error);
+ if (!isl_dim_match(left, isl_dim_in, right, isl_dim_in))
+ isl_die(left->ctx, isl_error_invalid,
+ "domains need to match", goto error);
+
+ dom = isl_dim_domain(isl_dim_copy(left));
+
+ ran1 = isl_dim_range(left);
+ ran2 = isl_dim_range(right);
+ nest = isl_dim_wrap(isl_dim_join(isl_dim_reverse(ran1), ran2));
+
+ return isl_dim_join(isl_dim_reverse(dom), nest);
+error:
+ isl_dim_free(left);
+ isl_dim_free(right);
+ return NULL;
+}
+
+__isl_give isl_dim *isl_dim_map_from_set(__isl_take isl_dim *dim)
{
struct isl_name **names = NULL;
if (!dim)
return NULL;
- if (n == 0)
+ if (num == 0)
return isl_dim_reset(dim, type);
+ if (!valid_dim_type(type))
+ isl_die(dim->ctx, isl_error_invalid,
+ "cannot drop dimensions of specified type", goto error);
+
isl_assert(dim->ctx, first + num <= n(dim, type), goto error);
dim = isl_dim_cow(dim);
if (!dim)
case isl_dim_in:
get_names(dim, isl_dim_out, 0, dim->n_out,
dim->names + offset(dim, isl_dim_out) - num);
- case isl_dim_out:
+ default:
;
}
dim->n_name -= num;
case isl_dim_param: dim->nparam -= num; break;
case isl_dim_in: dim->n_in -= num; break;
case isl_dim_out: dim->n_out -= num; break;
+ default: ;
}
dim = isl_dim_reset(dim, type);
+ if (type == isl_dim_param) {
+ if (dim && dim->nested[0] &&
+ !(dim->nested[0] = isl_dim_drop(dim->nested[0],
+ isl_dim_param, first, num)))
+ goto error;
+ if (dim && dim->nested[1] &&
+ !(dim->nested[1] = isl_dim_drop(dim->nested[1],
+ isl_dim_param, first, num)))
+ goto error;
+ }
return dim;
error:
isl_dim_free(dim);
unsigned isl_dim_total(struct isl_dim *dim)
{
- return dim->nparam + dim->n_in + dim->n_out;
+ return dim ? dim->nparam + dim->n_in + dim->n_out : 0;
}
int isl_dim_equal(struct isl_dim *dim1, struct isl_dim *dim2)
for (i = 0; i < dim->nparam; ++i) {
name = get_name(dim, isl_dim_param, i);
- hash = isl_hash_builtin(hash, name);
+ hash = isl_hash_name(hash, name);
}
name = tuple_name(dim, isl_dim_in);
- hash = isl_hash_builtin(hash, name);
+ hash = isl_hash_name(hash, name);
name = tuple_name(dim, isl_dim_out);
- hash = isl_hash_builtin(hash, name);
+ hash = isl_hash_name(hash, name);
hash = isl_hash_dim(hash, dim->nested[0]);
hash = isl_hash_dim(hash, dim->nested[1]);
return 0;
}
+int isl_dim_may_be_set(__isl_keep isl_dim *dim)
+{
+ if (!dim)
+ return -1;
+ if (isl_dim_size(dim, isl_dim_in) != 0)
+ return 0;
+ if (isl_dim_is_named_or_nested(dim, isl_dim_in))
+ return 0;
+ return 1;
+}
+
__isl_give isl_dim *isl_dim_reset(__isl_take isl_dim *dim,
enum isl_dim_type type)
{
if (!dim->nested[0] && !dim->nested[1])
return dim;
- isl_dim_free(dim->nested[0]);
- dim->nested[0] = NULL;
- isl_dim_free(dim->nested[1]);
- dim->nested[1] = NULL;
+ if (dim->nested[0])
+ dim = isl_dim_reset(dim, isl_dim_in);
+ if (dim && dim->nested[1])
+ dim = isl_dim_reset(dim, isl_dim_out);
return dim;
}
+__isl_give isl_dim *isl_dim_flatten_range(__isl_take isl_dim *dim)
+{
+ if (!dim)
+ return NULL;
+ if (!dim->nested[1])
+ return dim;
+
+ return isl_dim_reset(dim, isl_dim_out);
+}
+
/* Replace the dimensions of the given type of dst by those of src.
*/
__isl_give isl_dim *isl_dim_replace(__isl_take isl_dim *dst,
enum isl_dim_type type, __isl_keep isl_dim *src)
{
+ dst = isl_dim_cow(dst);
+
if (!dst || !src)
goto error;
- if (type == isl_dim_param) {
+ dst = isl_dim_drop(dst, type, 0, isl_dim_size(dst, type));
+ dst = isl_dim_add(dst, type, isl_dim_size(src, type));
+ dst = copy_names(dst, type, 0, src, type);
+
+ if (dst && type == isl_dim_param) {
int i;
for (i = 0; i <= 1; ++i) {
if (!dst->nested[i])
}
}
- dst = isl_dim_drop(dst, type, 0, isl_dim_size(dst, type));
- dst = isl_dim_add(dst, type, isl_dim_size(src, type));
- dst = copy_names(dst, type, 0, src, type);
-
return dst;
error:
isl_dim_free(dst);
return NULL;
}
+
+/* Given a dimension specification "dim" of a set, create a dimension
+ * specification for the lift of the set. In particular, the result
+ * is of the form [dim -> local[..]], with n_local variables in the
+ * range of the wrapped map.
+ */
+__isl_give isl_dim *isl_dim_lift(__isl_take isl_dim *dim, unsigned n_local)
+{
+ isl_dim *local_dim;
+
+ if (!dim)
+ return NULL;
+
+ local_dim = isl_dim_dup(dim);
+ local_dim = isl_dim_drop(local_dim, isl_dim_set, 0, dim->n_out);
+ local_dim = isl_dim_add(local_dim, isl_dim_set, n_local);
+ local_dim = isl_dim_set_tuple_name(local_dim, isl_dim_set, "local");
+ dim = isl_dim_join(isl_dim_from_domain(dim),
+ isl_dim_from_range(local_dim));
+ dim = isl_dim_wrap(dim);
+ dim = isl_dim_set_tuple_name(dim, isl_dim_set, "lifted");
+
+ return dim;
+}
+
+int isl_dim_can_zip(__isl_keep isl_dim *dim)
+{
+ if (!dim)
+ return -1;
+
+ return dim->nested[0] && dim->nested[1];
+}
+
+__isl_give isl_dim *isl_dim_zip(__isl_take isl_dim *dim)
+{
+ isl_dim *dom, *ran;
+ isl_dim *dom_dom, *dom_ran, *ran_dom, *ran_ran;
+
+ if (!isl_dim_can_zip(dim))
+ isl_die(dim->ctx, isl_error_invalid, "dim cannot be zipped",
+ goto error);
+
+ if (!dim)
+ return 0;
+ dom = isl_dim_unwrap(isl_dim_domain(isl_dim_copy(dim)));
+ ran = isl_dim_unwrap(isl_dim_range(dim));
+ dom_dom = isl_dim_domain(isl_dim_copy(dom));
+ dom_ran = isl_dim_range(dom);
+ ran_dom = isl_dim_domain(isl_dim_copy(ran));
+ ran_ran = isl_dim_range(ran);
+ dom = isl_dim_join(isl_dim_from_domain(dom_dom),
+ isl_dim_from_range(ran_dom));
+ ran = isl_dim_join(isl_dim_from_domain(dom_ran),
+ isl_dim_from_range(ran_ran));
+ return isl_dim_join(isl_dim_from_domain(isl_dim_wrap(dom)),
+ isl_dim_from_range(isl_dim_wrap(ran)));
+error:
+ isl_dim_free(dim);
+ return NULL;
+}
+
+int isl_dim_has_named_params(__isl_keep isl_dim *dim)
+{
+ int i;
+ unsigned off;
+
+ if (!dim)
+ return -1;
+ if (dim->nparam == 0)
+ return 1;
+ off = isl_dim_offset(dim, isl_dim_param);
+ if (off + dim->nparam > dim->n_name)
+ return 0;
+ for (i = 0; i < dim->nparam; ++i)
+ if (!dim->names[off + i])
+ return 0;
+ return 1;
+}
+
+/* Align the initial parameters of dim1 to match the order in dim2.
+ */
+__isl_give isl_dim *isl_dim_align_params(__isl_take isl_dim *dim1,
+ __isl_take isl_dim *dim2)
+{
+ isl_reordering *exp;
+
+ if (!isl_dim_has_named_params(dim1) || !isl_dim_has_named_params(dim2))
+ isl_die(isl_dim_get_ctx(dim1), isl_error_invalid,
+ "parameter alignment requires named parameters",
+ goto error);
+
+ exp = isl_parameter_alignment_reordering(dim1, dim2);
+ isl_dim_free(dim1);
+ isl_dim_free(dim2);
+ if (!exp)
+ return NULL;
+ dim1 = isl_dim_copy(exp->dim);
+ isl_reordering_free(exp);
+ return dim1;
+error:
+ isl_dim_free(dim1);
+ isl_dim_free(dim2);
+ return NULL;
+}