Coverage Report

Created: 2017-03-24 03:18

/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/tools/polly/lib/External/isl/isl_space.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright 2008-2009 Katholieke Universiteit Leuven
3
 * Copyright 2010      INRIA Saclay
4
 * Copyright 2013-2014 Ecole Normale Superieure
5
 *
6
 * Use of this software is governed by the MIT license
7
 *
8
 * Written by Sven Verdoolaege, K.U.Leuven, Departement
9
 * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
10
 * and INRIA Saclay - Ile-de-France, Parc Club Orsay Universite,
11
 * ZAC des vignes, 4 rue Jacques Monod, 91893 Orsay, France 
12
 * and Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France
13
 */
14
15
#include <stdlib.h>
16
#include <string.h>
17
#include <isl_space_private.h>
18
#include <isl_id_private.h>
19
#include <isl_reordering.h>
20
21
isl_ctx *isl_space_get_ctx(__isl_keep isl_space *dim)
22
862k
{
23
862k
  return dim ? dim->ctx : NULL;
24
862k
}
25
26
__isl_give isl_space *isl_space_alloc(isl_ctx *ctx,
27
      unsigned nparam, unsigned n_in, unsigned n_out)
28
2.83M
{
29
2.83M
  isl_space *dim;
30
2.83M
31
2.83M
  dim = isl_alloc_type(ctx, struct isl_space);
32
2.83M
  if (!dim)
33
1
    return NULL;
34
2.83M
35
2.83M
  dim->ctx = ctx;
36
2.83M
  isl_ctx_ref(ctx);
37
2.83M
  dim->ref = 1;
38
2.83M
  dim->nparam = nparam;
39
2.83M
  dim->n_in = n_in;
40
2.83M
  dim->n_out = n_out;
41
2.83M
42
2.83M
  dim->tuple_id[0] = NULL;
43
2.83M
  dim->tuple_id[1] = NULL;
44
2.83M
45
2.83M
  dim->nested[0] = NULL;
46
2.83M
  dim->nested[1] = NULL;
47
2.83M
48
2.83M
  dim->n_id = 0;
49
2.83M
  dim->ids = NULL;
50
2.83M
51
2.83M
  return dim;
52
2.83M
}
53
54
/* Mark the space as being that of a set, by setting the domain tuple
55
 * to isl_id_none.
56
 */
57
static __isl_give isl_space *mark_as_set(__isl_take isl_space *space)
58
829k
{
59
829k
  space = isl_space_cow(space);
60
829k
  if (!space)
61
0
    return NULL;
62
829k
  space = isl_space_set_tuple_id(space, isl_dim_in, &isl_id_none);
63
829k
  return space;
64
829k
}
65
66
/* Is the space that of a set?
67
 */
68
isl_bool isl_space_is_set(__isl_keep isl_space *space)
69
847k
{
70
847k
  if (!space)
71
0
    return isl_bool_error;
72
847k
  
if (847k
space->n_in != 0 || 847k
space->nested[0]723k
)
73
125k
    return isl_bool_false;
74
721k
  
if (721k
space->tuple_id[0] != &isl_id_none721k
)
75
11.8k
    return isl_bool_false;
76
709k
  return isl_bool_true;
77
721k
}
78
79
/* Is the given space that of a map?
80
 */
81
isl_bool isl_space_is_map(__isl_keep isl_space *space)
82
10.5k
{
83
10.5k
  if (!space)
84
0
    return isl_bool_error;
85
10.5k
  return space->tuple_id[0] != &isl_id_none &&
86
369
    space->tuple_id[1] != &isl_id_none;
87
10.5k
}
88
89
__isl_give isl_space *isl_space_set_alloc(isl_ctx *ctx,
90
      unsigned nparam, unsigned dim)
91
302k
{
92
302k
  isl_space *space;
93
302k
  space = isl_space_alloc(ctx, nparam, 0, dim);
94
302k
  space = mark_as_set(space);
95
302k
  return space;
96
302k
}
97
98
/* Mark the space as being that of a parameter domain, by setting
99
 * both tuples to isl_id_none.
100
 */
101
static __isl_give isl_space *mark_as_params(isl_space *space)
102
80.1k
{
103
80.1k
  if (!space)
104
0
    return NULL;
105
80.1k
  space = isl_space_set_tuple_id(space, isl_dim_in, &isl_id_none);
106
80.1k
  space = isl_space_set_tuple_id(space, isl_dim_out, &isl_id_none);
107
80.1k
  return space;
108
80.1k
}
109
110
/* Is the space that of a parameter domain?
111
 */
112
isl_bool isl_space_is_params(__isl_keep isl_space *space)
113
340k
{
114
340k
  if (!space)
115
11
    return isl_bool_error;
116
340k
  
if (340k
space->n_in != 0 || 340k
space->nested[0]284k
||
117
284k
      
space->n_out != 0284k
||
space->nested[1]216k
)
118
124k
    return isl_bool_false;
119
216k
  
if (216k
space->tuple_id[0] != &isl_id_none216k
)
120
14.8k
    return isl_bool_false;
121
201k
  
if (201k
space->tuple_id[1] != &isl_id_none201k
)
122
18.8k
    return isl_bool_false;
123
183k
  return isl_bool_true;
124
201k
}
125
126
/* Create a space for a parameter domain.
127
 */
128
__isl_give isl_space *isl_space_params_alloc(isl_ctx *ctx, unsigned nparam)
129
19.3k
{
130
19.3k
  isl_space *space;
131
19.3k
  space = isl_space_alloc(ctx, nparam, 0, 0);
132
19.3k
  space = mark_as_params(space);
133
19.3k
  return space;
134
19.3k
}
135
136
static unsigned global_pos(__isl_keep isl_space *dim,
137
         enum isl_dim_type type, unsigned pos)
138
40.3M
{
139
40.3M
  struct isl_ctx *ctx = dim->ctx;
140
40.3M
141
40.3M
  switch (type) {
142
27.6M
  case isl_dim_param:
143
27.6M
    isl_assert(ctx, pos < dim->nparam,
144
27.6M
          return isl_space_dim(dim, isl_dim_all));
145
27.6M
    return pos;
146
4.66M
  case isl_dim_in:
147
4.66M
    isl_assert(ctx, pos < dim->n_in,
148
4.66M
          return isl_space_dim(dim, isl_dim_all));
149
4.66M
    return pos + dim->nparam;
150
8.04M
  case isl_dim_out:
151
8.04M
    isl_assert(ctx, pos < dim->n_out,
152
8.04M
          return isl_space_dim(dim, isl_dim_all));
153
8.04M
    return pos + dim->nparam + dim->n_in;
154
0
  default:
155
0
    isl_assert(ctx, 0, return isl_space_dim(dim, isl_dim_all));
156
40.3M
  }
157
0
  return isl_space_dim(dim, isl_dim_all);
158
40.3M
}
159
160
/* Extend length of ids array to the total number of dimensions.
161
 */
162
static __isl_give isl_space *extend_ids(__isl_take isl_space *dim)
163
1.82M
{
164
1.82M
  isl_id **ids;
165
1.82M
  int i;
166
1.82M
167
1.82M
  if (isl_space_dim(dim, isl_dim_all) <= dim->n_id)
168
499k
    return dim;
169
1.82M
170
1.32M
  
if (1.32M
!dim->ids1.32M
)
{1.32M
171
1.32M
    dim->ids = isl_calloc_array(dim->ctx,
172
1.32M
        isl_id *, isl_space_dim(dim, isl_dim_all));
173
1.32M
    if (!dim->ids)
174
0
      goto error;
175
373
  } else {
176
373
    ids = isl_realloc_array(dim->ctx, dim->ids,
177
373
        isl_id *, isl_space_dim(dim, isl_dim_all));
178
373
    if (!ids)
179
0
      goto error;
180
373
    dim->ids = ids;
181
1.95k
    for (i = dim->n_id; 
i < isl_space_dim(dim, isl_dim_all)1.95k
;
++i1.57k
)
182
1.57k
      dim->ids[i] = NULL;
183
373
  }
184
1.32M
185
1.32M
  dim->n_id = isl_space_dim(dim, isl_dim_all);
186
1.32M
187
1.32M
  return dim;
188
0
error:
189
0
  isl_space_free(dim);
190
0
  return NULL;
191
1.32M
}
192
193
static __isl_give isl_space *set_id(__isl_take isl_space *dim,
194
  enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)
195
5.91M
{
196
5.91M
  dim = isl_space_cow(dim);
197
5.91M
198
5.91M
  if (!dim)
199
0
    goto error;
200
5.91M
201
5.91M
  pos = global_pos(dim, type, pos);
202
5.91M
  if (pos == isl_space_dim(dim, isl_dim_all))
203
0
    goto error;
204
5.91M
205
5.91M
  
if (5.91M
pos >= dim->n_id5.91M
)
{1.32M
206
1.32M
    if (!id)
207
0
      return dim;
208
1.32M
    dim = extend_ids(dim);
209
1.32M
    if (!dim)
210
0
      goto error;
211
1.32M
  }
212
5.91M
213
5.91M
  dim->ids[pos] = id;
214
5.91M
215
5.91M
  return dim;
216
0
error:
217
0
  isl_id_free(id);
218
0
  isl_space_free(dim);
219
0
  return NULL;
220
5.91M
}
221
222
static __isl_keep isl_id *get_id(__isl_keep isl_space *dim,
223
         enum isl_dim_type type, unsigned pos)
224
34.4M
{
225
34.4M
  if (!dim)
226
0
    return NULL;
227
34.4M
228
34.4M
  pos = global_pos(dim, type, pos);
229
34.4M
  if (pos == isl_space_dim(dim, isl_dim_all))
230
0
    return NULL;
231
34.4M
  
if (34.4M
pos >= dim->n_id34.4M
)
232
1.37M
    return NULL;
233
33.0M
  return dim->ids[pos];
234
34.4M
}
235
236
static unsigned offset(__isl_keep isl_space *dim, enum isl_dim_type type)
237
1.20M
{
238
1.20M
  switch (type) {
239
382k
  case isl_dim_param: return 0;
240
271k
  case isl_dim_in:  return dim->nparam;
241
554k
  case isl_dim_out: return dim->nparam + dim->n_in;
242
0
  default:    return 0;
243
1.20M
  }
244
1.20M
}
245
246
static unsigned n(__isl_keep isl_space *dim, enum isl_dim_type type)
247
173M
{
248
173M
  switch (type) {
249
34.8M
  case isl_dim_param: return dim->nparam;
250
19.4M
  case isl_dim_in:  return dim->n_in;
251
22.8M
  case isl_dim_out: return dim->n_out;
252
96.3M
  case isl_dim_all: return dim->nparam + dim->n_in + dim->n_out;
253
0
  default:    return 0;
254
173M
  }
255
173M
}
256
257
unsigned isl_space_dim(__isl_keep isl_space *dim, enum isl_dim_type type)
258
123M
{
259
123M
  if (!dim)
260
0
    return 0;
261
123M
  return n(dim, type);
262
123M
}
263
264
unsigned isl_space_offset(__isl_keep isl_space *dim, enum isl_dim_type type)
265
960k
{
266
960k
  if (!dim)
267
0
    return 0;
268
960k
  return offset(dim, type);
269
960k
}
270
271
static __isl_give isl_space *copy_ids(__isl_take isl_space *dst,
272
  enum isl_dim_type dst_type, unsigned offset, __isl_keep isl_space *src,
273
  enum isl_dim_type src_type)
274
4.93M
{
275
4.93M
  int i;
276
4.93M
  isl_id *id;
277
4.93M
278
4.93M
  if (!dst)
279
0
    return NULL;
280
4.93M
281
13.0M
  
for (i = 0; 4.93M
i < n(src, src_type)13.0M
;
++i8.08M
)
{8.08M
282
8.08M
    id = get_id(src, src_type, i);
283
8.08M
    if (!id)
284
3.68M
      continue;
285
4.39M
    dst = set_id(dst, dst_type, offset + i, isl_id_copy(id));
286
4.39M
    if (!dst)
287
0
      return NULL;
288
4.39M
  }
289
4.93M
  return dst;
290
4.93M
}
291
292
__isl_take isl_space *isl_space_dup(__isl_keep isl_space *dim)
293
2.15M
{
294
2.15M
  isl_space *dup;
295
2.15M
  if (!dim)
296
0
    return NULL;
297
2.15M
  dup = isl_space_alloc(dim->ctx, dim->nparam, dim->n_in, dim->n_out);
298
2.15M
  if (!dup)
299
1
    return NULL;
300
2.15M
  
if (2.15M
dim->tuple_id[0] &&2.15M
301
1.33M
      !(dup->tuple_id[0] = isl_id_copy(dim->tuple_id[0])))
302
0
    goto error;
303
2.15M
  
if (2.15M
dim->tuple_id[1] &&2.15M
304
478k
      !(dup->tuple_id[1] = isl_id_copy(dim->tuple_id[1])))
305
0
    goto error;
306
2.15M
  
if (2.15M
dim->nested[0] && 2.15M
!(dup->nested[0] = isl_space_copy(dim->nested[0]))278k
)
307
0
    goto error;
308
2.15M
  
if (2.15M
dim->nested[1] && 2.15M
!(dup->nested[1] = isl_space_copy(dim->nested[1]))438k
)
309
0
    goto error;
310
2.15M
  
if (2.15M
!dim->ids2.15M
)
311
907k
    return dup;
312
1.25M
  dup = copy_ids(dup, isl_dim_param, 0, dim, isl_dim_param);
313
1.25M
  dup = copy_ids(dup, isl_dim_in, 0, dim, isl_dim_in);
314
1.25M
  dup = copy_ids(dup, isl_dim_out, 0, dim, isl_dim_out);
315
1.25M
  return dup;
316
0
error:
317
0
  isl_space_free(dup);
318
0
  return NULL;
319
2.15M
}
320
321
__isl_give isl_space *isl_space_cow(__isl_take isl_space *dim)
322
12.3M
{
323
12.3M
  if (!dim)
324
1
    return NULL;
325
12.3M
326
12.3M
  
if (12.3M
dim->ref == 112.3M
)
327
10.2M
    return dim;
328
2.13M
  dim->ref--;
329
2.13M
  return isl_space_dup(dim);
330
12.3M
}
331
332
__isl_give isl_space *isl_space_copy(__isl_keep isl_space *dim)
333
8.94M
{
334
8.94M
  if (!dim)
335
6.48k
    return NULL;
336
8.94M
337
8.93M
  dim->ref++;
338
8.93M
  return dim;
339
8.94M
}
340
341
__isl_null isl_space *isl_space_free(__isl_take isl_space *space)
342
16.2M
{
343
16.2M
  int i;
344
16.2M
345
16.2M
  if (!space)
346
6.57M
    return NULL;
347
16.2M
348
9.63M
  
if (9.63M
--space->ref > 09.63M
)
349
6.79M
    return NULL;
350
9.63M
351
2.83M
  isl_id_free(space->tuple_id[0]);
352
2.83M
  isl_id_free(space->tuple_id[1]);
353
2.83M
354
2.83M
  isl_space_free(space->nested[0]);
355
2.83M
  isl_space_free(space->nested[1]);
356
2.83M
357
7.70M
  for (i = 0; 
i < space->n_id7.70M
;
++i4.86M
)
358
4.86M
    isl_id_free(space->ids[i]);
359
2.83M
  free(space->ids);
360
2.83M
  isl_ctx_deref(space->ctx);
361
2.83M
  
362
2.83M
  free(space);
363
2.83M
364
2.83M
  return NULL;
365
9.63M
}
366
367
/* Check if "s" is a valid dimension or tuple name.
368
 * We currently only forbid names that look like a number.
369
 *
370
 * s is assumed to be non-NULL.
371
 */
