71b0c47457650858a27685ce51bc59856d57f1f9
[platform/upstream/isl.git] / isl_dim.c
1 #include "isl_dim.h"
2 #include "isl_name.h"
3
4 struct isl_dim *isl_dim_alloc(struct isl_ctx *ctx,
5                         unsigned nparam, unsigned n_in, unsigned n_out)
6 {
7         struct isl_dim *dim;
8
9         dim = isl_alloc_type(ctx, struct isl_dim);
10         if (!dim)
11                 return NULL;
12
13         dim->ctx = ctx;
14         isl_ctx_ref(ctx);
15         dim->ref = 1;
16         dim->nparam = nparam;
17         dim->n_in = n_in;
18         dim->n_out = n_out;
19
20         dim->n_name = 0;
21         dim->names = NULL;
22
23         return dim;
24 }
25
26 struct isl_dim *isl_dim_set_alloc(struct isl_ctx *ctx,
27                         unsigned nparam, unsigned dim)
28 {
29         return isl_dim_alloc(ctx, nparam, 0, dim);
30 }
31
32 static unsigned global_pos(struct isl_dim *dim,
33                                  enum isl_dim_type type, unsigned pos)
34 {
35         struct isl_ctx *ctx = dim->ctx;
36
37         switch (type) {
38         case isl_dim_param:
39                 isl_assert(ctx, pos < dim->nparam, return isl_dim_total(dim));
40                 return pos;
41         case isl_dim_in:
42                 isl_assert(ctx, pos < dim->n_in, return isl_dim_total(dim));
43                 return pos + dim->nparam;
44         case isl_dim_out:
45                 isl_assert(ctx, pos < dim->n_out, return isl_dim_total(dim));
46                 return pos + dim->nparam + dim->n_in;
47         default:
48                 isl_assert(ctx, 0, goto error);
49         }
50         return isl_dim_total(dim);
51 }
52
53 static struct isl_dim *set_name(struct isl_dim *dim,
54                                  enum isl_dim_type type, unsigned pos,
55                                  struct isl_name *name)
56 {
57         struct isl_ctx *ctx = dim->ctx;
58         dim = isl_dim_cow(dim);
59
60         if (!dim)
61                 goto error;
62
63         pos = global_pos(dim, type, pos);
64         isl_assert(ctx, pos != isl_dim_total(dim), goto error);
65
66         if (pos >= dim->n_name) {
67                 if (!name)
68                         return dim;
69                 if (!dim->names) {
70                         dim->names = isl_calloc_array(dim->ctx,
71                                         struct isl_name *, isl_dim_total(dim));
72                         if (!dim->names)
73                                 goto error;
74                 } else {
75                         int i;
76                         dim->names = isl_realloc_array(dim->ctx, dim->names,
77                                         struct isl_name *, isl_dim_total(dim));
78                         if (!dim->names)
79                                 goto error;
80                         for (i = dim->n_name; i < isl_dim_total(dim); ++i)
81                                 dim->names[i] = NULL;
82                 }
83                 dim->n_name = isl_dim_total(dim);
84         }
85
86         dim->names[pos] = name;
87
88         return dim;
89 error:
90         isl_name_free(ctx, name);
91         isl_dim_free(dim);
92         return NULL;
93 }
94
95 static struct isl_name *get_name(struct isl_dim *dim,
96                                  enum isl_dim_type type, unsigned pos)
97 {
98         if (!dim)
99                 return NULL;
100
101         pos = global_pos(dim, type, pos);
102         if (pos == isl_dim_total(dim))
103                 return NULL;
104         if (pos >= dim->n_name)
105                 return NULL;
106         return dim->names[pos];
107 }
108
109 static unsigned n(struct isl_dim *dim, enum isl_dim_type type)
110 {
111         switch (type) {
112         case isl_dim_param:     return dim->nparam;
113         case isl_dim_in:        return dim->n_in;
114         case isl_dim_out:       return dim->n_out;
115         }
116 }
117
118 static struct isl_dim *copy_names(struct isl_dim *dst,
119         enum isl_dim_type dst_type, struct isl_dim *src,
120         enum isl_dim_type src_type)
121 {
122         int i;
123         struct isl_name *name;
124
125         for (i = 0; i < n(dst, dst_type); ++i) {
126                 name = get_name(src, src_type, i);
127                 if (!name)
128                         continue;
129                 dst = set_name(dst, dst_type, i, isl_name_copy(dst->ctx, name));
130                 if (!dst)
131                         return NULL;
132         }
133         return dst;
134 }
135
136 struct isl_dim *isl_dim_dup(struct isl_dim *dim)
137 {
138         struct isl_dim *dup;
139         dup = isl_dim_alloc(dim->ctx, dim->nparam, dim->n_in, dim->n_out);
140         if (!dim->names)
141                 return dup;
142         dup = copy_names(dup, isl_dim_param, dim, isl_dim_param);
143         dup = copy_names(dup, isl_dim_in, dim, isl_dim_in);
144         dup = copy_names(dup, isl_dim_out, dim, isl_dim_out);
145         return dup;
146 }
147
148 struct isl_dim *isl_dim_cow(struct isl_dim *dim)
149 {
150         if (!dim)
151                 return NULL;
152
153         if (dim->ref == 1)
154                 return dim;
155         dim->ref--;
156         return isl_dim_dup(dim);
157 }
158
159 struct isl_dim *isl_dim_copy(struct isl_dim *dim)
160 {
161         if (!dim)
162                 return NULL;
163
164         dim->ref++;
165         return dim;
166 }
167
168 void isl_dim_free(struct isl_dim *dim)
169 {
170         int i;
171
172         if (!dim)
173                 return;
174
175         if (--dim->ref > 0)
176                 return;
177
178         for (i = 0; i < dim->n_name; ++i)
179                 isl_name_free(dim->ctx, dim->names[i]);
180         free(dim->names);
181         isl_ctx_deref(dim->ctx);
182         
183         free(dim);
184 }
185
186 struct isl_dim *isl_dim_set_name(struct isl_dim *dim,
187                                  enum isl_dim_type type, unsigned pos,
188                                  const char *s)
189 {
190         struct isl_name *name;
191         if (!dim)
192                 return NULL;
193         name = isl_name_get(dim->ctx, s);
194         if (!name)
195                 goto error;
196         return set_name(dim, type, pos, name);
197 error:
198         isl_dim_free(dim);
199         return NULL;
200 }
201
202 const char *isl_dim_get_name(struct isl_dim *dim,
203                                  enum isl_dim_type type, unsigned pos)
204 {
205         struct isl_name *name = get_name(dim, type, pos);
206         return name ? name->name : NULL;
207 }
208
209 static int match(struct isl_dim *dim1, enum isl_dim_type dim1_type,
210                 struct isl_dim *dim2, enum isl_dim_type dim2_type)
211 {
212         int i;
213
214         if (n(dim1, dim1_type) != n(dim2, dim2_type))
215                 return 0;
216
217         if (!dim1->names && !dim2->names)
218                 return 1;
219
220         for (i = 0; i < n(dim1, dim1_type); ++i) {
221                 if (get_name(dim1, dim1_type, i) !=
222                     get_name(dim2, dim2_type, i))
223                         return 0;
224         }
225         return 1;
226 }
227
228 static void get_names(struct isl_dim *dim, enum isl_dim_type type,
229         unsigned first, unsigned n, struct isl_name **names)
230 {
231         int i;
232
233         for (i = 0; i < n ; ++i)
234                 names[i] = get_name(dim, type, first+i);
235 }
236
237 struct isl_dim *isl_dim_extend(struct isl_dim *dim,
238                         unsigned nparam, unsigned n_in, unsigned n_out)
239 {
240         struct isl_name **names = NULL;
241
242         if (!dim)
243                 return NULL;
244         if (dim->nparam == nparam && dim->n_in == n_in && dim->n_out == n_out)
245                 return dim;
246
247         isl_assert(dim->ctx, dim->nparam <= nparam, goto error);
248         isl_assert(dim->ctx, dim->n_in <= n_in, goto error);
249         isl_assert(dim->ctx, dim->n_out <= n_out, goto error);
250
251         dim = isl_dim_cow(dim);
252
253         if (dim->names) {
254                 names = isl_calloc_array(dim->ctx, struct isl_name *,
255                                          nparam + n_in + n_out);
256                 if (!names)
257                         goto error;
258                 get_names(dim, isl_dim_param, 0, dim->nparam, names);
259                 get_names(dim, isl_dim_in, 0, dim->n_in, names + nparam);
260                 get_names(dim, isl_dim_out, 0, dim->n_out,
261                                 names + nparam + n_in);
262                 free(dim->names);
263                 dim->names = names;
264                 dim->n_name = nparam + n_in + n_out;
265         }
266         dim->nparam = nparam;
267         dim->n_in = n_in;
268         dim->n_out = n_out;
269
270         return dim;
271 error:
272         free(names);
273         isl_dim_free(dim);
274         return NULL;
275 }
276
277 struct isl_dim *isl_dim_join(struct isl_dim *left, struct isl_dim *right)
278 {
279         struct isl_dim *dim;
280
281         if (!left || !right)
282                 goto error;
283
284         isl_assert(left->ctx, match(left, isl_dim_param, right, isl_dim_param),
285                         goto error);
286         isl_assert(left->ctx, match(left, isl_dim_out, right, isl_dim_in),
287                         goto error);
288
289         dim = isl_dim_alloc(left->ctx, left->nparam, left->n_in, right->n_out);
290         if (!dim)
291                 goto error;
292
293         dim = copy_names(dim, isl_dim_param, left, isl_dim_param);
294         dim = copy_names(dim, isl_dim_in, left, isl_dim_in);
295         dim = copy_names(dim, isl_dim_out, right, isl_dim_out);
296
297         isl_dim_free(left);
298         isl_dim_free(right);
299
300         return dim;
301 error:
302         isl_dim_free(left);
303         isl_dim_free(right);
304         return NULL;
305 }
306
307 struct isl_dim *isl_dim_map(struct isl_dim *dim)
308 {
309         struct isl_name **names = NULL;
310
311         if (!dim)
312                 return NULL;
313         isl_assert(dim->ctx, dim->n_in == 0, goto error);
314         if (dim->n_out == 0)
315                 return dim;
316         dim = isl_dim_cow(dim);
317         if (!dim)
318                 return NULL;
319         if (dim->names) {
320                 names = isl_calloc_array(dim->ctx, struct isl_name *,
321                                         dim->nparam + dim->n_out + dim->n_out);
322                 if (!names)
323                         goto error;
324                 get_names(dim, isl_dim_param, 0, dim->nparam, names);
325                 get_names(dim, isl_dim_out, 0, dim->n_out, names + dim->nparam);
326         }
327         dim->n_in = dim->n_out;
328         if (names) {
329                 copy_names(dim, isl_dim_out, dim, isl_dim_in);
330                 free(dim->names);
331                 dim->names = names;
332                 dim->n_name = dim->nparam + dim->n_out + dim->n_out;
333         }
334         return dim;
335 error:
336         isl_dim_free(dim);
337         return NULL;
338 }
339
340 static struct isl_dim *set_names(struct isl_dim *dim, enum isl_dim_type type,
341         unsigned first, unsigned n, struct isl_name **names)
342 {
343         int i;
344
345         for (i = 0; i < n ; ++i)
346                 dim = set_name(dim, type, first+i, names[i]);
347
348         return dim;
349 }
350
351 struct isl_dim *isl_dim_reverse(struct isl_dim *dim)
352 {
353         unsigned t;
354         struct isl_name **names = NULL;
355
356         if (!dim)
357                 return NULL;
358         if (match(dim, isl_dim_in, dim, isl_dim_out))
359                 return dim;
360
361         dim = isl_dim_cow(dim);
362         if (!dim)
363                 return NULL;
364
365         if (dim->names) {
366                 names = isl_alloc_array(dim->ctx, struct isl_name *,
367                                         dim->n_in + dim->n_out);
368                 if (!names)
369                         goto error;
370                 get_names(dim, isl_dim_in, 0, dim->n_in, names);
371                 get_names(dim, isl_dim_out, 0, dim->n_out, names + dim->n_in);
372         }
373
374         t = dim->n_in;
375         dim->n_in = dim->n_out;
376         dim->n_out = t;
377
378         if (dim->names) {
379                 dim = set_names(dim, isl_dim_out, 0, dim->n_out, names);
380                 dim = set_names(dim, isl_dim_in, 0, dim->n_in, names + dim->n_out);
381                 free(names);
382         }
383
384         return dim;
385 error:
386         free(names);
387         isl_dim_free(dim);
388         return NULL;
389 }
390
391 struct isl_dim *isl_dim_drop_inputs(struct isl_dim *dim,
392                 unsigned first, unsigned n)
393 {
394         int i;
395
396         if (!dim)
397                 return NULL;
398
399         if (n == 0)
400                 return dim;
401
402         isl_assert(dim->ctx, first + n <= dim->n_in, goto error);
403         dim = isl_dim_cow(dim);
404         if (!dim)
405                 goto error;
406         if (dim->names) {
407                 for (i = 0; i < n; ++i) {
408                         isl_name_free(dim->ctx,
409                                         get_name(dim, isl_dim_in, first+i));
410                 }
411                 for (i = first+n; i < dim->n_in; ++i)
412                         set_name(dim, isl_dim_in, i - n,
413                                 get_name(dim, isl_dim_in, i));
414                 get_names(dim, isl_dim_out, 0, dim->n_out,
415                                 dim->names + dim->nparam + dim->n_in - n);
416         }
417         dim->n_in -= n;
418         return dim;
419 error:
420         isl_dim_free(dim);
421         return NULL;
422 }
423
424 struct isl_dim *isl_dim_drop_outputs(struct isl_dim *dim,
425                 unsigned first, unsigned n)
426 {
427         int i;
428
429         if (!dim)
430                 return NULL;
431
432         if (n == 0)
433                 return dim;
434
435         isl_assert(dim->ctx, first + n <= dim->n_out, goto error);
436         dim = isl_dim_cow(dim);
437         if (!dim)
438                 goto error;
439         if (dim->names) {
440                 for (i = 0; i < n; ++i) {
441                         isl_name_free(dim->ctx,
442                                         get_name(dim, isl_dim_out, first+i));
443                 }
444                 for (i = first+n; i < dim->n_out; ++i)
445                         set_name(dim, isl_dim_out, i - n,
446                                 get_name(dim, isl_dim_out, i));
447         }
448         dim->n_out -= n;
449         return dim;
450 error:
451         isl_dim_free(dim);
452         return NULL;
453 }
454
455 struct isl_dim *isl_dim_domain(struct isl_dim *dim)
456 {
457         if (!dim)
458                 return NULL;
459         dim = isl_dim_drop_outputs(dim, 0, dim->n_out);
460         return isl_dim_reverse(dim);
461 }
462
463 struct isl_dim *isl_dim_underlying(struct isl_dim *dim, unsigned n_div)
464 {
465         int i;
466
467         if (!dim)
468                 return NULL;
469         if (n_div == 0 &&
470             dim->nparam == 0 && dim->n_in == 0 && dim->n_name == 0)
471                 return dim;
472         dim = isl_dim_cow(dim);
473         if (!dim)
474                 return NULL;
475         dim->n_out += dim->nparam + dim->n_in + n_div;
476         dim->nparam = 0;
477         dim->n_in = 0;
478
479         for (i = 0; i < dim->n_name; ++i)
480                 isl_name_free(dim->ctx, get_name(dim, isl_dim_out, i));
481         dim->n_name = 0;
482
483         return dim;
484 }
485
486 unsigned isl_dim_total(struct isl_dim *dim)
487 {
488         return dim->nparam + dim->n_in + dim->n_out;
489 }
490
491 int isl_dim_equal(struct isl_dim *dim1, struct isl_dim *dim2)
492 {
493         return match(dim1, isl_dim_param, dim2, isl_dim_param) &&
494                match(dim1, isl_dim_in, dim2, isl_dim_in) &&
495                match(dim1, isl_dim_out, dim2, isl_dim_out);
496 }
497
498 int isl_dim_compatible(struct isl_dim *dim1, struct isl_dim *dim2)
499 {
500         return dim1->nparam == dim2->nparam &&
501                dim1->n_in + dim1->n_out == dim2->n_in + dim2->n_out;
502 }