1/*
2 * Copyright 2010      INRIA Saclay
3 *
4 * Use of this software is governed by the MIT license
5 *
6 * Written by Sven Verdoolaege, INRIA Saclay - Ile-de-France,
7 * Parc Club Orsay Universite, ZAC des vignes, 4 rue Jacques Monod,
8 * 91893 Orsay, France
9 */
10
11#include <isl_ctx_private.h>
12#include <isl_space_private.h>
13#include <isl_reordering.h>
14
15__isl_give isl_reordering *isl_reordering_alloc(isl_ctx *ctx, int len)
16{
17	isl_reordering *exp;
18
19	exp = isl_alloc(ctx, struct isl_reordering,
20			sizeof(struct isl_reordering) + (len - 1) * sizeof(int));
21	if (!exp)
22		return NULL;
23
24	exp->ref = 1;
25	exp->len = len;
26	exp->dim = NULL;
27
28	return exp;
29}
30
31__isl_give isl_reordering *isl_reordering_copy(__isl_keep isl_reordering *exp)
32{
33	if (!exp)
34		return NULL;
35
36	exp->ref++;
37	return exp;
38}
39
40__isl_give isl_reordering *isl_reordering_dup(__isl_keep isl_reordering *r)
41{
42	int i;
43	isl_reordering *dup;
44
45	if (!r)
46		return NULL;
47
48	dup = isl_reordering_alloc(r->dim->ctx, r->len);
49	if (!dup)
50		return NULL;
51
52	dup->dim = isl_space_copy(r->dim);
53	if (!dup->dim)
54		return isl_reordering_free(dup);
55	for (i = 0; i < dup->len; ++i)
56		dup->pos[i] = r->pos[i];
57
58	return dup;
59}
60
61__isl_give isl_reordering *isl_reordering_cow(__isl_take isl_reordering *r)
62{
63	if (!r)
64		return NULL;
65
66	if (r->ref == 1)
67		return r;
68	r->ref--;
69	return isl_reordering_dup(r);
70}
71
72void *isl_reordering_free(__isl_take isl_reordering *exp)
73{
74	if (!exp)
75		return NULL;
76
77	if (--exp->ref > 0)
78		return NULL;
79
80	isl_space_free(exp->dim);
81	free(exp);
82	return NULL;
83}
84
85/* Construct a reordering that maps the parameters of "alignee"
86 * to the corresponding parameters in a new dimension specification
87 * that has the parameters of "aligner" first, followed by
88 * any remaining parameters of "alignee" that do not occur in "aligner".
89 */
90__isl_give isl_reordering *isl_parameter_alignment_reordering(
91	__isl_keep isl_space *alignee, __isl_keep isl_space *aligner)
92{
93	int i, j;
94	isl_reordering *exp;
95
96	if (!alignee || !aligner)
97		return NULL;
98
99	exp = isl_reordering_alloc(alignee->ctx, alignee->nparam);
100	if (!exp)
101		return NULL;
102
103	exp->dim = isl_space_copy(aligner);
104
105	for (i = 0; i < alignee->nparam; ++i) {
106		isl_id *id_i;
107		id_i = isl_space_get_dim_id(alignee, isl_dim_param, i);
108		if (!id_i)
109			isl_die(alignee->ctx, isl_error_invalid,
110				"cannot align unnamed parameters", goto error);
111		for (j = 0; j < aligner->nparam; ++j) {
112			isl_id *id_j;
113			id_j = isl_space_get_dim_id(aligner, isl_dim_param, j);
114			isl_id_free(id_j);
115			if (id_i == id_j)
116				break;
117		}
118		if (j < aligner->nparam) {
119			exp->pos[i] = j;
120			isl_id_free(id_i);
121		} else {
122			int pos;
123			pos = isl_space_dim(exp->dim, isl_dim_param);
124			exp->dim = isl_space_add_dims(exp->dim, isl_dim_param, 1);
125			exp->dim = isl_space_set_dim_id(exp->dim,
126						isl_dim_param, pos, id_i);
127			exp->pos[i] = pos;
128		}
129	}
130
131	if (!exp->dim)
132		return isl_reordering_free(exp);
133	return exp;
134error:
135	isl_reordering_free(exp);
136	return NULL;
137}
138
139__isl_give isl_reordering *isl_reordering_extend(__isl_take isl_reordering *exp,
140	unsigned extra)
141{
142	int i;
143	isl_reordering *res;
144	int offset;
145
146	if (!exp)
147		return NULL;
148	if (extra == 0)
149		return exp;
150
151	offset = isl_space_dim(exp->dim, isl_dim_all) - exp->len;
152	res = isl_reordering_alloc(exp->dim->ctx, exp->len + extra);
153	if (!res)
154		goto error;
155	res->dim = isl_space_copy(exp->dim);
156	for (i = 0; i < exp->len; ++i)
157		res->pos[i] = exp->pos[i];
158	for (i = exp->len; i < res->len; ++i)
159		res->pos[i] = offset + i;
160
161	isl_reordering_free(exp);
162
163	return res;
164error:
165	isl_reordering_free(exp);
166	return NULL;
167}
168
169__isl_give isl_reordering *isl_reordering_extend_space(
170	__isl_take isl_reordering *exp, __isl_take isl_space *dim)
171{
172	isl_reordering *res;
173
174	if (!exp || !dim)
175		goto error;
176
177	res = isl_reordering_extend(isl_reordering_copy(exp),
178				    isl_space_dim(dim, isl_dim_all) - exp->len);
179	res = isl_reordering_cow(res);
180	if (!res)
181		goto error;
182	isl_space_free(res->dim);
183	res->dim = isl_space_replace(dim, isl_dim_param, exp->dim);
184
185	isl_reordering_free(exp);
186
187	if (!res->dim)
188		return isl_reordering_free(res);
189
190	return res;
191error:
192	isl_reordering_free(exp);
193	isl_space_free(dim);
194	return NULL;
195}
196
197void isl_reordering_dump(__isl_keep isl_reordering *exp)
198{
199	int i;
200
201	for (i = 0; i < exp->len; ++i)
202		fprintf(stderr, "%d -> %d; ", i, exp->pos[i]);
203	fprintf(stderr, "\n");
204}
205