372
static int name_ok(isl_ctx *ctx, const char *s)
373
46.5k
{
374
46.5k
  char *p;
375
46.5k
  long dummy;
376
46.5k
377
46.5k
  dummy = strtol(s, &p, 0);
378
46.5k
  if (p != s)
379
0
    isl_die(ctx, isl_error_invalid, "name looks like a number",
380
46.5k
      return 0);
381
46.5k
382
46.5k
  return 1;
383
46.5k
}
384
385
/* Is it possible for the given dimension type to have a tuple id?
386
 */
387
static int space_can_have_id(__isl_keep isl_space *space,
388
  enum isl_dim_type type)
389
57.4k
{
390
57.4k
  if (!space)
391
0
    return 0;
392
57.4k
  
if (57.4k
isl_space_is_params(space)57.4k
)
393
0
    isl_die(space->ctx, isl_error_invalid,
394
57.4k
      "parameter spaces don't have tuple ids", return 0);
395
57.4k
  
if (57.4k
isl_space_is_set(space) && 57.4k
type != isl_dim_set14.0k
)
396
0
    isl_die(space->ctx, isl_error_invalid,
397
57.4k
      "set spaces can only have a set id", return 0);
398
57.4k
  
if (57.4k
type != isl_dim_in && 57.4k
type != isl_dim_out57.1k
)
399
0
    isl_die(space->ctx, isl_error_invalid,
400
57.4k
      "only input, output and set tuples can have ids",
401
57.4k
      return 0);
402
57.4k
403
57.4k
  return 1;
404
57.4k
}
405
406
/* Does the tuple have an id?
407
 */
408
isl_bool isl_space_has_tuple_id(__isl_keep isl_space *dim,
409
  enum isl_dim_type type)
410
56.8k
{
411
56.8k
  if (!space_can_have_id(dim, type))
412
0
    return isl_bool_error;
413
56.8k
  return dim->tuple_id[type - isl_dim_in] != NULL;
414
56.8k
}
415
416
__isl_give isl_id *isl_space_get_tuple_id(__isl_keep isl_space *dim,
417
  enum isl_dim_type type)
418
21.5k
{
419
21.5k
  int has_id;
420
21.5k
421
21.5k
  if (!dim)
422
0
    return NULL;
423
21.5k
  has_id = isl_space_has_tuple_id(dim, type);
424
21.5k
  if (has_id < 0)
425
0
    return NULL;
426
21.5k
  
if (21.5k
!has_id21.5k
)
427
0
    isl_die(dim->ctx, isl_error_invalid,
428
21.5k
      "tuple has no id", return NULL);
429
21.5k
  return isl_id_copy(dim->tuple_id[type - isl_dim_in]);
430
21.5k
}
431
432
__isl_give isl_space *isl_space_set_tuple_id(__isl_take isl_space *dim,
433
  enum isl_dim_type type, __isl_take isl_id *id)
434
1.04M
{
435
1.04M
  dim = isl_space_cow(dim);
436
1.04M
  if (
!dim || 1.04M
!id1.04M
)
437
0
    goto error;
438
1.04M
  
if (1.04M
type != isl_dim_in && 1.04M
type != isl_dim_out131k
)
439
0
    isl_die(dim->ctx, isl_error_invalid,
440
1.04M
      "only input, output and set tuples can have names",
441
1.04M
      goto error);
442
1.04M
443
1.04M
  isl_id_free(dim->tuple_id[type - isl_dim_in]);
444
1.04M
  dim->tuple_id[type - isl_dim_in] = id;
445
1.04M
446
1.04M
  return dim;
447
0
error:
448
0
  isl_id_free(id);
449
0
  isl_space_free(dim);
450
0
  return NULL;
451
1.04M
}
452
453
__isl_give isl_space *isl_space_reset_tuple_id(__isl_take isl_space *dim,
454
  enum isl_dim_type type)
455
4.70k
{
456
4.70k
  dim = isl_space_cow(dim);
457
4.70k
  if (!dim)
458
0
    return NULL;
459
4.70k
  
if (4.70k
type != isl_dim_in && 4.70k
type != isl_dim_out4.70k
)
460
0
    isl_die(dim->ctx, isl_error_invalid,
461
4.70k
      "only input, output and set tuples can have names",
462
4.70k
      goto error);
463
4.70k
464
4.70k
  isl_id_free(dim->tuple_id[type - isl_dim_in]);
465
4.70k
  dim->tuple_id[type - isl_dim_in] = NULL;
466
4.70k
467
4.70k
  return dim;
468
0
error:
469
0
  isl_space_free(dim);
470
0
  return NULL;
471
4.70k
}
472
473
/* Set the id of the given dimension of "space" to "id".
474
 * If the dimension already has an id, then it is replaced.
475
 * If the dimension is a parameter, then we need to change it
476
 * in the nested spaces (if any) as well.
477
 */
478
__isl_give isl_space *isl_space_set_dim_id(__isl_take isl_space *space,
479
  enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)
480
54.7k
{
481
54.7k
  space = isl_space_cow(space);
482
54.7k
  if (
!space || 54.7k
!id54.7k
)
483
0
    goto error;
484
54.7k
485
54.7k
  
if (54.7k
type == isl_dim_param54.7k
)
{40.0k
486
40.0k
    int i;
487
40.0k
488
120k
    for (i = 0; 
i < 2120k
;
++i80.1k
)
{80.1k
489
80.1k
      if (!space->nested[i])
490
80.1k
        continue;
491
0
      space->nested[i] =
492
0
        isl_space_set_dim_id(space->nested[i],
493
0
            type, pos, isl_id_copy(id));
494
0
      if (!space->nested[i])
495
0
        goto error;
496
0
    }
497
40.0k
  }
498
54.7k
499
54.7k
  isl_id_free(get_id(space, type, pos));
500
54.7k
  return set_id(space, type, pos, id);
501
0
error:
502
0
  isl_id_free(id);
503
0
  isl_space_free(space);
504
0
  return NULL;
505
54.7k
}
506
507
/* Reset the id of the given dimension of "space".
508
 * If the dimension already has an id, then it is removed.
509
 * If the dimension is a parameter, then we need to reset it
510
 * in the nested spaces (if any) as well.
511
 */
512
__isl_give isl_space *isl_space_reset_dim_id(__isl_take isl_space *space,
513
  enum isl_dim_type type, unsigned pos)
514
0
{
515
0
  space = isl_space_cow(space);
516
0
  if (!space)
517
0
    goto error;
518
0
519
0
  
if (0
type == isl_dim_param0
)
{0
520
0
    int i;
521
0
522
0
    for (i = 0; 
i < 20
;
++i0
)
{0
523
0
      if (!space->nested[i])
524
0
        continue;
525
0
      space->nested[i] =
526
0
        isl_space_reset_dim_id(space->nested[i],
527
0
              type, pos);
528
0
      if (!space->nested[i])
529
0
        goto error;
530
0
    }
531
0
  }
532
0
533
0
  isl_id_free(get_id(space, type, pos));
534
0
  return set_id(space, type, pos, NULL);
535
0
error:
536
0
  isl_space_free(space);
537
0
  return NULL;
538
0
}
539
540
isl_bool isl_space_has_dim_id(__isl_keep isl_space *dim,
541
  enum isl_dim_type type, unsigned pos)
542
932
{
543
932
  if (!dim)
544
0
    return isl_bool_error;
545
932
  return get_id(dim, type, pos) != NULL;
546
932
}
547
548
__isl_give isl_id *isl_space_get_dim_id(__isl_keep isl_space *dim,
549
  enum isl_dim_type type, unsigned pos)
550
802k
{
551
802k
  if (!dim)
552
0
    return NULL;
553
802k
  
if (802k
!get_id(dim, type, pos)802k
)
554
0
    isl_die(dim->ctx, isl_error_invalid,
555
802k
      "dim has no id", return NULL);
556
802k
  return isl_id_copy(get_id(dim, type, pos));
557
802k
}
558
559
__isl_give isl_space *isl_space_set_tuple_name(__isl_take isl_space *dim,
560
  enum isl_dim_type type, const char *s)
561
42.0k
{
562
42.0k
  isl_id *id;
563
42.0k
564
42.0k
  if (!dim)
565
0
    return NULL;
566
42.0k
567
42.0k
  
if (42.0k
!s42.0k
)
568
0
    return isl_space_reset_tuple_id(dim, type);
569
42.0k
570
42.0k
  
if (42.0k
!name_ok(dim->ctx, s)42.0k
)
571
0
    goto error;
572
42.0k
573
42.0k
  id = isl_id_alloc(dim->ctx, s, NULL);
574
42.0k
  return isl_space_set_tuple_id(dim, type, id);
575
0
error:
576
0
  isl_space_free(dim);
577
0
  return NULL;
578
42.0k
}
579
580
/* Does the tuple have a name?
581
 */
582
isl_bool isl_space_has_tuple_name(__isl_keep isl_space *space,
583
  enum isl_dim_type type)
584
562
{
585
562
  isl_id *id;
586
562
587
562
  if (!space_can_have_id(space, type))
588
0
    return isl_bool_error;
589
562
  id = space->tuple_id[type - isl_dim_in];
590
111
  return id && id->name;
591
562
}
592
593
const char *isl_space_get_tuple_name(__isl_keep isl_space *dim,
594
   enum isl_dim_type type)
595
6.71k
{
596
6.71k
  isl_id *id;
597
6.71k
  if (!dim)
598
0
    return NULL;
599
6.71k
  
if (6.71k
type != isl_dim_in && 6.71k
type != isl_dim_out4.02k
)
600
0
    return NULL;
601
6.71k
  id = dim->tuple_id[type - isl_dim_in];
602
5.75k
  return id ? id->name : NULL;
603
6.71k
}
604
605
__isl_give isl_space *isl_space_set_dim_name(__isl_take isl_space *dim,
606
         enum isl_dim_type type, unsigned pos,
607
         const char *s)
608
4.47k
{
609
4.47k
  isl_id *id;
610
4.47k
611
4.47k
  if (!dim)
612
0
    return NULL;
613
4.47k
  
if (4.47k
!s4.47k
)
614
0
    return isl_space_reset_dim_id(dim, type, pos);
615
4.47k
  
if (4.47k
!name_ok(dim->ctx, s)4.47k
)
616
0
    goto error;
617
4.47k
  id = isl_id_alloc(dim->ctx, s, NULL);
618
4.47k
  return isl_space_set_dim_id(dim, type, pos, id);
619
0
error:
620
0
  isl_space_free(dim);
621
0
  return NULL;
622
4.47k
}
623
624
/* Does the given dimension have a name?
625
 */
626
isl_bool isl_space_has_dim_name(__isl_keep isl_space *space,
627
  enum isl_dim_type type, unsigned pos)
628
4.04k
{
629
4.04k
  isl_id *id;
630
4.04k
631
4.04k
  if (!space)
632
0
    return isl_bool_error;
633
4.04k
  id = get_id(space, type, pos);
634
734
  return id && id->name;
635
4.04k
}
636
637
__isl_keep const char *isl_space_get_dim_name(__isl_keep isl_space *dim,
638
         enum isl_dim_type type, unsigned pos)
639
294k
{
640
294k
  isl_id *id = get_id(dim, type, pos);
641
269k
  return id ? id->name : NULL;
642
294k
}
643
644
int isl_space_find_dim_by_id(__isl_keep isl_space *dim, enum isl_dim_type type,
645
  __isl_keep isl_id *id)
646
350
{
647
350
  int i;
648
350
  int offset;
649
350
  int n;
650
350
651
350
  if (
!dim || 350
!id350
)
652
0
    return -1;
653
350
654
350
  offset = isl_space_offset(dim, type);
655
350
  n = isl_space_dim(dim, type);
656
453
  for (i = 0; 
i < n && 453
offset + i < dim->n_id452
;
++i103
)
657
452
    
if (452
dim->ids[offset + i] == id452
)
658
349
      return i;
659
350
660
1
  return -1;
661
350
}
662
663
int isl_space_find_dim_by_name(__isl_keep isl_space *space,
664
  enum isl_dim_type type, const char *name)
665
756
{
666
756
  int i;
667
756
  int offset;
668
756
  int n;
669
756
670
756
  if (
!space || 756
!name756
)
671
0
    return -1;
672
756
673
756
  offset = isl_space_offset(space, type);
674
756
  n = isl_space_dim(space, type);
675
1.22k
  for (i = 0; 
i < n && 1.22k
offset + i < space->n_id466
;
++i466
)
{466
676
466
    isl_id *id = get_id(space, type, i);
677
466
    if (
id && 466
id->name466
&&
!strcmp(id->name, name)466
)
678
0
      return i;
679
466
  }
680
756
681
756
  return -1;
682
756
}
683
684
/* Reset the user pointer on all identifiers of parameters and tuples
685
 * of "space".
686
 */
