| /* |
| * Copyright 2010 INRIA Saclay |
| * |
| * Use of this software is governed by the MIT license |
| * |
| * Written by Sven Verdoolaege, INRIA Saclay - Ile-de-France, |
| * Parc Club Orsay Universite, ZAC des vignes, 4 rue Jacques Monod, |
| * 91893 Orsay, France |
| */ |
| |
| #include <isl_ctx_private.h> |
| #include <isl/id.h> |
| #include <isl_space_private.h> |
| #include <isl_reordering.h> |
| |
| __isl_give isl_reordering *isl_reordering_alloc(isl_ctx *ctx, int len) |
| { |
| isl_reordering *exp; |
| |
| exp = isl_alloc(ctx, struct isl_reordering, |
| sizeof(struct isl_reordering) + (len - 1) * sizeof(int)); |
| if (!exp) |
| return NULL; |
| |
| exp->ref = 1; |
| exp->len = len; |
| exp->space = NULL; |
| |
| return exp; |
| } |
| |
| __isl_give isl_reordering *isl_reordering_copy(__isl_keep isl_reordering *exp) |
| { |
| if (!exp) |
| return NULL; |
| |
| exp->ref++; |
| return exp; |
| } |
| |
| __isl_give isl_reordering *isl_reordering_dup(__isl_keep isl_reordering *r) |
| { |
| int i; |
| isl_reordering *dup; |
| |
| if (!r) |
| return NULL; |
| |
| dup = isl_reordering_alloc(isl_reordering_get_ctx(r), r->len); |
| if (!dup) |
| return NULL; |
| |
| dup->space = isl_reordering_get_space(r); |
| if (!dup->space) |
| return isl_reordering_free(dup); |
| for (i = 0; i < dup->len; ++i) |
| dup->pos[i] = r->pos[i]; |
| |
| return dup; |
| } |
| |
| __isl_give isl_reordering *isl_reordering_cow(__isl_take isl_reordering *r) |
| { |
| if (!r) |
| return NULL; |
| |
| if (r->ref == 1) |
| return r; |
| r->ref--; |
| return isl_reordering_dup(r); |
| } |
| |
| __isl_null isl_reordering *isl_reordering_free(__isl_take isl_reordering *exp) |
| { |
| if (!exp) |
| return NULL; |
| |
| if (--exp->ref > 0) |
| return NULL; |
| |
| isl_space_free(exp->space); |
| free(exp); |
| return NULL; |
| } |
| |
| /* Return the isl_ctx to which "r" belongs. |
| */ |
| isl_ctx *isl_reordering_get_ctx(__isl_keep isl_reordering *r) |
| { |
| return isl_space_get_ctx(isl_reordering_peek_space(r)); |
| } |
| |
| /* Return the space of "r". |
| */ |
| __isl_keep isl_space *isl_reordering_peek_space(__isl_keep isl_reordering *r) |
| { |
| if (!r) |
| return NULL; |
| return r->space; |
| } |
| |
| /* Return a copy of the space of "r". |
| */ |
| __isl_give isl_space *isl_reordering_get_space(__isl_keep isl_reordering *r) |
| { |
| return isl_space_copy(isl_reordering_peek_space(r)); |
| } |
| |
| /* Construct a reordering that maps the parameters of "alignee" |
| * to the corresponding parameters in a new dimension specification |
| * that has the parameters of "aligner" first, followed by |
| * any remaining parameters of "alignee" that do not occur in "aligner". |
| */ |
| __isl_give isl_reordering *isl_parameter_alignment_reordering( |
| __isl_keep isl_space *alignee, __isl_keep isl_space *aligner) |
| { |
| int i, j; |
| isl_reordering *exp; |
| |
| if (!alignee || !aligner) |
| return NULL; |
| |
| exp = isl_reordering_alloc(alignee->ctx, alignee->nparam); |
| if (!exp) |
| return NULL; |
| |
| exp->space = isl_space_params(isl_space_copy(aligner)); |
| |
| for (i = 0; i < alignee->nparam; ++i) { |
| isl_id *id_i; |
| id_i = isl_space_get_dim_id(alignee, isl_dim_param, i); |
| if (!id_i) |
| isl_die(alignee->ctx, isl_error_invalid, |
| "cannot align unnamed parameters", goto error); |
| for (j = 0; j < aligner->nparam; ++j) { |
| isl_id *id_j; |
| id_j = isl_space_get_dim_id(aligner, isl_dim_param, j); |
| isl_id_free(id_j); |
| if (id_i == id_j) |
| break; |
| } |
| if (j < aligner->nparam) { |
| exp->pos[i] = j; |
| isl_id_free(id_i); |
| } else { |
| int pos; |
| pos = isl_space_dim(exp->space, isl_dim_param); |
| exp->space = isl_space_add_dims(exp->space, |
| isl_dim_param, 1); |
| exp->space = isl_space_set_dim_id(exp->space, |
| isl_dim_param, pos, id_i); |
| exp->pos[i] = pos; |
| } |
| } |
| |
| if (!exp->space) |
| return isl_reordering_free(exp); |
| return exp; |
| error: |
| isl_reordering_free(exp); |
| return NULL; |
| } |
| |
| __isl_give isl_reordering *isl_reordering_extend(__isl_take isl_reordering *exp, |
| unsigned extra) |
| { |
| int i; |
| isl_ctx *ctx; |
| isl_space *space; |
| isl_reordering *res; |
| int offset; |
| |
| if (!exp) |
| return NULL; |
| if (extra == 0) |
| return exp; |
| |
| ctx = isl_reordering_get_ctx(exp); |
| space = isl_reordering_peek_space(exp); |
| offset = isl_space_dim(space, isl_dim_all) - exp->len; |
| res = isl_reordering_alloc(ctx, exp->len + extra); |
| if (!res) |
| goto error; |
| res->space = isl_reordering_get_space(exp); |
| for (i = 0; i < exp->len; ++i) |
| res->pos[i] = exp->pos[i]; |
| for (i = exp->len; i < res->len; ++i) |
| res->pos[i] = offset + i; |
| |
| isl_reordering_free(exp); |
| |
| return res; |
| error: |
| isl_reordering_free(exp); |
| return NULL; |
| } |
| |
| __isl_give isl_reordering *isl_reordering_extend_space( |
| __isl_take isl_reordering *exp, __isl_take isl_space *space) |
| { |
| isl_space *exp_space; |
| isl_reordering *res; |
| |
| if (!exp || !space) |
| goto error; |
| |
| res = isl_reordering_extend(isl_reordering_copy(exp), |
| isl_space_dim(space, isl_dim_all) - exp->len); |
| res = isl_reordering_cow(res); |
| if (!res) |
| goto error; |
| isl_space_free(res->space); |
| exp_space = isl_reordering_peek_space(exp); |
| res->space = isl_space_replace_params(space, exp_space); |
| |
| isl_reordering_free(exp); |
| |
| if (!res->space) |
| return isl_reordering_free(res); |
| |
| return res; |
| error: |
| isl_reordering_free(exp); |
| isl_space_free(space); |
| return NULL; |
| } |
| |
| void isl_reordering_dump(__isl_keep isl_reordering *exp) |
| { |
| int i; |
| |
| isl_space_dump(exp->space); |
| for (i = 0; i < exp->len; ++i) |
| fprintf(stderr, "%d -> %d; ", i, exp->pos[i]); |
| fprintf(stderr, "\n"); |
| } |