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