687
__isl_give isl_space *isl_space_reset_user(__isl_take isl_space *space)
688
0
{
689
0
  int i;
690
0
  isl_ctx *ctx;
691
0
  isl_id *id;
692
0
  const char *name;
693
0
694
0
  if (!space)
695
0
    return NULL;
696
0
697
0
  ctx = isl_space_get_ctx(space);
698
0
699
0
  for (i = 0; 
i < space->nparam && 0
i < space->n_id0
;
++i0
)
{0
700
0
    if (!isl_id_get_user(space->ids[i]))
701
0
      continue;
702
0
    space = isl_space_cow(space);
703
0
    if (!space)
704
0
      return NULL;
705
0
    name = isl_id_get_name(space->ids[i]);
706
0
    id = isl_id_alloc(ctx, name, NULL);
707
0
    isl_id_free(space->ids[i]);
708
0
    space->ids[i] = id;
709
0
    if (!id)
710
0
      return isl_space_free(space);
711
0
  }
712
0
713
0
  
for (i = 0; 0
i < 20
;
++i0
)
{0
714
0
    if (!space->tuple_id[i])
715
0
      continue;
716
0
    
if (0
!isl_id_get_user(space->tuple_id[i])0
)
717
0
      continue;
718
0
    space = isl_space_cow(space);
719
0
    if (!space)
720
0
      return NULL;
721
0
    name = isl_id_get_name(space->tuple_id[i]);
722
0
    id = isl_id_alloc(ctx, name, NULL);
723
0
    isl_id_free(space->tuple_id[i]);
724
0
    space->tuple_id[i] = id;
725
0
    if (!id)
726
0
      return isl_space_free(space);
727
0
  }
728
0
729
0
  
for (i = 0; 0
i < 20
;
++i0
)
{0
730
0
    if (!space->nested[i])
731
0
      continue;
732
0
    space = isl_space_cow(space);
733
0
    if (!space)
734
0
      return NULL;
735
0
    space->nested[i] = isl_space_reset_user(space->nested[i]);
736
0
    if (!space->nested[i])
737
0
      return isl_space_free(space);
738
0
  }
739
0
740
0
  return space;
741
0
}
742
743
static __isl_keep isl_id *tuple_id(__isl_keep isl_space *dim,
744
  enum isl_dim_type type)
745
23.7M
{
746
23.7M
  if (!dim)
747
0
    return NULL;
748
23.7M
  
if (23.7M
type == isl_dim_in23.7M
)
749
7.46M
    return dim->tuple_id[0];
750
16.2M
  
if (16.2M
type == isl_dim_out16.2M
)
751
6.77M
    return dim->tuple_id[1];
752
9.50M
  return NULL;
753
16.2M
}
754
755
static __isl_keep isl_space *nested(__isl_keep isl_space *dim,
756
  enum isl_dim_type type)
757
22.1M
{
758
22.1M
  if (!dim)
759
0
    return NULL;
760
22.1M
  
if (22.1M
type == isl_dim_in22.1M
)
761
6.41M
    return dim->nested[0];
762
15.7M
  
if (15.7M
type == isl_dim_out15.7M
)
763
6.20M
    return dim->nested[1];
764
9.50M
  return NULL;
765
15.7M
}
766
767
/* Are the two spaces the same, apart from positions and names of parameters?
768
 */
769
isl_bool isl_space_has_equal_tuples(__isl_keep isl_space *space1,
770
  __isl_keep isl_space *space2)
771
3.46M
{
772
3.46M
  if (
!space1 || 3.46M
!space23.46M
)
773
0
    return isl_bool_error;
774
3.46M
  
if (3.46M
space1 == space23.46M
)
775
879k
    return isl_bool_true;
776
2.58M
  return isl_space_tuple_is_equal(space1, isl_dim_in,
777
2.58M
          space2, isl_dim_in) &&
778
2.23M
         isl_space_tuple_is_equal(space1, isl_dim_out,
779
2.23M
          space2, isl_dim_out);
780
3.46M
}
781
782
/* Check if the tuple of type "type1" of "space1" is the same as
783
 * the tuple of type "type2" of "space2".
784
 *
785
 * That is, check if the tuples have the same identifier, the same dimension
786
 * and the same internal structure.
787
 * The identifiers of the dimensions inside the tuples do not affect the result.
788
 *
789
 * Note that this function only checks the tuples themselves.
790
 * If nested tuples are involved, then we need to be careful not
791
 * to have result affected by possibly differing parameters
792
 * in those nested tuples.
793
 */
794
isl_bool isl_space_tuple_is_equal(__isl_keep isl_space *space1,
795
  enum isl_dim_type type1, __isl_keep isl_space *space2,
796
  enum isl_dim_type type2)
797
11.3M
{
798
11.3M
  isl_id *id1, *id2;
799
11.3M
  isl_space *nested1, *nested2;
800
11.3M
801
11.3M
  if (
!space1 || 11.3M
!space211.3M
)
802
0
    return isl_bool_error;
803
11.3M
804
11.3M
  
if (11.3M
space1 == space2 && 11.3M
type1 == type2995k
)
805
5.20k
    return isl_bool_true;
806
11.3M
807
11.3M
  
if (11.3M
n(space1, type1) != n(space2, type2)11.3M
)
808
1.10M
    return isl_bool_false;
809
10.2M
  id1 = tuple_id(space1, type1);
810
10.2M
  id2 = tuple_id(space2, type2);
811
10.2M
  if (!id1 ^ !id2)
812
363k
    return isl_bool_false;
813
9.87M
  
if (9.87M
id1 && 9.87M
id1 != id22.34M
)
814
85.6k
    return isl_bool_false;
815
9.79M
  nested1 = nested(space1, type1);
816
9.79M
  nested2 = nested(space2, type2);
817
9.79M
  if (!nested1 ^ !nested2)
818
33.1k
    return isl_bool_false;
819
9.75M
  
if (9.75M
nested1 && 9.75M
!isl_space_has_equal_tuples(nested1, nested2)1.44M
)
820
6.60k
    return isl_bool_false;
821
9.75M
  return isl_bool_true;
822
9.75M
}
823
824
/* This is the old, undocumented, name for isl_space_tuple_is_equal.
825
 * It will be removed at some point.
826
 */
827
int isl_space_tuple_match(__isl_keep isl_space *space1, enum isl_dim_type type1,
828
  __isl_keep isl_space *space2, enum isl_dim_type type2)
829
0
{
830
0
  return isl_space_tuple_is_equal(space1, type1, space2, type2);
831
0
}
832
833
static isl_bool match(__isl_keep isl_space *space1, enum isl_dim_type type1,
834
  __isl_keep isl_space *space2, enum isl_dim_type type2)
835
6.19M
{
836
6.19M
  int i;
837
6.19M
838
6.19M
  if (
space1 == space2 && 6.19M
type1 == type21.63M
)
839
646k
    return isl_bool_true;
840
6.19M
841
5.54M
  
if (5.54M
!isl_space_tuple_is_equal(space1, type1, space2, type2)5.54M
)
842
1.06M
    return isl_bool_false;
843
5.54M
844
4.48M
  
if (4.48M
!space1->ids && 4.48M
!space2->ids2.08M
)
845
1.97M
    return isl_bool_true;
846
4.48M
847
8.71M
  
for (i = 0; 2.50M
i < n(space1, type1)8.71M
;
++i6.21M
)
{6.24M
848
6.24M
    if (get_id(space1, type1, i) != get_id(space2, type2, i))
849
29.7k
      return isl_bool_false;
850
6.24M
  }
851
2.47M
  return isl_bool_true;
852
2.50M
}
853
854
/* Do "space1" and "space2" have the same parameters?
855
 */
856
isl_bool isl_space_has_equal_params(__isl_keep isl_space *space1,
857
  __isl_keep isl_space *space2)
858
4.91M
{
859
4.91M
  if (
!space1 || 4.91M
!space24.91M
)
860
0
    return isl_bool_error;
861
4.91M
862
4.91M
  return match(space1, isl_dim_param, space2, isl_dim_param);
863
4.91M
}
864
865
/* Do "space1" and "space2" have the same identifiers for all
866
 * the tuple variables?
867
 */
868
isl_bool isl_space_has_equal_ids(__isl_keep isl_space *space1,
869
  __isl_keep isl_space *space2)
870
148k
{
871
148k
  isl_bool equal;
872
148k
873
148k
  if (
!space1 || 148k
!space2148k
)
874
0
    return isl_bool_error;
875
148k
876
148k
  equal = match(space1, isl_dim_in, space2, isl_dim_in);
877
148k
  if (
equal < 0 || 148k
!equal148k
)
878
137
    return equal;
879
147k
  return match(space1, isl_dim_out, space2, isl_dim_out);
880
148k
}
881
882
isl_bool isl_space_match(__isl_keep isl_space *space1, enum isl_dim_type type1,
883
  __isl_keep isl_space *space2, enum isl_dim_type type2)
884
0
{
885
0
  if (
!space1 || 0
!space20
)
886
0
    return isl_bool_error;
887
0
888
0
  return match(space1, type1, space2, type2);
889
0
}
890
891
static void get_ids(__isl_keep isl_space *dim, enum isl_dim_type type,
892
  unsigned first, unsigned n, __isl_keep isl_id **ids)
893
2.23M
{
894
2.23M
  int i;
895
2.23M
896
5.02M
  for (i = 0; 
i < n5.02M
;
++i2.78M
)
897
2.78M
    ids[i] = get_id(dim, type, first + i);
898
2.23M
}
899
900
static __isl_give isl_space *space_extend(__isl_take isl_space *space,
901
      unsigned nparam, unsigned n_in, unsigned n_out)
902
474k
{
903
474k
  isl_id **ids = NULL;
904
474k
905
474k
  if (!space)
906
0
    return NULL;
907
474k
  
if (474k
space->nparam == nparam &&474k
908
349k
      
space->n_in == n_in349k
&&
space->n_out == n_out344k
)
909
16.0k
    return space;
910
474k
911
458k
  
isl_assert458k
(space->ctx, space->nparam <= nparam, goto error);458k
912
458k
  
isl_assert458k
(space->ctx, space->n_in <= n_in, goto error);458k
913
458k
  
isl_assert458k
(space->ctx, space->n_out <= n_out, goto error);458k
914
458k
915
458k
  space = isl_space_cow(space);
916
458k
  if (!space)
917
0
    goto error;
918
458k
919
458k
  
if (458k
space->ids458k
)
{239k
920
239k
    unsigned n;
921
239k
    n = nparam + n_in + n_out;
922
239k
    if (
n < nparam || 239k
n < n_in239k
||
n < n_out239k
)
923
0
      isl_die(isl_space_get_ctx(space), isl_error_invalid,
924
239k
        "overflow in total number of dimensions",
925
239k
        goto error);
926
239k
    
ids = 239k
isl_calloc_array239k
(space->ctx, isl_id *, n);
927
239k
    if (!ids)
928
0
      goto error;
929
239k
    get_ids(space, isl_dim_param, 0, space->nparam, ids);
930
239k
    get_ids(space, isl_dim_in, 0, space->n_in, ids + nparam);
931
239k
    get_ids(space, isl_dim_out, 0, space->n_out,
932
239k
      ids + nparam + n_in);
933
239k
    free(space->ids);
934
239k
    space->ids = ids;
935
239k
    space->n_id = nparam + n_in + n_out;
936
239k
  }
937
458k
  space->nparam = nparam;
938
458k
  space->n_in = n_in;
939
458k
  space->n_out = n_out;
940
458k
941
458k
  return space;
942
0
error:
943
0
  free(ids);
944
0
  isl_space_free(space);
945
0
  return NULL;
946
458k
}
947
948
__isl_give isl_space *isl_space_extend(__isl_take isl_space *space,
949
  unsigned nparam, unsigned n_in, unsigned n_out)
950
0
{
951
0
  return space_extend(space, nparam, n_in, n_out);
952
0
}
953
954
__isl_give isl_space *isl_space_add_dims(__isl_take isl_space *space,
955
  enum isl_dim_type type, unsigned n)
956
474k
{
957
474k
  space = isl_space_reset(space, type);
958
474k
  if (!space)
959
1
    return NULL;
960
474k
  switch (type) {
961
140k
  case isl_dim_param:
962
140k
    space = space_extend(space,
963
140k
        space->nparam + n, space->n_in, space->n_out);
964
140k
    if (
space && 140k
space->nested[0]140k
&&
965
3.33k
        !(space->nested[0] = isl_space_add_dims(space->nested[0],
966
3.33k
                isl_dim_param, n)))
967
0
      goto error;
968
140k
    
if (140k
space && 140k
space->nested[1]140k
&&
969
2.89k
        !(space->nested[1] = isl_space_add_dims(space->nested[1],
970
2.89k
                isl_dim_param, n)))
971
0
      goto error;
972
140k
    return space;
973
5.60k
  case isl_dim_in:
974
5.60k
    return space_extend(space,
975
5.60k
        space->nparam, space->n_in + n, space->n_out);
976
328k
  case isl_dim_out:
977
328k
    return space_extend(space,
978
328k
        space->nparam, space->n_in, space->n_out + n);
979
0
  default:
980
0
    isl_die(space->ctx, isl_error_invalid,
981
474k
      "cannot add dimensions of specified type", goto error);
982
474k
  }
983
0
error:
984
0
  isl_space_free(space);
985
0
  return NULL;
986
474k
}
987
988
static int valid_dim_type(enum isl_dim_type type)
989
1.09M
{
990
1.09M
  switch (type) {
991
1.09M
  case isl_dim_param:
992
1.09M
  case isl_dim_in:
993
1.09M
  case isl_dim_out:
994
1.09M
    return 1;
995
0
  default:
996
0
    return 0;
997
1.09M
  }
998
1.09M
}
999
1000
/* Insert "n" dimensions of type "type" at position "pos".
1001
 * If we are inserting parameters, then they are also inserted in
1002
 * any nested spaces.
1003
 */
1004
__isl_give isl_space *isl_space_insert_dims(__isl_take isl_space *dim,
1005
  enum isl_dim_type type, unsigned pos, unsigned n)
