isl_dim: allow specification of tuple names
[platform/upstream/isl.git] / isl_dim.c
1 /*
2  * Copyright 2008-2009 Katholieke Universiteit Leuven
3  *
4  * Use of this software is governed by the GNU LGPLv2.1 license
5  *
6  * Written by Sven Verdoolaege, K.U.Leuven, Departement
7  * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
8  */
9
10 #include <stdlib.h>
11 #include <isl_dim.h>
12 #include "isl_name.h"
13
14 struct isl_dim *isl_dim_alloc(struct isl_ctx *ctx,
15                         unsigned nparam, unsigned n_in, unsigned n_out)
16 {
17         struct isl_dim *dim;
18
19         dim = isl_alloc_type(ctx, struct isl_dim);
20         if (!dim)
21                 return NULL;
22
23         dim->ctx = ctx;
24         isl_ctx_ref(ctx);
25         dim->ref = 1;
26         dim->nparam = nparam;
27         dim->n_in = n_in;
28         dim->n_out = n_out;
29
30         dim->tuple_name[0] = NULL;
31         dim->tuple_name[1] = NULL;
32
33         dim->n_name = 0;
34         dim->names = NULL;
35
36         return dim;
37 }
38
39 struct isl_dim *isl_dim_set_alloc(struct isl_ctx *ctx,
40                         unsigned nparam, unsigned dim)
41 {
42         return isl_dim_alloc(ctx, nparam, 0, dim);
43 }
44
45 static unsigned global_pos(struct isl_dim *dim,
46                                  enum isl_dim_type type, unsigned pos)
47 {
48         struct isl_ctx *ctx = dim->ctx;
49
50         switch (type) {
51         case isl_dim_param:
52                 isl_assert(ctx, pos < dim->nparam, return isl_dim_total(dim));
53                 return pos;
54         case isl_dim_in:
55                 isl_assert(ctx, pos < dim->n_in, return isl_dim_total(dim));
56                 return pos + dim->nparam;
57         case isl_dim_out:
58                 isl_assert(ctx, pos < dim->n_out, return isl_dim_total(dim));
59                 return pos + dim->nparam + dim->n_in;
60         default:
61                 isl_assert(ctx, 0, return isl_dim_total(dim));
62         }
63         return isl_dim_total(dim);
64 }
65
66 /* Extend length of names array to the total number of dimensions.
67  */
68 static __isl_give isl_dim *extend_names(__isl_take isl_dim *dim)
69 {
70         struct isl_name **names;
71         int i;
72
73         if (isl_dim_total(dim) <= dim->n_name)
74                 return dim;
75
76         if (!dim->names) {
77                 dim->names = isl_calloc_array(dim->ctx,
78                                 struct isl_name *, isl_dim_total(dim));
79                 if (!dim->names)
80                         goto error;
81         } else {
82                 names = isl_realloc_array(dim->ctx, dim->names,
83                                 struct isl_name *, isl_dim_total(dim));
84                 if (!names)
85                         goto error;
86                 dim->names = names;
87                 for (i = dim->n_name; i < isl_dim_total(dim); ++i)
88                         dim->names[i] = NULL;
89         }
90
91         dim->n_name = isl_dim_total(dim);
92
93         return dim;
94 error:
95         isl_dim_free(dim);
96         return NULL;
97 }
98
99 static struct isl_dim *set_name(struct isl_dim *dim,
100                                  enum isl_dim_type type, unsigned pos,
101                                  struct isl_name *name)
102 {
103         struct isl_ctx *ctx = dim->ctx;
104         dim = isl_dim_cow(dim);
105
106         if (!dim)
107                 goto error;
108
109         pos = global_pos(dim, type, pos);
110         isl_assert(ctx, pos != isl_dim_total(dim), goto error);
111
112         if (pos >= dim->n_name) {
113                 if (!name)
114                         return dim;
115                 dim = extend_names(dim);
116                 if (!dim)
117                         goto error;
118         }
119
120         dim->names[pos] = name;
121
122         return dim;
123 error:
124         isl_name_free(ctx, name);
125         isl_dim_free(dim);
126         return NULL;
127 }
128
129 static struct isl_name *get_name(struct isl_dim *dim,
130                                  enum isl_dim_type type, unsigned pos)
131 {
132         if (!dim)
133                 return NULL;
134
135         pos = global_pos(dim, type, pos);
136         if (pos == isl_dim_total(dim))
137                 return NULL;
138         if (pos >= dim->n_name)
139                 return NULL;
140         return dim->names[pos];
141 }
142
143 static unsigned offset(struct isl_dim *dim, enum isl_dim_type type)
144 {
145         switch (type) {
146         case isl_dim_param:     return 0;
147         case isl_dim_in:        return dim->nparam;
148         case isl_dim_out:       return dim->nparam + dim->n_in;
149         default:                return 0;
150         }
151 }
152
153 static unsigned n(struct isl_dim *dim, enum isl_dim_type type)
154 {
155         switch (type) {
156         case isl_dim_param:     return dim->nparam;
157         case isl_dim_in:        return dim->n_in;
158         case isl_dim_out:       return dim->n_out;
159         default:                return 0;
160         }
161 }
162
163 unsigned isl_dim_size(struct isl_dim *dim, enum isl_dim_type type)
164 {
165         if (!dim)
166                 return 0;
167         return n(dim, type);
168 }
169
170 unsigned isl_dim_offset(__isl_keep isl_dim *dim, enum isl_dim_type type)
171 {
172         if (!dim)
173                 return 0;
174         return offset(dim, type);
175 }
176
177 static struct isl_dim *copy_names(struct isl_dim *dst,
178         enum isl_dim_type dst_type, unsigned offset, struct isl_dim *src,
179         enum isl_dim_type src_type)
180 {
181         int i;
182         struct isl_name *name;
183
184         if (!dst)
185                 return NULL;
186
187         for (i = 0; i < n(src, src_type); ++i) {
188                 name = get_name(src, src_type, i);
189                 if (!name)
190                         continue;
191                 dst = set_name(dst, dst_type, offset + i,
192                                         isl_name_copy(dst->ctx, name));
193                 if (!dst)
194                         return NULL;
195         }
196         return dst;
197 }
198
199 struct isl_dim *isl_dim_dup(struct isl_dim *dim)
200 {
201         struct isl_dim *dup;
202         if (!dim)
203                 return NULL;
204         dup = isl_dim_alloc(dim->ctx, dim->nparam, dim->n_in, dim->n_out);
205         if (dim->tuple_name[0] &&
206             !(dup->tuple_name[0] = isl_name_copy(dim->ctx, dim->tuple_name[0])))
207                 goto error;
208         if (dim->tuple_name[1] &&
209             !(dup->tuple_name[1] = isl_name_copy(dim->ctx, dim->tuple_name[1])))
210                 goto error;
211         if (!dim->names)
212                 return dup;
213         dup = copy_names(dup, isl_dim_param, 0, dim, isl_dim_param);
214         dup = copy_names(dup, isl_dim_in, 0, dim, isl_dim_in);
215         dup = copy_names(dup, isl_dim_out, 0, dim, isl_dim_out);
216         return dup;
217 error:
218         isl_dim_free(dup);
219         return NULL;
220 }
221
222 struct isl_dim *isl_dim_cow(struct isl_dim *dim)
223 {
224         if (!dim)
225                 return NULL;
226
227         if (dim->ref == 1)
228                 return dim;
229         dim->ref--;
230         return isl_dim_dup(dim);
231 }
232
233 struct isl_dim *isl_dim_copy(struct isl_dim *dim)
234 {
235         if (!dim)
236                 return NULL;
237
238         dim->ref++;
239         return dim;
240 }
241
242 void isl_dim_free(struct isl_dim *dim)
243 {
244         int i;
245
246         if (!dim)
247                 return;
248
249         if (--dim->ref > 0)
250                 return;
251
252         isl_name_free(dim->ctx, dim->tuple_name[0]);
253         isl_name_free(dim->ctx, dim->tuple_name[1]);
254
255         for (i = 0; i < dim->n_name; ++i)
256                 isl_name_free(dim->ctx, dim->names[i]);
257         free(dim->names);
258         isl_ctx_deref(dim->ctx);
259         
260         free(dim);
261 }
262
263 static int name_ok(isl_ctx *ctx, const char *s)
264 {
265         char *p;
266         long dummy;
267
268         dummy = strtol(s, &p, 0);
269         if (p != s)
270                 isl_die(ctx, isl_error_invalid, "name looks like a number",
271                         return 0);
272
273         return 1;
274 }
275
276 __isl_give isl_dim *isl_dim_set_tuple_name(__isl_take isl_dim *dim,
277         enum isl_dim_type type, const char *s)
278 {
279         struct isl_name *name;
280
281         dim = isl_dim_cow(dim);
282         if (!dim)
283                 return NULL;
284         if (type != isl_dim_in && type != isl_dim_out)
285                 isl_die(dim->ctx, isl_error_invalid,
286                         "only input, output and set tuples can have names",
287                         goto error);
288         if (!name_ok(dim->ctx, s))
289                 goto error;
290         name = isl_name_get(dim->ctx, s);
291         if (!name)
292                 goto error;
293
294         isl_name_free(dim->ctx, dim->tuple_name[type - isl_dim_in]);
295         dim->tuple_name[type - isl_dim_in] = name;
296
297         return dim;
298 error:
299         isl_dim_free(dim);
300         return NULL;
301 }
302
303 const char *isl_dim_get_tuple_name(__isl_keep isl_dim *dim,
304          enum isl_dim_type type)
305 {
306         struct isl_name *name;
307         if (!dim)
308                 return NULL;
309         if (type != isl_dim_in && type != isl_dim_out)
310                 return NULL;
311         name = dim->tuple_name[type - isl_dim_in];
312         return name ? name->name : NULL;
313 }
314
315 struct isl_dim *isl_dim_set_name(struct isl_dim *dim,
316                                  enum isl_dim_type type, unsigned pos,
317                                  const char *s)
318 {
319         struct isl_name *name;
320
321         if (!dim)
322                 return NULL;
323         if (!name_ok(dim->ctx, s))
324                 goto error;
325         name = isl_name_get(dim->ctx, s);
326         if (!name)
327                 goto error;
328         return set_name(dim, type, pos, name);
329 error:
330         isl_dim_free(dim);
331         return NULL;
332 }
333
334 const char *isl_dim_get_name(struct isl_dim *dim,
335                                  enum isl_dim_type type, unsigned pos)
336 {
337         struct isl_name *name = get_name(dim, type, pos);
338         return name ? name->name : NULL;
339 }
340
341 static struct isl_name *tuple_name(__isl_keep isl_dim *dim,
342         enum isl_dim_type type)
343 {
344         if (!dim)
345                 return NULL;
346         if (type == isl_dim_in)
347                 return dim->tuple_name[0];
348         if (type == isl_dim_out)
349                 return dim->tuple_name[1];
350         return NULL;
351 }
352
353 int isl_dim_tuple_match(__isl_keep isl_dim *dim1, enum isl_dim_type dim1_type,
354                         __isl_keep isl_dim *dim2, enum isl_dim_type dim2_type)
355 {
356         struct isl_name *name1, *name2;
357
358         if (n(dim1, dim1_type) != n(dim2, dim2_type))
359                 return 0;
360         name1 = tuple_name(dim1, dim1_type);
361         name2 = tuple_name(dim2, dim2_type);
362         if (!name1 ^ !name2)
363                 return 0;
364         if (name1 && name1->name != name2->name)
365                 return 0;
366         return 1;
367 }
368
369 static int match(struct isl_dim *dim1, enum isl_dim_type dim1_type,
370                 struct isl_dim *dim2, enum isl_dim_type dim2_type)
371 {
372         int i;
373
374         if (!isl_dim_tuple_match(dim1, dim1_type, dim2, dim2_type))
375                 return 0;
376
377         if (!dim1->names && !dim2->names)
378                 return 1;
379
380         for (i = 0; i < n(dim1, dim1_type); ++i) {
381                 if (get_name(dim1, dim1_type, i) !=
382                     get_name(dim2, dim2_type, i))
383                         return 0;
384         }
385         return 1;
386 }
387
388 int isl_dim_match(struct isl_dim *dim1, enum isl_dim_type dim1_type,
389                 struct isl_dim *dim2, enum isl_dim_type dim2_type)
390 {
391         return match(dim1, dim1_type, dim2, dim2_type);
392 }
393
394 static void get_names(struct isl_dim *dim, enum isl_dim_type type,
395         unsigned first, unsigned n, struct isl_name **names)
396 {
397         int i;
398
399         for (i = 0; i < n ; ++i)
400                 names[i] = get_name(dim, type, first+i);
401 }
402
403 struct isl_dim *isl_dim_extend(struct isl_dim *dim,
404                         unsigned nparam, unsigned n_in, unsigned n_out)
405 {
406         struct isl_name **names = NULL;
407
408         if (!dim)
409                 return NULL;
410         if (dim->nparam == nparam && dim->n_in == n_in && dim->n_out == n_out)
411                 return dim;
412
413         isl_assert(dim->ctx, dim->nparam <= nparam, goto error);
414         isl_assert(dim->ctx, dim->n_in <= n_in, goto error);
415         isl_assert(dim->ctx, dim->n_out <= n_out, goto error);
416
417         dim = isl_dim_cow(dim);
418
419         if (dim->names) {
420                 names = isl_calloc_array(dim->ctx, struct isl_name *,
421                                          nparam + n_in + n_out);
422                 if (!names)
423                         goto error;
424                 get_names(dim, isl_dim_param, 0, dim->nparam, names);
425                 get_names(dim, isl_dim_in, 0, dim->n_in, names + nparam);
426                 get_names(dim, isl_dim_out, 0, dim->n_out,
427                                 names + nparam + n_in);
428                 free(dim->names);
429                 dim->names = names;
430                 dim->n_name = nparam + n_in + n_out;
431         }
432         dim->nparam = nparam;
433         dim->n_in = n_in;
434         dim->n_out = n_out;
435
436         return dim;
437 error:
438         free(names);
439         isl_dim_free(dim);
440         return NULL;
441 }
442
443 struct isl_dim *isl_dim_add(struct isl_dim *dim, enum isl_dim_type type,
444         unsigned n)
445 {
446         if (!dim)
447                 return NULL;
448         if ((type == isl_dim_in || type == isl_dim_out) &&
449             dim->tuple_name[type - isl_dim_in]) {
450                 dim = isl_dim_cow(dim);
451                 if (!dim)
452                         return NULL;
453                 isl_name_free(dim->ctx, dim->tuple_name[type - isl_dim_in]);
454                 dim->tuple_name[type - isl_dim_in] = NULL;
455         }
456         switch (type) {
457         case isl_dim_param:
458                 return isl_dim_extend(dim,
459                                         dim->nparam + n, dim->n_in, dim->n_out);
460         case isl_dim_in:
461                 return isl_dim_extend(dim,
462                                         dim->nparam, dim->n_in + n, dim->n_out);
463         case isl_dim_out:
464                 return isl_dim_extend(dim,
465                                         dim->nparam, dim->n_in, dim->n_out + n);
466         }
467         return dim;
468 }
469
470 __isl_give isl_dim *isl_dim_insert(__isl_take isl_dim *dim,
471         enum isl_dim_type type, unsigned pos, unsigned n)
472 {
473         struct isl_name **names = NULL;
474
475         if (!dim)
476                 return NULL;
477         if (n == 0 && !isl_dim_get_tuple_name(dim, type))
478                 return dim;
479
480         isl_assert(dim->ctx, pos <= isl_dim_size(dim, type), goto error);
481
482         dim = isl_dim_cow(dim);
483         if (!dim)
484                 return NULL;
485
486         if (dim->names) {
487                 enum isl_dim_type t;
488                 int off;
489                 int size[3];
490                 names = isl_calloc_array(dim->ctx, struct isl_name *,
491                                      dim->nparam + dim->n_in + dim->n_out + n);
492                 if (!names)
493                         goto error;
494                 off = 0;
495                 size[isl_dim_param] = dim->nparam;
496                 size[isl_dim_in] = dim->n_in;
497                 size[isl_dim_out] = dim->n_out;
498                 for (t = isl_dim_param; t <= isl_dim_out; ++t) {
499                         if (t != type) {
500                                 get_names(dim, t, 0, size[t], names + off);
501                                 off += size[t];
502                         } else {
503                                 get_names(dim, t, 0, pos, names + off);
504                                 off += pos + n;
505                                 get_names(dim, t, pos, size[t]-pos, names+off);
506                                 off += size[t] - pos;
507                         }
508                 }
509                 free(dim->names);
510                 dim->names = names;
511                 dim->n_name = dim->nparam + dim->n_in + dim->n_out + n;
512         }
513         switch (type) {
514         case isl_dim_param:     dim->nparam += n; break;
515         case isl_dim_in:        dim->n_in += n; break;
516         case isl_dim_out:       dim->n_out += n; break;
517         }
518         if (type == isl_dim_in || type == isl_dim_out) {
519                 isl_name_free(dim->ctx, dim->tuple_name[type - isl_dim_in]);
520                 dim->tuple_name[type - isl_dim_in] = NULL;
521         }
522
523         return dim;
524 error:
525         isl_dim_free(dim);
526         return NULL;
527 }
528
529 __isl_give isl_dim *isl_dim_move(__isl_take isl_dim *dim,
530         enum isl_dim_type dst_type, unsigned dst_pos,
531         enum isl_dim_type src_type, unsigned src_pos, unsigned n)
532 {
533         if (!dim)
534                 return NULL;
535         if (n == 0)
536                 return dim;
537
538         isl_assert(dim->ctx, src_pos + n <= isl_dim_size(dim, src_type),
539                 goto error);
540
541         if (dst_type == src_type && dst_pos == src_pos)
542                 return dim;
543
544         isl_assert(dim->ctx, dst_type != src_type, goto error);
545
546         dim = isl_dim_cow(dim);
547         if (!dim)
548                 return NULL;
549
550         if (dim->names) {
551                 struct isl_name **names;
552                 enum isl_dim_type t;
553                 int off;
554                 int size[3];
555                 names = isl_calloc_array(dim->ctx, struct isl_name *,
556                                          dim->nparam + dim->n_in + dim->n_out);
557                 if (!names)
558                         goto error;
559                 off = 0;
560                 size[isl_dim_param] = dim->nparam;
561                 size[isl_dim_in] = dim->n_in;
562                 size[isl_dim_out] = dim->n_out;
563                 for (t = isl_dim_param; t <= isl_dim_out; ++t) {
564                         if (t == dst_type) {
565                                 get_names(dim, t, 0, dst_pos, names + off);
566                                 off += dst_pos;
567                                 get_names(dim, src_type, src_pos, n, names+off);
568                                 off += n;
569                                 get_names(dim, t, dst_pos, size[t] - dst_pos,
570                                                 names + off);
571                                 off += size[t] - dst_pos;
572                         } else if (t == src_type) {
573                                 get_names(dim, t, 0, src_pos, names + off);
574                                 off += src_pos;
575                                 get_names(dim, t, src_pos + n,
576                                             size[t] - src_pos - n, names + off);
577                                 off += size[t] - src_pos - n;
578                         } else {
579                                 get_names(dim, t, 0, size[t], names + off);
580                                 off += size[t];
581                         }
582                 }
583                 free(dim->names);
584                 dim->names = names;
585                 dim->n_name = dim->nparam + dim->n_in + dim->n_out;
586         }
587
588         switch (dst_type) {
589         case isl_dim_param:     dim->nparam += n; break;
590         case isl_dim_in:        dim->n_in += n; break;
591         case isl_dim_out:       dim->n_out += n; break;
592         }
593
594         switch (src_type) {
595         case isl_dim_param:     dim->nparam -= n; break;
596         case isl_dim_in:        dim->n_in -= n; break;
597         case isl_dim_out:       dim->n_out -= n; break;
598         }
599
600         return dim;
601 error:
602         isl_dim_free(dim);
603         return NULL;
604 }
605
606 struct isl_dim *isl_dim_join(struct isl_dim *left, struct isl_dim *right)
607 {
608         struct isl_dim *dim;
609
610         if (!left || !right)
611                 goto error;
612
613         isl_assert(left->ctx, match(left, isl_dim_param, right, isl_dim_param),
614                         goto error);
615         isl_assert(left->ctx,
616                 isl_dim_tuple_match(left, isl_dim_out, right, isl_dim_in),
617                 goto error);
618
619         dim = isl_dim_alloc(left->ctx, left->nparam, left->n_in, right->n_out);
620         if (!dim)
621                 goto error;
622
623         dim = copy_names(dim, isl_dim_param, 0, left, isl_dim_param);
624         dim = copy_names(dim, isl_dim_in, 0, left, isl_dim_in);
625         dim = copy_names(dim, isl_dim_out, 0, right, isl_dim_out);
626
627         if (dim && left->tuple_name[0] &&
628             !(dim->tuple_name[0] = isl_name_copy(dim->ctx, left->tuple_name[0])))
629                 goto error;
630         if (dim && right->tuple_name[1] &&
631             !(dim->tuple_name[1] = isl_name_copy(dim->ctx, right->tuple_name[1])))
632                 goto error;
633
634         isl_dim_free(left);
635         isl_dim_free(right);
636
637         return dim;
638 error:
639         isl_dim_free(left);
640         isl_dim_free(right);
641         return NULL;
642 }
643
644 struct isl_dim *isl_dim_product(struct isl_dim *left, struct isl_dim *right)
645 {
646         struct isl_dim *dim;
647
648         if (!left || !right)
649                 goto error;
650
651         isl_assert(left->ctx, match(left, isl_dim_param, right, isl_dim_param),
652                         goto error);
653
654         dim = isl_dim_alloc(left->ctx, left->nparam,
655                         left->n_in + right->n_in, left->n_out + right->n_out);
656         if (!dim)
657                 goto error;
658
659         dim = copy_names(dim, isl_dim_param, 0, left, isl_dim_param);
660         dim = copy_names(dim, isl_dim_in, 0, left, isl_dim_in);
661         dim = copy_names(dim, isl_dim_in, left->n_in, right, isl_dim_in);
662         dim = copy_names(dim, isl_dim_out, 0, left, isl_dim_out);
663         dim = copy_names(dim, isl_dim_out, left->n_out, right, isl_dim_out);
664
665         isl_dim_free(left);
666         isl_dim_free(right);
667
668         return dim;
669 error:
670         isl_dim_free(left);
671         isl_dim_free(right);
672         return NULL;
673 }
674
675 struct isl_dim *isl_dim_map(struct isl_dim *dim)
676 {
677         struct isl_name **names = NULL;
678
679         if (!dim)
680                 return NULL;
681         isl_assert(dim->ctx, dim->n_in == 0, goto error);
682         if (dim->n_out == 0 && !dim->tuple_name[1])
683                 return dim;
684         dim = isl_dim_cow(dim);
685         if (!dim)
686                 return NULL;
687         if (dim->names) {
688                 names = isl_calloc_array(dim->ctx, struct isl_name *,
689                                         dim->nparam + dim->n_out + dim->n_out);
690                 if (!names)
691                         goto error;
692                 get_names(dim, isl_dim_param, 0, dim->nparam, names);
693                 get_names(dim, isl_dim_out, 0, dim->n_out, names + dim->nparam);
694         }
695         dim->n_in = dim->n_out;
696         if (names) {
697                 free(dim->names);
698                 dim->names = names;
699                 dim->n_name = dim->nparam + dim->n_out + dim->n_out;
700                 dim = copy_names(dim, isl_dim_out, 0, dim, isl_dim_in);
701         }
702         isl_name_free(dim->ctx, dim->tuple_name[0]);
703         dim->tuple_name[0] = isl_name_copy(dim->ctx, dim->tuple_name[1]);
704         return dim;
705 error:
706         isl_dim_free(dim);
707         return NULL;
708 }
709
710 static struct isl_dim *set_names(struct isl_dim *dim, enum isl_dim_type type,
711         unsigned first, unsigned n, struct isl_name **names)
712 {
713         int i;
714
715         for (i = 0; i < n ; ++i)
716                 dim = set_name(dim, type, first+i, names[i]);
717
718         return dim;
719 }
720
721 struct isl_dim *isl_dim_reverse(struct isl_dim *dim)
722 {
723         unsigned t;
724         struct isl_name **names = NULL;
725         struct isl_name *name;
726
727         if (!dim)
728                 return NULL;
729         if (match(dim, isl_dim_in, dim, isl_dim_out))
730                 return dim;
731
732         dim = isl_dim_cow(dim);
733         if (!dim)
734                 return NULL;
735
736         name = dim->tuple_name[0];
737         dim->tuple_name[0] = dim->tuple_name[1];
738         dim->tuple_name[1] = name;
739
740         if (dim->names) {
741                 names = isl_alloc_array(dim->ctx, struct isl_name *,
742                                         dim->n_in + dim->n_out);
743                 if (!names)
744                         goto error;
745                 get_names(dim, isl_dim_in, 0, dim->n_in, names);
746                 get_names(dim, isl_dim_out, 0, dim->n_out, names + dim->n_in);
747         }
748
749         t = dim->n_in;
750         dim->n_in = dim->n_out;
751         dim->n_out = t;
752
753         if (dim->names) {
754                 dim = set_names(dim, isl_dim_out, 0, dim->n_out, names);
755                 dim = set_names(dim, isl_dim_in, 0, dim->n_in, names + dim->n_out);
756                 free(names);
757         }
758
759         return dim;
760 error:
761         free(names);
762         isl_dim_free(dim);
763         return NULL;
764 }
765
766 struct isl_dim *isl_dim_drop(struct isl_dim *dim, enum isl_dim_type type,
767                 unsigned first, unsigned num)
768 {
769         int i;
770
771         if (!dim)
772                 return NULL;
773
774         if (n == 0)
775                 return dim;
776
777         isl_assert(dim->ctx, first + num <= n(dim, type), goto error);
778         dim = isl_dim_cow(dim);
779         if (!dim)
780                 goto error;
781         if (dim->names) {
782                 dim = extend_names(dim);
783                 if (!dim)
784                         goto error;
785                 for (i = 0; i < num; ++i)
786                         isl_name_free(dim->ctx, get_name(dim, type, first+i));
787                 for (i = first+num; i < n(dim, type); ++i)
788                         set_name(dim, type, i - num, get_name(dim, type, i));
789                 switch (type) {
790                 case isl_dim_param:
791                         get_names(dim, isl_dim_in, 0, dim->n_in,
792                                 dim->names + offset(dim, isl_dim_in) - num);
793                 case isl_dim_in:
794                         get_names(dim, isl_dim_out, 0, dim->n_out,
795                                 dim->names + offset(dim, isl_dim_out) - num);
796                 case isl_dim_out:
797                         ;
798                 }
799                 dim->n_name -= num;
800         }
801         switch (type) {
802         case isl_dim_param:     dim->nparam -= num; break;
803         case isl_dim_in:        dim->n_in -= num; break;
804         case isl_dim_out:       dim->n_out -= num; break;
805         }
806         if (type == isl_dim_in || type == isl_dim_out) {
807                 isl_name_free(dim->ctx, dim->tuple_name[type - isl_dim_in]);
808                 dim->tuple_name[type - isl_dim_in] = NULL;
809         }
810         return dim;
811 error:
812         isl_dim_free(dim);
813         return NULL;
814 }
815
816 struct isl_dim *isl_dim_drop_inputs(struct isl_dim *dim,
817                 unsigned first, unsigned n)
818 {
819         if (!dim)
820                 return NULL;
821         return isl_dim_drop(dim, isl_dim_in, first, n);
822 }
823
824 struct isl_dim *isl_dim_drop_outputs(struct isl_dim *dim,
825                 unsigned first, unsigned n)
826 {
827         if (!dim)
828                 return NULL;
829         return isl_dim_drop(dim, isl_dim_out, first, n);
830 }
831
832 struct isl_dim *isl_dim_domain(struct isl_dim *dim)
833 {
834         if (!dim)
835                 return NULL;
836         dim = isl_dim_drop_outputs(dim, 0, dim->n_out);
837         return isl_dim_reverse(dim);
838 }
839
840 struct isl_dim *isl_dim_range(struct isl_dim *dim)
841 {
842         if (!dim)
843                 return NULL;
844         return isl_dim_drop_inputs(dim, 0, dim->n_in);
845 }
846
847 __isl_give isl_dim *isl_dim_as_set_dim(__isl_take isl_dim *dim)
848 {
849         dim = isl_dim_cow(dim);
850         if (!dim)
851                 return NULL;
852
853         dim->n_out += dim->n_in;
854         dim->n_in = 0;
855         isl_name_free(dim->ctx, dim->tuple_name[0]);
856         isl_name_free(dim->ctx, dim->tuple_name[1]);
857         dim->tuple_name[0] = NULL;
858         dim->tuple_name[1] = NULL;
859
860         return dim;
861 }
862
863 struct isl_dim *isl_dim_underlying(struct isl_dim *dim, unsigned n_div)
864 {
865         int i;
866
867         if (!dim)
868                 return NULL;
869         if (n_div == 0 &&
870             dim->nparam == 0 && dim->n_in == 0 && dim->n_name == 0 &&
871             !dim->tuple_name[1])
872                 return dim;
873         dim = isl_dim_cow(dim);
874         if (!dim)
875                 return NULL;
876         dim->n_out += dim->nparam + dim->n_in + n_div;
877         dim->nparam = 0;
878         dim->n_in = 0;
879
880         for (i = 0; i < dim->n_name; ++i)
881                 isl_name_free(dim->ctx, get_name(dim, isl_dim_out, i));
882         dim->n_name = 0;
883         isl_name_free(dim->ctx, dim->tuple_name[0]);
884         isl_name_free(dim->ctx, dim->tuple_name[1]);
885         dim->tuple_name[0] = NULL;
886         dim->tuple_name[1] = NULL;
887
888         return dim;
889 }
890
891 unsigned isl_dim_total(struct isl_dim *dim)
892 {
893         return dim->nparam + dim->n_in + dim->n_out;
894 }
895
896 int isl_dim_equal(struct isl_dim *dim1, struct isl_dim *dim2)
897 {
898         return match(dim1, isl_dim_param, dim2, isl_dim_param) &&
899                isl_dim_tuple_match(dim1, isl_dim_in, dim2, isl_dim_in) &&
900                isl_dim_tuple_match(dim1, isl_dim_out, dim2, isl_dim_out);
901 }
902
903 int isl_dim_compatible(struct isl_dim *dim1, struct isl_dim *dim2)
904 {
905         return dim1->nparam == dim2->nparam &&
906                dim1->n_in + dim1->n_out == dim2->n_in + dim2->n_out;
907 }