isl_dim_set_name: plug memory leak when overwriting name
[platform/upstream/isl.git] / isl_dim.c
1 /*
2  * Copyright 2008-2009 Katholieke Universiteit Leuven
3  * Copyright 2010      INRIA Saclay
4  *
5  * Use of this software is governed by the GNU LGPLv2.1 license
6  *
7  * Written by Sven Verdoolaege, K.U.Leuven, Departement
8  * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
9  * and INRIA Saclay - Ile-de-France, Parc Club Orsay Universite,
10  * ZAC des vignes, 4 rue Jacques Monod, 91893 Orsay, France 
11  */
12
13 #include <stdlib.h>
14 #include <isl_dim_private.h>
15 #include "isl_name.h"
16
17 isl_ctx *isl_dim_get_ctx(__isl_keep isl_dim *dim)
18 {
19         return dim ? dim->ctx : NULL;
20 }
21
22 struct isl_dim *isl_dim_alloc(struct isl_ctx *ctx,
23                         unsigned nparam, unsigned n_in, unsigned n_out)
24 {
25         struct isl_dim *dim;
26
27         dim = isl_alloc_type(ctx, struct isl_dim);
28         if (!dim)
29                 return NULL;
30
31         dim->ctx = ctx;
32         isl_ctx_ref(ctx);
33         dim->ref = 1;
34         dim->nparam = nparam;
35         dim->n_in = n_in;
36         dim->n_out = n_out;
37
38         dim->tuple_name[0] = NULL;
39         dim->tuple_name[1] = NULL;
40
41         dim->nested[0] = NULL;
42         dim->nested[1] = NULL;
43
44         dim->n_name = 0;
45         dim->names = NULL;
46
47         return dim;
48 }
49
50 struct isl_dim *isl_dim_set_alloc(struct isl_ctx *ctx,
51                         unsigned nparam, unsigned dim)
52 {
53         return isl_dim_alloc(ctx, nparam, 0, dim);
54 }
55
56 static unsigned global_pos(struct isl_dim *dim,
57                                  enum isl_dim_type type, unsigned pos)
58 {
59         struct isl_ctx *ctx = dim->ctx;
60
61         switch (type) {
62         case isl_dim_param:
63                 isl_assert(ctx, pos < dim->nparam, return isl_dim_total(dim));
64                 return pos;
65         case isl_dim_in:
66                 isl_assert(ctx, pos < dim->n_in, return isl_dim_total(dim));
67                 return pos + dim->nparam;
68         case isl_dim_out:
69                 isl_assert(ctx, pos < dim->n_out, return isl_dim_total(dim));
70                 return pos + dim->nparam + dim->n_in;
71         default:
72                 isl_assert(ctx, 0, return isl_dim_total(dim));
73         }
74         return isl_dim_total(dim);
75 }
76
77 /* Extend length of names array to the total number of dimensions.
78  */
79 static __isl_give isl_dim *extend_names(__isl_take isl_dim *dim)
80 {
81         struct isl_name **names;
82         int i;
83
84         if (isl_dim_total(dim) <= dim->n_name)
85                 return dim;
86
87         if (!dim->names) {
88                 dim->names = isl_calloc_array(dim->ctx,
89                                 struct isl_name *, isl_dim_total(dim));
90                 if (!dim->names)
91                         goto error;
92         } else {
93                 names = isl_realloc_array(dim->ctx, dim->names,
94                                 struct isl_name *, isl_dim_total(dim));
95                 if (!names)
96                         goto error;
97                 dim->names = names;
98                 for (i = dim->n_name; i < isl_dim_total(dim); ++i)
99                         dim->names[i] = NULL;
100         }
101
102         dim->n_name = isl_dim_total(dim);
103
104         return dim;
105 error:
106         isl_dim_free(dim);
107         return NULL;
108 }
109
110 static struct isl_dim *set_name(struct isl_dim *dim,
111                                  enum isl_dim_type type, unsigned pos,
112                                  struct isl_name *name)
113 {
114         struct isl_ctx *ctx = dim->ctx;
115         dim = isl_dim_cow(dim);
116
117         if (!dim)
118                 goto error;
119
120         pos = global_pos(dim, type, pos);
121         if (pos == isl_dim_total(dim))
122                 goto error;
123
124         if (pos >= dim->n_name) {
125                 if (!name)
126                         return dim;
127                 dim = extend_names(dim);
128                 if (!dim)
129                         goto error;
130         }
131
132         dim->names[pos] = name;
133
134         return dim;
135 error:
136         isl_name_free(ctx, name);
137         isl_dim_free(dim);
138         return NULL;
139 }
140
141 static struct isl_name *get_name(struct isl_dim *dim,
142                                  enum isl_dim_type type, unsigned pos)
143 {
144         if (!dim)
145                 return NULL;
146
147         pos = global_pos(dim, type, pos);
148         if (pos == isl_dim_total(dim))
149                 return NULL;
150         if (pos >= dim->n_name)
151                 return NULL;
152         return dim->names[pos];
153 }
154
155 static unsigned offset(struct isl_dim *dim, enum isl_dim_type type)
156 {
157         switch (type) {
158         case isl_dim_param:     return 0;
159         case isl_dim_in:        return dim->nparam;
160         case isl_dim_out:       return dim->nparam + dim->n_in;
161         default:                return 0;
162         }
163 }
164
165 static unsigned n(struct isl_dim *dim, enum isl_dim_type type)
166 {
167         switch (type) {
168         case isl_dim_param:     return dim->nparam;
169         case isl_dim_in:        return dim->n_in;
170         case isl_dim_out:       return dim->n_out;
171         default:                return 0;
172         }
173 }
174
175 unsigned isl_dim_size(struct isl_dim *dim, enum isl_dim_type type)
176 {
177         if (!dim)
178                 return 0;
179         return n(dim, type);
180 }
181
182 unsigned isl_dim_offset(__isl_keep isl_dim *dim, enum isl_dim_type type)
183 {
184         if (!dim)
185                 return 0;
186         return offset(dim, type);
187 }
188
189 static struct isl_dim *copy_names(struct isl_dim *dst,
190         enum isl_dim_type dst_type, unsigned offset, struct isl_dim *src,
191         enum isl_dim_type src_type)
192 {
193         int i;
194         struct isl_name *name;
195
196         if (!dst)
197                 return NULL;
198
199         for (i = 0; i < n(src, src_type); ++i) {
200                 name = get_name(src, src_type, i);
201                 if (!name)
202                         continue;
203                 dst = set_name(dst, dst_type, offset + i,
204                                         isl_name_copy(dst->ctx, name));
205                 if (!dst)
206                         return NULL;
207         }
208         return dst;
209 }
210
211 struct isl_dim *isl_dim_dup(struct isl_dim *dim)
212 {
213         struct isl_dim *dup;
214         if (!dim)
215                 return NULL;
216         dup = isl_dim_alloc(dim->ctx, dim->nparam, dim->n_in, dim->n_out);
217         if (dim->tuple_name[0] &&
218             !(dup->tuple_name[0] = isl_name_copy(dim->ctx, dim->tuple_name[0])))
219                 goto error;
220         if (dim->tuple_name[1] &&
221             !(dup->tuple_name[1] = isl_name_copy(dim->ctx, dim->tuple_name[1])))
222                 goto error;
223         if (dim->nested[0] && !(dup->nested[0] = isl_dim_copy(dim->nested[0])))
224                 goto error;
225         if (dim->nested[1] && !(dup->nested[1] = isl_dim_copy(dim->nested[1])))
226                 goto error;
227         if (!dim->names)
228                 return dup;
229         dup = copy_names(dup, isl_dim_param, 0, dim, isl_dim_param);
230         dup = copy_names(dup, isl_dim_in, 0, dim, isl_dim_in);
231         dup = copy_names(dup, isl_dim_out, 0, dim, isl_dim_out);
232         return dup;
233 error:
234         isl_dim_free(dup);
235         return NULL;
236 }
237
238 struct isl_dim *isl_dim_cow(struct isl_dim *dim)
239 {
240         if (!dim)
241                 return NULL;
242
243         if (dim->ref == 1)
244                 return dim;
245         dim->ref--;
246         return isl_dim_dup(dim);
247 }
248
249 struct isl_dim *isl_dim_copy(struct isl_dim *dim)
250 {
251         if (!dim)
252                 return NULL;
253
254         dim->ref++;
255         return dim;
256 }
257
258 void isl_dim_free(struct isl_dim *dim)
259 {
260         int i;
261
262         if (!dim)
263                 return;
264
265         if (--dim->ref > 0)
266                 return;
267
268         isl_name_free(dim->ctx, dim->tuple_name[0]);
269         isl_name_free(dim->ctx, dim->tuple_name[1]);
270
271         isl_dim_free(dim->nested[0]);
272         isl_dim_free(dim->nested[1]);
273
274         for (i = 0; i < dim->n_name; ++i)
275                 isl_name_free(dim->ctx, dim->names[i]);
276         free(dim->names);
277         isl_ctx_deref(dim->ctx);
278         
279         free(dim);
280 }
281
282 static int name_ok(isl_ctx *ctx, const char *s)
283 {
284         char *p;
285         long dummy;
286
287         dummy = strtol(s, &p, 0);
288         if (p != s)
289                 isl_die(ctx, isl_error_invalid, "name looks like a number",
290                         return 0);
291
292         return 1;
293 }
294
295 __isl_give isl_dim *isl_dim_set_tuple_name(__isl_take isl_dim *dim,
296         enum isl_dim_type type, const char *s)
297 {
298         struct isl_name *name;
299
300         dim = isl_dim_cow(dim);
301         if (!dim)
302                 return NULL;
303         if (type != isl_dim_in && type != isl_dim_out)
304                 isl_die(dim->ctx, isl_error_invalid,
305                         "only input, output and set tuples can have names",
306                         goto error);
307         if (!s) {
308                 name = NULL;
309         } else {
310                 if (!name_ok(dim->ctx, s))
311                         goto error;
312                 name = isl_name_get(dim->ctx, s);
313                 if (!name)
314                         goto error;
315         }
316
317         isl_name_free(dim->ctx, dim->tuple_name[type - isl_dim_in]);
318         dim->tuple_name[type - isl_dim_in] = name;
319
320         return dim;
321 error:
322         isl_dim_free(dim);
323         return NULL;
324 }
325
326 const char *isl_dim_get_tuple_name(__isl_keep isl_dim *dim,
327          enum isl_dim_type type)
328 {
329         struct isl_name *name;
330         if (!dim)
331                 return NULL;
332         if (type != isl_dim_in && type != isl_dim_out)
333                 return NULL;
334         name = dim->tuple_name[type - isl_dim_in];
335         return name ? name->name : NULL;
336 }
337
338 struct isl_dim *isl_dim_set_name(struct isl_dim *dim,
339                                  enum isl_dim_type type, unsigned pos,
340                                  const char *s)
341 {
342         struct isl_name *name;
343
344         if (!dim)
345                 return NULL;
346         if (!name_ok(dim->ctx, s))
347                 goto error;
348         isl_name_free(dim->ctx, get_name(dim, type, pos));
349         name = isl_name_get(dim->ctx, s);
350         if (!name)
351                 goto error;
352         return set_name(dim, type, pos, name);
353 error:
354         isl_dim_free(dim);
355         return NULL;
356 }
357
358 const char *isl_dim_get_name(struct isl_dim *dim,
359                                  enum isl_dim_type type, unsigned pos)
360 {
361         struct isl_name *name = get_name(dim, type, pos);
362         return name ? name->name : NULL;
363 }
364
365 static struct isl_name *tuple_name(__isl_keep isl_dim *dim,
366         enum isl_dim_type type)
367 {
368         if (!dim)
369                 return NULL;
370         if (type == isl_dim_in)
371                 return dim->tuple_name[0];
372         if (type == isl_dim_out)
373                 return dim->tuple_name[1];
374         return NULL;
375 }
376
377 static __isl_keep isl_dim *nested(__isl_keep isl_dim *dim,
378         enum isl_dim_type type)
379 {
380         if (!dim)
381                 return NULL;
382         if (type == isl_dim_in)
383                 return dim->nested[0];
384         if (type == isl_dim_out)
385                 return dim->nested[1];
386         return NULL;
387 }
388
389 int isl_dim_tuple_match(__isl_keep isl_dim *dim1, enum isl_dim_type dim1_type,
390                         __isl_keep isl_dim *dim2, enum isl_dim_type dim2_type)
391 {
392         struct isl_name *name1, *name2;
393         isl_dim *nested1, *nested2;
394
395         if (n(dim1, dim1_type) != n(dim2, dim2_type))
396                 return 0;
397         name1 = tuple_name(dim1, dim1_type);
398         name2 = tuple_name(dim2, dim2_type);
399         if (!name1 ^ !name2)
400                 return 0;
401         if (name1 && name1->name != name2->name)
402                 return 0;
403         nested1 = nested(dim1, dim1_type);
404         nested2 = nested(dim2, dim2_type);
405         if (!nested1 ^ !nested2)
406                 return 0;
407         if (nested1 && !isl_dim_equal(nested1, nested2))
408                 return 0;
409         return 1;
410 }
411
412 static int match(struct isl_dim *dim1, enum isl_dim_type dim1_type,
413                 struct isl_dim *dim2, enum isl_dim_type dim2_type)
414 {
415         int i;
416
417         if (!isl_dim_tuple_match(dim1, dim1_type, dim2, dim2_type))
418                 return 0;
419
420         if (!dim1->names && !dim2->names)
421                 return 1;
422
423         for (i = 0; i < n(dim1, dim1_type); ++i) {
424                 if (get_name(dim1, dim1_type, i) !=
425                     get_name(dim2, dim2_type, i))
426                         return 0;
427         }
428         return 1;
429 }
430
431 int isl_dim_match(struct isl_dim *dim1, enum isl_dim_type dim1_type,
432                 struct isl_dim *dim2, enum isl_dim_type dim2_type)
433 {
434         return match(dim1, dim1_type, dim2, dim2_type);
435 }
436
437 static void get_names(struct isl_dim *dim, enum isl_dim_type type,
438         unsigned first, unsigned n, struct isl_name **names)
439 {
440         int i;
441
442         for (i = 0; i < n ; ++i)
443                 names[i] = get_name(dim, type, first+i);
444 }
445
446 struct isl_dim *isl_dim_extend(struct isl_dim *dim,
447                         unsigned nparam, unsigned n_in, unsigned n_out)
448 {
449         struct isl_name **names = NULL;
450
451         if (!dim)
452                 return NULL;
453         if (dim->nparam == nparam && dim->n_in == n_in && dim->n_out == n_out)
454                 return dim;
455
456         isl_assert(dim->ctx, dim->nparam <= nparam, goto error);
457         isl_assert(dim->ctx, dim->n_in <= n_in, goto error);
458         isl_assert(dim->ctx, dim->n_out <= n_out, goto error);
459
460         dim = isl_dim_cow(dim);
461
462         if (dim->names) {
463                 names = isl_calloc_array(dim->ctx, struct isl_name *,
464                                          nparam + n_in + n_out);
465                 if (!names)
466                         goto error;
467                 get_names(dim, isl_dim_param, 0, dim->nparam, names);
468                 get_names(dim, isl_dim_in, 0, dim->n_in, names + nparam);
469                 get_names(dim, isl_dim_out, 0, dim->n_out,
470                                 names + nparam + n_in);
471                 free(dim->names);
472                 dim->names = names;
473                 dim->n_name = nparam + n_in + n_out;
474         }
475         dim->nparam = nparam;
476         dim->n_in = n_in;
477         dim->n_out = n_out;
478
479         return dim;
480 error:
481         free(names);
482         isl_dim_free(dim);
483         return NULL;
484 }
485
486 struct isl_dim *isl_dim_add(struct isl_dim *dim, enum isl_dim_type type,
487         unsigned n)
488 {
489         if (!dim)
490                 return NULL;
491         dim = isl_dim_reset(dim, type);
492         switch (type) {
493         case isl_dim_param:
494                 dim = isl_dim_extend(dim,
495                                         dim->nparam + n, dim->n_in, dim->n_out);
496                 if (dim && dim->nested[0] &&
497                     !(dim->nested[0] = isl_dim_add(dim->nested[0],
498                                                     isl_dim_param, n)))
499                         goto error;
500                 if (dim && dim->nested[1] &&
501                     !(dim->nested[1] = isl_dim_add(dim->nested[1],
502                                                     isl_dim_param, n)))
503                         goto error;
504                 return dim;
505         case isl_dim_in:
506                 return isl_dim_extend(dim,
507                                         dim->nparam, dim->n_in + n, dim->n_out);
508         case isl_dim_out:
509                 return isl_dim_extend(dim,
510                                         dim->nparam, dim->n_in, dim->n_out + n);
511         }
512         return dim;
513 error:
514         isl_dim_free(dim);
515         return NULL;
516 }
517
518 __isl_give isl_dim *isl_dim_insert(__isl_take isl_dim *dim,
519         enum isl_dim_type type, unsigned pos, unsigned n)
520 {
521         struct isl_name **names = NULL;
522
523         if (!dim)
524                 return NULL;
525         if (n == 0)
526                 return isl_dim_reset(dim, type);
527
528         isl_assert(dim->ctx, pos <= isl_dim_size(dim, type), goto error);
529
530         dim = isl_dim_cow(dim);
531         if (!dim)
532                 return NULL;
533
534         if (dim->names) {
535                 enum isl_dim_type t;
536                 int off;
537                 int s[3];
538                 int *size = s - isl_dim_param;
539                 names = isl_calloc_array(dim->ctx, struct isl_name *,
540                                      dim->nparam + dim->n_in + dim->n_out + n);
541                 if (!names)
542                         goto error;
543                 off = 0;
544                 size[isl_dim_param] = dim->nparam;
545                 size[isl_dim_in] = dim->n_in;
546                 size[isl_dim_out] = dim->n_out;
547                 for (t = isl_dim_param; t <= isl_dim_out; ++t) {
548                         if (t != type) {
549                                 get_names(dim, t, 0, size[t], names + off);
550                                 off += size[t];
551                         } else {
552                                 get_names(dim, t, 0, pos, names + off);
553                                 off += pos + n;
554                                 get_names(dim, t, pos, size[t]-pos, names+off);
555                                 off += size[t] - pos;
556                         }
557                 }
558                 free(dim->names);
559                 dim->names = names;
560                 dim->n_name = dim->nparam + dim->n_in + dim->n_out + n;
561         }
562         switch (type) {
563         case isl_dim_param:     dim->nparam += n; break;
564         case isl_dim_in:        dim->n_in += n; break;
565         case isl_dim_out:       dim->n_out += n; break;
566         }
567         dim = isl_dim_reset(dim, type);
568
569         return dim;
570 error:
571         isl_dim_free(dim);
572         return NULL;
573 }
574
575 __isl_give isl_dim *isl_dim_move(__isl_take isl_dim *dim,
576         enum isl_dim_type dst_type, unsigned dst_pos,
577         enum isl_dim_type src_type, unsigned src_pos, unsigned n)
578 {
579         if (!dim)
580                 return NULL;
581         if (n == 0)
582                 return dim;
583
584         isl_assert(dim->ctx, src_pos + n <= isl_dim_size(dim, src_type),
585                 goto error);
586
587         if (dst_type == src_type && dst_pos == src_pos)
588                 return dim;
589
590         isl_assert(dim->ctx, dst_type != src_type, goto error);
591
592         dim = isl_dim_reset(dim, src_type);
593         dim = isl_dim_reset(dim, dst_type);
594
595         dim = isl_dim_cow(dim);
596         if (!dim)
597                 return NULL;
598
599         if (dim->names) {
600                 struct isl_name **names;
601                 enum isl_dim_type t;
602                 int off;
603                 int s[3];
604                 int *size = s - isl_dim_param;
605                 names = isl_calloc_array(dim->ctx, struct isl_name *,
606                                          dim->nparam + dim->n_in + dim->n_out);
607                 if (!names)
608                         goto error;
609                 off = 0;
610                 size[isl_dim_param] = dim->nparam;
611                 size[isl_dim_in] = dim->n_in;
612                 size[isl_dim_out] = dim->n_out;
613                 for (t = isl_dim_param; t <= isl_dim_out; ++t) {
614                         if (t == dst_type) {
615                                 get_names(dim, t, 0, dst_pos, names + off);
616                                 off += dst_pos;
617                                 get_names(dim, src_type, src_pos, n, names+off);
618                                 off += n;
619                                 get_names(dim, t, dst_pos, size[t] - dst_pos,
620                                                 names + off);
621                                 off += size[t] - dst_pos;
622                         } else if (t == src_type) {
623                                 get_names(dim, t, 0, src_pos, names + off);
624                                 off += src_pos;
625                                 get_names(dim, t, src_pos + n,
626                                             size[t] - src_pos - n, names + off);
627                                 off += size[t] - src_pos - n;
628                         } else {
629                                 get_names(dim, t, 0, size[t], names + off);
630                                 off += size[t];
631                         }
632                 }
633                 free(dim->names);
634                 dim->names = names;
635                 dim->n_name = dim->nparam + dim->n_in + dim->n_out;
636         }
637
638         switch (dst_type) {
639         case isl_dim_param:     dim->nparam += n; break;
640         case isl_dim_in:        dim->n_in += n; break;
641         case isl_dim_out:       dim->n_out += n; break;
642         }
643
644         switch (src_type) {
645         case isl_dim_param:     dim->nparam -= n; break;
646         case isl_dim_in:        dim->n_in -= n; break;
647         case isl_dim_out:       dim->n_out -= n; break;
648         }
649
650         return dim;
651 error:
652         isl_dim_free(dim);
653         return NULL;
654 }
655
656 struct isl_dim *isl_dim_join(struct isl_dim *left, struct isl_dim *right)
657 {
658         struct isl_dim *dim;
659
660         if (!left || !right)
661                 goto error;
662
663         isl_assert(left->ctx, match(left, isl_dim_param, right, isl_dim_param),
664                         goto error);
665         isl_assert(left->ctx,
666                 isl_dim_tuple_match(left, isl_dim_out, right, isl_dim_in),
667                 goto error);
668
669         dim = isl_dim_alloc(left->ctx, left->nparam, left->n_in, right->n_out);
670         if (!dim)
671                 goto error;
672
673         dim = copy_names(dim, isl_dim_param, 0, left, isl_dim_param);
674         dim = copy_names(dim, isl_dim_in, 0, left, isl_dim_in);
675         dim = copy_names(dim, isl_dim_out, 0, right, isl_dim_out);
676
677         if (dim && left->tuple_name[0] &&
678             !(dim->tuple_name[0] = isl_name_copy(dim->ctx, left->tuple_name[0])))
679                 goto error;
680         if (dim && right->tuple_name[1] &&
681             !(dim->tuple_name[1] = isl_name_copy(dim->ctx, right->tuple_name[1])))
682                 goto error;
683         if (dim && left->nested[0] &&
684             !(dim->nested[0] = isl_dim_copy(left->nested[0])))
685                 goto error;
686         if (dim && right->nested[1] &&
687             !(dim->nested[1] = isl_dim_copy(right->nested[1])))
688                 goto error;
689
690         isl_dim_free(left);
691         isl_dim_free(right);
692
693         return dim;
694 error:
695         isl_dim_free(left);
696         isl_dim_free(right);
697         return NULL;
698 }
699
700 struct isl_dim *isl_dim_product(struct isl_dim *left, struct isl_dim *right)
701 {
702         isl_dim *dom1, *dom2, *nest1, *nest2;
703
704         if (!left || !right)
705                 goto error;
706
707         isl_assert(left->ctx, match(left, isl_dim_param, right, isl_dim_param),
708                         goto error);
709
710         dom1 = isl_dim_domain(isl_dim_copy(left));
711         dom2 = isl_dim_domain(isl_dim_copy(right));
712         nest1 = isl_dim_wrap(isl_dim_join(isl_dim_reverse(dom1), dom2));
713
714         dom1 = isl_dim_range(left);
715         dom2 = isl_dim_range(right);
716         nest2 = isl_dim_wrap(isl_dim_join(isl_dim_reverse(dom1), dom2));
717
718         return isl_dim_join(isl_dim_reverse(nest1), nest2);
719 error:
720         isl_dim_free(left);
721         isl_dim_free(right);
722         return NULL;
723 }
724
725 struct isl_dim *isl_dim_map(struct isl_dim *dim)
726 {
727         struct isl_name **names = NULL;
728
729         if (!dim)
730                 return NULL;
731         isl_assert(dim->ctx, dim->n_in == 0, goto error);
732         if (dim->n_out == 0 && !isl_dim_is_named_or_nested(dim, isl_dim_out))
733                 return dim;
734         dim = isl_dim_cow(dim);
735         if (!dim)
736                 return NULL;
737         if (dim->names) {
738                 names = isl_calloc_array(dim->ctx, struct isl_name *,
739                                         dim->nparam + dim->n_out + dim->n_out);
740                 if (!names)
741                         goto error;
742                 get_names(dim, isl_dim_param, 0, dim->nparam, names);
743                 get_names(dim, isl_dim_out, 0, dim->n_out, names + dim->nparam);
744         }
745         dim->n_in = dim->n_out;
746         if (names) {
747                 free(dim->names);
748                 dim->names = names;
749                 dim->n_name = dim->nparam + dim->n_out + dim->n_out;
750                 dim = copy_names(dim, isl_dim_out, 0, dim, isl_dim_in);
751         }
752         isl_name_free(dim->ctx, dim->tuple_name[0]);
753         dim->tuple_name[0] = isl_name_copy(dim->ctx, dim->tuple_name[1]);
754         isl_dim_free(dim->nested[0]);
755         dim->nested[0] = isl_dim_copy(dim->nested[1]);
756         return dim;
757 error:
758         isl_dim_free(dim);
759         return NULL;
760 }
761
762 static struct isl_dim *set_names(struct isl_dim *dim, enum isl_dim_type type,
763         unsigned first, unsigned n, struct isl_name **names)
764 {
765         int i;
766
767         for (i = 0; i < n ; ++i)
768                 dim = set_name(dim, type, first+i, names[i]);
769
770         return dim;
771 }
772
773 struct isl_dim *isl_dim_reverse(struct isl_dim *dim)
774 {
775         unsigned t;
776         isl_dim *nested;
777         struct isl_name **names = NULL;
778         struct isl_name *name;
779
780         if (!dim)
781                 return NULL;
782         if (match(dim, isl_dim_in, dim, isl_dim_out))
783                 return dim;
784
785         dim = isl_dim_cow(dim);
786         if (!dim)
787                 return NULL;
788
789         name = dim->tuple_name[0];
790         dim->tuple_name[0] = dim->tuple_name[1];
791         dim->tuple_name[1] = name;
792
793         nested = dim->nested[0];
794         dim->nested[0] = dim->nested[1];
795         dim->nested[1] = nested;
796
797         if (dim->names) {
798                 names = isl_alloc_array(dim->ctx, struct isl_name *,
799                                         dim->n_in + dim->n_out);
800                 if (!names)
801                         goto error;
802                 get_names(dim, isl_dim_in, 0, dim->n_in, names);
803                 get_names(dim, isl_dim_out, 0, dim->n_out, names + dim->n_in);
804         }
805
806         t = dim->n_in;
807         dim->n_in = dim->n_out;
808         dim->n_out = t;
809
810         if (dim->names) {
811                 dim = set_names(dim, isl_dim_out, 0, dim->n_out, names);
812                 dim = set_names(dim, isl_dim_in, 0, dim->n_in, names + dim->n_out);
813                 free(names);
814         }
815
816         return dim;
817 error:
818         free(names);
819         isl_dim_free(dim);
820         return NULL;
821 }
822
823 struct isl_dim *isl_dim_drop(struct isl_dim *dim, enum isl_dim_type type,
824                 unsigned first, unsigned num)
825 {
826         int i;
827
828         if (!dim)
829                 return NULL;
830
831         if (n == 0)
832                 return isl_dim_reset(dim, type);
833
834         isl_assert(dim->ctx, first + num <= n(dim, type), goto error);
835         dim = isl_dim_cow(dim);
836         if (!dim)
837                 goto error;
838         if (dim->names) {
839                 dim = extend_names(dim);
840                 if (!dim)
841                         goto error;
842                 for (i = 0; i < num; ++i)
843                         isl_name_free(dim->ctx, get_name(dim, type, first+i));
844                 for (i = first+num; i < n(dim, type); ++i)
845                         set_name(dim, type, i - num, get_name(dim, type, i));
846                 switch (type) {
847                 case isl_dim_param:
848                         get_names(dim, isl_dim_in, 0, dim->n_in,
849                                 dim->names + offset(dim, isl_dim_in) - num);
850                 case isl_dim_in:
851                         get_names(dim, isl_dim_out, 0, dim->n_out,
852                                 dim->names + offset(dim, isl_dim_out) - num);
853                 case isl_dim_out:
854                         ;
855                 }
856                 dim->n_name -= num;
857         }
858         switch (type) {
859         case isl_dim_param:     dim->nparam -= num; break;
860         case isl_dim_in:        dim->n_in -= num; break;
861         case isl_dim_out:       dim->n_out -= num; break;
862         }
863         dim = isl_dim_reset(dim, type);
864         if (type == isl_dim_param) {
865                 if (dim && dim->nested[0] &&
866                     !(dim->nested[0] = isl_dim_drop(dim->nested[0],
867                                                     isl_dim_param, first, num)))
868                         goto error;
869                 if (dim && dim->nested[1] &&
870                     !(dim->nested[1] = isl_dim_drop(dim->nested[1],
871                                                     isl_dim_param, first, num)))
872                         goto error;
873         }
874         return dim;
875 error:
876         isl_dim_free(dim);
877         return NULL;
878 }
879
880 struct isl_dim *isl_dim_drop_inputs(struct isl_dim *dim,
881                 unsigned first, unsigned n)
882 {
883         if (!dim)
884                 return NULL;
885         return isl_dim_drop(dim, isl_dim_in, first, n);
886 }
887
888 struct isl_dim *isl_dim_drop_outputs(struct isl_dim *dim,
889                 unsigned first, unsigned n)
890 {
891         if (!dim)
892                 return NULL;
893         return isl_dim_drop(dim, isl_dim_out, first, n);
894 }
895
896 struct isl_dim *isl_dim_domain(struct isl_dim *dim)
897 {
898         if (!dim)
899                 return NULL;
900         dim = isl_dim_drop_outputs(dim, 0, dim->n_out);
901         return isl_dim_reverse(dim);
902 }
903
904 __isl_give isl_dim *isl_dim_from_domain(__isl_take isl_dim *dim)
905 {
906         return isl_dim_reverse(dim);
907 }
908
909 struct isl_dim *isl_dim_range(struct isl_dim *dim)
910 {
911         if (!dim)
912                 return NULL;
913         return isl_dim_drop_inputs(dim, 0, dim->n_in);
914 }
915
916 __isl_give isl_dim *isl_dim_from_range(__isl_take isl_dim *dim)
917 {
918         return dim;
919 }
920
921 __isl_give isl_dim *isl_dim_as_set_dim(__isl_take isl_dim *dim)
922 {
923         dim = isl_dim_cow(dim);
924         if (!dim)
925                 return NULL;
926
927         dim->n_out += dim->n_in;
928         dim->n_in = 0;
929         dim = isl_dim_reset(dim, isl_dim_in);
930         dim = isl_dim_reset(dim, isl_dim_out);
931
932         return dim;
933 }
934
935 struct isl_dim *isl_dim_underlying(struct isl_dim *dim, unsigned n_div)
936 {
937         int i;
938
939         if (!dim)
940                 return NULL;
941         if (n_div == 0 &&
942             dim->nparam == 0 && dim->n_in == 0 && dim->n_name == 0)
943                 return isl_dim_reset(isl_dim_reset(dim, isl_dim_in), isl_dim_out);
944         dim = isl_dim_cow(dim);
945         if (!dim)
946                 return NULL;
947         dim->n_out += dim->nparam + dim->n_in + n_div;
948         dim->nparam = 0;
949         dim->n_in = 0;
950
951         for (i = 0; i < dim->n_name; ++i)
952                 isl_name_free(dim->ctx, get_name(dim, isl_dim_out, i));
953         dim->n_name = 0;
954         dim = isl_dim_reset(dim, isl_dim_in);
955         dim = isl_dim_reset(dim, isl_dim_out);
956
957         return dim;
958 }
959
960 unsigned isl_dim_total(struct isl_dim *dim)
961 {
962         return dim ? dim->nparam + dim->n_in + dim->n_out : 0;
963 }
964
965 int isl_dim_equal(struct isl_dim *dim1, struct isl_dim *dim2)
966 {
967         return match(dim1, isl_dim_param, dim2, isl_dim_param) &&
968                isl_dim_tuple_match(dim1, isl_dim_in, dim2, isl_dim_in) &&
969                isl_dim_tuple_match(dim1, isl_dim_out, dim2, isl_dim_out);
970 }
971
972 int isl_dim_compatible(struct isl_dim *dim1, struct isl_dim *dim2)
973 {
974         return dim1->nparam == dim2->nparam &&
975                dim1->n_in + dim1->n_out == dim2->n_in + dim2->n_out;
976 }
977
978 static uint32_t isl_hash_dim(uint32_t hash, __isl_keep isl_dim *dim)
979 {
980         int i;
981         struct isl_name *name;
982
983         if (!dim)
984                 return hash;
985
986         hash = isl_hash_builtin(hash, dim->nparam);
987         hash = isl_hash_builtin(hash, dim->n_in);
988         hash = isl_hash_builtin(hash, dim->n_out);
989
990         for (i = 0; i < dim->nparam; ++i) {
991                 name = get_name(dim, isl_dim_param, i);
992                 hash = isl_hash_name(hash, name);
993         }
994
995         name = tuple_name(dim, isl_dim_in);
996         hash = isl_hash_name(hash, name);
997         name = tuple_name(dim, isl_dim_out);
998         hash = isl_hash_name(hash, name);
999
1000         hash = isl_hash_dim(hash, dim->nested[0]);
1001         hash = isl_hash_dim(hash, dim->nested[1]);
1002
1003         return hash;
1004 }
1005
1006 uint32_t isl_dim_get_hash(__isl_keep isl_dim *dim)
1007 {
1008         uint32_t hash;
1009
1010         if (!dim)
1011                 return 0;
1012
1013         hash = isl_hash_init();
1014         hash = isl_hash_dim(hash, dim);
1015
1016         return hash;
1017 }
1018
1019 int isl_dim_is_wrapping(__isl_keep isl_dim *dim)
1020 {
1021         if (!dim)
1022                 return -1;
1023
1024         if (dim->n_in != 0 || dim->tuple_name[0] || dim->nested[0])
1025                 return 0;
1026
1027         return dim->nested[1] != NULL;
1028 }
1029
1030 __isl_give isl_dim *isl_dim_wrap(__isl_take isl_dim *dim)
1031 {
1032         isl_dim *wrap;
1033
1034         if (!dim)
1035                 return NULL;
1036
1037         wrap = isl_dim_alloc(dim->ctx, dim->nparam, 0, dim->n_in + dim->n_out);
1038
1039         wrap = copy_names(wrap, isl_dim_param, 0, dim, isl_dim_param);
1040         wrap = copy_names(wrap, isl_dim_set, 0, dim, isl_dim_in);
1041         wrap = copy_names(wrap, isl_dim_set, dim->n_in, dim, isl_dim_out);
1042
1043         if (!wrap)
1044                 goto error;
1045
1046         wrap->nested[1] = dim;
1047
1048         return wrap;
1049 error:
1050         isl_dim_free(dim);
1051         return NULL;
1052 }
1053
1054 __isl_give isl_dim *isl_dim_unwrap(__isl_take isl_dim *dim)
1055 {
1056         isl_dim *unwrap;
1057
1058         if (!dim)
1059                 return NULL;
1060
1061         if (!isl_dim_is_wrapping(dim))
1062                 isl_die(dim->ctx, isl_error_invalid, "not a wrapping dim",
1063                         goto error);
1064
1065         unwrap = isl_dim_copy(dim->nested[1]);
1066         isl_dim_free(dim);
1067
1068         return unwrap;
1069 error:
1070         isl_dim_free(dim);
1071         return NULL;
1072 }
1073
1074 int isl_dim_is_named_or_nested(__isl_keep isl_dim *dim, enum isl_dim_type type)
1075 {
1076         if (type != isl_dim_in && type != isl_dim_out)
1077                 return 0;
1078         if (!dim)
1079                 return -1;
1080         if (dim->tuple_name[type - isl_dim_in])
1081                 return 1;
1082         if (dim->nested[type - isl_dim_in])
1083                 return 1;
1084         return 0;
1085 }
1086
1087 __isl_give isl_dim *isl_dim_reset(__isl_take isl_dim *dim,
1088         enum isl_dim_type type)
1089 {
1090         if (!isl_dim_is_named_or_nested(dim, type))
1091                 return dim;
1092
1093         dim = isl_dim_cow(dim);
1094         if (!dim)
1095                 return NULL;
1096
1097         isl_name_free(dim->ctx, dim->tuple_name[type - isl_dim_in]);
1098         dim->tuple_name[type - isl_dim_in] = NULL;
1099         isl_dim_free(dim->nested[type - isl_dim_in]);
1100         dim->nested[type - isl_dim_in] = NULL;
1101
1102         return dim;
1103 }
1104
1105 __isl_give isl_dim *isl_dim_flatten(__isl_take isl_dim *dim)
1106 {
1107         if (!dim)
1108                 return NULL;
1109         if (!dim->nested[0] && !dim->nested[1])
1110                 return dim;
1111
1112         if (dim->nested[0])
1113                 dim = isl_dim_reset(dim, isl_dim_in);
1114         if (dim && dim->nested[1])
1115                 dim = isl_dim_reset(dim, isl_dim_out);
1116
1117         return dim;
1118 }
1119
1120 /* Replace the dimensions of the given type of dst by those of src.
1121  */
1122 __isl_give isl_dim *isl_dim_replace(__isl_take isl_dim *dst,
1123         enum isl_dim_type type, __isl_keep isl_dim *src)
1124 {
1125         dst = isl_dim_cow(dst);
1126
1127         if (!dst || !src)
1128                 goto error;
1129
1130         dst = isl_dim_drop(dst, type, 0, isl_dim_size(dst, type));
1131         dst = isl_dim_add(dst, type, isl_dim_size(src, type));
1132         dst = copy_names(dst, type, 0, src, type);
1133
1134         if (dst && type == isl_dim_param) {
1135                 int i;
1136                 for (i = 0; i <= 1; ++i) {
1137                         if (!dst->nested[i])
1138                                 continue;
1139                         dst->nested[i] = isl_dim_replace(dst->nested[i],
1140                                                          type, src);
1141                         if (!dst->nested[i])
1142                                 goto error;
1143                 }
1144         }
1145
1146         return dst;
1147 error:
1148         isl_dim_free(dst);
1149         return NULL;
1150 }