1006
107k
{
1007
107k
  isl_id **ids = NULL;
1008
107k
1009
107k
  if (!dim)
1010
0
    return NULL;
1011
107k
  
if (107k
n == 0107k
)
1012
2
    return isl_space_reset(dim, type);
1013
107k
1014
107k
  
if (107k
!valid_dim_type(type)107k
)
1015
0
    isl_die(dim->ctx, isl_error_invalid,
1016
107k
      "cannot insert dimensions of specified type",
1017
107k
      goto error);
1018
107k
1019
107k
  
isl_assert107k
(dim->ctx, pos <= isl_space_dim(dim, type), goto error);107k
1020
107k
1021
107k
  dim = isl_space_cow(dim);
1022
107k
  if (!dim)
1023
0
    return NULL;
1024
107k
1025
107k
  
if (107k
dim->ids107k
)
{45.1k
1026
45.1k
    enum isl_dim_type t, o = isl_dim_param;
1027
45.1k
    int off;
1028
45.1k
    int s[3];
1029
45.1k
    ids = isl_calloc_array(dim->ctx, isl_id *,
1030
45.1k
             dim->nparam + dim->n_in + dim->n_out + n);
1031
45.1k
    if (!ids)
1032
0
      goto error;
1033
45.1k
    off = 0;
1034
45.1k
    s[isl_dim_param - o] = dim->nparam;
1035
45.1k
    s[isl_dim_in - o] = dim->n_in;
1036
45.1k
    s[isl_dim_out - o] = dim->n_out;
1037
180k
    for (t = isl_dim_param; 
t <= isl_dim_out180k
;
++t135k
)
{135k
1038
135k
      if (
t != type135k
)
{90.3k
1039
90.3k
        get_ids(dim, t, 0, s[t - o], ids + off);
1040
90.3k
        off += s[t - o];
1041
45.1k
      } else {
1042
45.1k
        get_ids(dim, t, 0, pos, ids + off);
1043
45.1k
        off += pos + n;
1044
45.1k
        get_ids(dim, t, pos, s[t - o] - pos, ids + off);
1045
45.1k
        off += s[t - o] - pos;
1046
45.1k
      }
1047
135k
    }
1048
45.1k
    free(dim->ids);
1049
45.1k
    dim->ids = ids;
1050
45.1k
    dim->n_id = dim->nparam + dim->n_in + dim->n_out + n;
1051
45.1k
  }
1052
107k
  switch (type) {
1053
1.83k
  case isl_dim_param: dim->nparam += n; break;
1054
6.57k
  case isl_dim_in:  dim->n_in += n; break;
1055
98.6k
  case isl_dim_out: dim->n_out += n; break;
1056
0
  default:    ;
1057
107k
  }
1058
107k
  dim = isl_space_reset(dim, type);
1059
107k
1060
107k
  if (
type == isl_dim_param107k
)
{1.83k
1061
1.83k
    if (
dim && 1.83k
dim->nested[0]1.83k
&&
1062
0
        !(dim->nested[0] = isl_space_insert_dims(dim->nested[0],
1063
0
                isl_dim_param, pos, n)))
1064
0
      goto error;
1065
1.83k
    
if (1.83k
dim && 1.83k
dim->nested[1]1.83k
&&
1066
3
        !(dim->nested[1] = isl_space_insert_dims(dim->nested[1],
1067
3
                isl_dim_param, pos, n)))
1068
0
      goto error;
1069
1.83k
  }
1070
107k
1071
107k
  return dim;
1072
0
error:
1073
0
  isl_space_free(dim);
1074
0
  return NULL;
1075
107k
}
1076
1077
__isl_give isl_space *isl_space_move_dims(__isl_take isl_space *dim,
1078
  enum isl_dim_type dst_type, unsigned dst_pos,
1079
  enum isl_dim_type src_type, unsigned src_pos, unsigned n)
1080
784
{
1081
784
  int i;
1082
784
1083
784
  if (!dim)
1084
0
    return NULL;
1085
784
  
if (784
n == 0784
)
{109
1086
109
    dim = isl_space_reset(dim, src_type);
1087
109
    return isl_space_reset(dim, dst_type);
1088
109
  }
1089
784
1090
675
  
isl_assert675
(dim->ctx, src_pos + n <= isl_space_dim(dim, src_type),675
1091
675
    goto error);
1092
675
1093
675
  
if (675
dst_type == src_type && 675
dst_pos == src_pos0
)
1094
0
    return dim;
1095
675
1096
675
  
isl_assert675
(dim->ctx, dst_type != src_type, goto error);675
1097
675
1098
675
  dim = isl_space_reset(dim, src_type);
1099
675
  dim = isl_space_reset(dim, dst_type);
1100
675
1101
675
  dim = isl_space_cow(dim);
1102
675
  if (!dim)
1103
0
    return NULL;
1104
675
1105
675
  
if (675
dim->ids675
)
{449
1106
449
    isl_id **ids;
1107
449
    enum isl_dim_type t, o = isl_dim_param;
1108
449
    int off;
1109
449
    int s[3];
1110
449
    ids = isl_calloc_array(dim->ctx, isl_id *,
1111
449
           dim->nparam + dim->n_in + dim->n_out);
1112
449
    if (!ids)
1113
0
      goto error;
1114
449
    off = 0;
1115
449
    s[isl_dim_param - o] = dim->nparam;
1116
449
    s[isl_dim_in - o] = dim->n_in;
1117
449
    s[isl_dim_out - o] = dim->n_out;
1118
1.79k
    for (t = isl_dim_param; 
t <= isl_dim_out1.79k
;
++t1.34k
)
{1.34k
1119
1.34k
      if (
t == dst_type1.34k
)
{449
1120
449
        get_ids(dim, t, 0, dst_pos, ids + off);
1121
449
        off += dst_pos;
1122
449
        get_ids(dim, src_type, src_pos, n, ids + off);
1123
449
        off += n;
1124
449
        get_ids(dim, t, dst_pos, s[t - o] - dst_pos,
1125
449
            ids + off);
1126
449
        off += s[t - o] - dst_pos;
1127
898
      } else 
if (898
t == src_type898
)
{449
1128
449
        get_ids(dim, t, 0, src_pos, ids + off);
1129
449
        off += src_pos;
1130
449
        get_ids(dim, t, src_pos + n,
1131
449
              s[t - o] - src_pos - n, ids + off);
1132
449
        off += s[t - o] - src_pos - n;
1133
449
      } else {
1134
449
        get_ids(dim, t, 0, s[t - o], ids + off);
1135
449
        off += s[t - o];
1136
449
      }
1137
1.34k
    }
1138
449
    free(dim->ids);
1139
449
    dim->ids = ids;
1140
449
    dim->n_id = dim->nparam + dim->n_in + dim->n_out;
1141
449
  }
1142
675
1143
675
  switch (dst_type) {
1144
37
  case isl_dim_param: dim->nparam += n; break;
1145
277
  case isl_dim_in:  dim->n_in += n; break;
1146
361
  case isl_dim_out: dim->n_out += n; break;
1147
0
  default:    ;
1148
675
  }
1149
675
1150
675
  switch (src_type) {
1151
232
  case isl_dim_param: dim->nparam -= n; break;
1152
147
  case isl_dim_in:  dim->n_in -= n; break;
1153
296
  case isl_dim_out: dim->n_out -= n; break;
1154
0
  default:    ;
1155
675
  }
1156
675
1157
675
  
if (675
dst_type != isl_dim_param && 675
src_type != isl_dim_param638
)
1158
406
    return dim;
1159
675
1160
807
  
for (i = 0; 269
i < 2807
;
++i538
)
{538
1161
538
    if (!dim->nested[i])
1162
521
      continue;
1163
17
    dim->nested[i] = isl_space_replace(dim->nested[i],
1164
17
             isl_dim_param, dim);
1165
17
    if (!dim->nested[i])
1166
0
      goto error;
1167
17
  }
1168
269
1169
269
  return dim;
1170
0
error:
1171
0
  isl_space_free(dim);
1172
0
  return NULL;
1173
269
}
1174
1175
/* Check that "space1" and "space2" have the same parameters,
1176
 * reporting an error if they do not.
1177
 */
1178
isl_stat isl_space_check_equal_params(__isl_keep isl_space *space1,
1179
  __isl_keep isl_space *space2)
1180
301k
{
1181
301k
  isl_bool equal;
1182
301k
1183
301k
  equal = isl_space_has_equal_params(space1, space2);
1184
301k
  if (equal < 0)
1185
0
    return isl_stat_error;
1186
301k
  
if (301k
!equal301k
)
1187
0
    isl_die(isl_space_get_ctx(space1), isl_error_invalid,
1188
301k
      "parameters need to match", return isl_stat_error);
1189
301k
  return isl_stat_ok;
1190
301k
}
1191
1192
__isl_give isl_space *isl_space_join(__isl_take isl_space *left,
1193
  __isl_take isl_space *right)
1194
249k
{
1195
249k
  isl_space *dim;
1196
249k
1197
249k
  if (isl_space_check_equal_params(left, right) < 0)
1198
0
    goto error;
1199
249k
1200
249k
  
isl_assert249k
(left->ctx,249k
1201
249k
    isl_space_tuple_is_equal(left, isl_dim_out, right, isl_dim_in),
1202
249k
    goto error);
1203
249k
1204
249k
  dim = isl_space_alloc(left->ctx, left->nparam, left->n_in, right->n_out);
1205
249k
  if (!dim)
1206
0
    goto error;
1207
249k
1208
249k
  dim = copy_ids(dim, isl_dim_param, 0, left, isl_dim_param);
1209
249k
  dim = copy_ids(dim, isl_dim_in, 0, left, isl_dim_in);
1210
249k
  dim = copy_ids(dim, isl_dim_out, 0, right, isl_dim_out);
1211
249k
1212
249k
  if (
dim && 249k
left->tuple_id[0]249k
&&
1213
94.5k
      !(dim->tuple_id[0] = isl_id_copy(left->tuple_id[0])))
1214
0
    goto error;
1215
249k
  
if (249k
dim && 249k
right->tuple_id[1]249k
&&
1216
71.8k
      !(dim->tuple_id[1] = isl_id_copy(right->tuple_id[1])))
1217
0
    goto error;
1218
249k
  
if (249k
dim && 249k
left->nested[0]249k
&&
1219
69.7k
      !(dim->nested[0] = isl_space_copy(left->nested[0])))
1220
0
    goto error;
1221
249k
  
if (249k
dim && 249k
right->nested[1]249k
&&
1222
107k
      !(dim->nested[1] = isl_space_copy(right->nested[1])))
1223
0
    goto error;
1224
249k
1225
249k
  isl_space_free(left);
1226
249k
  isl_space_free(right);
1227
249k
1228
249k
  return dim;
1229
0
error:
1230
0
  isl_space_free(left);
1231
0
  isl_space_free(right);
1232
0
  return NULL;
1233
249k
}
1234
1235
/* Given two map spaces { A -> C } and { B -> D }, construct the space
1236
 * { [A -> B] -> [C -> D] }.
1237
 * Given two set spaces { A } and { B }, construct the space { [A -> B] }.
1238
 */
1239
__isl_give isl_space *isl_space_product(__isl_take isl_space *left,
1240
  __isl_take isl_space *right)
1241
1.93k
{
1242
1.93k
  isl_space *dom1, *dom2, *nest1, *nest2;
1243
1.93k
  int is_set;
1244
1.93k
1245
1.93k
  if (
!left || 1.93k
!right1.93k
)
1246
0
    goto error;
1247
1.93k
1248
1.93k
  is_set = isl_space_is_set(left);
1249
1.93k
  if (is_set != isl_space_is_set(right))
1250
0
    isl_die(isl_space_get_ctx(left), isl_error_invalid,
1251
1.93k
      "expecting either two set spaces or two map spaces",
1252
1.93k
      goto error);
1253
1.93k
  
if (1.93k
is_set1.93k
)
1254
220
    return isl_space_range_product(left, right);
1255
1.93k
1256
1.71k
  
if (1.71k
isl_space_check_equal_params(left, right) < 01.71k
)
1257
0
    goto error;
1258
1.71k
1259
1.71k
  dom1 = isl_space_domain(isl_space_copy(left));
1260
1.71k
  dom2 = isl_space_domain(isl_space_copy(right));
1261
1.71k
  nest1 = isl_space_wrap(isl_space_join(isl_space_reverse(dom1), dom2));
1262
1.71k
1263
1.71k
  dom1 = isl_space_range(left);
1264
1.71k
  dom2 = isl_space_range(right);
1265
1.71k
  nest2 = isl_space_wrap(isl_space_join(isl_space_reverse(dom1), dom2));
1266
1.71k
1267
1.71k
  return isl_space_join(isl_space_reverse(nest1), nest2);
1268
0
error:
1269
0
  isl_space_free(left);
1270
0
  isl_space_free(right);
1271
0
  return NULL;
1272
1.71k
}
1273
1274
/* Given two spaces { A -> C } and { B -> C }, construct the space
1275
 * { [A -> B] -> C }
1276
 */
1277
__isl_give isl_space *isl_space_domain_product(__isl_take isl_space *left,
1278
  __isl_take isl_space *right)
1279
1.33k
{
1280
1.33k
  isl_space *ran, *dom1, *dom2, *nest;
1281
1.33k
1282
1.33k
  if (isl_space_check_equal_params(left, right) < 0)
1283
0
    goto error;
1284
1.33k
1285
1.33k
  
if (1.33k
!isl_space_tuple_is_equal(left, isl_dim_out, right, isl_dim_out)1.33k
)
1286
0
    isl_die(left->ctx, isl_error_invalid,
1287
1.33k
      "ranges need to match", goto error);
1288
1.33k
1289
1.33k
  ran = isl_space_range(isl_space_copy(left));
1290
1.33k
1291
1.33k
  dom1 = isl_space_domain(left);
1292
1.33k
  dom2 = isl_space_domain(right);
1293
1.33k
  nest = isl_space_wrap(isl_space_join(isl_space_reverse(dom1), dom2));
1294
1.33k
1295
1.33k
  return isl_space_join(isl_space_reverse(nest), ran);
1296
0
error:
1297
0
  isl_space_free(left);
1298
0
  isl_space_free(right);
1299
0
  return NULL;
1300
1.33k
}
1301
1302
__isl_give isl_space *isl_space_range_product(__isl_take isl_space *left,
1303
  __isl_take isl_space *right)
