X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=isl_space.c;h=e6f957c48276c3fc8c6b39879abe7279fe4948cb;hb=de51a9bc4da5dd3f1f9f57c2362da6f9752c44e0;hp=a7d7d53a48dcd85cad157485b285c1404a2a9ea7;hpb=d07eed3bf4d0e290118588ca80997a8035eaeb21;p=platform%2Fupstream%2Fisl.git diff --git a/isl_space.c b/isl_space.c index a7d7d53..e6f957c 100644 --- a/isl_space.c +++ b/isl_space.c @@ -2,7 +2,7 @@ * Copyright 2008-2009 Katholieke Universiteit Leuven * Copyright 2010 INRIA Saclay * - * Use of this software is governed by the GNU LGPLv2.1 license + * Use of this software is governed by the MIT license * * Written by Sven Verdoolaege, K.U.Leuven, Departement * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium @@ -48,10 +48,86 @@ __isl_give isl_space *isl_space_alloc(isl_ctx *ctx, return dim; } +/* Mark the space as being that of a set, by setting the domain tuple + * to isl_id_none. + */ +static __isl_give isl_space *mark_as_set(__isl_take isl_space *space) +{ + space = isl_space_cow(space); + if (!space) + return NULL; + space = isl_space_set_tuple_id(space, isl_dim_in, &isl_id_none); + return space; +} + +/* Is the space that of a set? + */ +int isl_space_is_set(__isl_keep isl_space *space) +{ + if (!space) + return -1; + if (space->n_in != 0 || space->nested[0]) + return 0; + if (space->tuple_id[0] != &isl_id_none) + return 0; + return 1; +} + +/* Is the given space that of a map? + */ +int isl_space_is_map(__isl_keep isl_space *space) +{ + if (!space) + return -1; + return space->tuple_id[0] != &isl_id_none && + space->tuple_id[1] != &isl_id_none; +} + __isl_give isl_space *isl_space_set_alloc(isl_ctx *ctx, unsigned nparam, unsigned dim) { - return isl_space_alloc(ctx, nparam, 0, dim); + isl_space *space; + space = isl_space_alloc(ctx, nparam, 0, dim); + space = mark_as_set(space); + return space; +} + +/* Mark the space as being that of a parameter domain, by setting + * both tuples to isl_id_none. + */ +static __isl_give isl_space *mark_as_params(isl_space *space) +{ + if (!space) + return NULL; + space = isl_space_set_tuple_id(space, isl_dim_in, &isl_id_none); + space = isl_space_set_tuple_id(space, isl_dim_out, &isl_id_none); + return space; +} + +/* Is the space that of a parameter domain? + */ +int isl_space_is_params(__isl_keep isl_space *space) +{ + if (!space) + return -1; + if (space->n_in != 0 || space->nested[0] || + space->n_out != 0 || space->nested[1]) + return 0; + if (space->tuple_id[0] != &isl_id_none) + return 0; + if (space->tuple_id[1] != &isl_id_none) + return 0; + return 1; +} + +/* Create a space for a parameter domain. + */ +__isl_give isl_space *isl_space_params_alloc(isl_ctx *ctx, unsigned nparam) +{ + isl_space *space; + space = isl_space_alloc(ctx, nparam, 0, 0); + space = mark_as_params(space); + return space; } static unsigned global_pos(__isl_keep isl_space *dim, @@ -216,6 +292,8 @@ __isl_take isl_space *isl_space_dup(__isl_keep isl_space *dim) if (!dim) return NULL; dup = isl_space_alloc(dim->ctx, dim->nparam, dim->n_in, dim->n_out); + if (!dup) + return NULL; if (dim->tuple_id[0] && !(dup->tuple_id[0] = isl_id_copy(dim->tuple_id[0]))) goto error; @@ -257,15 +335,15 @@ __isl_give isl_space *isl_space_copy(__isl_keep isl_space *dim) return dim; } -void isl_space_free(__isl_take isl_space *dim) +void *isl_space_free(__isl_take isl_space *dim) { int i; if (!dim) - return; + return NULL; if (--dim->ref > 0) - return; + return NULL; isl_id_free(dim->tuple_id[0]); isl_id_free(dim->tuple_id[1]); @@ -279,8 +357,15 @@ void isl_space_free(__isl_take isl_space *dim) isl_ctx_deref(dim->ctx); free(dim); + + return NULL; } +/* Check if "s" is a valid dimension or tuple name. + * We currently only forbid names that look like a number. + * + * s is assumed to be non-NULL. + */ static int name_ok(isl_ctx *ctx, const char *s) { char *p; @@ -294,27 +379,47 @@ static int name_ok(isl_ctx *ctx, const char *s) return 1; } -int isl_space_has_tuple_id(__isl_keep isl_space *dim, enum isl_dim_type type) +/* Is it possible for the given dimension type to have a tuple id? + */ +static int space_can_have_id(__isl_keep isl_space *space, + enum isl_dim_type type) { - if (!dim) - return -1; + if (!space) + return 0; + if (isl_space_is_params(space)) + isl_die(space->ctx, isl_error_invalid, + "parameter spaces don't have tuple ids", return 0); + if (isl_space_is_set(space) && type != isl_dim_set) + isl_die(space->ctx, isl_error_invalid, + "set spaces can only have a set id", return 0); if (type != isl_dim_in && type != isl_dim_out) - isl_die(dim->ctx, isl_error_invalid, + isl_die(space->ctx, isl_error_invalid, "only input, output and set tuples can have ids", - return -1); + return 0); + + return 1; +} + +/* Does the tuple have an id? + */ +int isl_space_has_tuple_id(__isl_keep isl_space *dim, enum isl_dim_type type) +{ + if (!space_can_have_id(dim, type)) + return -1; return dim->tuple_id[type - isl_dim_in] != NULL; } __isl_give isl_id *isl_space_get_tuple_id(__isl_keep isl_space *dim, enum isl_dim_type type) { + int has_id; + if (!dim) return NULL; - if (type != isl_dim_in && type != isl_dim_out) - isl_die(dim->ctx, isl_error_invalid, - "only input, output and set tuples can have ids", - return NULL); - if (!dim->tuple_id[type - isl_dim_in]) + has_id = isl_space_has_tuple_id(dim, type); + if (has_id < 0) + return NULL; + if (!has_id) isl_die(dim->ctx, isl_error_invalid, "tuple has no id", return NULL); return isl_id_copy(dim->tuple_id[type - isl_dim_in]); @@ -361,17 +466,70 @@ error: return NULL; } -__isl_give isl_space *isl_space_set_dim_id(__isl_take isl_space *dim, +/* Set the id of the given dimension of "space" to "id". + * If the dimension already has an id, then it is replaced. + * If the dimension is a parameter, then we need to change it + * in the nested spaces (if any) as well. + */ +__isl_give isl_space *isl_space_set_dim_id(__isl_take isl_space *space, enum isl_dim_type type, unsigned pos, __isl_take isl_id *id) { - dim = isl_space_cow(dim); - if (!dim || !id) + space = isl_space_cow(space); + if (!space || !id) goto error; - isl_id_free(get_id(dim, type, pos)); - return set_id(dim, type, pos, id); + + if (type == isl_dim_param) { + int i; + + for (i = 0; i < 2; ++i) { + if (!space->nested[i]) + continue; + space->nested[i] = + isl_space_set_dim_id(space->nested[i], + type, pos, isl_id_copy(id)); + if (!space->nested[i]) + goto error; + } + } + + isl_id_free(get_id(space, type, pos)); + return set_id(space, type, pos, id); error: isl_id_free(id); - isl_space_free(dim); + isl_space_free(space); + return NULL; +} + +/* Reset the id of the given dimension of "space". + * If the dimension already has an id, then it is removed. + * If the dimension is a parameter, then we need to reset it + * in the nested spaces (if any) as well. + */ +__isl_give isl_space *isl_space_reset_dim_id(__isl_take isl_space *space, + enum isl_dim_type type, unsigned pos) +{ + space = isl_space_cow(space); + if (!space) + goto error; + + if (type == isl_dim_param) { + int i; + + for (i = 0; i < 2; ++i) { + if (!space->nested[i]) + continue; + space->nested[i] = + isl_space_reset_dim_id(space->nested[i], + type, pos); + if (!space->nested[i]) + goto error; + } + } + + isl_id_free(get_id(space, type, pos)); + return set_id(space, type, pos, NULL); +error: + isl_space_free(space); return NULL; } @@ -415,6 +573,19 @@ error: return NULL; } +/* Does the tuple have a name? + */ +int isl_space_has_tuple_name(__isl_keep isl_space *space, + enum isl_dim_type type) +{ + isl_id *id; + + if (!space_can_have_id(space, type)) + return -1; + id = space->tuple_id[type - isl_dim_in]; + return id && id->name; +} + const char *isl_space_get_tuple_name(__isl_keep isl_space *dim, enum isl_dim_type type) { @@ -435,6 +606,8 @@ __isl_give isl_space *isl_space_set_dim_name(__isl_take isl_space *dim, if (!dim) return NULL; + if (!s) + return isl_space_reset_dim_id(dim, type, pos); if (!name_ok(dim->ctx, s)) goto error; id = isl_id_alloc(dim->ctx, s, NULL); @@ -444,6 +617,19 @@ error: return NULL; } +/* Does the given dimension have a name? + */ +int isl_space_has_dim_name(__isl_keep isl_space *space, + enum isl_dim_type type, unsigned pos) +{ + isl_id *id; + + if (!space) + return -1; + id = get_id(space, type, pos); + return id && id->name; +} + __isl_keep const char *isl_space_get_dim_name(__isl_keep isl_space *dim, enum isl_dim_type type, unsigned pos) { @@ -470,6 +656,26 @@ int isl_space_find_dim_by_id(__isl_keep isl_space *dim, enum isl_dim_type type, return -1; } +int isl_space_find_dim_by_name(__isl_keep isl_space *space, + enum isl_dim_type type, const char *name) +{ + int i; + int offset; + int n; + + if (!space || !name) + return -1; + + offset = isl_space_offset(space, type); + n = isl_space_dim(space, type); + for (i = 0; i < n && offset + i < space->n_id; ++i) + if (space->ids[offset + i]->name && + !strcmp(space->ids[offset + i]->name, name)) + return i; + + return -1; +} + static __isl_keep isl_id *tuple_id(__isl_keep isl_space *dim, enum isl_dim_type type) { @@ -503,6 +709,9 @@ int isl_space_tuple_match(__isl_keep isl_space *dim1, enum isl_dim_type dim1_typ if (!dim1 || !dim2) return -1; + if (dim1 == dim2 && dim1_type == dim2_type) + return 1; + if (n(dim1, dim1_type) != n(dim2, dim2_type)) return 0; id1 = tuple_id(dim1, dim1_type); @@ -525,6 +734,9 @@ static int match(__isl_keep isl_space *dim1, enum isl_dim_type dim1_type, { int i; + if (dim1 == dim2 && dim1_type == dim2_type) + return 1; + if (!isl_space_tuple_match(dim1, dim1_type, dim2, dim2_type)) return 0; @@ -541,6 +753,9 @@ static int match(__isl_keep isl_space *dim1, enum isl_dim_type dim1_type, int isl_space_match(__isl_keep isl_space *dim1, enum isl_dim_type dim1_type, __isl_keep isl_space *dim2, enum isl_dim_type dim2_type) { + if (!dim1 || !dim2) + return -1; + return match(dim1, dim1_type, dim2, dim2_type); } @@ -568,6 +783,8 @@ __isl_give isl_space *isl_space_extend(__isl_take isl_space *dim, isl_assert(dim->ctx, dim->n_out <= n_out, goto error); dim = isl_space_cow(dim); + if (!dim) + goto error; if (dim->ids) { ids = isl_calloc_array(dim->ctx, isl_id *, @@ -638,6 +855,10 @@ static int valid_dim_type(enum isl_dim_type type) } } +/* Insert "n" dimensions of type "type" at position "pos". + * If we are inserting parameters, then they are also inserted in + * any nested spaces. + */ __isl_give isl_space *isl_space_insert_dims(__isl_take isl_space *dim, enum isl_dim_type type, unsigned pos, unsigned n) { @@ -660,27 +881,26 @@ __isl_give isl_space *isl_space_insert_dims(__isl_take isl_space *dim, return NULL; if (dim->ids) { - enum isl_dim_type t; + enum isl_dim_type t, o = isl_dim_param; int off; int s[3]; - int *size = s - isl_dim_param; ids = isl_calloc_array(dim->ctx, isl_id *, dim->nparam + dim->n_in + dim->n_out + n); if (!ids) goto error; off = 0; - size[isl_dim_param] = dim->nparam; - size[isl_dim_in] = dim->n_in; - size[isl_dim_out] = dim->n_out; + s[isl_dim_param - o] = dim->nparam; + s[isl_dim_in - o] = dim->n_in; + s[isl_dim_out - o] = dim->n_out; for (t = isl_dim_param; t <= isl_dim_out; ++t) { if (t != type) { - get_ids(dim, t, 0, size[t], ids + off); - off += size[t]; + get_ids(dim, t, 0, s[t - o], ids + off); + off += s[t - o]; } else { get_ids(dim, t, 0, pos, ids + off); off += pos + n; - get_ids(dim, t, pos, size[t] - pos, ids + off); - off += size[t] - pos; + get_ids(dim, t, pos, s[t - o] - pos, ids + off); + off += s[t - o] - pos; } } free(dim->ids); @@ -695,6 +915,17 @@ __isl_give isl_space *isl_space_insert_dims(__isl_take isl_space *dim, } dim = isl_space_reset(dim, type); + if (type == isl_dim_param) { + if (dim && dim->nested[0] && + !(dim->nested[0] = isl_space_insert_dims(dim->nested[0], + isl_dim_param, pos, n))) + goto error; + if (dim && dim->nested[1] && + !(dim->nested[1] = isl_space_insert_dims(dim->nested[1], + isl_dim_param, pos, n))) + goto error; + } + return dim; error: isl_space_free(dim); @@ -729,36 +960,35 @@ __isl_give isl_space *isl_space_move_dims(__isl_take isl_space *dim, if (dim->ids) { isl_id **ids; - enum isl_dim_type t; + enum isl_dim_type t, o = isl_dim_param; int off; int s[3]; - int *size = s - isl_dim_param; ids = isl_calloc_array(dim->ctx, isl_id *, dim->nparam + dim->n_in + dim->n_out); if (!ids) goto error; off = 0; - size[isl_dim_param] = dim->nparam; - size[isl_dim_in] = dim->n_in; - size[isl_dim_out] = dim->n_out; + s[isl_dim_param - o] = dim->nparam; + s[isl_dim_in - o] = dim->n_in; + s[isl_dim_out - o] = dim->n_out; for (t = isl_dim_param; t <= isl_dim_out; ++t) { if (t == dst_type) { get_ids(dim, t, 0, dst_pos, ids + off); off += dst_pos; get_ids(dim, src_type, src_pos, n, ids + off); off += n; - get_ids(dim, t, dst_pos, size[t] - dst_pos, + get_ids(dim, t, dst_pos, s[t - o] - dst_pos, ids + off); - off += size[t] - dst_pos; + off += s[t - o] - dst_pos; } else if (t == src_type) { get_ids(dim, t, 0, src_pos, ids + off); off += src_pos; get_ids(dim, t, src_pos + n, - size[t] - src_pos - n, ids + off); - off += size[t] - src_pos - n; + s[t - o] - src_pos - n, ids + off); + off += s[t - o] - src_pos - n; } else { - get_ids(dim, t, 0, size[t], ids + off); - off += size[t]; + get_ids(dim, t, 0, s[t - o], ids + off); + off += s[t - o]; } } free(dim->ids); @@ -869,6 +1099,37 @@ error: return NULL; } +/* Given two spaces { A -> C } and { B -> C }, construct the space + * { [A -> B] -> C } + */ +__isl_give isl_space *isl_space_domain_product(__isl_take isl_space *left, + __isl_take isl_space *right) +{ + isl_space *ran, *dom1, *dom2, *nest; + + if (!left || !right) + goto error; + + if (!match(left, isl_dim_param, right, isl_dim_param)) + isl_die(left->ctx, isl_error_invalid, + "parameters need to match", goto error); + if (!isl_space_tuple_match(left, isl_dim_out, right, isl_dim_out)) + isl_die(left->ctx, isl_error_invalid, + "ranges need to match", goto error); + + ran = isl_space_range(isl_space_copy(left)); + + dom1 = isl_space_domain(left); + dom2 = isl_space_domain(right); + nest = isl_space_wrap(isl_space_join(isl_space_reverse(dom1), dom2)); + + return isl_space_join(isl_space_reverse(nest), ran); +error: + isl_space_free(left); + isl_space_free(right); + return NULL; +} + __isl_give isl_space *isl_space_range_product(__isl_take isl_space *left, __isl_take isl_space *right) { @@ -898,13 +1159,14 @@ error: __isl_give isl_space *isl_space_map_from_set(__isl_take isl_space *dim) { + isl_ctx *ctx; isl_id **ids = NULL; if (!dim) return NULL; - isl_assert(dim->ctx, dim->n_in == 0, goto error); - if (dim->n_out == 0 && !isl_space_is_named_or_nested(dim, isl_dim_out)) - return dim; + ctx = isl_space_get_ctx(dim); + if (!isl_space_is_set(dim)) + isl_die(ctx, isl_error_invalid, "not a set space", goto error); dim = isl_space_cow(dim); if (!dim) return NULL; @@ -933,6 +1195,24 @@ error: return NULL; } +__isl_give isl_space *isl_space_map_from_domain_and_range( + __isl_take isl_space *domain, __isl_take isl_space *range) +{ + if (!domain || !range) + goto error; + if (!isl_space_is_set(domain)) + isl_die(isl_space_get_ctx(domain), isl_error_invalid, + "domain is not a set space", goto error); + if (!isl_space_is_set(range)) + isl_die(isl_space_get_ctx(range), isl_error_invalid, + "range is not a set space", goto error); + return isl_space_join(isl_space_reverse(domain), range); +error: + isl_space_free(domain); + isl_space_free(range); + return NULL; +} + static __isl_give isl_space *set_ids(__isl_take isl_space *dim, enum isl_dim_type type, unsigned first, unsigned n, __isl_take isl_id **ids) @@ -1078,24 +1358,71 @@ __isl_give isl_space *isl_space_domain(__isl_take isl_space *dim) if (!dim) return NULL; dim = isl_space_drop_outputs(dim, 0, dim->n_out); - return isl_space_reverse(dim); + dim = isl_space_reverse(dim); + dim = mark_as_set(dim); + return dim; } __isl_give isl_space *isl_space_from_domain(__isl_take isl_space *dim) { - return isl_space_reverse(dim); + if (!dim) + return NULL; + if (!isl_space_is_set(dim)) + isl_die(isl_space_get_ctx(dim), isl_error_invalid, + "not a set space", goto error); + dim = isl_space_reverse(dim); + dim = isl_space_reset(dim, isl_dim_out); + return dim; +error: + isl_space_free(dim); + return NULL; } __isl_give isl_space *isl_space_range(__isl_take isl_space *dim) { if (!dim) return NULL; - return isl_space_drop_inputs(dim, 0, dim->n_in); + dim = isl_space_drop_inputs(dim, 0, dim->n_in); + dim = mark_as_set(dim); + return dim; } __isl_give isl_space *isl_space_from_range(__isl_take isl_space *dim) { - return dim; + if (!dim) + return NULL; + if (!isl_space_is_set(dim)) + isl_die(isl_space_get_ctx(dim), isl_error_invalid, + "not a set space", goto error); + return isl_space_reset(dim, isl_dim_in); +error: + isl_space_free(dim); + return NULL; +} + +__isl_give isl_space *isl_space_params(__isl_take isl_space *space) +{ + if (isl_space_is_params(space)) + return space; + space = isl_space_drop_dims(space, + isl_dim_in, 0, isl_space_dim(space, isl_dim_in)); + space = isl_space_drop_dims(space, + isl_dim_out, 0, isl_space_dim(space, isl_dim_out)); + space = mark_as_params(space); + return space; +} + +__isl_give isl_space *isl_space_set_from_params(__isl_take isl_space *space) +{ + if (!space) + return NULL; + if (!isl_space_is_params(space)) + isl_die(isl_space_get_ctx(space), isl_error_invalid, + "not a parameter space", goto error); + return isl_space_reset(space, isl_dim_set); +error: + isl_space_free(space); + return NULL; } __isl_give isl_space *isl_space_as_set_space(__isl_take isl_space *dim) @@ -1138,15 +1465,75 @@ __isl_give isl_space *isl_space_underlying(__isl_take isl_space *dim, return dim; } +/* Are the two spaces the same, including positions and names of parameters? + */ int isl_space_is_equal(__isl_keep isl_space *dim1, __isl_keep isl_space *dim2) { if (!dim1 || !dim2) return -1; + if (dim1 == dim2) + return 1; return match(dim1, isl_dim_param, dim2, isl_dim_param) && isl_space_tuple_match(dim1, isl_dim_in, dim2, isl_dim_in) && isl_space_tuple_match(dim1, isl_dim_out, dim2, isl_dim_out); } +/* Is space1 equal to the domain of space2? + * + * In the internal version we also allow space2 to be the space of a set, + * provided space1 is a parameter space. + */ +int isl_space_is_domain_internal(__isl_keep isl_space *space1, + __isl_keep isl_space *space2) +{ + if (!space1 || !space2) + return -1; + if (!isl_space_is_set(space1)) + return 0; + return match(space1, isl_dim_param, space2, isl_dim_param) && + isl_space_tuple_match(space1, isl_dim_set, space2, isl_dim_in); +} + +/* Is space1 equal to the domain of space2? + */ +int isl_space_is_domain(__isl_keep isl_space *space1, + __isl_keep isl_space *space2) +{ + if (!space2) + return -1; + if (!isl_space_is_map(space2)) + return 0; + return isl_space_is_domain_internal(space1, space2); +} + +/* Is space1 equal to the range of space2? + * + * In the internal version, space2 is allowed to be the space of a set, + * in which case it should be equal to space1. + */ +int isl_space_is_range_internal(__isl_keep isl_space *space1, + __isl_keep isl_space *space2) +{ + if (!space1 || !space2) + return -1; + if (!isl_space_is_set(space1)) + return 0; + return match(space1, isl_dim_param, space2, isl_dim_param) && + isl_space_tuple_match(space1, isl_dim_set, space2, isl_dim_out); +} + +/* Is space1 equal to the range of space2? + */ +int isl_space_is_range(__isl_keep isl_space *space1, + __isl_keep isl_space *space2) +{ + if (!space2) + return -1; + if (!isl_space_is_map(space2)) + return 0; + return isl_space_is_range_internal(space1, space2); +} + int isl_space_compatible(__isl_keep isl_space *dim1, __isl_keep isl_space *dim2) { @@ -1162,9 +1549,9 @@ static uint32_t isl_hash_dim(uint32_t hash, __isl_keep isl_space *dim) if (!dim) return hash; - hash = isl_hash_builtin(hash, dim->nparam); - hash = isl_hash_builtin(hash, dim->n_in); - hash = isl_hash_builtin(hash, dim->n_out); + isl_hash_byte(hash, dim->nparam % 256); + isl_hash_byte(hash, dim->n_in % 256); + isl_hash_byte(hash, dim->n_out % 256); for (i = 0; i < dim->nparam; ++i) { id = get_id(dim, isl_dim_param, i); @@ -1200,7 +1587,7 @@ int isl_space_is_wrapping(__isl_keep isl_space *dim) if (!dim) return -1; - if (dim->n_in != 0 || dim->tuple_id[0] || dim->nested[0]) + if (!isl_space_is_set(dim)) return 0; return dim->nested[1] != NULL; @@ -1213,7 +1600,8 @@ __isl_give isl_space *isl_space_wrap(__isl_take isl_space *dim) if (!dim) return NULL; - wrap = isl_space_alloc(dim->ctx, dim->nparam, 0, dim->n_in + dim->n_out); + wrap = isl_space_set_alloc(dim->ctx, + dim->nparam, dim->n_in + dim->n_out); wrap = copy_ids(wrap, isl_dim_param, 0, dim, isl_dim_param); wrap = copy_ids(wrap, isl_dim_set, 0, dim, isl_dim_in); @@ -1238,7 +1626,7 @@ __isl_give isl_space *isl_space_unwrap(__isl_take isl_space *dim) return NULL; if (!isl_space_is_wrapping(dim)) - isl_die(dim->ctx, isl_error_invalid, "not a wrapping dim", + isl_die(dim->ctx, isl_error_invalid, "not a wrapping space", goto error); unwrap = isl_space_copy(dim->nested[1]); @@ -1267,6 +1655,8 @@ int isl_space_may_be_set(__isl_keep isl_space *dim) { if (!dim) return -1; + if (isl_space_is_set(dim)) + return 1; if (isl_space_dim(dim, isl_dim_in) != 0) return 0; if (isl_space_is_named_or_nested(dim, isl_dim_in)) @@ -1307,6 +1697,16 @@ __isl_give isl_space *isl_space_flatten(__isl_take isl_space *dim) return dim; } +__isl_give isl_space *isl_space_flatten_domain(__isl_take isl_space *dim) +{ + if (!dim) + return NULL; + if (!dim->nested[0]) + return dim; + + return isl_space_reset(dim, isl_dim_in); +} + __isl_give isl_space *isl_space_flatten_range(__isl_take isl_space *dim) { if (!dim) @@ -1391,7 +1791,7 @@ __isl_give isl_space *isl_space_zip(__isl_take isl_space *dim) goto error); if (!dim) - return 0; + return NULL; dom = isl_space_unwrap(isl_space_domain(isl_space_copy(dim))); ran = isl_space_unwrap(isl_space_range(dim)); dom_dom = isl_space_domain(isl_space_copy(dom)); @@ -1409,6 +1809,82 @@ error: return NULL; } +/* Can we apply isl_space_curry to "space"? + * That is, does it have a nested relation in its domain? + */ +int isl_space_can_curry(__isl_keep isl_space *space) +{ + if (!space) + return -1; + + return !!space->nested[0]; +} + +/* Given a space (A -> B) -> C, return the corresponding space + * A -> (B -> C). + */ +__isl_give isl_space *isl_space_curry(__isl_take isl_space *space) +{ + isl_space *dom, *ran; + isl_space *dom_dom, *dom_ran; + + if (!space) + return NULL; + + if (!isl_space_can_curry(space)) + isl_die(space->ctx, isl_error_invalid, + "space cannot be curried", goto error); + + dom = isl_space_unwrap(isl_space_domain(isl_space_copy(space))); + ran = isl_space_range(space); + dom_dom = isl_space_domain(isl_space_copy(dom)); + dom_ran = isl_space_range(dom); + ran = isl_space_join(isl_space_from_domain(dom_ran), + isl_space_from_range(ran)); + return isl_space_join(isl_space_from_domain(dom_dom), + isl_space_from_range(isl_space_wrap(ran))); +error: + isl_space_free(space); + return NULL; +} + +/* Can we apply isl_space_uncurry to "space"? + * That is, does it have a nested relation in its range? + */ +int isl_space_can_uncurry(__isl_keep isl_space *space) +{ + if (!space) + return -1; + + return !!space->nested[1]; +} + +/* Given a space A -> (B -> C), return the corresponding space + * (A -> B) -> C. + */ +__isl_give isl_space *isl_space_uncurry(__isl_take isl_space *space) +{ + isl_space *dom, *ran; + isl_space *ran_dom, *ran_ran; + + if (!space) + return NULL; + + if (!isl_space_can_uncurry(space)) + isl_die(space->ctx, isl_error_invalid, + "space cannot be uncurried", + return isl_space_free(space)); + + dom = isl_space_domain(isl_space_copy(space)); + ran = isl_space_unwrap(isl_space_range(space)); + ran_dom = isl_space_domain(isl_space_copy(ran)); + ran_ran = isl_space_range(ran); + dom = isl_space_join(isl_space_from_domain(dom), + isl_space_from_range(ran_dom)); + return isl_space_join(isl_space_from_domain(isl_space_wrap(dom)), + isl_space_from_range(ran_ran)); +} + int isl_space_has_named_params(__isl_keep isl_space *dim) { int i; @@ -1439,8 +1915,9 @@ __isl_give isl_space *isl_space_align_params(__isl_take isl_space *dim1, "parameter alignment requires named parameters", goto error); + dim2 = isl_space_params(dim2); exp = isl_parameter_alignment_reordering(dim1, dim2); - isl_space_free(dim1); + exp = isl_reordering_extend_space(exp, dim1); isl_space_free(dim2); if (!exp) return NULL; @@ -1452,3 +1929,41 @@ error: isl_space_free(dim2); return NULL; } + +/* Given the space of set (domain), construct a space for a map + * with as domain the given space and as range the range of "model". + */ +__isl_give isl_space *isl_space_extend_domain_with_range( + __isl_take isl_space *space, __isl_take isl_space *model) +{ + if (!model) + goto error; + + space = isl_space_from_domain(space); + space = isl_space_add_dims(space, isl_dim_out, + isl_space_dim(model, isl_dim_out)); + if (isl_space_has_tuple_id(model, isl_dim_out)) + space = isl_space_set_tuple_id(space, isl_dim_out, + isl_space_get_tuple_id(model, isl_dim_out)); + if (!space) + goto error; + if (model->nested[1]) { + isl_space *nested = isl_space_copy(model->nested[1]); + int n_nested, n_space; + nested = isl_space_align_params(nested, isl_space_copy(space)); + n_nested = isl_space_dim(nested, isl_dim_param); + n_space = isl_space_dim(space, isl_dim_param); + if (n_nested > n_space) + nested = isl_space_drop_dims(nested, isl_dim_param, + n_space, n_nested - n_space); + if (!nested) + goto error; + space->nested[1] = nested; + } + isl_space_free(model); + return space; +error: + isl_space_free(model); + isl_space_free(space); + return NULL; +}