5a053f73caf9ba0a9b8a9d2141514103c96bbb2f
[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_private.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 (!s) {
289                 name = NULL;
290         } else {
291                 if (!name_ok(dim->ctx, s))
292                         goto error;
293                 name = isl_name_get(dim->ctx, s);
294                 if (!name)
295                         goto error;
296         }
297
298         isl_name_free(dim->ctx, dim->tuple_name[type - isl_dim_in]);
299         dim->tuple_name[type - isl_dim_in] = name;
300
301         return dim;
302 error:
303         isl_dim_free(dim);
304         return NULL;
305 }
306
307 const char *isl_dim_get_tuple_name(__isl_keep isl_dim *dim,
308          enum isl_dim_type type)
309 {
310         struct isl_name *name;
311         if (!dim)
312                 return NULL;
313         if (type != isl_dim_in && type != isl_dim_out)
314                 return NULL;
315         name = dim->tuple_name[type - isl_dim_in];
316         return name ? name->name : NULL;
317 }
318
319 struct isl_dim *isl_dim_set_name(struct isl_dim *dim,
320                                  enum isl_dim_type type, unsigned pos,
321                                  const char *s)
322 {
323         struct isl_name *name;
324
325         if (!dim)
326                 return NULL;
327         if (!name_ok(dim->ctx, s))
328                 goto error;
329         name = isl_name_get(dim->ctx, s);
330         if (!name)
331                 goto error;
332         return set_name(dim, type, pos, name);
333 error:
334         isl_dim_free(dim);
335         return NULL;
336 }
337
338 const char *isl_dim_get_name(struct isl_dim *dim,
339                                  enum isl_dim_type type, unsigned pos)
340 {
341         struct isl_name *name = get_name(dim, type, pos);
342         return name ? name->name : NULL;
343 }
344
345 static struct isl_name *tuple_name(__isl_keep isl_dim *dim,
346         enum isl_dim_type type)
347 {
348         if (!dim)
349                 return NULL;
350         if (type == isl_dim_in)
351                 return dim->tuple_name[0];
352         if (type == isl_dim_out)
353                 return dim->tuple_name[1];
354         return NULL;
355 }
356
357 int isl_dim_tuple_match(__isl_keep isl_dim *dim1, enum isl_dim_type dim1_type,
358                         __isl_keep isl_dim *dim2, enum isl_dim_type dim2_type)
359 {
360         struct isl_name *name1, *name2;
361
362         if (n(dim1, dim1_type) != n(dim2, dim2_type))
363                 return 0;
364         name1 = tuple_name(dim1, dim1_type);
365         name2 = tuple_name(dim2, dim2_type);
366         if (!name1 ^ !name2)
367                 return 0;
368         if (name1 && name1->name != name2->name)
369                 return 0;
370         return 1;
371 }
372
373 static int match(struct isl_dim *dim1, enum isl_dim_type dim1_type,
374                 struct isl_dim *dim2, enum isl_dim_type dim2_type)
375 {
376         int i;
377
378         if (!isl_dim_tuple_match(dim1, dim1_type, dim2, dim2_type))
379                 return 0;
380
381         if (!dim1->names && !dim2->names)
382                 return 1;
383
384         for (i = 0; i < n(dim1, dim1_type); ++i) {
385                 if (get_name(dim1, dim1_type, i) !=
386                     get_name(dim2, dim2_type, i))
387                         return 0;
388         }
389         return 1;
390 }
391
392 int isl_dim_match(struct isl_dim *dim1, enum isl_dim_type dim1_type,
393                 struct isl_dim *dim2, enum isl_dim_type dim2_type)
394 {
395         return match(dim1, dim1_type, dim2, dim2_type);
396 }
397
398 static void get_names(struct isl_dim *dim, enum isl_dim_type type,
399         unsigned first, unsigned n, struct isl_name **names)
400 {
401         int i;
402
403         for (i = 0; i < n ; ++i)
404                 names[i] = get_name(dim, type, first+i);
405 }
406
407 struct isl_dim *isl_dim_extend(struct isl_dim *dim,
408                         unsigned nparam, unsigned n_in, unsigned n_out)
409 {
410         struct isl_name **names = NULL;
411
412         if (!dim)
413                 return NULL;
414         if (dim->nparam == nparam && dim->n_in == n_in && dim->n_out == n_out)
415                 return dim;
416
417         isl_assert(dim->ctx, dim->nparam <= nparam, goto error);
418         isl_assert(dim->ctx, dim->n_in <= n_in, goto error);
419         isl_assert(dim->ctx, dim->n_out <= n_out, goto error);
420
421         dim = isl_dim_cow(dim);
422
423         if (dim->names) {
424                 names = isl_calloc_array(dim->ctx, struct isl_name *,
425                                          nparam + n_in + n_out);
426                 if (!names)
427                         goto error;
428                 get_names(dim, isl_dim_param, 0, dim->nparam, names);
429                 get_names(dim, isl_dim_in, 0, dim->n_in, names + nparam);
430                 get_names(dim, isl_dim_out, 0, dim->n_out,
431                                 names + nparam + n_in);
432                 free(dim->names);
433                 dim->names = names;
434                 dim->n_name = nparam + n_in + n_out;
435         }
436         dim->nparam = nparam;
437         dim->n_in = n_in;
438         dim->n_out = n_out;
439
440         return dim;
441 error:
442         free(names);
443         isl_dim_free(dim);
444         return NULL;
445 }
446
447 struct isl_dim *isl_dim_add(struct isl_dim *dim, enum isl_dim_type type,
448         unsigned n)
449 {
450         if (!dim)
451                 return NULL;
452         if ((type == isl_dim_in || type == isl_dim_out) &&
453             dim->tuple_name[type - isl_dim_in]) {
454                 dim = isl_dim_cow(dim);
455                 if (!dim)
456                         return NULL;
457                 isl_name_free(dim->ctx, dim->tuple_name[type - isl_dim_in]);
458                 dim->tuple_name[type - isl_dim_in] = NULL;
459         }
460         switch (type) {
461         case isl_dim_param:
462                 return isl_dim_extend(dim,
463                                         dim->nparam + n, dim->n_in, dim->n_out);
464         case isl_dim_in:
465                 return isl_dim_extend(dim,
466                                         dim->nparam, dim->n_in + n, dim->n_out);
467         case isl_dim_out:
468                 return isl_dim_extend(dim,
469                                         dim->nparam, dim->n_in, dim->n_out + n);
470         }
471         return dim;
472 }
473
474 __isl_give isl_dim *isl_dim_insert(__isl_take isl_dim *dim,
475         enum isl_dim_type type, unsigned pos, unsigned n)
476 {
477         struct isl_name **names = NULL;
478
479         if (!dim)
480                 return NULL;
481         if (n == 0 && !isl_dim_get_tuple_name(dim, type))
482                 return dim;
483
484         isl_assert(dim->ctx, pos <= isl_dim_size(dim, type), goto error);
485
486         dim = isl_dim_cow(dim);
487         if (!dim)
488                 return NULL;
489
490         if (dim->names) {
491                 enum isl_dim_type t;
492                 int off;
493                 int size[3];
494                 names = isl_calloc_array(dim->ctx, struct isl_name *,
495                                      dim->nparam + dim->n_in + dim->n_out + n);
496                 if (!names)
497                         goto error;
498                 off = 0;
499                 size[isl_dim_param] = dim->nparam;
500                 size[isl_dim_in] = dim->n_in;
501                 size[isl_dim_out] = dim->n_out;
502                 for (t = isl_dim_param; t <= isl_dim_out; ++t) {
503                         if (t != type) {
504                                 get_names(dim, t, 0, size[t], names + off);
505                                 off += size[t];
506                         } else {
507                                 get_names(dim, t, 0, pos, names + off);
508                                 off += pos + n;
509                                 get_names(dim, t, pos, size[t]-pos, names+off);
510                                 off += size[t] - pos;
511                         }
512                 }
513                 free(dim->names);
514                 dim->names = names;
515                 dim->n_name = dim->nparam + dim->n_in + dim->n_out + n;
516         }
517         switch (type) {
518         case isl_dim_param:     dim->nparam += n; break;
519         case isl_dim_in:        dim->n_in += n; break;
520         case isl_dim_out:       dim->n_out += n; break;
521         }
522         if (type == isl_dim_in || type == isl_dim_out) {
523                 isl_name_free(dim->ctx, dim->tuple_name[type - isl_dim_in]);
524                 dim->tuple_name[type - isl_dim_in] = NULL;
525         }
526
527         return dim;
528 error:
529         isl_dim_free(dim);
530         return NULL;
531 }
532
533 __isl_give isl_dim *isl_dim_move(__isl_take isl_dim *dim,
534         enum isl_dim_type dst_type, unsigned dst_pos,
535         enum isl_dim_type src_type, unsigned src_pos, unsigned n)
536 {
537         if (!dim)
538                 return NULL;
539         if (n == 0)
540                 return dim;
541
542         isl_assert(dim->ctx, src_pos + n <= isl_dim_size(dim, src_type),
543                 goto error);
544
545         if (dst_type == src_type && dst_pos == src_pos)
546                 return dim;
547
548         isl_assert(dim->ctx, dst_type != src_type, goto error);
549
550         dim = isl_dim_cow(dim);
551         if (!dim)
552                 return NULL;
553
554         if (dim->names) {
555                 struct isl_name **names;
556                 enum isl_dim_type t;
557                 int off;
558                 int size[3];
559                 names = isl_calloc_array(dim->ctx, struct isl_name *,
560                                          dim->nparam + dim->n_in + dim->n_out);
561                 if (!names)
562                         goto error;
563                 off = 0;
564                 size[isl_dim_param] = dim->nparam;
565                 size[isl_dim_in] = dim->n_in;
566                 size[isl_dim_out] = dim->n_out;
567                 for (t = isl_dim_param; t <= isl_dim_out; ++t) {
568                         if (t == dst_type) {
569                                 get_names(dim, t, 0, dst_pos, names + off);
570                                 off += dst_pos;
571                                 get_names(dim, src_type, src_pos, n, names+off);
572                                 off += n;
573                                 get_names(dim, t, dst_pos, size[t] - dst_pos,
574                                                 names + off);
575                                 off += size[t] - dst_pos;
576                         } else if (t == src_type) {
577                                 get_names(dim, t, 0, src_pos, names + off);
578                                 off += src_pos;
579                                 get_names(dim, t, src_pos + n,
580                                             size[t] - src_pos - n, names + off);
581                                 off += size[t] - src_pos - n;
582                         } else {
583                                 get_names(dim, t, 0, size[t], names + off);
584                                 off += size[t];
585                         }
586                 }
587                 free(dim->names);
588                 dim->names = names;
589                 dim->n_name = dim->nparam + dim->n_in + dim->n_out;
590         }
591
592         switch (dst_type) {
593         case isl_dim_param:     dim->nparam += n; break;
594         case isl_dim_in:        dim->n_in += n; break;
595         case isl_dim_out:       dim->n_out += n; break;
596         }
597
598         switch (src_type) {
599         case isl_dim_param:     dim->nparam -= n; break;
600         case isl_dim_in:        dim->n_in -= n; break;
601         case isl_dim_out:       dim->n_out -= n; break;
602         }
603
604         return dim;
605 error:
606         isl_dim_free(dim);
607         return NULL;
608 }
609
610 struct isl_dim *isl_dim_join(struct isl_dim *left, struct isl_dim *right)
611 {
612         struct isl_dim *dim;
613
614         if (!left || !right)
615                 goto error;
616
617         isl_assert(left->ctx, match(left, isl_dim_param, right, isl_dim_param),
618                         goto error);
619         isl_assert(left->ctx,
620                 isl_dim_tuple_match(left, isl_dim_out, right, isl_dim_in),
621                 goto error);
622
623         dim = isl_dim_alloc(left->ctx, left->nparam, left->n_in, right->n_out);
624         if (!dim)
625                 goto error;
626
627         dim = copy_names(dim, isl_dim_param, 0, left, isl_dim_param);
628         dim = copy_names(dim, isl_dim_in, 0, left, isl_dim_in);
629         dim = copy_names(dim, isl_dim_out, 0, right, isl_dim_out);
630
631         if (dim && left->tuple_name[0] &&
632             !(dim->tuple_name[0] = isl_name_copy(dim->ctx, left->tuple_name[0])))
633                 goto error;
634         if (dim && right->tuple_name[1] &&
635             !(dim->tuple_name[1] = isl_name_copy(dim->ctx, right->tuple_name[1])))
636                 goto error;
637
638         isl_dim_free(left);
639         isl_dim_free(right);
640
641         return dim;
642 error:
643         isl_dim_free(left);
644         isl_dim_free(right);
645         return NULL;
646 }
647
648 struct isl_dim *isl_dim_product(struct isl_dim *left, struct isl_dim *right)
649 {
650         struct isl_dim *dim;
651
652         if (!left || !right)
653                 goto error;
654
655         isl_assert(left->ctx, match(left, isl_dim_param, right, isl_dim_param),
656                         goto error);
657
658         dim = isl_dim_alloc(left->ctx, left->nparam,
659                         left->n_in + right->n_in, left->n_out + right->n_out);
660         if (!dim)
661                 goto error;
662
663         dim = copy_names(dim, isl_dim_param, 0, left, isl_dim_param);
664         dim = copy_names(dim, isl_dim_in, 0, left, isl_dim_in);
665         dim = copy_names(dim, isl_dim_in, left->n_in, right, isl_dim_in);
666         dim = copy_names(dim, isl_dim_out, 0, left, isl_dim_out);
667         dim = copy_names(dim, isl_dim_out, left->n_out, right, isl_dim_out);
668
669         isl_dim_free(left);
670         isl_dim_free(right);
671
672         return dim;
673 error:
674         isl_dim_free(left);
675         isl_dim_free(right);
676         return NULL;
677 }
678
679 struct isl_dim *isl_dim_map(struct isl_dim *dim)
680 {
681         struct isl_name **names = NULL;
682
683         if (!dim)
684                 return NULL;
685         isl_assert(dim->ctx, dim->n_in == 0, goto error);
686         if (dim->n_out == 0 && !dim->tuple_name[1])
687                 return dim;
688         dim = isl_dim_cow(dim);
689         if (!dim)
690                 return NULL;
691         if (dim->names) {
692                 names = isl_calloc_array(dim->ctx, struct isl_name *,
693                                         dim->nparam + dim->n_out + dim->n_out);
694                 if (!names)
695                         goto error;
696                 get_names(dim, isl_dim_param, 0, dim->nparam, names);
697                 get_names(dim, isl_dim_out, 0, dim->n_out, names + dim->nparam);
698         }
699         dim->n_in = dim->n_out;
700         if (names) {
701                 free(dim->names);
702                 dim->names = names;
703                 dim->n_name = dim->nparam + dim->n_out + dim->n_out;
704                 dim = copy_names(dim, isl_dim_out, 0, dim, isl_dim_in);
705         }
706         isl_name_free(dim->ctx, dim->tuple_name[0]);
707         dim->tuple_name[0] = isl_name_copy(dim->ctx, dim->tuple_name[1]);
708         return dim;
709 error:
710         isl_dim_free(dim);
711         return NULL;
712 }
713
714 static struct isl_dim *set_names(struct isl_dim *dim, enum isl_dim_type type,
715         unsigned first, unsigned n, struct isl_name **names)
716 {
717         int i;
718
719         for (i = 0; i < n ; ++i)
720                 dim = set_name(dim, type, first+i, names[i]);
721
722         return dim;
723 }
724
725 struct isl_dim *isl_dim_reverse(struct isl_dim *dim)
726 {
727         unsigned t;
728         struct isl_name **names = NULL;
729         struct isl_name *name;
730
731         if (!dim)
732                 return NULL;
733         if (match(dim, isl_dim_in, dim, isl_dim_out))
734                 return dim;
735
736         dim = isl_dim_cow(dim);
737         if (!dim)
738                 return NULL;
739
740         name = dim->tuple_name[0];
741         dim->tuple_name[0] = dim->tuple_name[1];
742         dim->tuple_name[1] = name;
743
744         if (dim->names) {
745                 names = isl_alloc_array(dim->ctx, struct isl_name *,
746                                         dim->n_in + dim->n_out);
747                 if (!names)
748                         goto error;
749                 get_names(dim, isl_dim_in, 0, dim->n_in, names);
750                 get_names(dim, isl_dim_out, 0, dim->n_out, names + dim->n_in);
751         }
752
753         t = dim->n_in;
754         dim->n_in = dim->n_out;
755         dim->n_out = t;
756
757         if (dim->names) {
758                 dim = set_names(dim, isl_dim_out, 0, dim->n_out, names);
759                 dim = set_names(dim, isl_dim_in, 0, dim->n_in, names + dim->n_out);
760                 free(names);
761         }
762
763         return dim;
764 error:
765         free(names);
766         isl_dim_free(dim);
767         return NULL;
768 }
769
770 struct isl_dim *isl_dim_drop(struct isl_dim *dim, enum isl_dim_type type,
771                 unsigned first, unsigned num)
772 {
773         int i;
774
775         if (!dim)
776                 return NULL;
777
778         if (n == 0 && !isl_dim_get_tuple_name(dim, type))
779                 return dim;
780
781         isl_assert(dim->ctx, first + num <= n(dim, type), goto error);
782         dim = isl_dim_cow(dim);
783         if (!dim)
784                 goto error;
785         if (dim->names) {
786                 dim = extend_names(dim);
787                 if (!dim)
788                         goto error;
789                 for (i = 0; i < num; ++i)
790                         isl_name_free(dim->ctx, get_name(dim, type, first+i));
791                 for (i = first+num; i < n(dim, type); ++i)
792                         set_name(dim, type, i - num, get_name(dim, type, i));
793                 switch (type) {
794                 case isl_dim_param:
795                         get_names(dim, isl_dim_in, 0, dim->n_in,
796                                 dim->names + offset(dim, isl_dim_in) - num);
797                 case isl_dim_in:
798                         get_names(dim, isl_dim_out, 0, dim->n_out,
799                                 dim->names + offset(dim, isl_dim_out) - num);
800                 case isl_dim_out:
801                         ;
802                 }
803                 dim->n_name -= num;
804         }
805         switch (type) {
806         case isl_dim_param:     dim->nparam -= num; break;
807         case isl_dim_in:        dim->n_in -= num; break;
808         case isl_dim_out:       dim->n_out -= num; break;
809         }
810         if (type == isl_dim_in || type == isl_dim_out) {
811                 isl_name_free(dim->ctx, dim->tuple_name[type - isl_dim_in]);
812                 dim->tuple_name[type - isl_dim_in] = NULL;
813         }
814         return dim;
815 error:
816         isl_dim_free(dim);
817         return NULL;
818 }
819
820 struct isl_dim *isl_dim_drop_inputs(struct isl_dim *dim,
821                 unsigned first, unsigned n)
822 {
823         if (!dim)
824                 return NULL;
825         return isl_dim_drop(dim, isl_dim_in, first, n);
826 }
827
828 struct isl_dim *isl_dim_drop_outputs(struct isl_dim *dim,
829                 unsigned first, unsigned n)
830 {
831         if (!dim)
832                 return NULL;
833         return isl_dim_drop(dim, isl_dim_out, first, n);
834 }
835
836 struct isl_dim *isl_dim_domain(struct isl_dim *dim)
837 {
838         if (!dim)
839                 return NULL;
840         dim = isl_dim_drop_outputs(dim, 0, dim->n_out);
841         return isl_dim_reverse(dim);
842 }
843
844 struct isl_dim *isl_dim_range(struct isl_dim *dim)
845 {
846         if (!dim)
847                 return NULL;
848         return isl_dim_drop_inputs(dim, 0, dim->n_in);
849 }
850
851 __isl_give isl_dim *isl_dim_as_set_dim(__isl_take isl_dim *dim)
852 {
853         dim = isl_dim_cow(dim);
854         if (!dim)
855                 return NULL;
856
857         dim->n_out += dim->n_in;
858         dim->n_in = 0;
859         isl_name_free(dim->ctx, dim->tuple_name[0]);
860         isl_name_free(dim->ctx, dim->tuple_name[1]);
861         dim->tuple_name[0] = NULL;
862         dim->tuple_name[1] = NULL;
863
864         return dim;
865 }
866
867 struct isl_dim *isl_dim_underlying(struct isl_dim *dim, unsigned n_div)
868 {
869         int i;
870
871         if (!dim)
872                 return NULL;
873         if (n_div == 0 &&
874             dim->nparam == 0 && dim->n_in == 0 && dim->n_name == 0 &&
875             !dim->tuple_name[1])
876                 return dim;
877         dim = isl_dim_cow(dim);
878         if (!dim)
879                 return NULL;
880         dim->n_out += dim->nparam + dim->n_in + n_div;
881         dim->nparam = 0;
882         dim->n_in = 0;
883
884         for (i = 0; i < dim->n_name; ++i)
885                 isl_name_free(dim->ctx, get_name(dim, isl_dim_out, i));
886         dim->n_name = 0;
887         isl_name_free(dim->ctx, dim->tuple_name[0]);
888         isl_name_free(dim->ctx, dim->tuple_name[1]);
889         dim->tuple_name[0] = NULL;
890         dim->tuple_name[1] = NULL;
891
892         return dim;
893 }
894
895 unsigned isl_dim_total(struct isl_dim *dim)
896 {
897         return dim->nparam + dim->n_in + dim->n_out;
898 }
899
900 int isl_dim_equal(struct isl_dim *dim1, struct isl_dim *dim2)
901 {
902         return match(dim1, isl_dim_param, dim2, isl_dim_param) &&
903                isl_dim_tuple_match(dim1, isl_dim_in, dim2, isl_dim_in) &&
904                isl_dim_tuple_match(dim1, isl_dim_out, dim2, isl_dim_out);
905 }
906
907 int isl_dim_compatible(struct isl_dim *dim1, struct isl_dim *dim2)
908 {
909         return dim1->nparam == dim2->nparam &&
910                dim1->n_in + dim1->n_out == dim2->n_in + dim2->n_out;
911 }
912
913 uint32_t isl_dim_get_hash(__isl_keep isl_dim *dim)
914 {
915         int i;
916         uint32_t hash;
917         struct isl_name *name;
918
919         if (!dim)
920                 return 0;
921         hash = isl_hash_init();
922
923         hash = isl_hash_builtin(hash, dim->nparam);
924         hash = isl_hash_builtin(hash, dim->n_in);
925         hash = isl_hash_builtin(hash, dim->n_out);
926
927         for (i = 0; i < dim->nparam; ++i) {
928                 name = get_name(dim, isl_dim_param, i);
929                 hash = isl_hash_builtin(hash, name);
930         }
931
932         name = tuple_name(dim, isl_dim_in);
933         hash = isl_hash_builtin(hash, name);
934         name = tuple_name(dim, isl_dim_out);
935         hash = isl_hash_builtin(hash, name);
936
937         return hash;
938 }