1304
48.5k
{
1305
48.5k
  isl_space *dom, *ran1, *ran2, *nest;
1306
48.5k
1307
48.5k
  if (isl_space_check_equal_params(left, right) < 0)
1308
0
    goto error;
1309
48.5k
1310
48.5k
  
if (48.5k
!isl_space_tuple_is_equal(left, isl_dim_in, right, isl_dim_in)48.5k
)
1311
0
    isl_die(left->ctx, isl_error_invalid,
1312
48.5k
      "domains need to match", goto error);
1313
48.5k
1314
48.5k
  dom = isl_space_domain(isl_space_copy(left));
1315
48.5k
1316
48.5k
  ran1 = isl_space_range(left);
1317
48.5k
  ran2 = isl_space_range(right);
1318
48.5k
  nest = isl_space_wrap(isl_space_join(isl_space_reverse(ran1), ran2));
1319
48.5k
1320
48.5k
  return isl_space_join(isl_space_reverse(dom), nest);
1321
0
error:
1322
0
  isl_space_free(left);
1323
0
  isl_space_free(right);
1324
0
  return NULL;
1325
48.5k
}
1326
1327
/* Given a space of the form [A -> B] -> [C -> D], return the space A -> C.
1328
 */
1329
__isl_give isl_space *isl_space_factor_domain(__isl_take isl_space *space)
1330
0
{
1331
0
  space = isl_space_domain_factor_domain(space);
1332
0
  space = isl_space_range_factor_domain(space);
1333
0
  return space;
1334
0
}
1335
1336
/* Given a space of the form [A -> B] -> C, return the space A -> C.
1337
 */
1338
__isl_give isl_space *isl_space_domain_factor_domain(
1339
  __isl_take isl_space *space)
1340
29
{
1341
29
  isl_space *nested;
1342
29
  isl_space *domain;
1343
29
1344
29
  if (!space)
1345
0
    return NULL;
1346
29
  
if (29
!isl_space_domain_is_wrapping(space)29
)
1347
0
    isl_die(isl_space_get_ctx(space), isl_error_invalid,
1348
29
      "domain not a product", return isl_space_free(space));
1349
29
1350
29
  nested = space->nested[0];
1351
29
  domain = isl_space_copy(space);
1352
29
  domain = isl_space_drop_dims(domain, isl_dim_in,
1353
29
          nested->n_in, nested->n_out);
1354
29
  if (!domain)
1355
0
    return isl_space_free(space);
1356
29
  
if (29
nested->tuple_id[0]29
)
{29
1357
29
    domain->tuple_id[0] = isl_id_copy(nested->tuple_id[0]);
1358
29
    if (!domain->tuple_id[0])
1359
0
      goto error;
1360
29
  }
1361
29
  
if (29
nested->nested[0]29
)
{0
1362
0
    domain->nested[0] = isl_space_copy(nested->nested[0]);
1363
0
    if (!domain->nested[0])
1364
0
      goto error;
1365
0
  }
1366
29
1367
29
  isl_space_free(space);
1368
29
  return domain;
1369
0
error:
1370
0
  isl_space_free(space);
1371
0
  isl_space_free(domain);
1372
0
  return NULL;
1373
29
}
1374
1375
/* Given a space of the form [A -> B] -> C, return the space B -> C.
1376
 */
1377
__isl_give isl_space *isl_space_domain_factor_range(
1378
  __isl_take isl_space *space)
1379
7.03k
{
1380
7.03k
  isl_space *nested;
1381
7.03k
  isl_space *range;
1382
7.03k
1383
7.03k
  if (!space)
1384
0
    return NULL;
1385
7.03k
  
if (7.03k
!isl_space_domain_is_wrapping(space)7.03k
)
1386
0
    isl_die(isl_space_get_ctx(space), isl_error_invalid,
1387
7.03k
      "domain not a product", return isl_space_free(space));
1388
7.03k
1389
7.03k
  nested = space->nested[0];
1390
7.03k
  range = isl_space_copy(space);
1391
7.03k
  range = isl_space_drop_dims(range, isl_dim_in, 0, nested->n_in);
1392
7.03k
  if (!range)
1393
0
    return isl_space_free(space);
1394
7.03k
  
if (7.03k
nested->tuple_id[1]7.03k
)
{4.22k
1395
4.22k
    range->tuple_id[0] = isl_id_copy(nested->tuple_id[1]);
1396
4.22k
    if (!range->tuple_id[0])
1397
0
      goto error;
1398
4.22k
  }
1399
7.03k
  
if (7.03k
nested->nested[1]7.03k
)
{2.80k
1400
2.80k
    range->nested[0] = isl_space_copy(nested->nested[1]);
1401
2.80k
    if (!range->nested[0])
1402
0
      goto error;
1403
2.80k
  }
1404
7.03k
1405
7.03k
  isl_space_free(space);
1406
7.03k
  return range;
1407
0
error:
1408
0
  isl_space_free(space);
1409
0
  isl_space_free(range);
1410
0
  return NULL;
1411
7.03k
}
1412
1413
/* Given a space of the form A -> [B -> C], return the space A -> B.
1414
 */
1415
__isl_give isl_space *isl_space_range_factor_domain(
1416
  __isl_take isl_space *space)
1417
1.19k
{
1418
1.19k
  isl_space *nested;
1419
1.19k
  isl_space *domain;
1420
1.19k
1421
1.19k
  if (!space)
1422
0
    return NULL;
1423
1.19k
  
if (1.19k
!isl_space_range_is_wrapping(space)1.19k
)
1424
0
    isl_die(isl_space_get_ctx(space), isl_error_invalid,
1425
1.19k
      "range not a product", return isl_space_free(space));
1426
1.19k
1427
1.19k
  nested = space->nested[1];
1428
1.19k
  domain = isl_space_copy(space);
1429
1.19k
  domain = isl_space_drop_dims(domain, isl_dim_out,
1430
1.19k
          nested->n_in, nested->n_out);
1431
1.19k
  if (!domain)
1432
0
    return isl_space_free(space);
1433
1.19k
  
if (1.19k
nested->tuple_id[0]1.19k
)
{697
1434
697
    domain->tuple_id[1] = isl_id_copy(nested->tuple_id[0]);
1435
697
    if (!domain->tuple_id[1])
1436
0
      goto error;
1437
697
  }
1438
1.19k
  
if (1.19k
nested->nested[0]1.19k
)
{481
1439
481
    domain->nested[1] = isl_space_copy(nested->nested[0]);
1440
481
    if (!domain->nested[1])
1441
0
      goto error;
1442
481
  }
1443
1.19k
1444
1.19k
  isl_space_free(space);
1445
1.19k
  return domain;
1446
0
error:
1447
0
  isl_space_free(space);
1448
0
  isl_space_free(domain);
1449
0
  return NULL;
1450
1.19k
}
1451
1452
/* Internal function that selects the range of the map that is
1453
 * embedded in either a set space or the range of a map space.
1454
 * In particular, given a space of the form [A -> B], return the space B.
1455
 * Given a space of the form A -> [B -> C], return the space A -> C.
1456
 */
1457
static __isl_give isl_space *range_factor_range(__isl_take isl_space *space)
1458
4.28k
{
1459
4.28k
  isl_space *nested;
1460
4.28k
  isl_space *range;
1461
4.28k
1462
4.28k
  if (!space)
1463
0
    return NULL;
1464
4.28k
1465
4.28k
  nested = space->nested[1];
1466
4.28k
  range = isl_space_copy(space);
1467
4.28k
  range = isl_space_drop_dims(range, isl_dim_out, 0, nested->n_in);
1468
4.28k
  if (!range)
1469
0
    return isl_space_free(space);
1470
4.28k
  
if (4.28k
nested->tuple_id[1]4.28k
)
{0
1471
0
    range->tuple_id[1] = isl_id_copy(nested->tuple_id[1]);
1472
0
    if (!range->tuple_id[1])
1473
0
      goto error;
1474
0
  }
1475
4.28k
  
if (4.28k
nested->nested[1]4.28k
)
{4.28k
1476
4.28k
    range->nested[1] = isl_space_copy(nested->nested[1]);
1477
4.28k
    if (!range->nested[1])
1478
0
      goto error;
1479
4.28k
  }
1480
4.28k
1481
4.28k
  isl_space_free(space);
1482
4.28k
  return range;
1483
0
error:
1484
0
  isl_space_free(space);
1485
0
  isl_space_free(range);
1486
0
  return NULL;
1487
4.28k
}
1488
1489
/* Given a space of the form A -> [B -> C], return the space A -> C.
1490
 */
1491
__isl_give isl_space *isl_space_range_factor_range(
1492
  __isl_take isl_space *space)
1493
4.28k
{
1494
4.28k
  if (!space)
1495
0
    return NULL;
1496
4.28k
  
if (4.28k
!isl_space_range_is_wrapping(space)4.28k
)
1497
0
    isl_die(isl_space_get_ctx(space), isl_error_invalid,
1498
4.28k
      "range not a product", return isl_space_free(space));
1499
4.28k
1500
4.28k
  return range_factor_range(space);
1501
4.28k
}
1502
1503
/* Given a space of the form [A -> B], return the space B.
1504
 */
1505
static __isl_give isl_space *set_factor_range(__isl_take isl_space *space)
1506
0
{
1507
0
  if (!space)
1508
0
    return NULL;
1509
0
  
if (0
!isl_space_is_wrapping(space)0
)
1510
0
    isl_die(isl_space_get_ctx(space), isl_error_invalid,
1511
0
      "not a product", return isl_space_free(space));
1512
0
1513
0
  return range_factor_range(space);
1514
0
}
1515
1516
/* Given a space of the form [A -> B] -> [C -> D], return the space B -> D.
1517
 * Given a space of the form [A -> B], return the space B.
1518
 */
1519
__isl_give isl_space *isl_space_factor_range(__isl_take isl_space *space)
1520
4.28k
{
1521
4.28k
  if (!space)
1522
0
    return NULL;
1523
4.28k
  
if (4.28k
isl_space_is_set(space)4.28k
)
1524
0
    return set_factor_range(space);
1525
4.28k
  space = isl_space_domain_factor_range(space);
1526
4.28k
  space = isl_space_range_factor_range(space);
1527
4.28k
  return space;
1528
4.28k
}
1529
1530
__isl_give isl_space *isl_space_map_from_set(__isl_take isl_space *dim)
1531
7.73k
{
1532
7.73k
  isl_ctx *ctx;
1533
7.73k
  isl_id **ids = NULL;
1534
7.73k
1535
7.73k
  if (!dim)
1536
1
    return NULL;
1537
7.73k
  ctx = isl_space_get_ctx(dim);
1538
7.73k
  if (!isl_space_is_set(dim))
1539
0
    isl_die(ctx, isl_error_invalid, "not a set space", goto error);
1540
7.73k
  dim = isl_space_cow(dim);
1541
7.73k
  if (!dim)
1542
0
    return NULL;
1543
7.73k
  
if (7.73k
dim->ids7.73k
)
{4.82k
1544
4.82k
    ids = isl_calloc_array(dim->ctx, isl_id *,
1545
4.82k
          dim->nparam + dim->n_out + dim->n_out);
1546
4.82k
    if (!ids)
1547
0
      goto error;
1548
4.82k
    get_ids(dim, isl_dim_param, 0, dim->nparam, ids);
1549
4.82k
    get_ids(dim, isl_dim_out, 0, dim->n_out, ids + dim->nparam);
1550
4.82k
  }
1551
7.73k
  dim->n_in = dim->n_out;
1552
7.73k
  if (
ids7.73k
)
{4.82k
1553
4.82k
    free(dim->ids);
1554
4.82k
    dim->ids = ids;
1555
4.82k
    dim->n_id = dim->nparam + dim->n_out + dim->n_out;
1556
4.82k
    dim = copy_ids(dim, isl_dim_out, 0, dim, isl_dim_in);
1557
4.82k
  }
1558
7.73k
  isl_id_free(dim->tuple_id[0]);
1559
7.73k
  dim->tuple_id[0] = isl_id_copy(dim->tuple_id[1]);
1560
7.73k
  isl_space_free(dim->nested[0]);
1561
7.73k
  dim->nested[0] = isl_space_copy(dim->nested[1]);
1562
7.73k
  return dim;
1563
0
error:
1564
0
  isl_space_free(dim);
1565
0
  return NULL;
1566
7.73k
}
1567
1568
__isl_give isl_space *isl_space_map_from_domain_and_range(
1569
  __isl_take isl_space *domain, __isl_take isl_space *range)
1570
38.3k
{
1571
38.3k
  if (
!domain || 38.3k
!range38.3k
)
1572
0
    goto error;
1573
38.3k
  
if (38.3k
!isl_space_is_set(domain)38.3k
)
1574
0
    isl_die(isl_space_get_ctx(domain), isl_error_invalid,
1575
38.3k
      "domain is not a set space", goto error);
1576
38.3k
  
if (38.3k
!isl_space_is_set(range)38.3k
)
1577
0
    isl_die(isl_space_get_ctx(range), isl_error_invalid,
1578
38.3k
      "range is not a set space", goto error);
1579
38.3k
  return isl_space_join(isl_space_reverse(domain), range);
1580
0
error:
1581
0
  isl_space_free(domain);
1582
0
  isl_space_free(range);
1583
0
  return NULL;
1584
38.3k
}
1585
1586
static __isl_give isl_space *set_ids(__isl_take isl_space *dim,
1587
  enum isl_dim_type type,
1588
  unsigned first, unsigned n, __isl_take isl_id **ids)
1589
1.07M
{
1590
1.07M
  int i;
1591
1.07M
1592
2.49M
  for (i = 0; 
i < n2.49M
;
++i1.41M
)
1593
1.41M
    dim = set_id(dim, type, first + i, ids[i]);
1594
1.07M
1595
1.07M
  return dim;
1596
1.07M
}
1597
1598
__isl_give isl_space *isl_space_reverse(__isl_take isl_space *dim)
1599
984k
{
1600
984k
  unsigned t;
1601
984k
  isl_space *nested;
1602
984k
  isl_id **ids = NULL;
1603
984k
  isl_id *id;
1604
984k
1605
984k
  if (!dim)
1606
0
    return NULL;
1607
984k
  
if (984k
match(dim, isl_dim_in, dim, isl_dim_out)984k
)
1608
62.0k
    return dim;
1609
984k
1610
922k
  dim = isl_space_cow(dim);
1611
922k
  if (!dim)
1612
0
    return NULL;
1613
922k
1614
922k
  id = dim->tuple_id[0];
1615
922k
  dim->tuple_id[0] = dim->tuple_id[1];
1616
922k
  dim->tuple_id[1] = id;
1617
922k
1618
922k
  nested = dim->nested[0];
1619
922k
  dim->nested[0] = dim->nested[1];
1620
922k
  dim->nested[1] = nested;
1621
922k
1622
922k
  if (
dim->ids922k
)
{537k
1623
537k
    int n_id = dim->n_in + dim->n_out;
1624
537k
    ids = isl_alloc_array(dim->ctx, isl_id *, n_id);
1625
537k
    if (
n_id && 537k
!ids460k
)
1626
0
      goto error;
1627
537k
    get_ids(dim, isl_dim_in, 0, dim->n_in, ids);
1628
537k
    get_ids(dim, isl_dim_out, 0, dim->n_out, ids + dim->n_in);
1629
537k
  }
1630
922k
1631
922k
  t = dim->n_in;
1632
922k
  dim->n_in = dim->n_out;
1633
922k
  dim->n_out = t;
1634
922k
1635
922k
  if (
dim->ids922k
)
{537k
1636
537k
    dim = set_ids(dim, isl_dim_out, 0, dim->n_out, ids);
1637
537k
    dim = set_ids(dim, isl_dim_in, 0, dim->n_in, ids + dim->n_out);
1638
537k
    free(ids);
1639
537k
  }
1640
922k
1641
922k
  return dim;
1642
0
error:
1643
0
  free(ids);
1644
0
  isl_space_free(dim);
1645
0
  return NULL;
1646
922k
}
1647
1648
__isl_give isl_space *isl_space_drop_dims(__isl_take isl_space *dim,
1649
  enum isl_dim_type type, unsigned first, unsigned num)
1650
1.25M
{
1651
1.25M
  int i;
1652
1.25M
1653
1.25M
  if (!dim)
1654
0
    return NULL;
1655
1.25M
1656
1.25M
  
if (1.25M
num == 01.25M
)
1657
264k
    return isl_space_reset(dim, type);
1658
1.25M
1659
987k
  
if (987k
!valid_dim_type(type)987k
)
1660
0
    isl_die(dim->ctx, isl_error_invalid,
1661
987k
      "cannot drop dimensions of specified type", goto error);
1662
987k
1663
987k
  
if (987k
first + num > n(dim, type) || 987k
first + num < first987k
)
1664
0
    isl_die(isl_space_get_ctx(dim), isl_error_invalid,
1665
987k
      "index out of bounds", return isl_space_free(dim));
1666
987k
  dim = isl_space_cow(dim);
1667
987k
  if (!dim)
1668
0
    goto error;
1669
987k
  
if (987k
dim->ids987k
)
{499k
1670
499k
    dim = extend_ids(dim);
1671
499k
    if (!dim)
1672
0
      goto error;
1673
1.62M
    
for (i = 0; 499k
i < num1.62M
;
++i1.12M
)
1674
1.12M
      isl_id_free(get_id(dim, type, first + i));
1675
538k
    for (i = first+num; 
i < n(dim, type)538k
;
++i39.0k
)
1676
39.0k
      set_id(dim, type, i - num, get_id(dim, type, i));
1677
499k
    switch (type) {
1678
63.7k
    case isl_dim_param:
1679
63.7k
      get_ids(dim, isl_dim_in, 0, dim->n_in,
1680
63.7k
        dim->ids + offset(dim, isl_dim_in) - num);
1681
183k
    case isl_dim_in:
1682
183k
      get_ids(dim, isl_dim_out, 0, dim->n_out,
1683
183k
        dim->ids + offset(dim, isl_dim_out) - num);
1684
499k
    default:
1685
499k
      ;
1686
499k
    }
1687
499k
    dim->n_id -= num;
1688
499k
  }
1689
987k
  switch (type) {
1690
63.8k
  case isl_dim_param: dim->nparam -= num; break;
1691
173k
  case isl_dim_in:  dim->n_in -= num; break;
1692
750k
  case isl_dim_out: dim->n_out -= num; break;
1693
0
  default:    ;
1694
987k
  }
1695
987k
  dim = isl_space_reset(dim, type);
1696
987k
  if (
type == isl_dim_param987k
)
{63.8k
1697
63.8k
    if (
dim && 63.8k
dim->nested[0]63.8k
&&
1698
1.29k
        !(dim->nested[0] = isl_space_drop_dims(dim->nested[0],
1699
1.29k
                isl_dim_param, first, num)))
1700
0
      goto error;
1701
63.8k
    
if (63.8k
dim && 63.8k
dim->nested[1]63.8k
&&
1702
1.02k
        !(dim->nested[1] = isl_space_drop_dims(dim->nested[1],
1703
1.02k
                isl_dim_param, first, num)))
1704
0
      goto error;
1705
63.8k
  }
1706
987k
  return dim;
1707
0
error:
1708
0
  isl_space_free(dim);
1709
0
  return NULL;
1710
987k
}
1711
1712
__isl_give isl_space *isl_space_drop_inputs(__isl_take isl_space *dim,
1713
    unsigned first, unsigned n)
1714
0
{
1715
0
  if (!dim)
1716
0
    return NULL;
1717
0
  return isl_space_drop_dims(dim, isl_dim_in, first, n);
1718
0
}
1719
1720
__isl_give isl_space *isl_space_drop_outputs(__isl_take isl_space *dim,
1721
    unsigned first, unsigned n)
1722
0
{
1723
0
  if (!dim)
1724
0
    return NULL;
1725
0
  return isl_space_drop_dims(dim, isl_dim_out, first, n);
1726
0
}
1727
1728
__isl_give isl_space *isl_space_domain(__isl_take isl_space *space)
1729
359k
{
1730
359k
  if (!space)
1731
0
    return NULL;
1732
359k
  space = isl_space_drop_dims(space, isl_dim_out, 0, space->n_out);
1733
359k
  space = isl_space_reverse(space);
1734
359k
  space = mark_as_set(space);
1735
359k
  return space;
1736
359k
}
1737
1738
__isl_give isl_space *isl_space_from_domain(__isl_take isl_space *dim)
1739
355k
{
1740
355k
  if (!dim)
1741
0
    return NULL;
1742
355k
  
if (355k
!isl_space_is_set(dim)355k
)
1743
0
    isl_die(isl_space_get_ctx(dim), isl_error_invalid,
1744
355k
      "not a set space", goto error);
1745
355k
  dim = isl_space_reverse(dim);
1746
355k
  dim = isl_space_reset(dim, isl_dim_out);
1747
355k
  return dim;
1748
0
error:
1749
0
  isl_space_free(dim);
1750
0
  return NULL;
1751
355k
}
1752
1753
__isl_give isl_space *isl_space_range(__isl_take isl_space *space)
1754
167k
{
1755
167k
  if (!space)
1756
0
    return NULL;
1757
167k
  space = isl_space_drop_dims(space, isl_dim_in, 0, space->n_in);
1758
167k
  space = mark_as_set(space);
1759
167k
  return space;
1760
167k
}
1761
1762
__isl_give isl_space *isl_space_from_range(__isl_take isl_space *dim)
1763
105k
{
1764
105k
  if (!dim)
1765
0
    return NULL;
1766
105k
  
if (105k
!isl_space_is_set(dim)105k
)
1767
0
    isl_die(isl_space_get_ctx(dim), isl_error_invalid,
1768
105k
      "not a set space", goto error);
1769
105k
  return isl_space_reset(dim, isl_dim_in);
1770
0
error:
1771
0
  isl_space_free(dim);
1772
0
  return NULL;
1773
105k
}
1774
1775
/* Given a map space A -> B, return the map space [A -> B] -> A.
1776
 */
1777
__isl_give isl_space *isl_space_domain_map(__isl_take isl_space *space)
1778
356
{
1779
356
  isl_space *domain;
1780
356
1781
356
  domain = isl_space_from_range(isl_space_domain(isl_space_copy(space)));
1782
356
  space = isl_space_from_domain(isl_space_wrap(space));
1783
356
  space = isl_space_join(space, domain);
1784
356
1785
356
  return space;
1786
356
}
1787
1788
/* Given a map space A -> B, return the map space [A -> B] -> B.
1789
 */
1790
__isl_give isl_space *isl_space_range_map(__isl_take isl_space *space)
1791
0
{
1792
0
  isl_space *range;
1793
0
1794
0
  range = isl_space_from_range(isl_space_range(isl_space_copy(space)));
1795
0
  space = isl_space_from_domain(isl_space_wrap(space));
1796
0
  space = isl_space_join(space, range);
1797
0
1798
0
  return space;
1799
0
}
1800
1801
__isl_give isl_space *isl_space_params(__isl_take isl_space *space)
1802
229k
{
1803
229k
  if (isl_space_is_params(space))
1804
168k
    return space;
1805
60.7k
  space = isl_space_drop_dims(space,
1806
60.7k
          isl_dim_in, 0, isl_space_dim(space, isl_dim_in));
1807
60.7k
  space = isl_space_drop_dims(space,
1808
60.7k
          isl_dim_out, 0, isl_space_dim(space, isl_dim_out));
1809
60.7k
  space = mark_as_params(space);
1810
60.7k
  return space;
1811
229k
}
1812
1813
__isl_give isl_space *isl_space_set_from_params(__isl_take isl_space *space)
1814
9.39k
{
1815
9.39k
  if (!space)
1816
0
    return NULL;
1817
9.39k
  
if (9.39k
!isl_space_is_params(space)9.39k
)
1818
0
    isl_die(isl_space_get_ctx(space), isl_error_invalid,
1819
9.39k
      "not a parameter space", goto error);
1820
9.39k
  return isl_space_reset(space, isl_dim_set);
1821
0
error:
1822
0
  isl_space_free(space);
1823
0
  return NULL;
1824
9.39k
}
1825
1826
__isl_give isl_space *isl_space_underlying(__isl_take isl_space *dim,
1827
  unsigned n_div)
1828
284k
{
1829
284k
  int i;
1830
284k
1831
284k
  if (!dim)
1832
0
    return NULL;
1833
284k
  
if (284k
n_div == 0 &&284k
1834
275k
      
dim->nparam == 0275k
&&
dim->n_in == 0138k
&&
dim->n_id == 0116k
)
1835
87.8k
    return isl_space_reset(isl_space_reset(dim, isl_dim_in), isl_dim_out);
1836
196k
  dim = isl_space_cow(dim);
1837
196k
  if (!dim)
1838
0
    return NULL;
1839
196k
  dim->n_out += dim->nparam + dim->n_in + n_div;
1840
196k
  dim->nparam = 0;
1841
196k
  dim->n_in = 0;
1842
196k
1843
1.07M
  for (i = 0; 
i < dim->n_id1.07M
;
++i877k
)
1844
877k
    isl_id_free(get_id(dim, isl_dim_out, i));
1845
196k
  dim->n_id = 0;
1846
196k
  dim = isl_space_reset(dim, isl_dim_in);
1847
196k
  dim = isl_space_reset(dim, isl_dim_out);
1848
196k
1849
196k
  return dim;
1850
196k
}
1851
1852
/* Are the two spaces the same, including positions and names of parameters?
1853
 */
1854
isl_bool isl_space_is_equal(__isl_keep isl_space *space1,
1855
  __isl_keep isl_space *space2)
1856
4.67M
{
1857
4.67M
  isl_bool equal;
1858
4.67M
1859
4.67M
  if (
!space1 || 4.67M
!space24.67M
)
1860
0
    return isl_bool_error;
1861
4.67M
  
if (4.67M
space1 == space24.67M
)
1862
2.59M
    return isl_bool_true;
1863
2.07M
  equal = isl_space_has_equal_params(space1, space2);
1864
2.07M
  if (
equal < 0 || 2.07M
!equal2.07M
)
1865
51.6k
    return equal;
1866
2.02M
  return isl_space_has_equal_tuples(space1, space2);
1867
2.07M
}
1868
1869
/* Is space1 equal to the domain of space2?
1870
 *
1871
 * In the internal version we also allow space2 to be the space of a set,
1872
 * provided space1 is a parameter space.
1873
 */
1874
isl_bool isl_space_is_domain_internal(__isl_keep isl_space *space1,
1875
  __isl_keep isl_space *space2)
1876
47
{
1877
47
  isl_bool equal_params;
1878
47
1879
47
  if (
!space1 || 47
!space247
)
1880
0
    return isl_bool_error;
1881
47
  
if (47
!isl_space_is_set(space1)47
)
1882
0
    return isl_bool_false;
1883
47
  equal_params = isl_space_has_equal_params(space1, space2);
1884
47
  if (
equal_params < 0 || 47
!equal_params47
)
1885
0
    return equal_params;
1886
47
  return isl_space_tuple_is_equal(space1, isl_dim_set,
1887
47
          space2, isl_dim_in);
1888
47
}
1889
1890
/* Is space1 equal to the domain of space2?
1891
 */
1892
isl_bool isl_space_is_domain(__isl_keep isl_space *space1,
1893
  __isl_keep isl_space *space2)
1894
19
{
1895
19
  if (!space2)
1896
0
    return isl_bool_error;
1897
19
  
if (19
!isl_space_is_map(space2)19
)
1898
0
    return isl_bool_false;
1899
19
  return isl_space_is_domain_internal(space1, space2);
1900
19
}
1901
1902
/* Is space1 equal to the range of space2?
1903
 *
1904
 * In the internal version, space2 is allowed to be the space of a set,
1905
 * in which case it should be equal to space1.
1906
 */
1907
isl_bool isl_space_is_range_internal(__isl_keep isl_space *space1,
1908
  __isl_keep isl_space *space2)
1909
8.11k
{
1910
8.11k
  isl_bool equal_params;
1911
8.11k
1912
8.11k
  if (
!space1 || 8.11k
!space28.11k
)
1913
0
    return isl_bool_error;
1914
8.11k
  
if (8.11k
!isl_space_is_set(space1)8.11k
)
1915
0
    return isl_bool_false;
1916
8.11k
  equal_params = isl_space_has_equal_params(space1, space2);
1917
8.11k
  if (
equal_params < 0 || 8.11k
!equal_params8.11k
)
1918
0
    return equal_params;
1919
8.11k
  return isl_space_tuple_is_equal(space1, isl_dim_set,
1920
8.11k
          space2, isl_dim_out);
1921
8.11k
}
1922
1923
/* Is space1 equal to the range of space2?
1924
 */
1925
isl_bool isl_space_is_range(__isl_keep isl_space *space1,
1926
  __isl_keep isl_space *space2)
1927
0
{
1928
0
  if (!space2)
1929
0
    return isl_bool_error;
1930
0
  
if (0
!isl_space_is_map(space2)0
)
1931
0
    return isl_bool_false;
1932
0
  return isl_space_is_range_internal(space1, space2);
1933
0
}
1934
1935
/* Update "hash" by hashing in "space".
1936
 * Changes in this function should be reflected in isl_hash_space_domain.
1937
 */
1938
static uint32_t isl_hash_space(uint32_t hash, __isl_keep isl_space *space)
1939
974k
{
1940
974k
  int i;
1941
974k
  isl_id *id;
1942
974k
1943
974k
  if (!space)
1944
619k
    return hash;
1945
974k
1946
354k
  
isl_hash_byte354k
(hash, space->nparam % 256);354k
1947
354k
  isl_hash_byte(hash, space->n_in % 256);
1948
354k
  isl_hash_byte(hash, space->n_out % 256);
1949
354k
1950
963k
  for (i = 0; 
i < space->nparam963k
;
++i608k
)
{608k
1951
608k
    id = get_id(space, isl_dim_param, i);
1952
608k
    hash = isl_hash_id(hash, id);
1953
608k
  }
1954
354k
1955
354k
  id = tuple_id(space, isl_dim_in);
1956
354k
  hash = isl_hash_id(hash, id);
1957
354k
  id = tuple_id(space, isl_dim_out);
1958
354k
  hash = isl_hash_id(hash, id);
1959
354k
1960
354k
  hash = isl_hash_space(hash, space->nested[0]);
1961
354k
  hash = isl_hash_space(hash, space->nested[1]);
1962
354k
1963
354k
  return hash;
1964
974k
}
1965
1966
/* Update "hash" by hashing in the domain of "space".
1967
 * The result of this function is equal to the result of applying
1968
 * isl_hash_space to the domain of "space".
1969
 */
1970
static uint32_t isl_hash_space_domain(uint32_t hash,
1971
  __isl_keep isl_space *space)
1972
18.1k
{
1973
18.1k
  int i;
1974
18.1k
  isl_id *id;
1975
18.1k
1976
18.1k
  if (!space)
1977
0
    return hash;
1978
18.1k
1979
18.1k
  
isl_hash_byte18.1k
(hash, space->nparam % 256);18.1k
1980
18.1k
  isl_hash_byte(hash, 0);
1981
18.1k
  isl_hash_byte(hash, space->n_in % 256);
1982
18.1k
1983
47.6k
  for (i = 0; 
i < space->nparam47.6k
;
++i29.4k
)
{29.4k
1984
29.4k
    id = get_id(space, isl_dim_param, i);
1985
29.4k
    hash = isl_hash_id(hash, id);
1986
29.4k
  }
1987
18.1k
1988
18.1k
  hash = isl_hash_id(hash, &isl_id_none);
1989
18.1k
  id = tuple_id(space, isl_dim_in);
1990
18.1k
  hash = isl_hash_id(hash, id);
1991
18.1k
1992
18.1k
  hash = isl_hash_space(hash, space->nested[0]);
1993
18.1k
1994
18.1k
  return hash;
1995
18.1k
}
1996
1997
uint32_t isl_space_get_hash(__isl_keep isl_space *dim)
1998
246k
{
1999
246k
  uint32_t hash;
2000
246k
2001
246k
  if (!dim)
2002
0
    return 0;
2003
246k
2004
246k
  
hash = 246k
isl_hash_init246k
();
2005
246k
  hash = isl_hash_space(hash, dim);
2006
246k
2007
246k
  return hash;
2008
246k
}
2009
2010
/* Return the hash value of the domain of "space".
2011
 * That is, isl_space_get_domain_hash(space) is equal to
2012
 * isl_space_get_hash(isl_space_domain(space)).
2013
 */
2014
uint32_t isl_space_get_domain_hash(__isl_keep isl_space *space)
2015
18.1k
{
2016
18.1k
  uint32_t hash;
2017
18.1k
2018
18.1k
  if (!space)
2019
0
    return 0;
2020
18.1k
2021
18.1k
  
hash = 18.1k
isl_hash_init18.1k
();
2022
18.1k
  hash = isl_hash_space_domain(hash, space);
2023
18.1k
2024
18.1k
  return hash;
2025
18.1k
}
2026
2027
isl_bool isl_space_is_wrapping(__isl_keep isl_space *dim)
2028
28.6k
{
2029
28.6k
  if (!dim)
2030
0
    return isl_bool_error;
2031
28.6k
2032
28.6k
  
if (28.6k
!isl_space_is_set(dim)28.6k
)
2033
0
    return isl_bool_false;
2034
28.6k
2035
28.6k
  return dim->nested[1] != NULL;
2036
28.6k
}
2037
2038
/* Is "space" the space of a map where the domain is a wrapped map space?
2039
 */
2040
isl_bool isl_space_domain_is_wrapping(__isl_keep isl_space *space)
2041
14.3k
{
2042
14.3k
  if (!space)
2043
0
    return isl_bool_error;
2044
14.3k
2045
14.3k
  
if (14.3k
isl_space_is_set(space)14.3k
)
2046
0
    return isl_bool_false;
2047
14.3k
2048
14.3k
  return space->nested[0] != NULL;
2049
14.3k
}
2050
2051
/* Is "space" the space of a map where the range is a wrapped map space?
2052
 */
2053
isl_bool isl_space_range_is_wrapping(__isl_keep isl_space *space)
2054
21.6k
{
2055
21.6k
  if (!space)
2056
0
    return isl_bool_error;
2057
21.6k
2058
21.6k
  
if (21.6k
isl_space_is_set(space)21.6k
)
2059
684
    return isl_bool_false;
2060
21.6k
2061
20.9k
  return space->nested[1] != NULL;
2062
21.6k
}
2063
2064
__isl_give isl_space *isl_space_wrap(__isl_take isl_space *dim)
2065
109k
{
2066
109k
  isl_space *wrap;
2067
109k
2068
109k
  if (!dim)
2069
0
    return NULL;
2070
109k
2071
109k
  wrap = isl_space_set_alloc(dim->ctx,
2072
109k
            dim->nparam, dim->n_in + dim->n_out);
2073
109k
2074
109k
  wrap = copy_ids(wrap, isl_dim_param, 0, dim, isl_dim_param);
2075
109k
  wrap = copy_ids(wrap, isl_dim_set, 0, dim, isl_dim_in);
2076
109k
  wrap = copy_ids(wrap, isl_dim_set, dim->n_in, dim, isl_dim_out);
2077
109k
2078
109k
  if (!wrap)
2079
0
    goto error;
2080
109k
2081
109k
  wrap->nested[1] = dim;
2082
109k
2083
109k
  return wrap;
2084
0
error:
2085
0
  isl_space_free(dim);
2086
0
  return NULL;
2087
109k
}
2088
2089
__isl_give isl_space *isl_space_unwrap(__isl_take isl_space *dim)
2090
19.4k
{
2091
19.4k
  isl_space *unwrap;
2092
19.4k
2093
19.4k
  if (!dim)
2094
0
    return NULL;
2095
19.4k
2096
19.4k
  
if (19.4k
!isl_space_is_wrapping(dim)19.4k
)
2097
0
    isl_die(dim->ctx, isl_error_invalid, "not a wrapping space",
2098
19.4k
      goto error);
2099
19.4k
2100
19.4k
  unwrap = isl_space_copy(dim->nested[1]);
2101
19.4k
  isl_space_free(dim);
2102
19.4k
2103
19.4k
  return unwrap;
2104
0
error:
2105
0
  isl_space_free(dim);
2106
0
  return NULL;
2107
19.4k
}
2108
2109
isl_bool isl_space_is_named_or_nested(__isl_keep isl_space *space,
2110
  enum isl_dim_type type)
2111
3.25M
{
2112
3.25M
  if (
type != isl_dim_in && 3.25M
type != isl_dim_out2.36M
)
2113
249k
    return isl_bool_false;
2114
3.00M
  
if (3.00M
!space3.00M
)
2115
1
    return isl_bool_error;
2116
3.00M
  
if (3.00M
space->tuple_id[type - isl_dim_in]3.00M
)
2117
1.31M
    return isl_bool_true;
2118
1.68M
  
if (1.68M
space->nested[type - isl_dim_in]1.68M
)
2119
319k
    return isl_bool_true;
2120
1.36M
  return isl_bool_false;
2121
1.68M
}
2122
2123
isl_bool isl_space_may_be_set(__isl_keep isl_space *space)
2124
271
{
2125
271
  isl_bool nested;
2126
271
2127
271
  if (!space)
2128
0
    return isl_bool_error;
2129
271
  
if (271
isl_space_is_set(space)271
)
2130
166
    return isl_bool_true;
2131
105
  
if (105
isl_space_dim(space, isl_dim_in) != 0105
)
2132
0
    return isl_bool_false;
2133
105
  nested = isl_space_is_named_or_nested(space, isl_dim_in);
2134
105
  if (
nested < 0 || 105
nested105
)
2135
0
    return isl_bool_not(nested);
2136
105
  return isl_bool_true;
2137
105
}
2138
2139
__isl_give isl_space *isl_space_reset(__isl_take isl_space *dim,
2140
  enum isl_dim_type type)
2141
2.94M
{
2142
2.94M
  if (!isl_space_is_named_or_nested(dim, type))
2143
1.44M
    return dim;
2144
2.94M
2145
1.49M
  dim = isl_space_cow(dim);
2146
1.49M
  if (!dim)
2147
2
    return NULL;
2148
1.49M
2149
1.49M
  isl_id_free(dim->tuple_id[type - isl_dim_in]);
2150
1.49M
  dim->tuple_id[type - isl_dim_in] = NULL;
2151
1.49M
  isl_space_free(dim->nested[type - isl_dim_in]);
2152
1.49M
  dim->nested[type - isl_dim_in] = NULL;
2153
1.49M
2154
1.49M
  return dim;
2155
1.49M
}
2156
2157
__isl_give isl_space *isl_space_flatten(__isl_take isl_space *dim)
2158
19.9k
{
2159
19.9k
  if (!dim)
2160
0
    return NULL;
2161
19.9k
  
if (19.9k
!dim->nested[0] && 19.9k
!dim->nested[1]19.9k
)
2162
0
    return dim;
2163
19.9k
2164
19.9k
  
if (19.9k
dim->nested[0]19.9k
)
2165
0
    dim = isl_space_reset(dim, isl_dim_in);
2166
19.9k
  if (
dim && 19.9k
dim->nested[1]19.9k
)
2167
19.9k
    dim = isl_space_reset(dim, isl_dim_out);
2168
19.9k
2169
19.9k
  return dim;
2170
19.9k
}
2171
2172
__isl_give isl_space *isl_space_flatten_domain(__isl_take isl_space *dim)
2173
30
{
2174
30
  if (!dim)
2175
0
    return NULL;
2176
30
  
if (30
!dim->nested[0]30
)
2177
0
    return dim;
2178
30
2179
30
  return isl_space_reset(dim, isl_dim_in);
2180
30
}
2181
2182
__isl_give isl_space *isl_space_flatten_range(__isl_take isl_space *dim)
2183
30.9k
{
2184
30.9k
  if (!dim)
2185
0
    return NULL;
2186
30.9k
  
if (30.9k
!dim->nested[1]30.9k
)
2187
0
    return dim;
2188
30.9k
2189
30.9k
  return isl_space_reset(dim, isl_dim_out);
2190
30.9k
}
2191
2192
/* Replace the dimensions of the given type of dst by those of src.
2193
 */
2194
__isl_give isl_space *isl_space_replace(__isl_take isl_space *dst,
2195
  enum isl_dim_type type, __isl_keep isl_space *src)
2196
96.9k
{
2197
96.9k
  dst = isl_space_cow(dst);
2198
96.9k
2199
96.9k
  if (
!dst || 96.9k
!src96.9k
)
2200
0
    goto error;
2201
96.9k
2202
96.9k
  dst = isl_space_drop_dims(dst, type, 0, isl_space_dim(dst, type));
2203
96.9k
  dst = isl_space_add_dims(dst, type, isl_space_dim(src, type));
2204
96.9k
  dst = copy_ids(dst, type, 0, src, type);
2205
96.9k
2206
96.9k
  if (
dst && 96.9k
type == isl_dim_param96.9k
)
{96.9k
2207
96.9k
    int i;
2208
290k
    for (i = 0; 
i <= 1290k
;
++i193k
)
{193k
2209
193k
      if (!dst->nested[i])
2210
188k
        continue;
2211
5.19k
      dst->nested[i] = isl_space_replace(dst->nested[i],
2212
5.19k
               type, src);
2213
5.19k
      if (!dst->nested[i])
2214
0
        goto error;
2215
5.19k
    }
2216
96.9k
  }
2217
96.9k
2218
96.9k
  return dst;
2219
0
error:
2220
0
  isl_space_free(dst);
2221
0
  return NULL;
2222
96.9k
}
2223
2224
/* Given a dimension specification "dim" of a set, create a dimension
2225
 * specification for the lift of the set.  In particular, the result
2226
 * is of the form [dim -> local[..]], with n_local variables in the
2227
 * range of the wrapped map.
2228
 */
2229
__isl_give isl_space *isl_space_lift(__isl_take isl_space *dim, unsigned n_local)
2230
18.6k
{
2231
18.6k
  isl_space *local_dim;
2232
18.6k
2233
18.6k
  if (!dim)
2234
0
    return NULL;
2235
18.6k
2236
18.6k
  local_dim = isl_space_dup(dim);
2237
18.6k
  local_dim = isl_space_drop_dims(local_dim, isl_dim_set, 0, dim->n_out);
2238
18.6k
  local_dim = isl_space_add_dims(local_dim, isl_dim_set, n_local);
2239
18.6k
  local_dim = isl_space_set_tuple_name(local_dim, isl_dim_set, "local");
2240
18.6k
  dim = isl_space_join(isl_space_from_domain(dim),
2241
18.6k
          isl_space_from_range(local_dim));
2242
18.6k
  dim = isl_space_wrap(dim);
2243
18.6k
  dim = isl_space_set_tuple_name(dim, isl_dim_set, "lifted");
2244
18.6k
2245
18.6k
  return dim;
2246
18.6k
}
2247
2248
isl_bool isl_space_can_zip(__isl_keep isl_space *dim)
2249
4.15k
{
2250
4.15k
  if (!dim)
2251
0
    return isl_bool_error;
2252
4.15k
2253
4.15k
  
return dim->nested[0] && 4.15k
dim->nested[1]4.13k
;
2254
4.15k
}
2255
2256
__isl_give isl_space *isl_space_zip(__isl_take isl_space *dim)
2257
1.80k
{
2258
1.80k
  isl_space *dom, *ran;
2259
1.80k
  isl_space *dom_dom, *dom_ran, *ran_dom, *ran_ran;
2260
1.80k
2261
1.80k
  if (!isl_space_can_zip(dim))
2262
0
    isl_die(dim->ctx, isl_error_invalid, "dim cannot be zipped",
2263
1.80k
      goto error);
2264
1.80k
2265
1.80k
  
if (1.80k
!dim1.80k
)
2266
0
    return NULL;
2267
1.80k
  dom = isl_space_unwrap(isl_space_domain(isl_space_copy(dim)));
2268
1.80k
  ran = isl_space_unwrap(isl_space_range(dim));
2269
1.80k
  dom_dom = isl_space_domain(isl_space_copy(dom));
2270
1.80k
  dom_ran = isl_space_range(dom);
2271
1.80k
  ran_dom = isl_space_domain(isl_space_copy(ran));
2272
1.80k
  ran_ran = isl_space_range(ran);
2273
1.80k
  dom = isl_space_join(isl_space_from_domain(dom_dom),
2274
1.80k
         isl_space_from_range(ran_dom));
2275
1.80k
  ran = isl_space_join(isl_space_from_domain(dom_ran),
2276
1.80k
         isl_space_from_range(ran_ran));
2277
1.80k
  return isl_space_join(isl_space_from_domain(isl_space_wrap(dom)),
2278
1.80k
          isl_space_from_range(isl_space_wrap(ran)));
2279
0
error:
2280
0
  isl_space_free(dim);
2281
0
  return NULL;
2282
1.80k
}
2283
2284
/* Can we apply isl_space_curry to "space"?
2285
 * That is, does it have a nested relation in its domain?
2286
 */
2287
isl_bool isl_space_can_curry(__isl_keep isl_space *space)
2288
13.0k
{
2289
13.0k
  if (!space)
2290
0
    return isl_bool_error;
2291
13.0k
2292
13.0k
  return !!space->nested[0];
2293
13.0k
}
2294
2295
/* Given a space (A -> B) -> C, return the corresponding space
2296
 * A -> (B -> C).
2297
 */
2298
__isl_give isl_space *isl_space_curry(__isl_take isl_space *space)
2299
4.30k
{
2300
4.30k
  isl_space *dom, *ran;
2301
4.30k
  isl_space *dom_dom, *dom_ran;
2302
4.30k
2303
4.30k
  if (!space)
2304
0
    return NULL;
2305
4.30k
2306
4.30k
  
if (4.30k
!isl_space_can_curry(space)4.30k
)
2307
0
    isl_die(space->ctx, isl_error_invalid,
2308
4.30k
      "space cannot be curried", goto error);
2309
4.30k
2310
4.30k
  dom = isl_space_unwrap(isl_space_domain(isl_space_copy(space)));
2311
4.30k
  ran = isl_space_range(space);
2312
4.30k
  dom_dom = isl_space_domain(isl_space_copy(dom));
2313
4.30k
  dom_ran = isl_space_range(dom);
2314
4.30k
  ran = isl_space_join(isl_space_from_domain(dom_ran),
2315
4.30k
         isl_space_from_range(ran));
2316
4.30k
  return isl_space_join(isl_space_from_domain(dom_dom),
2317
4.30k
          isl_space_from_range(isl_space_wrap(ran)));
2318
0
error:
2319
0
  isl_space_free(space);
2320
0
  return NULL;
2321
4.30k
}
2322
2323
/* Can isl_space_range_curry be applied to "space"?
2324
 * That is, does it have a nested relation in its range,
2325
 * the domain of which is itself a nested relation?
2326
 */
2327
isl_bool isl_space_can_range_curry(__isl_keep isl_space *space)
2328
8.66k
{
2329
8.66k
  isl_bool can;
2330
8.66k
2331
8.66k
  if (!space)
2332
0
    return isl_bool_error;
2333
8.66k
  can = isl_space_range_is_wrapping(space);
2334
8.66k
  if (
can < 0 || 8.66k
!can8.66k
)
2335
0
    return can;
2336
8.66k
  return isl_space_can_curry(space->nested[1]);
2337
8.66k
}
2338
2339
/* Given a space A -> ((B -> C) -> D), return the corresponding space
2340
 * A -> (B -> (C -> D)).
2341
 */
2342
__isl_give isl_space *isl_space_range_curry(__isl_take isl_space *space)
2343
4.28k
{
2344
4.28k
  if (!space)
2345
0
    return NULL;
2346
4.28k
2347
4.28k
  
if (4.28k
!isl_space_can_range_curry(space)4.28k
)
2348
0
    isl_die(isl_space_get_ctx(space), isl_error_invalid,
2349
4.28k
      "space range cannot be curried",
2350
4.28k
      return isl_space_free(space));
2351
4.28k
2352
4.28k
  space = isl_space_cow(space);
2353
4.28k
  if (!space)
2354
0
    return NULL;
2355
4.28k
  space->nested[1] = isl_space_curry(space->nested[1]);
2356
4.28k
  if (!space->nested[1])
2357
0
    return isl_space_free(space);
2358
4.28k
2359
4.28k
  return space;
2360
4.28k
}
2361
2362
/* Can we apply isl_space_uncurry to "space"?
2363
 * That is, does it have a nested relation in its range?
2364
 */
2365
isl_bool isl_space_can_uncurry(__isl_keep isl_space *space)
2366
258
{
2367
258
  if (!space)
2368
0
    return isl_bool_error;
2369
258
2370
258
  return !!space->nested[1];
2371
258
}
2372
2373
/* Given a space A -> (B -> C), return the corresponding space
2374
 * (A -> B) -> C.
2375
 */
2376
__isl_give isl_space *isl_space_uncurry(__isl_take isl_space *space)
2377
96
{
2378
96
  isl_space *dom, *ran;
2379
96
  isl_space *ran_dom, *ran_ran;
2380
96
2381
96
  if (!space)
2382
0
    return NULL;
2383
96
2384
96
  
if (96
!isl_space_can_uncurry(space)96
)
2385
0
    isl_die(space->ctx, isl_error_invalid,
2386
96
      "space cannot be uncurried",
2387
96
      return isl_space_free(space));
2388
96
2389
96
  dom = isl_space_domain(isl_space_copy(space));
2390
96
  ran = isl_space_unwrap(isl_space_range(space));
2391
96
  ran_dom = isl_space_domain(isl_space_copy(ran));
2392
96
  ran_ran = isl_space_range(ran);
2393
96
  dom = isl_space_join(isl_space_from_domain(dom),
2394
96
         isl_space_from_range(ran_dom));
2395
96
  return isl_space_join(isl_space_from_domain(isl_space_wrap(dom)),
2396
96
          isl_space_from_range(ran_ran));
2397
96
}
2398
2399
isl_bool isl_space_has_named_params(__isl_keep isl_space *space)
2400
309k
{
2401
309k
  int i;
2402
309k
  unsigned off;
2403
309k
2404
309k
  if (!space)
2405
0
    return isl_bool_error;
2406
309k
  
if (309k
space->nparam == 0309k
)
2407
120k
    return isl_bool_true;
2408
189k
  off = isl_space_offset(space, isl_dim_param);
2409
189k
  if (off + space->nparam > space->n_id)
2410
0
    return isl_bool_false;
2411
767k
  
for (i = 0; 189k
i < space->nparam767k
;
++i577k
)
2412
577k
    
if (577k
!space->ids[off + i]577k
)
2413
0
      return isl_bool_false;
2414
189k
  return isl_bool_true;
2415
189k
}
2416
2417
/* Check that "space" has only named parameters, reporting an error
2418
 * if it does not.
2419
 */
2420
isl_stat isl_space_check_named_params(__isl_keep isl_space *space)
2421
133k
{
2422
133k
  isl_bool named;
2423
133k
2424
133k
  named = isl_space_has_named_params(space);
2425
133k
  if (named < 0)
2426
0
    return isl_stat_error;
2427
133k
  
if (133k
!named133k
)
2428
0
    isl_die(isl_space_get_ctx(space), isl_error_invalid,
2429
133k
      "unaligned unnamed parameters", return isl_stat_error);
2430
133k
2431
133k
  return isl_stat_ok;
2432
133k
}
2433
2434
/* Align the initial parameters of dim1 to match the order in dim2.
2435
 */
2436
__isl_give isl_space *isl_space_align_params(__isl_take isl_space *dim1,
2437
  __isl_take isl_space *dim2)
2438
14.2k
{
2439
14.2k
  isl_reordering *exp;
2440
14.2k
2441
14.2k
  if (
!isl_space_has_named_params(dim1) || 14.2k
!isl_space_has_named_params(dim2)14.2k
)
2442
0
    isl_die(isl_space_get_ctx(dim1), isl_error_invalid,
2443
14.2k
      "parameter alignment requires named parameters",
2444
14.2k
      goto error);
2445
14.2k
2446
14.2k
  dim2 = isl_space_params(dim2);
2447
14.2k
  exp = isl_parameter_alignment_reordering(dim1, dim2);
2448
14.2k
  exp = isl_reordering_extend_space(exp, dim1);
2449
14.2k
  isl_space_free(dim2);
2450
14.2k
  if (!exp)
2451
0
    return NULL;
2452
14.2k
  dim1 = isl_space_copy(exp->dim);
2453
14.2k
  isl_reordering_free(exp);
2454
14.2k
  return dim1;
2455
0
error:
2456
0
  isl_space_free(dim1);
2457
0
  isl_space_free(dim2);
2458
0
  return NULL;
2459
14.2k
}
2460
2461
/* Given the space of set (domain), construct a space for a map
2462
 * with as domain the given space and as range the range of "model".
2463
 */
2464
__isl_give isl_space *isl_space_extend_domain_with_range(
2465
  __isl_take isl_space *space, __isl_take isl_space *model)
2466
32.3k
{
2467
32.3k
  if (!model)
2468
0
    goto error;
2469
32.3k
2470
32.3k
  space = isl_space_from_domain(space);
2471
32.3k
  space = isl_space_add_dims(space, isl_dim_out,
2472
32.3k
            isl_space_dim(model, isl_dim_out));
2473
32.3k
  if (isl_space_has_tuple_id(model, isl_dim_out))
2474
8
    space = isl_space_set_tuple_id(space, isl_dim_out,
2475
8
        isl_space_get_tuple_id(model, isl_dim_out));
2476
32.3k
  if (!space)
2477
0
    goto error;
2478
32.3k
  
if (32.3k
model->nested[1]32.3k
)
{1
2479
1
    isl_space *nested = isl_space_copy(model->nested[1]);
2480
1
    int n_nested, n_space;
2481
1
    nested = isl_space_align_params(nested, isl_space_copy(space));
2482
1
    n_nested = isl_space_dim(nested, isl_dim_param);
2483
1
    n_space = isl_space_dim(space, isl_dim_param);
2484
1
    if (n_nested > n_space)
2485
0
      nested = isl_space_drop_dims(nested, isl_dim_param,
2486
0
            n_space, n_nested - n_space);
2487
1
    if (!nested)
2488
0
      goto error;
2489
1
    space->nested[1] = nested;
2490
1
  }
2491
32.3k
  isl_space_free(model);
2492
32.3k
  return space;
2493
0
error:
2494
0
  isl_space_free(model);
2495
0
  isl_space_free(space);
2496
0
  return NULL;
2497
32.3k
}
2498
2499
/* Compare the "type" dimensions of two isl_spaces.
2500
 *
2501
 * The order is fairly arbitrary.
2502
 */
2503
static int isl_space_cmp_type(__isl_keep isl_space *space1,
2504
  __isl_keep isl_space *space2, enum isl_dim_type type)
2505
1.26M
{
2506
1.26M
  int cmp;
2507
1.26M
  isl_space *nested1, *nested2;
2508
1.26M
2509
1.26M
  if (isl_space_dim(space1, type) != isl_space_dim(space2, type))
2510
0
    return isl_space_dim(space1, type) -
2511
0
      isl_space_dim(space2, type);
2512
1.26M
2513
1.26M
  cmp = isl_id_cmp(tuple_id(space1, type), tuple_id(space2, type));
2514
1.26M
  if (cmp != 0)
2515
0
    return cmp;
2516
1.26M
2517
1.26M
  nested1 = nested(space1, type);
2518
1.26M
  nested2 = nested(space2, type);
2519
1.26M
  if (!nested1 != !nested2)
2520
0
    return !nested1 - !nested2;
2521
1.26M
2522
1.26M
  
if (1.26M
nested11.26M
)
2523
51.1k
    return isl_space_cmp(nested1, nested2);
2524
1.26M
2525
1.21M
  return 0;
2526
1.26M
}
2527
2528
/* Compare two isl_spaces.
2529
 *
2530
 * The order is fairly arbitrary.
2531
 */
2532
int isl_space_cmp(__isl_keep isl_space *space1, __isl_keep isl_space *space2)
2533
1.58M
{
2534
1.58M
  int i;
2535
1.58M
  int cmp;
2536
1.58M
2537
1.58M
  if (space1 == space2)
2538
1.15M
    return 0;
2539
422k
  
if (422k
!space1422k
)
2540
0
    return -1;
2541
422k
  
if (422k
!space2422k
)
2542
0
    return 1;
2543
422k
2544
422k
  cmp = isl_space_cmp_type(space1, space2, isl_dim_param);
2545
422k
  if (cmp != 0)
2546
0
    return cmp;
2547
422k
  cmp = isl_space_cmp_type(space1, space2, isl_dim_in);
2548
422k
  if (cmp != 0)
2549
0
    return cmp;
2550
422k
  cmp = isl_space_cmp_type(space1, space2, isl_dim_out);
2551
422k
  if (cmp != 0)
2552
0
    return cmp;
2553
422k
2554
422k
  
if (422k
!space1->ids && 422k
!space2->ids59.4k
)
2555
59.3k
    return 0;
2556
422k
2557
3.59M
  
for (i = 0; 363k
i < n(space1, isl_dim_param)3.59M
;
++i3.23M
)
{3.23M
2558
3.23M
    cmp = isl_id_cmp(get_id(space1, isl_dim_param, i),
2559
3.23M
         get_id(space2, isl_dim_param, i));
2560
3.23M
    if (cmp != 0)
2561
0
      return cmp;
2562
3.23M
  }
2563
363k
2564
363k
  return 0;
2565
363k
}