Coverage Report

Created: 2017-04-27 19:33

/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
913k
{
23
913k
  return dim ? dim->ctx : NULL;
24
913k
}
25
26
__isl_give isl_space *isl_space_alloc(isl_ctx *ctx,
27
      unsigned nparam, unsigned n_in, unsigned n_out)
28
3.21M
{
29
3.21M
  isl_space *dim;
30
3.21M
31
3.21M
  dim = isl_alloc_type(ctx, struct isl_space);
32
3.21M
  if (!dim)
33
1
    return NULL;
34
3.21M
35
3.21M
  dim->ctx = ctx;
36
3.21M
  isl_ctx_ref(ctx);
37
3.21M
  dim->ref = 1;
38
3.21M
  dim->nparam = nparam;
39
3.21M
  dim->n_in = n_in;
40
3.21M
  dim->n_out = n_out;
41
3.21M
42
3.21M
  dim->tuple_id[0] = NULL;
43
3.21M
  dim->tuple_id[1] = NULL;
44
3.21M
45
3.21M
  dim->nested[0] = NULL;
46
3.21M
  dim->nested[1] = NULL;
47
3.21M
48
3.21M
  dim->n_id = 0;
49
3.21M
  dim->ids = NULL;
50
3.21M
51
3.21M
  return dim;
52
3.21M
}
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
964k
{
59
964k
  space = isl_space_cow(space);
60
964k
  if (!space)
61
0
    return NULL;
62
964k
  space = isl_space_set_tuple_id(space, isl_dim_in, &isl_id_none);
63
964k
  return space;
64
964k
}
65
66
/* Is the space that of a set?
67
 */
68
isl_bool isl_space_is_set(__isl_keep isl_space *space)
69
1.01M
{
70
1.01M
  if (!space)
71
0
    return isl_bool_error;
72
1.01M
  
if (1.01M
space->n_in != 0 || 1.01M
space->nested[0]832k
)
73
184k
    return isl_bool_false;
74
826k
  
if (826k
space->tuple_id[0] != &isl_id_none826k
)
75
12.4k
    return isl_bool_false;
76
814k
  return isl_bool_true;
77
826k
}
78
79
/* Is the given space that of a map?
80
 */
81
isl_bool isl_space_is_map(__isl_keep isl_space *space)
82
11.7k
{
83
11.7k
  if (!space)
84
0
    return isl_bool_error;
85
11.7k
  return space->tuple_id[0] != &isl_id_none &&
86
372
    space->tuple_id[1] != &isl_id_none;
87
11.7k
}
88
89
__isl_give isl_space *isl_space_set_alloc(isl_ctx *ctx,
90
      unsigned nparam, unsigned dim)
91
334k
{
92
334k
  isl_space *space;
93
334k
  space = isl_space_alloc(ctx, nparam, 0, dim);
94
334k
  space = mark_as_set(space);
95
334k
  return space;
96
334k
}
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
93.2k
{
103
93.2k
  if (!space)
104
0
    return NULL;
105
93.2k
  space = isl_space_set_tuple_id(space, isl_dim_in, &isl_id_none);
106
93.2k
  space = isl_space_set_tuple_id(space, isl_dim_out, &isl_id_none);
107
93.2k
  return space;
108
93.2k
}
109
110
/* Is the space that of a parameter domain?
111
 */
112
isl_bool isl_space_is_params(__isl_keep isl_space *space)
113
426k
{
114
426k
  if (!space)
115
11
    return isl_bool_error;
116
426k
  
if (426k
space->n_in != 0 || 426k
space->nested[0]355k
||
117
355k
      
space->n_out != 0355k
||
space->nested[1]275k
)
118
151k
    return isl_bool_false;
119
275k
  
if (275k
space->tuple_id[0] != &isl_id_none275k
)
120
15.2k
    return isl_bool_false;
121
259k
  
if (259k
space->tuple_id[1] != &isl_id_none259k
)
122
19.5k
    return isl_bool_false;
123
240k
  return isl_bool_true;
124
259k
}
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.8k
{
130
19.8k
  isl_space *space;
131
19.8k
  space = isl_space_alloc(ctx, nparam, 0, 0);
132
19.8k
  space = mark_as_params(space);
133
19.8k
  return space;
134
19.8k
}
135
136
static unsigned global_pos(__isl_keep isl_space *dim,
137
         enum isl_dim_type type, unsigned pos)
138
50.2M
{
139
50.2M
  struct isl_ctx *ctx = dim->ctx;
140
50.2M
141
50.2M
  switch (type) {
142
28.7M
  case isl_dim_param:
143
28.7M
    isl_assert(ctx, pos < dim->nparam,
144
28.7M
          return isl_space_dim(dim, isl_dim_all));
145
28.7M
    return pos;
146
8.24M
  case isl_dim_in:
147
8.24M
    isl_assert(ctx, pos < dim->n_in,
148
8.24M
          return isl_space_dim(dim, isl_dim_all));
149
8.24M
    return pos + dim->nparam;
150
13.2M
  case isl_dim_out:
151
13.2M
    isl_assert(ctx, pos < dim->n_out,
152
13.2M
          return isl_space_dim(dim, isl_dim_all));
153
13.2M
    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
50.2M
  }
157
0
  return isl_space_dim(dim, isl_dim_all);
158
50.2M
}
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
2.43M
{
164
2.43M
  isl_id **ids;
165
2.43M
  int i;
166
2.43M
167
2.43M
  if (isl_space_dim(dim, isl_dim_all) <= dim->n_id)
168
692k
    return dim;
169
2.43M
170
1.73M
  
if (1.73M
!dim->ids1.73M
)
{1.73M
171
1.73M
    dim->ids = isl_calloc_array(dim->ctx,
172
1.73M
        isl_id *, isl_space_dim(dim, isl_dim_all));
173
1.73M
    if (!dim->ids)
174
0
      goto error;
175
535
  } else {
176
535
    ids = isl_realloc_array(dim->ctx, dim->ids,
177
535
        isl_id *, isl_space_dim(dim, isl_dim_all));
178
535
    if (!ids)
179
0
      goto error;
180
535
    dim->ids = ids;
181
2.81k
    for (i = dim->n_id; 
i < isl_space_dim(dim, isl_dim_all)2.81k
;
++i2.27k
)
182
2.27k
      dim->ids[i] = NULL;
183
535
  }
184
1.73M
185
1.73M
  dim->n_id = isl_space_dim(dim, isl_dim_all);
186
1.73M
187
1.73M
  return dim;
188
0
error:
189
0
  isl_space_free(dim);
190
0
  return NULL;
191
1.73M
}
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
9.75M
{
196
9.75M
  dim = isl_space_cow(dim);
197
9.75M
198
9.75M
  if (!dim)
199
0
    goto error;
200
9.75M
201
9.75M
  pos = global_pos(dim, type, pos);
202
9.75M
  if (pos == isl_space_dim(dim, isl_dim_all))
203
0
    goto error;
204
9.75M
205
9.75M
  
if (9.75M
pos >= dim->n_id9.75M
)
{1.73M
206
1.73M
    if (!id)
207
0
      return dim;
208
1.73M
    dim = extend_ids(dim);
209
1.73M
    if (!dim)
210
0
      goto error;
211
1.73M
  }
212
9.75M
213
9.75M
  dim->ids[pos] = id;
214
9.75M
215
9.75M
  return dim;
216
0
error:
217
0
  isl_id_free(id);
218
0
  isl_space_free(dim);
219
0
  return NULL;
220
9.75M
}
221
222
static __isl_keep isl_id *get_id(__isl_keep isl_space *dim,
223
         enum isl_dim_type type, unsigned pos)
224
40.4M
{
225
40.4M
  if (!dim)
226
0
    return NULL;
227
40.4M
228
40.4M
  pos = global_pos(dim, type, pos);
229
40.4M
  if (pos == isl_space_dim(dim, isl_dim_all))
230
0
    return NULL;
231
40.4M
  
if (40.4M
pos >= dim->n_id40.4M
)
232
1.38M
    return NULL;
233
39.0M
  return dim->ids[pos];
234
40.4M
}
235
236
static unsigned offset(__isl_keep isl_space *dim, enum isl_dim_type type)
237
1.48M
{
238
1.48M
  switch (type) {
239
445k
  case isl_dim_param: return 0;
240
340k
  case isl_dim_in:  return dim->nparam;
241
697k
  case isl_dim_out: return dim->nparam + dim->n_in;
242
0
  default:    return 0;
243
1.48M
  }
244
1.48M
}
245
246
static unsigned n(__isl_keep isl_space *dim, enum isl_dim_type type)
247
203M
{
248
203M
  switch (type) {
249
39.4M
  case isl_dim_param: return dim->nparam;
250
23.1M
  case isl_dim_in:  return dim->n_in;
251
27.2M
  case isl_dim_out: return dim->n_out;
252
113M
  case isl_dim_all: return dim->nparam + dim->n_in + dim->n_out;
253
0
  default:    return 0;
254
203M
  }
255
203M
}
256
257
unsigned isl_space_dim(__isl_keep isl_space *dim, enum isl_dim_type type)
258
144M
{
259
144M
  if (!dim)
260
0
    return 0;
261
144M
  return n(dim, type);
262
144M
}
263
264
unsigned isl_space_offset(__isl_keep isl_space *dim, enum isl_dim_type type)
265
1.16M
{
266
1.16M
  if (!dim)
267
0
    return 0;
268
1.16M
  return offset(dim, type);
269
1.16M
}
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
6.20M
{
275
6.20M
  int i;
276
6.20M
  isl_id *id;
277
6.20M
278
6.20M
  if (!dst)
279
0
    return NULL;
280
6.20M
281
17.1M
  
for (i = 0; 6.20M
i < n(src, src_type)17.1M
;
++i10.9M
)
{10.9M
282
10.9M
    id = get_id(src, src_type, i);
283
10.9M
    if (!id)
284
3.63M
      continue;
285
7.27M
    dst = set_id(dst, dst_type, offset + i, isl_id_copy(id));
286
7.27M
    if (!dst)
287
0
      return NULL;
288
7.27M
  }
289
6.20M
  return dst;
290
6.20M
}
291
292
__isl_take isl_space *isl_space_dup(__isl_keep isl_space *dim)
293
2.42M
{
294
2.42M
  isl_space *dup;
295
2.42M
  if (!dim)
296
0
    return NULL;
297
2.42M
  dup = isl_space_alloc(dim->ctx, dim->nparam, dim->n_in, dim->n_out);
298
2.42M
  if (!dup)
299
1
    return NULL;
300
2.42M
  
if (2.42M
dim->tuple_id[0] &&2.42M
301
1.42M
      !(dup->tuple_id[0] = isl_id_copy(dim->tuple_id[0])))
302
0
    goto error;
303
2.42M
  
if (2.42M
dim->tuple_id[1] &&2.42M
304
584k
      !(dup->tuple_id[1] = isl_id_copy(dim->tuple_id[1])))
305
0
    goto error;
306
2.42M
  
if (2.42M
dim->nested[0] && 2.42M
!(dup->nested[0] = isl_space_copy(dim->nested[0]))404k
)
307
0
    goto error;
308
2.42M
  
if (2.42M
dim->nested[1] && 2.42M
!(dup->nested[1] = isl_space_copy(dim->nested[1]))535k
)
309
0
    goto error;
310
2.42M
  
if (2.42M
!dim->ids2.42M
)
311
843k
    return dup;
312
1.58M
  dup = copy_ids(dup, isl_dim_param, 0, dim, isl_dim_param);
313
1.58M
  dup = copy_ids(dup, isl_dim_in, 0, dim, isl_dim_in);
314
1.58M
  dup = copy_ids(dup, isl_dim_out, 0, dim, isl_dim_out);
315
1.58M
  return dup;
316
0
error:
317
0
  isl_space_free(dup);
318
0
  return NULL;
319
2.42M
}
320
321
__isl_give isl_space *isl_space_cow(__isl_take isl_space *dim)
322
17.1M
{
323
17.1M
  if (!dim)
324
1
    return NULL;
325
17.1M
326
17.1M
  
if (17.1M
dim->ref == 117.1M
)
327
14.7M
    return dim;
328
2.40M
  dim->ref--;
329
2.40M
  return isl_space_dup(dim);
330
17.1M
}
331
332
__isl_give isl_space *isl_space_copy(__isl_keep isl_space *dim)
333
10.2M
{
334
10.2M
  if (!dim)
335
6.54k
    return NULL;
336
10.2M
337
10.2M
  dim->ref++;
338
10.2M
  return dim;
339
10.2M
}
340
341
__isl_null isl_space *isl_space_free(__isl_take isl_space *space)
342
18.2M
{
343
18.2M
  int i;
344
18.2M
345
18.2M
  if (!space)
346
7.27M
    return NULL;
347
18.2M
348
11.0M
  
if (11.0M
--space->ref > 011.0M
)
349
7.81M
    return NULL;
350
11.0M
351
3.21M
  isl_id_free(space->tuple_id[0]);
352
3.21M
  isl_id_free(space->tuple_id[1]);
353
3.21M
354
3.21M
  isl_space_free(space->nested[0]);
355
3.21M
  isl_space_free(space->nested[1]);
356
3.21M
357
10.0M
  for (i = 0; 
i < space->n_id10.0M
;
++i6.84M
)
358
6.84M
    isl_id_free(space->ids[i]);
359
3.21M
  free(space->ids);
360
3.21M
  isl_ctx_deref(space->ctx);
361
3.21M
  
362
3.21M
  free(space);
363
3.21M
364
3.21M
  return NULL;
365
11.0M
}
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.9k
{
374
46.9k
  char *p;
375
46.9k
  long dummy;
376
46.9k
377
46.9k
  dummy = strtol(s, &p, 0);
378
46.9k
  if (p != s)
379
0
    isl_die(ctx, isl_error_invalid, "name looks like a number",
380
46.9k
      return 0);
381
46.9k
382
46.9k
  return 1;
383
46.9k
}
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
64.2k
{
390
64.2k
  if (!space)
391
0
    return 0;
392
64.2k
  
if (64.2k
isl_space_is_params(space)64.2k
)
393
0
    isl_die(space->ctx, isl_error_invalid,
394
64.2k
      "parameter spaces don't have tuple ids", return 0);
395
64.2k
  
if (64.2k
isl_space_is_set(space) && 64.2k
type != isl_dim_set17.7k
)
396
0
    isl_die(space->ctx, isl_error_invalid,
397
64.2k
      "set spaces can only have a set id", return 0);
398
64.2k
  
if (64.2k
type != isl_dim_in && 64.2k
type != isl_dim_out64.0k
)
399
0
    isl_die(space->ctx, isl_error_invalid,
400
64.2k
      "only input, output and set tuples can have ids",
401
64.2k
      return 0);
402
64.2k
403
64.2k
  return 1;
404
64.2k
}
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
63.6k
{
411
63.6k
  if (!space_can_have_id(dim, type))
412
0
    return isl_bool_error;
413
63.6k
  return dim->tuple_id[type - isl_dim_in] != NULL;
414
63.6k
}
415
416
__isl_give isl_id *isl_space_get_tuple_id(__isl_keep isl_space *dim,
417
  enum isl_dim_type type)
418
22.0k
{
419
22.0k
  int has_id;
420
22.0k
421
22.0k
  if (!dim)
422
0
    return NULL;
423
22.0k
  has_id = isl_space_has_tuple_id(dim, type);
424
22.0k
  if (has_id < 0)
425
0
    return NULL;
426
22.0k
  
if (22.0k
!has_id22.0k
)
427
0
    isl_die(dim->ctx, isl_error_invalid,
428
22.0k
      "tuple has no id", return NULL);
429
22.0k
  return isl_id_copy(dim->tuple_id[type - isl_dim_in]);
430
22.0k
}
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.20M
{
435
1.20M
  dim = isl_space_cow(dim);
436
1.20M
  if (
!dim || 1.20M
!id1.20M
)
437
0
    goto error;
438
1.20M
  
if (1.20M
type != isl_dim_in && 1.20M
type != isl_dim_out145k
)
439
0
    isl_die(dim->ctx, isl_error_invalid,
440
1.20M
      "only input, output and set tuples can have names",
441
1.20M
      goto error);
442
1.20M
443
1.20M
  isl_id_free(dim->tuple_id[type - isl_dim_in]);
444
1.20M
  dim->tuple_id[type - isl_dim_in] = id;
445
1.20M
446
1.20M
  return dim;
447
0
error:
448
0
  isl_id_free(id);
449
0
  isl_space_free(dim);
450
0
  return NULL;
451
1.20M
}
452
453
__isl_give isl_space *isl_space_reset_tuple_id(__isl_take isl_space *dim,
454
  enum isl_dim_type type)
455
4.78k
{
456
4.78k
  dim = isl_space_cow(dim);
457
4.78k
  if (!dim)
458
0
    return NULL;
459
4.78k
  
if (4.78k
type != isl_dim_in && 4.78k
type != isl_dim_out4.78k
)
460
0
    isl_die(dim->ctx, isl_error_invalid,
461
4.78k
      "only input, output and set tuples can have names",
462
4.78k
      goto error);
463
4.78k
464
4.78k
  isl_id_free(dim->tuple_id[type - isl_dim_in]);
465
4.78k
  dim->tuple_id[type - isl_dim_in] = NULL;
466
4.78k
467
4.78k
  return dim;
468
0
error:
469
0
  isl_space_free(dim);
470
0
  return NULL;
471
4.78k
}
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
56.9k
{
481
56.9k
  space = isl_space_cow(space);
482
56.9k
  if (
!space || 56.9k
!id56.9k
)
483
0
    goto error;
484
56.9k
485
56.9k
  
if (56.9k
type == isl_dim_param56.9k
)
{41.3k
486
41.3k
    int i;
487
41.3k
488
124k
    for (i = 0; 
i < 2124k
;
++i82.6k
)
{82.6k
489
82.6k
      if (!space->nested[i])
490
82.6k
        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
41.3k
  }
498
56.9k
499
56.9k
  isl_id_free(get_id(space, type, pos));
500
56.9k
  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
56.9k
}
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
934
{
543
934
  if (!dim)
544
0
    return isl_bool_error;
545
934
  return get_id(dim, type, pos) != NULL;
546
934
}
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
809k
{
551
809k
  if (!dim)
552
0
    return NULL;
553
809k
  
if (809k
!get_id(dim, type, pos)809k
)
554
0
    isl_die(dim->ctx, isl_error_invalid,
555
809k
      "dim has no id", return NULL);
556
809k
  return isl_id_copy(get_id(dim, type, pos));
557
809k
}
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.3k
{
562
42.3k
  isl_id *id;
563
42.3k
564
42.3k
  if (!dim)
565
0
    return NULL;
566
42.3k
567
42.3k
  
if (42.3k
!s42.3k
)
568
0
    return isl_space_reset_tuple_id(dim, type);
569
42.3k
570
42.3k
  
if (42.3k
!name_ok(dim->ctx, s)42.3k
)
571
0
    goto error;
572
42.3k
573
42.3k
  id = isl_id_alloc(dim->ctx, s, NULL);
574
42.3k
  return isl_space_set_tuple_id(dim, type, id);
575
0
error:
576
0
  isl_space_free(dim);
577
0
  return NULL;
578
42.3k
}
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
624
{
585
624
  isl_id *id;
586
624
587
624
  if (!space_can_have_id(space, type))
588
0
    return isl_bool_error;
589
624
  id = space->tuple_id[type - isl_dim_in];
590
147
  return id && id->name;
591
624
}
592
593
const char *isl_space_get_tuple_name(__isl_keep isl_space *dim,
594
   enum isl_dim_type type)
595
6.88k
{
596
6.88k
  isl_id *id;
597
6.88k
  if (!dim)
598
0
    return NULL;
599
6.88k
  
if (6.88k
type != isl_dim_in && 6.88k
type != isl_dim_out4.10k
)
600
0
    return NULL;
601
6.88k
  id = dim->tuple_id[type - isl_dim_in];
602
5.92k
  return id ? id->name : NULL;
603
6.88k
}
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.61k
{
609
4.61k
  isl_id *id;
610
4.61k
611
4.61k
  if (!dim)
612
0
    return NULL;
613
4.61k
  
if (4.61k
!s4.61k
)
614
0
    return isl_space_reset_dim_id(dim, type, pos);
615
4.61k
  
if (4.61k
!name_ok(dim->ctx, s)4.61k
)
616
0
    goto error;
617
4.61k
  id = isl_id_alloc(dim->ctx, s, NULL);
618
4.61k
  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.61k
}
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.26k
{
629
4.26k
  isl_id *id;
630
4.26k
631
4.26k
  if (!space)
632
0
    return isl_bool_error;
633
4.26k
  id = get_id(space, type, pos);
634
812
  return id && id->name;
635
4.26k
}
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
295k
{
640
295k
  isl_id *id = get_id(dim, type, pos);
641
269k
  return id ? id->name : NULL;
642
295k
}
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
770
{
666
770
  int i;
667
770
  int offset;
668
770
  int n;
669
770
670
770
  if (
!space || 770
!name770
)
671
0
    return -1;
672
770
673
770
  offset = isl_space_offset(space, type);
674
770
  n = isl_space_dim(space, type);
675
1.23k
  for (i = 0; 
i < n && 1.23k
offset + i < space->n_id467
;
++i467
)
{467
676
467
    isl_id *id = get_id(space, type, i);
677
467
    if (
id && 467
id->name467
&&
!strcmp(id->name, name)467
)
678
0
      return i;
679
467
  }
680
770
681
770
  return -1;
682
770
}
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
26.9M
{
746
26.9M
  if (!dim)
747
0
    return NULL;
748
26.9M
  
if (26.9M
type == isl_dim_in26.9M
)
749
8.47M
    return dim->tuple_id[0];
750
18.4M
  
if (18.4M
type == isl_dim_out18.4M
)
751
7.70M
    return dim->tuple_id[1];
752
10.7M
  return NULL;
753
18.4M
}
754
755
static __isl_keep isl_space *nested(__isl_keep isl_space *dim,
756
  enum isl_dim_type type)
757
25.0M
{
758
25.0M
  if (!dim)
759
0
    return NULL;
760
25.0M
  
if (25.0M
type == isl_dim_in25.0M
)
761
7.25M
    return dim->nested[0];
762
17.7M
  
if (17.7M
type == isl_dim_out17.7M
)
763
7.01M
    return dim->nested[1];
764
10.7M
  return NULL;
765
17.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
4.02M
{
772
4.02M
  if (
!space1 || 4.02M
!space24.02M
)
773
0
    return isl_bool_error;
774
4.02M
  
if (4.02M
space1 == space24.02M
)
775
1.07M
    return isl_bool_true;
776
2.95M
  return isl_space_tuple_is_equal(space1, isl_dim_in,
777
2.95M
          space2, isl_dim_in) &&
778
2.53M
         isl_space_tuple_is_equal(space1, isl_dim_out,
779
2.53M
          space2, isl_dim_out);
780
4.02M
}
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
13.0M
{
798
13.0M
  isl_id *id1, *id2;
799
13.0M
  isl_space *nested1, *nested2;
800
13.0M
801
13.0M
  if (
!space1 || 13.0M
!space213.0M
)
802
0
    return isl_bool_error;
803
13.0M
804
13.0M
  
if (13.0M
space1 == space2 && 13.0M
type1 == type21.15M
)
805
5.69k
    return isl_bool_true;
806
13.0M
807
13.0M
  
if (13.0M
n(space1, type1) != n(space2, type2)13.0M
)
808
1.28M
    return isl_bool_false;
809
11.7M
  id1 = tuple_id(space1, type1);
810
11.7M
  id2 = tuple_id(space2, type2);
811
11.7M
  if (!id1 ^ !id2)
812
401k
    return isl_bool_false;
813
11.3M
  
if (11.3M
id1 && 11.3M
id1 != id22.67M
)
814
94.6k
    return isl_bool_false;
815
11.2M
  nested1 = nested(space1, type1);
816
11.2M
  nested2 = nested(space2, type2);
817
11.2M
  if (!nested1 ^ !nested2)
818
40.2k
    return isl_bool_false;
819
11.1M
  
if (11.1M
nested1 && 11.1M
!isl_space_has_equal_tuples(nested1, nested2)1.77M
)
820
13.7k
    return isl_bool_false;
821
11.1M
  return isl_bool_true;
822
11.1M
}
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
7.07M
{
836
7.07M
  int i;
837
7.07M
838
7.07M
  if (
space1 == space2 && 7.07M
type1 == type21.86M
)
839
725k
    return isl_bool_true;
840
7.07M
841
6.35M
  
if (6.35M
!isl_space_tuple_is_equal(space1, type1, space2, type2)6.35M
)
842
1.22M
    return isl_bool_false;
843
6.35M
844
5.13M
  
if (5.13M
!space1->ids && 5.13M
!space2->ids1.29M
)
845
1.19M
    return isl_bool_true;
846
5.13M
847
10.5M
  
for (i = 0; 3.93M
i < n(space1, type1)10.5M
;
++i6.58M
)
{6.62M
848
6.62M
    if (get_id(space1, type1, i) != get_id(space2, type2, i))
849
32.2k
      return isl_bool_false;
850
6.62M
  }
851
3.90M
  return isl_bool_true;
852
3.93M
}
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
5.62M
{
859
5.62M
  if (
!space1 || 5.62M
!space25.62M
)
860
0
    return isl_bool_error;
861
5.62M
862
5.62M
  return match(space1, isl_dim_param, space2, isl_dim_param);
863
5.62M
}
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
155k
{
871
155k
  isl_bool equal;
872
155k
873
155k
  if (
!space1 || 155k
!space2155k
)
874
0
    return isl_bool_error;
875
155k
876
155k
  equal = match(space1, isl_dim_in, space2, isl_dim_in);
877
155k
  if (
equal < 0 || 155k
!equal155k
)
878
137
    return equal;
879
155k
  return match(space1, isl_dim_out, space2, isl_dim_out);
880
155k
}
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.82M
{
894
2.82M
  int i;
895
2.82M
896
6.89M
  for (i = 0; 
i < n6.89M
;
++i4.06M
)
897
4.06M
    ids[i] = get_id(dim, type, first + i);
898
2.82M
}
899
900
static __isl_give isl_space *space_extend(__isl_take isl_space *space,
901
      unsigned nparam, unsigned n_in, unsigned n_out)
902
499k
{
903
499k
  isl_id **ids = NULL;
904
499k
905
499k
  if (!space)
906
0
    return NULL;
907
499k
  
if (499k
space->nparam == nparam &&499k
908
367k
      
space->n_in == n_in367k
&&
space->n_out == n_out362k
)
909
22.6k
    return space;
910
499k
911
476k
  
isl_assert476k
(space->ctx, space->nparam <= nparam, goto error);476k
912
476k
  
isl_assert476k
(space->ctx, space->n_in <= n_in, goto error);476k
913
476k
  
isl_assert476k
(space->ctx, space->n_out <= n_out, goto error);476k
914
476k
915
476k
  space = isl_space_cow(space);
916
476k
  if (!space)
917
0
    goto error;
918
476k
919
476k
  
if (476k
space->ids476k
)
{255k
920
255k
    unsigned n;
921
255k
    n = nparam + n_in + n_out;
922
255k
    if (
n < nparam || 255k
n < n_in255k
||
n < n_out255k
)
923
0
      isl_die(isl_space_get_ctx(space), isl_error_invalid,
924
255k
        "overflow in total number of dimensions",
925
255k
        goto error);
926
255k
    
ids = 255k
isl_calloc_array255k
(space->ctx, isl_id *, n);
927
255k
    if (!ids)
928
0
      goto error;
929
255k
    get_ids(space, isl_dim_param, 0, space->nparam, ids);
930
255k
    get_ids(space, isl_dim_in, 0, space->n_in, ids + nparam);
931
255k
    get_ids(space, isl_dim_out, 0, space->n_out,
932
255k
      ids + nparam + n_in);
933
255k
    free(space->ids);
934
255k
    space->ids = ids;
935
255k
    space->n_id = nparam + n_in + n_out;
936
255k
  }
937
476k
  space->nparam = nparam;
938
476k
  space->n_in = n_in;
939
476k
  space->n_out = n_out;
940
476k
941
476k
  return space;
942
0
error:
943
0
  free(ids);
944
0
  isl_space_free(space);
945
0
  return NULL;
946
476k
}
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
499k
{
957
499k
  space = isl_space_reset(space, type);
958
499k
  if (!space)
959
1
    return NULL;
960
499k
  switch (type) {
961
153k
  case isl_dim_param:
962
153k
    space = space_extend(space,
963
153k
        space->nparam + n, space->n_in, space->n_out);
964
153k
    if (
space && 153k
space->nested[0]153k
&&
965
6.05k
        !(space->nested[0] = isl_space_add_dims(space->nested[0],
966
6.05k
                isl_dim_param, n)))
967
0
      goto error;
968
153k
    
if (153k
space && 153k
space->nested[1]153k
&&
969
4.46k
        !(space->nested[1] = isl_space_add_dims(space->nested[1],
970
4.46k
                isl_dim_param, n)))
971
0
      goto error;
972
153k
    return space;
973
5.90k
  case isl_dim_in:
974
5.90k
    return space_extend(space,
975
5.90k
        space->nparam, space->n_in + n, space->n_out);
976
340k
  case isl_dim_out:
977
340k
    return space_extend(space,
978
340k
        space->nparam, space->n_in, space->n_out + n);
979
0
  default:
980
0
    isl_die(space->ctx, isl_error_invalid,
981
499k
      "cannot add dimensions of specified type", goto error);
982
499k
  }
983
0
error:
984
0
  isl_space_free(space);
985
0
  return NULL;
986
499k
}
987
988
static int valid_dim_type(enum isl_dim_type type)
989
1.27M
{
990
1.27M
  switch (type) {
991
1.27M
  case isl_dim_param:
992
1.27M
  case isl_dim_in:
993
1.27M
  case isl_dim_out:
994
1.27M
    return 1;
995
0
  default:
996
0
    return 0;
997
1.27M
  }
998
1.27M
}
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
117k
{
1007
117k
  isl_id **ids = NULL;
1008
117k
1009
117k
  if (!dim)
1010
0
    return NULL;
1011
117k
  
if (117k
n == 0117k
)
1012
2
    return isl_space_reset(dim, type);
1013
117k
1014
117k
  
if (117k
!valid_dim_type(type)117k
)
1015
0
    isl_die(dim->ctx, isl_error_invalid,
1016
117k
      "cannot insert dimensions of specified type",
1017
117k
      goto error);
1018
117k
1019
117k
  
isl_assert117k
(dim->ctx, pos <= isl_space_dim(dim, type), goto error);117k
1020
117k
1021
117k
  dim = isl_space_cow(dim);
1022
117k
  if (!dim)
1023
0
    return NULL;
1024
117k
1025
117k
  
if (117k
dim->ids117k
)
{65.8k
1026
65.8k
    enum isl_dim_type t, o = isl_dim_param;
1027
65.8k
    int off;
1028
65.8k
    int s[3];
1029
65.8k
    ids = isl_calloc_array(dim->ctx, isl_id *,
1030
65.8k
             dim->nparam + dim->n_in + dim->n_out + n);
1031
65.8k
    if (!ids)
1032
0
      goto error;
1033
65.8k
    off = 0;
1034
65.8k
    s[isl_dim_param - o] = dim->nparam;
1035
65.8k
    s[isl_dim_in - o] = dim->n_in;
1036
65.8k
    s[isl_dim_out - o] = dim->n_out;
1037
263k
    for (t = isl_dim_param; 
t <= isl_dim_out263k
;
++t197k
)
{197k
1038
197k
      if (
t != type197k
)
{131k
1039
131k
        get_ids(dim, t, 0, s[t - o], ids + off);
1040
131k
        off += s[t - o];
1041
65.8k
      } else {
1042
65.8k
        get_ids(dim, t, 0, pos, ids + off);
1043
65.8k
        off += pos + n;
1044
65.8k
        get_ids(dim, t, pos, s[t - o] - pos, ids + off);
1045
65.8k
        off += s[t - o] - pos;
1046
65.8k
      }
1047
197k
    }
1048
65.8k
    free(dim->ids);
1049
65.8k
    dim->ids = ids;
1050
65.8k
    dim->n_id = dim->nparam + dim->n_in + dim->n_out + n;
1051
65.8k
  }
1052
117k
  switch (type) {
1053
1.84k
  case isl_dim_param: dim->nparam += n; break;
1054
7.04k
  case isl_dim_in:  dim->n_in += n; break;
1055
109k
  case isl_dim_out: dim->n_out += n; break;
1056
0
  default:    ;
1057
117k
  }
1058
117k
  dim = isl_space_reset(dim, type);
1059
117k
1060
117k
  if (
type == isl_dim_param117k
)
{1.84k
1061
1.84k
    if (
dim && 1.84k
dim->nested[0]1.84k
&&
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.84k
    
if (1.84k
dim && 1.84k
dim->nested[1]1.84k
&&
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.84k
  }
1070
117k
1071
117k
  return dim;
1072
0
error:
1073
0
  isl_space_free(dim);
1074
0
  return NULL;
1075
117k
}
1076
1077
__isl_give isl_space *isl_space_move_dims(__isl_take isl_space *space,
1078
  enum isl_dim_type dst_type, unsigned dst_pos,
1079
  enum isl_dim_type src_type, unsigned src_pos, unsigned n)
1080
802
{
1081
802
  int i;
1082
802
1083
802
  space = isl_space_reset(space, src_type);
1084
802
  space = isl_space_reset(space, dst_type);
1085
802
  if (!space)
1086
0
    return NULL;
1087
802
  
if (802
n == 0802
)
1088
109
    return space;
1089
802
1090
693
  
isl_assert693
(space->ctx, src_pos + n <= isl_space_dim(space, src_type),693
1091
693
    goto error);
1092
693
1093
693
  
if (693
dst_type == src_type && 693
dst_pos == src_pos0
)
1094
0
    return space;
1095
693
1096
693
  
isl_assert693
(space->ctx, dst_type != src_type, goto error);693
1097
693
1098
693
  space = isl_space_cow(space);
1099
693
  if (!space)
1100
0
    return NULL;
1101
693
1102
693
  
if (693
space->ids693
)
{465
1103
465
    isl_id **ids;
1104
465
    enum isl_dim_type t, o = isl_dim_param;
1105
465
    int off;
1106
465
    int s[3];
1107
465
    ids = isl_calloc_array(space->ctx, isl_id *,
1108
465
         space->nparam + space->n_in + space->n_out);
1109
465
    if (!ids)
1110
0
      goto error;
1111
465
    off = 0;
1112
465
    s[isl_dim_param - o] = space->nparam;
1113
465
    s[isl_dim_in - o] = space->n_in;
1114
465
    s[isl_dim_out - o] = space->n_out;
1115
1.86k
    for (t = isl_dim_param; 
t <= isl_dim_out1.86k
;
++t1.39k
)
{1.39k
1116
1.39k
      if (
t == dst_type1.39k
)
{465
1117
465
        get_ids(space, t, 0, dst_pos, ids + off);
1118
465
        off += dst_pos;
1119
465
        get_ids(space, src_type, src_pos, n, ids + off);
1120
465
        off += n;
1121
465
        get_ids(space, t, dst_pos, s[t - o] - dst_pos,
1122
465
            ids + off);
1123
465
        off += s[t - o] - dst_pos;
1124
930
      } else 
if (930
t == src_type930
)
{465
1125
465
        get_ids(space, t, 0, src_pos, ids + off);
1126
465
        off += src_pos;
1127
465
        get_ids(space, t, src_pos + n,
1128
465
              s[t - o] - src_pos - n, ids + off);
1129
465
        off += s[t - o] - src_pos - n;
1130
465
      } else {
1131
465
        get_ids(space, t, 0, s[t - o], ids + off);
1132
465
        off += s[t - o];
1133
465
      }
1134
1.39k
    }
1135
465
    free(space->ids);
1136
465
    space->ids = ids;
1137
465
    space->n_id = space->nparam + space->n_in + space->n_out;
1138
465
  }
1139
693
1140
693
  switch (dst_type) {
1141
38
  case isl_dim_param: space->nparam += n; break;
1142
285
  case isl_dim_in:  space->n_in += n; break;
1143
370
  case isl_dim_out: space->n_out += n; break;
1144
0
  default:    ;
1145
693
  }
1146
693
1147
693
  switch (src_type) {
1148
233
  case isl_dim_param: space->nparam -= n; break;
1149
155
  case isl_dim_in:  space->n_in -= n; break;
1150
305
  case isl_dim_out: space->n_out -= n; break;
1151
0
  default:    ;
1152
693
  }
1153
693
1154
693
  
if (693
dst_type != isl_dim_param && 693
src_type != isl_dim_param655
)
1155
422
    return space;
1156
693
1157
813
  
for (i = 0; 271
i < 2813
;
++i542
)
{542
1158
542
    if (!space->nested[i])
1159
525
      continue;
1160
17
    space->nested[i] = isl_space_replace(space->nested[i],
1161
17
             isl_dim_param, space);
1162
17
    if (!space->nested[i])
1163
0
      goto error;
1164
17
  }
1165
271
1166
271
  return space;
1167
0
error:
1168
0
  isl_space_free(space);
1169
0
  return NULL;
1170
271
}
1171
1172
/* Check that "space1" and "space2" have the same parameters,
1173
 * reporting an error if they do not.
1174
 */
1175
isl_stat isl_space_check_equal_params(__isl_keep isl_space *space1,
1176
  __isl_keep isl_space *space2)
1177
378k
{
1178
378k
  isl_bool equal;
1179
378k
1180
378k
  equal = isl_space_has_equal_params(space1, space2);
1181
378k
  if (equal < 0)
1182
0
    return isl_stat_error;
1183
378k
  
if (378k
!equal378k
)
1184
0
    isl_die(isl_space_get_ctx(space1), isl_error_invalid,
1185
378k
      "parameters need to match", return isl_stat_error);
1186
378k
  return isl_stat_ok;
1187
378k
}
1188
1189
__isl_give isl_space *isl_space_join(__isl_take isl_space *left,
1190
  __isl_take isl_space *right)
1191
319k
{
1192
319k
  isl_space *dim;
1193
319k
1194
319k
  if (isl_space_check_equal_params(left, right) < 0)
1195
0
    goto error;
1196
319k
1197
319k
  
isl_assert319k
(left->ctx,319k
1198
319k
    isl_space_tuple_is_equal(left, isl_dim_out, right, isl_dim_in),
1199
319k
    goto error);
1200
319k
1201
319k
  dim = isl_space_alloc(left->ctx, left->nparam, left->n_in, right->n_out);
1202
319k
  if (!dim)
1203
0
    goto error;
1204
319k
1205
319k
  dim = copy_ids(dim, isl_dim_param, 0, left, isl_dim_param);
1206
319k
  dim = copy_ids(dim, isl_dim_in, 0, left, isl_dim_in);
1207
319k
  dim = copy_ids(dim, isl_dim_out, 0, right, isl_dim_out);
1208
319k
1209
319k
  if (
dim && 319k
left->tuple_id[0]319k
&&
1210
104k
      !(dim->tuple_id[0] = isl_id_copy(left->tuple_id[0])))
1211
0
    goto error;
1212
319k
  
if (319k
dim && 319k
right->tuple_id[1]319k
&&
1213
94.8k
      !(dim->tuple_id[1] = isl_id_copy(right->tuple_id[1])))
1214
0
    goto error;
1215
319k
  
if (319k
dim && 319k
left->nested[0]319k
&&
1216
115k
      !(dim->nested[0] = isl_space_copy(left->nested[0])))
1217
0
    goto error;
1218
319k
  
if (319k
dim && 319k
right->nested[1]319k
&&
1219
145k
      !(dim->nested[1] = isl_space_copy(right->nested[1])))
1220
0
    goto error;
1221
319k
1222
319k
  isl_space_free(left);
1223
319k
  isl_space_free(right);
1224
319k
1225
319k
  return dim;
1226
0
error:
1227
0
  isl_space_free(left);
1228
0
  isl_space_free(right);
1229
0
  return NULL;
1230
319k
}
1231
1232
/* Given two map spaces { A -> C } and { B -> D }, construct the space
1233
 * { [A -> B] -> [C -> D] }.
1234
 * Given two set spaces { A } and { B }, construct the space { [A -> B] }.
1235
 */
1236
__isl_give isl_space *isl_space_product(__isl_take isl_space *left,
1237
  __isl_take isl_space *right)
1238
1.95k
{
1239
1.95k
  isl_space *dom1, *dom2, *nest1, *nest2;
1240
1.95k
  int is_set;
1241
1.95k
1242
1.95k
  if (
!left || 1.95k
!right1.95k
)
1243
0
    goto error;
1244
1.95k
1245
1.95k
  is_set = isl_space_is_set(left);
1246
1.95k
  if (is_set != isl_space_is_set(right))
1247
0
    isl_die(isl_space_get_ctx(left), isl_error_invalid,
1248
1.95k
      "expecting either two set spaces or two map spaces",
1249
1.95k
      goto error);
1250
1.95k
  
if (1.95k
is_set1.95k
)
1251
220
    return isl_space_range_product(left, right);
1252
1.95k
1253
1.73k
  
if (1.73k
isl_space_check_equal_params(left, right) < 01.73k
)
1254
0
    goto error;
1255
1.73k
1256
1.73k
  dom1 = isl_space_domain(isl_space_copy(left));
1257
1.73k
  dom2 = isl_space_domain(isl_space_copy(right));
1258
1.73k
  nest1 = isl_space_wrap(isl_space_join(isl_space_reverse(dom1), dom2));
1259
1.73k
1260
1.73k
  dom1 = isl_space_range(left);
1261
1.73k
  dom2 = isl_space_range(right);
1262
1.73k
  nest2 = isl_space_wrap(isl_space_join(isl_space_reverse(dom1), dom2));
1263
1.73k
1264
1.73k
  return isl_space_join(isl_space_reverse(nest1), nest2);
1265
0
error:
1266
0
  isl_space_free(left);
1267
0
  isl_space_free(right);
1268
0
  return NULL;
1269
1.73k
}
1270
1271
/* Given two spaces { A -> C } and { B -> C }, construct the space
1272
 * { [A -> B] -> C }
1273
 */
1274
__isl_give isl_space *isl_space_domain_product(__isl_take isl_space *left,
1275
  __isl_take isl_space *right)
1276
1.35k
{
1277
1.35k
  isl_space *ran, *dom1, *dom2, *nest;
1278
1.35k
1279
1.35k
  if (isl_space_check_equal_params(left, right) < 0)
1280
0
    goto error;
1281
1.35k
1282
1.35k
  
if (1.35k
!isl_space_tuple_is_equal(left, isl_dim_out, right, isl_dim_out)1.35k
)
1283
0
    isl_die(left->ctx, isl_error_invalid,
1284
1.35k
      "ranges need to match", goto error);
1285
1.35k
1286
1.35k
  ran = isl_space_range(isl_space_copy(left));
1287
1.35k
1288
1.35k
  dom1 = isl_space_domain(left);
1289
1.35k
  dom2 = isl_space_domain(right);
1290
1.35k
  nest = isl_space_wrap(isl_space_join(isl_space_reverse(dom1), dom2));
1291
1.35k
1292
1.35k
  return isl_space_join(isl_space_reverse(nest), ran);
1293
0
error:
1294
0
  isl_space_free(left);
1295
0
  isl_space_free(right);
1296
0
  return NULL;
1297
1.35k
}
1298
1299
__isl_give isl_space *isl_space_range_product(__isl_take isl_space *left,
1300
  __isl_take isl_space *right)
1301
55.8k
{
1302
55.8k
  isl_space *dom, *ran1, *ran2, *nest;
1303
55.8k
1304
55.8k
  if (isl_space_check_equal_params(left, right) < 0)
1305
0
    goto error;
1306
55.8k
1307
55.8k
  
if (55.8k
!isl_space_tuple_is_equal(left, isl_dim_in, right, isl_dim_in)55.8k
)
1308
0
    isl_die(left->ctx, isl_error_invalid,
1309
55.8k
      "domains need to match", goto error);
1310
55.8k
1311
55.8k
  dom = isl_space_domain(isl_space_copy(left));
1312
55.8k
1313
55.8k
  ran1 = isl_space_range(left);
1314
55.8k
  ran2 = isl_space_range(right);
1315
55.8k
  nest = isl_space_wrap(isl_space_join(isl_space_reverse(ran1), ran2));
1316
55.8k
1317
55.8k
  return isl_space_join(isl_space_reverse(dom), nest);
1318
0
error:
1319
0
  isl_space_free(left);
1320
0
  isl_space_free(right);
1321
0
  return NULL;
1322
55.8k
}
1323
1324
/* Given a space of the form [A -> B] -> [C -> D], return the space A -> C.
1325
 */
1326
__isl_give isl_space *isl_space_factor_domain(__isl_take isl_space *space)
1327
0
{
1328
0
  space = isl_space_domain_factor_domain(space);
1329
0
  space = isl_space_range_factor_domain(space);
1330
0
  return space;
1331
0
}
1332
1333
/* Given a space of the form [A -> B] -> C, return the space A -> C.
1334
 */
1335
__isl_give isl_space *isl_space_domain_factor_domain(
1336
  __isl_take isl_space *space)
1337
343
{
1338
343
  isl_space *nested;
1339
343
  isl_space *domain;
1340
343
1341
343
  if (!space)
1342
0
    return NULL;
1343
343
  
if (343
!isl_space_domain_is_wrapping(space)343
)
1344
0
    isl_die(isl_space_get_ctx(space), isl_error_invalid,
1345
343
      "domain not a product", return isl_space_free(space));
1346
343
1347
343
  nested = space->nested[0];
1348
343
  domain = isl_space_copy(space);
1349
343
  domain = isl_space_drop_dims(domain, isl_dim_in,
1350
343
          nested->n_in, nested->n_out);
1351
343
  if (!domain)
1352
0
    return isl_space_free(space);
1353
343
  
if (343
nested->tuple_id[0]343
)
{200
1354
200
    domain->tuple_id[0] = isl_id_copy(nested->tuple_id[0]);
1355
200
    if (!domain->tuple_id[0])
1356
0
      goto error;
1357
200
  }
1358
343
  
if (343
nested->nested[0]343
)
{143
1359
143
    domain->nested[0] = isl_space_copy(nested->nested[0]);
1360
143
    if (!domain->nested[0])
1361
0
      goto error;
1362
143
  }
1363
343
1364
343
  isl_space_free(space);
1365
343
  return domain;
1366
0
error:
1367
0
  isl_space_free(space);
1368
0
  isl_space_free(domain);
1369
0
  return NULL;
1370
343
}
1371
1372
/* Given a space of the form [A -> B] -> C, return the space B -> C.
1373
 */
1374
__isl_give isl_space *isl_space_domain_factor_range(
1375
  __isl_take isl_space *space)
1376
16.1k
{
1377
16.1k
  isl_space *nested;
1378
16.1k
  isl_space *range;
1379
16.1k
1380
16.1k
  if (!space)
1381
0
    return NULL;
1382
16.1k
  
if (16.1k
!isl_space_domain_is_wrapping(space)16.1k
)
1383
0
    isl_die(isl_space_get_ctx(space), isl_error_invalid,
1384
16.1k
      "domain not a product", return isl_space_free(space));
1385
16.1k
1386
16.1k
  nested = space->nested[0];
1387
16.1k
  range = isl_space_copy(space);
1388
16.1k
  range = isl_space_drop_dims(range, isl_dim_in, 0, nested->n_in);
1389
16.1k
  if (!range)
1390
0
    return isl_space_free(space);
1391
16.1k
  
if (16.1k
nested->tuple_id[1]16.1k
)
{10.2k
1392
10.2k
    range->tuple_id[0] = isl_id_copy(nested->tuple_id[1]);
1393
10.2k
    if (!range->tuple_id[0])
1394
0
      goto error;
1395
10.2k
  }
1396
16.1k
  
if (16.1k
nested->nested[1]16.1k
)
{5.87k
1397
5.87k
    range->nested[0] = isl_space_copy(nested->nested[1]);
1398
5.87k
    if (!range->nested[0])
1399
0
      goto error;
1400
5.87k
  }
1401
16.1k
1402
16.1k
  isl_space_free(space);
1403
16.1k
  return range;
1404
0
error:
1405
0
  isl_space_free(space);
1406
0
  isl_space_free(range);
1407
0
  return NULL;
1408
16.1k
}
1409
1410
/* Given a space of the form A -> [B -> C], return the space A -> B.
1411
 */
1412
__isl_give isl_space *isl_space_range_factor_domain(
1413
  __isl_take isl_space *space)
1414
1.47k
{
1415
1.47k
  isl_space *nested;
1416
1.47k
  isl_space *domain;
1417
1.47k
1418
1.47k
  if (!space)
1419
0
    return NULL;
1420
1.47k
  
if (1.47k
!isl_space_range_is_wrapping(space)1.47k
)
1421
0
    isl_die(isl_space_get_ctx(space), isl_error_invalid,
1422
1.47k
      "range not a product", return isl_space_free(space));
1423
1.47k
1424
1.47k
  nested = space->nested[1];
1425
1.47k
  domain = isl_space_copy(space);
1426
1.47k
  domain = isl_space_drop_dims(domain, isl_dim_out,
1427
1.47k
          nested->n_in, nested->n_out);
1428
1.47k
  if (!domain)
1429
0
    return isl_space_free(space);
1430
1.47k
  
if (1.47k
nested->tuple_id[0]1.47k
)
{846
1431
846
    domain->tuple_id[1] = isl_id_copy(nested->tuple_id[0]);
1432
846
    if (!domain->tuple_id[1])
1433
0
      goto error;
1434
846
  }
1435
1.47k
  
if (1.47k
nested->nested[0]1.47k
)
{612
1436
612
    domain->nested[1] = isl_space_copy(nested->nested[0]);
1437
612
    if (!domain->nested[1])
1438
0
      goto error;
1439
612
  }
1440
1.47k
1441
1.47k
  isl_space_free(space);
1442
1.47k
  return domain;
1443
0
error:
1444
0
  isl_space_free(space);
1445
0
  isl_space_free(domain);
1446
0
  return NULL;
1447
1.47k
}
1448
1449
/* Internal function that selects the range of the map that is
1450
 * embedded in either a set space or the range of a map space.
1451
 * In particular, given a space of the form [A -> B], return the space B.
1452
 * Given a space of the form A -> [B -> C], return the space A -> C.
1453
 */
1454
static __isl_give isl_space *range_factor_range(__isl_take isl_space *space)
1455
10.4k
{
1456
10.4k
  isl_space *nested;
1457
10.4k
  isl_space *range;
1458
10.4k
1459
10.4k
  if (!space)
1460
0
    return NULL;
1461
10.4k
1462
10.4k
  nested = space->nested[1];
1463
10.4k
  range = isl_space_copy(space);
1464
10.4k
  range = isl_space_drop_dims(range, isl_dim_out, 0, nested->n_in);
1465
10.4k
  if (!range)
1466
0
    return isl_space_free(space);
1467
10.4k
  
if (10.4k
nested->tuple_id[1]10.4k
)
{466
1468
466
    range->tuple_id[1] = isl_id_copy(nested->tuple_id[1]);
1469
466
    if (!range->tuple_id[1])
1470
0
      goto error;
1471
466
  }
1472
10.4k
  
if (10.4k
nested->nested[1]10.4k
)
{10.0k
1473
10.0k
    range->nested[1] = isl_space_copy(nested->nested[1]);
1474
10.0k
    if (!range->nested[1])
1475
0
      goto error;
1476
10.0k
  }
1477
10.4k
1478
10.4k
  isl_space_free(space);
1479
10.4k
  return range;
1480
0
error:
1481
0
  isl_space_free(space);
1482
0
  isl_space_free(range);
1483
0
  return NULL;
1484
10.4k
}
1485
1486
/* Given a space of the form A -> [B -> C], return the space A -> C.
1487
 */
1488
__isl_give isl_space *isl_space_range_factor_range(
1489
  __isl_take isl_space *space)
1490
10.4k
{
1491
10.4k
  if (!space)
1492
0
    return NULL;
1493
10.4k
  
if (10.4k
!isl_space_range_is_wrapping(space)10.4k
)
1494
0
    isl_die(isl_space_get_ctx(space), isl_error_invalid,
1495
10.4k
      "range not a product", return isl_space_free(space));
1496
10.4k
1497
10.4k
  return range_factor_range(space);
1498
10.4k
}
1499
1500
/* Given a space of the form [A -> B], return the space B.
1501
 */
1502
static __isl_give isl_space *set_factor_range(__isl_take isl_space *space)
1503
0
{
1504
0
  if (!space)
1505
0
    return NULL;
1506
0
  
if (0
!isl_space_is_wrapping(space)0
)
1507
0
    isl_die(isl_space_get_ctx(space), isl_error_invalid,
1508
0
      "not a product", return isl_space_free(space));
1509
0
1510
0
  return range_factor_range(space);
1511
0
}
1512
1513
/* Given a space of the form [A -> B] -> [C -> D], return the space B -> D.
1514
 * Given a space of the form [A -> B], return the space B.
1515
 */
1516
__isl_give isl_space *isl_space_factor_range(__isl_take isl_space *space)
1517
10.0k
{
1518
10.0k
  if (!space)
1519
0
    return NULL;
1520
10.0k
  
if (10.0k
isl_space_is_set(space)10.0k
)
1521
0
    return set_factor_range(space);
1522
10.0k
  space = isl_space_domain_factor_range(space);
1523
10.0k
  space = isl_space_range_factor_range(space);
1524
10.0k
  return space;
1525
10.0k
}
1526
1527
__isl_give isl_space *isl_space_map_from_set(__isl_take isl_space *dim)
1528
8.04k
{
1529
8.04k
  isl_ctx *ctx;
1530
8.04k
  isl_id **ids = NULL;
1531
8.04k
1532
8.04k
  if (!dim)
1533
1
    return NULL;
1534
8.04k
  ctx = isl_space_get_ctx(dim);
1535
8.04k
  if (!isl_space_is_set(dim))
1536
0
    isl_die(ctx, isl_error_invalid, "not a set space", goto error);
1537
8.04k
  dim = isl_space_cow(dim);
1538
8.04k
  if (!dim)
1539
0
    return NULL;
1540
8.04k
  
if (8.04k
dim->ids8.04k
)
{6.21k
1541
6.21k
    ids = isl_calloc_array(dim->ctx, isl_id *,
1542
6.21k
          dim->nparam + dim->n_out + dim->n_out);
1543
6.21k
    if (!ids)
1544
0
      goto error;
1545
6.21k
    get_ids(dim, isl_dim_param, 0, dim->nparam, ids);
1546
6.21k
    get_ids(dim, isl_dim_out, 0, dim->n_out, ids + dim->nparam);
1547
6.21k
  }
1548
8.04k
  dim->n_in = dim->n_out;
1549
8.04k
  if (
ids8.04k
)
{6.21k
1550
6.21k
    free(dim->ids);
1551
6.21k
    dim->ids = ids;
1552
6.21k
    dim->n_id = dim->nparam + dim->n_out + dim->n_out;
1553
6.21k
    dim = copy_ids(dim, isl_dim_out, 0, dim, isl_dim_in);
1554
6.21k
  }
1555
8.04k
  isl_id_free(dim->tuple_id[0]);
1556
8.04k
  dim->tuple_id[0] = isl_id_copy(dim->tuple_id[1]);
1557
8.04k
  isl_space_free(dim->nested[0]);
1558
8.04k
  dim->nested[0] = isl_space_copy(dim->nested[1]);
1559
8.04k
  return dim;
1560
0
error:
1561
0
  isl_space_free(dim);
1562
0
  return NULL;
1563
8.04k
}
1564
1565
__isl_give isl_space *isl_space_map_from_domain_and_range(
1566
  __isl_take isl_space *domain, __isl_take isl_space *range)
1567
42.3k
{
1568
42.3k
  if (
!domain || 42.3k
!range42.3k
)
1569
0
    goto error;
1570
42.3k
  
if (42.3k
!isl_space_is_set(domain)42.3k
)
1571
0
    isl_die(isl_space_get_ctx(domain), isl_error_invalid,
1572
42.3k
      "domain is not a set space", goto error);
1573
42.3k
  
if (42.3k
!isl_space_is_set(range)42.3k
)
1574
0
    isl_die(isl_space_get_ctx(range), isl_error_invalid,
1575
42.3k
      "range is not a set space", goto error);
1576
42.3k
  return isl_space_join(isl_space_reverse(domain), range);
1577
0
error:
1578
0
  isl_space_free(domain);
1579
0
  isl_space_free(range);
1580
0
  return NULL;
1581
42.3k
}
1582
1583
static __isl_give isl_space *set_ids(__isl_take isl_space *dim,
1584
  enum isl_dim_type type,
1585
  unsigned first, unsigned n, __isl_take isl_id **ids)
1586
1.46M
{
1587
1.46M
  int i;
1588
1.46M
1589
3.79M
  for (i = 0; 
i < n3.79M
;
++i2.33M
)
1590
2.33M
    dim = set_id(dim, type, first + i, ids[i]);
1591
1.46M
1592
1.46M
  return dim;
1593
1.46M
}
1594
1595
__isl_give isl_space *isl_space_reverse(__isl_take isl_space *dim)
1596
1.14M
{
1597
1.14M
  unsigned t;
1598
1.14M
  isl_space *nested;
1599
1.14M
  isl_id **ids = NULL;
1600
1.14M
  isl_id *id;
1601
1.14M
1602
1.14M
  if (!dim)
1603
0
    return NULL;
1604
1.14M
  
if (1.14M
match(dim, isl_dim_in, dim, isl_dim_out)1.14M
)
1605
67.6k
    return dim;
1606
1.14M
1607
1.07M
  dim = isl_space_cow(dim);
1608
1.07M
  if (!dim)
1609
0
    return NULL;
1610
1.07M
1611
1.07M
  id = dim->tuple_id[0];
1612
1.07M
  dim->tuple_id[0] = dim->tuple_id[1];
1613
1.07M
  dim->tuple_id[1] = id;
1614
1.07M
1615
1.07M
  nested = dim->nested[0];
1616
1.07M
  dim->nested[0] = dim->nested[1];
1617
1.07M
  dim->nested[1] = nested;
1618
1.07M
1619
1.07M
  if (
dim->ids1.07M
)
{730k
1620
730k
    int n_id = dim->n_in + dim->n_out;
1621
730k
    ids = isl_alloc_array(dim->ctx, isl_id *, n_id);
1622
730k
    if (
n_id && 730k
!ids633k
)
1623
0
      goto error;
1624
730k
    get_ids(dim, isl_dim_in, 0, dim->n_in, ids);
1625
730k
    get_ids(dim, isl_dim_out, 0, dim->n_out, ids + dim->n_in);
1626
730k
  }
1627
1.07M
1628
1.07M
  t = dim->n_in;
1629
1.07M
  dim->n_in = dim->n_out;
1630
1.07M
  dim->n_out = t;
1631
1.07M
1632
1.07M
  if (
dim->ids1.07M
)
{730k
1633
730k
    dim = set_ids(dim, isl_dim_out, 0, dim->n_out, ids);
1634
730k
    dim = set_ids(dim, isl_dim_in, 0, dim->n_in, ids + dim->n_out);
1635
730k
    free(ids);
1636
730k
  }
1637
1.07M
1638
1.07M
  return dim;
1639
0
error:
1640
0
  free(ids);
1641
0
  isl_space_free(dim);
1642
0
  return NULL;
1643
1.07M
}
1644
1645
__isl_give isl_space *isl_space_drop_dims(__isl_take isl_space *dim,
1646
  enum isl_dim_type type, unsigned first, unsigned num)
1647
1.44M
{
1648
1.44M
  int i;
1649
1.44M
1650
1.44M
  if (!dim)
1651
0
    return NULL;
1652
1.44M
1653
1.44M
  
if (1.44M
num == 01.44M
)
1654
288k
    return isl_space_reset(dim, type);
1655
1.44M
1656
1.16M
  
if (1.16M
!valid_dim_type(type)1.16M
)
1657
0
    isl_die(dim->ctx, isl_error_invalid,
1658
1.16M
      "cannot drop dimensions of specified type", goto error);
1659
1.16M
1660
1.16M
  
if (1.16M
first + num > n(dim, type) || 1.16M
first + num < first1.16M
)
1661
0
    isl_die(isl_space_get_ctx(dim), isl_error_invalid,
1662
1.16M
      "index out of bounds", return isl_space_free(dim));
1663
1.16M
  dim = isl_space_cow(dim);
1664
1.16M
  if (!dim)
1665
0
    goto error;
1666
1.16M
  
if (1.16M
dim->ids1.16M
)
{693k
1667
693k
    dim = extend_ids(dim);
1668
693k
    if (!dim)
1669
0
      goto error;
1670
2.57M
    
for (i = 0; 693k
i < num2.57M
;
++i1.88M
)
1671
1.88M
      isl_id_free(get_id(dim, type, first + i));
1672
777k
    for (i = first+num; 
i < n(dim, type)777k
;
++i83.9k
)
1673
83.9k
      set_id(dim, type, i - num, get_id(dim, type, i));
1674
693k
    switch (type) {
1675
68.5k
    case isl_dim_param:
1676
68.5k
      get_ids(dim, isl_dim_in, 0, dim->n_in,
1677
68.5k
        dim->ids + offset(dim, isl_dim_in) - num);
1678
254k
    case isl_dim_in:
1679
254k
      get_ids(dim, isl_dim_out, 0, dim->n_out,
1680
254k
        dim->ids + offset(dim, isl_dim_out) - num);
1681
693k
    default:
1682
693k
      ;
1683
693k
    }
1684
693k
    dim->n_id -= num;
1685
693k
  }
1686
1.16M
  switch (type) {
1687
68.6k
  case isl_dim_param: dim->nparam -= num; break;
1688
243k
  case isl_dim_in:  dim->n_in -= num; break;
1689
848k
  case isl_dim_out: dim->n_out -= num; break;
1690
0
  default:    ;
1691
1.16M
  }
1692
1.16M
  dim = isl_space_reset(dim, type);
1693
1.16M
  if (
type == isl_dim_param1.16M
)
{68.6k
1694
68.6k
    if (
dim && 68.6k
dim->nested[0]68.6k
&&
1695
2.37k
        !(dim->nested[0] = isl_space_drop_dims(dim->nested[0],
1696
2.37k
                isl_dim_param, first, num)))
1697
0
      goto error;
1698
68.6k
    
if (68.6k
dim && 68.6k
dim->nested[1]68.6k
&&
1699
1.65k
        !(dim->nested[1] = isl_space_drop_dims(dim->nested[1],
1700
1.65k
                isl_dim_param, first, num)))
1701
0
      goto error;
1702
68.6k
  }
1703
1.16M
  return dim;
1704
0
error:
1705
0
  isl_space_free(dim);
1706
0
  return NULL;
1707
1.16M
}
1708
1709
__isl_give isl_space *isl_space_drop_inputs(__isl_take isl_space *dim,
1710
    unsigned first, unsigned n)
1711
0
{
1712
0
  if (!dim)
1713
0
    return NULL;
1714
0
  return isl_space_drop_dims(dim, isl_dim_in, first, n);
1715
0
}
1716
1717
__isl_give isl_space *isl_space_drop_outputs(__isl_take isl_space *dim,
1718
    unsigned first, unsigned n)
1719
0
{
1720
0
  if (!dim)
1721
0
    return NULL;
1722
0
  return isl_space_drop_dims(dim, isl_dim_out, first, n);
1723
0
}
1724
1725
__isl_give isl_space *isl_space_domain(__isl_take isl_space *space)
1726
419k
{
1727
419k
  if (!space)
1728
0
    return NULL;
1729
419k
  space = isl_space_drop_dims(space, isl_dim_out, 0, space->n_out);
1730
419k
  space = isl_space_reverse(space);
1731
419k
  space = mark_as_set(space);
1732
419k
  return space;
1733
419k
}
1734
1735
__isl_give isl_space *isl_space_from_domain(__isl_take isl_space *dim)
1736
389k
{
1737
389k
  if (!dim)
1738
0
    return NULL;
1739
389k
  
if (389k
!isl_space_is_set(dim)389k
)
1740
0
    isl_die(isl_space_get_ctx(dim), isl_error_invalid,
1741
389k
      "not a set space", goto error);
1742
389k
  dim = isl_space_reverse(dim);
1743
389k
  dim = isl_space_reset(dim, isl_dim_out);
1744
389k
  return dim;
1745
0
error:
1746
0
  isl_space_free(dim);
1747
0
  return NULL;
1748
389k
}
1749
1750
__isl_give isl_space *isl_space_range(__isl_take isl_space *space)
1751
210k
{
1752
210k
  if (!space)
1753
0
    return NULL;
1754
210k
  space = isl_space_drop_dims(space, isl_dim_in, 0, space->n_in);
1755
210k
  space = mark_as_set(space);
1756
210k
  return space;
1757
210k
}
1758
1759
__isl_give isl_space *isl_space_from_range(__isl_take isl_space *dim)
1760
139k
{
1761
139k
  if (!dim)
1762
0
    return NULL;
1763
139k
  
if (139k
!isl_space_is_set(dim)139k
)
1764
0
    isl_die(isl_space_get_ctx(dim), isl_error_invalid,
1765
139k
      "not a set space", goto error);
1766
139k
  return isl_space_reset(dim, isl_dim_in);
1767
0
error:
1768
0
  isl_space_free(dim);
1769
0
  return NULL;
1770
139k
}
1771
1772
/* Given a map space A -> B, return the map space [A -> B] -> A.
1773
 */
1774
__isl_give isl_space *isl_space_domain_map(__isl_take isl_space *space)
1775
767
{
1776
767
  isl_space *domain;
1777
767
1778
767
  domain = isl_space_from_range(isl_space_domain(isl_space_copy(space)));
1779
767
  space = isl_space_from_domain(isl_space_wrap(space));
1780
767
  space = isl_space_join(space, domain);
1781
767
1782
767
  return space;
1783
767
}
1784
1785
/* Given a map space A -> B, return the map space [A -> B] -> B.
1786
 */
1787
__isl_give isl_space *isl_space_range_map(__isl_take isl_space *space)
1788
0
{
1789
0
  isl_space *range;
1790
0
1791
0
  range = isl_space_from_range(isl_space_range(isl_space_copy(space)));
1792
0
  space = isl_space_from_domain(isl_space_wrap(space));
1793
0
  space = isl_space_join(space, range);
1794
0
1795
0
  return space;
1796
0
}
1797
1798
__isl_give isl_space *isl_space_params(__isl_take isl_space *space)
1799
297k
{
1800
297k
  if (isl_space_is_params(space))
1801
223k
    return space;
1802
73.3k
  space = isl_space_drop_dims(space,
1803
73.3k
          isl_dim_in, 0, isl_space_dim(space, isl_dim_in));
1804
73.3k
  space = isl_space_drop_dims(space,
1805
73.3k
          isl_dim_out, 0, isl_space_dim(space, isl_dim_out));
1806
73.3k
  space = mark_as_params(space);
1807
73.3k
  return space;
1808
297k
}
1809
1810
__isl_give isl_space *isl_space_set_from_params(__isl_take isl_space *space)
1811
11.0k
{
1812
11.0k
  if (!space)
1813
0
    return NULL;
1814
11.0k
  
if (11.0k
!isl_space_is_params(space)11.0k
)
1815
0
    isl_die(isl_space_get_ctx(space), isl_error_invalid,
1816
11.0k
      "not a parameter space", goto error);
1817
11.0k
  return isl_space_reset(space, isl_dim_set);
1818
0
error:
1819
0
  isl_space_free(space);
1820
0
  return NULL;
1821
11.0k
}
1822
1823
__isl_give isl_space *isl_space_underlying(__isl_take isl_space *dim,
1824
  unsigned n_div)
1825
300k
{
1826
300k
  int i;
1827
300k
1828
300k
  if (!dim)
1829
0
    return NULL;
1830
300k
  
if (300k
n_div == 0 &&300k
1831
291k
      
dim->nparam == 0291k
&&
dim->n_in == 0149k
&&
dim->n_id == 0122k
)
1832
73.3k
    return isl_space_reset(isl_space_reset(dim, isl_dim_in), isl_dim_out);
1833
227k
  dim = isl_space_cow(dim);
1834
227k
  if (!dim)
1835
0
    return NULL;
1836
227k
  dim->n_out += dim->nparam + dim->n_in + n_div;
1837
227k
  dim->nparam = 0;
1838
227k
  dim->n_in = 0;
1839
227k
1840
1.37M
  for (i = 0; 
i < dim->n_id1.37M
;
++i1.14M
)
1841
1.14M
    isl_id_free(get_id(dim, isl_dim_out, i));
1842
227k
  dim->n_id = 0;
1843
227k
  dim = isl_space_reset(dim, isl_dim_in);
1844
227k
  dim = isl_space_reset(dim, isl_dim_out);
1845
227k
1846
227k
  return dim;
1847
227k
}
1848
1849
/* Are the two spaces the same, including positions and names of parameters?
1850
 */
1851
isl_bool isl_space_is_equal(__isl_keep isl_space *space1,
1852
  __isl_keep isl_space *space2)
1853
5.13M
{
1854
5.13M
  isl_bool equal;
1855
5.13M
1856
5.13M
  if (
!space1 || 5.13M
!space25.13M
)
1857
0
    return isl_bool_error;
1858
5.13M
  
if (5.13M
space1 == space25.13M
)
1859
2.83M
    return isl_bool_true;
1860
2.29M
  equal = isl_space_has_equal_params(space1, space2);
1861
2.29M
  if (
equal < 0 || 2.29M
!equal2.29M
)
1862
51.9k
    return equal;
1863
2.24M
  return isl_space_has_equal_tuples(space1, space2);
1864
2.29M
}
1865
1866
/* Is space1 equal to the domain of space2?
1867
 *
1868
 * In the internal version we also allow space2 to be the space of a set,
1869
 * provided space1 is a parameter space.
1870
 */
1871
isl_bool isl_space_is_domain_internal(__isl_keep isl_space *space1,
1872
  __isl_keep isl_space *space2)
1873
47
{
1874
47
  isl_bool equal_params;
1875
47
1876
47
  if (
!space1 || 47
!space247
)
1877
0
    return isl_bool_error;
1878
47
  
if (47
!isl_space_is_set(space1)47
)
1879
0
    return isl_bool_false;
1880
47
  equal_params = isl_space_has_equal_params(space1, space2);
1881
47
  if (
equal_params < 0 || 47
!equal_params47
)
1882
0
    return equal_params;
1883
47
  return isl_space_tuple_is_equal(space1, isl_dim_set,
1884
47
          space2, isl_dim_in);
1885
47
}
1886
1887
/* Is space1 equal to the domain of space2?
1888
 */
1889
isl_bool isl_space_is_domain(__isl_keep isl_space *space1,
1890
  __isl_keep isl_space *space2)
1891
19
{
1892
19
  if (!space2)
1893
0
    return isl_bool_error;
1894
19
  
if (19
!isl_space_is_map(space2)19
)
1895
0
    return isl_bool_false;
1896
19
  return isl_space_is_domain_internal(space1, space2);
1897
19
}
1898
1899
/* Is space1 equal to the range of space2?
1900
 *
1901
 * In the internal version, space2 is allowed to be the space of a set,
1902
 * in which case it should be equal to space1.
1903
 */
1904
isl_bool isl_space_is_range_internal(__isl_keep isl_space *space1,
1905
  __isl_keep isl_space *space2)
1906
9.19k
{
1907
9.19k
  isl_bool equal_params;
1908
9.19k
1909
9.19k
  if (
!space1 || 9.19k
!space29.19k
)
1910
0
    return isl_bool_error;
1911
9.19k
  
if (9.19k
!isl_space_is_set(space1)9.19k
)
1912
0
    return isl_bool_false;
1913
9.19k
  equal_params = isl_space_has_equal_params(space1, space2);
1914
9.19k
  if (
equal_params < 0 || 9.19k
!equal_params9.19k
)
1915
0
    return equal_params;
1916
9.19k
  return isl_space_tuple_is_equal(space1, isl_dim_set,
1917
9.19k
          space2, isl_dim_out);
1918
9.19k
}
1919
1920
/* Is space1 equal to the range of space2?
1921
 */
1922
isl_bool isl_space_is_range(__isl_keep isl_space *space1,
1923
  __isl_keep isl_space *space2)
1924
0
{
1925
0
  if (!space2)
1926
0
    return isl_bool_error;
1927
0
  
if (0
!isl_space_is_map(space2)0
)
1928
0
    return isl_bool_false;
1929
0
  return isl_space_is_range_internal(space1, space2);
1930
0
}
1931
1932
/* Update "hash" by hashing in "space".
1933
 * Changes in this function should be reflected in isl_hash_space_domain.
1934
 */
1935
static uint32_t isl_hash_space(uint32_t hash, __isl_keep isl_space *space)
1936
1.23M
{
1937
1.23M
  int i;
1938
1.23M
  isl_id *id;
1939
1.23M
1940
1.23M
  if (!space)
1941
779k
    return hash;
1942
1.23M
1943
452k
  
isl_hash_byte452k
(hash, space->nparam % 256);452k
1944
452k
  isl_hash_byte(hash, space->n_in % 256);
1945
452k
  isl_hash_byte(hash, space->n_out % 256);
1946
452k
1947
1.11M
  for (i = 0; 
i < space->nparam1.11M
;
++i662k
)
{662k
1948
662k
    id = get_id(space, isl_dim_param, i);
1949
662k
    hash = isl_hash_id(hash, id);
1950
662k
  }
1951
452k
1952
452k
  id = tuple_id(space, isl_dim_in);
1953
452k
  hash = isl_hash_id(hash, id);
1954
452k
  id = tuple_id(space, isl_dim_out);
1955
452k
  hash = isl_hash_id(hash, id);
1956
452k
1957
452k
  hash = isl_hash_space(hash, space->nested[0]);
1958
452k
  hash = isl_hash_space(hash, space->nested[1]);
1959
452k
1960
452k
  return hash;
1961
1.23M
}
1962
1963
/* Update "hash" by hashing in the domain of "space".
1964
 * The result of this function is equal to the result of applying
1965
 * isl_hash_space to the domain of "space".
1966
 */
1967
static uint32_t isl_hash_space_domain(uint32_t hash,
1968
  __isl_keep isl_space *space)
1969
18.3k
{
1970
18.3k
  int i;
1971
18.3k
  isl_id *id;
1972
18.3k
1973
18.3k
  if (!space)
1974
0
    return hash;
1975
18.3k
1976
18.3k
  
isl_hash_byte18.3k
(hash, space->nparam % 256);18.3k
1977
18.3k
  isl_hash_byte(hash, 0);
1978
18.3k
  isl_hash_byte(hash, space->n_in % 256);
1979
18.3k
1980
47.8k
  for (i = 0; 
i < space->nparam47.8k
;
++i29.4k
)
{29.4k
1981
29.4k
    id = get_id(space, isl_dim_param, i);
1982
29.4k
    hash = isl_hash_id(hash, id);
1983
29.4k
  }
1984
18.3k
1985
18.3k
  hash = isl_hash_id(hash, &isl_id_none);
1986
18.3k
  id = tuple_id(space, isl_dim_in);
1987
18.3k
  hash = isl_hash_id(hash, id);
1988
18.3k
1989
18.3k
  hash = isl_hash_space(hash, space->nested[0]);
1990
18.3k
1991
18.3k
  return hash;
1992
18.3k
}
1993
1994
uint32_t isl_space_get_hash(__isl_keep isl_space *dim)
1995
308k
{
1996
308k
  uint32_t hash;
1997
308k
1998
308k
  if (!dim)
1999
0
    return 0;
2000
308k
2001
308k
  
hash = 308k
isl_hash_init308k
();
2002
308k
  hash = isl_hash_space(hash, dim);
2003
308k
2004
308k
  return hash;
2005
308k
}
2006
2007
/* Return the hash value of the domain of "space".
2008
 * That is, isl_space_get_domain_hash(space) is equal to
2009
 * isl_space_get_hash(isl_space_domain(space)).
2010
 */
2011
uint32_t isl_space_get_domain_hash(__isl_keep isl_space *space)
2012
18.3k
{
2013
18.3k
  uint32_t hash;
2014
18.3k
2015
18.3k
  if (!space)
2016
0
    return 0;
2017
18.3k
2018
18.3k
  
hash = 18.3k
isl_hash_init18.3k
();
2019
18.3k
  hash = isl_hash_space_domain(hash, space);
2020
18.3k
2021
18.3k
  return hash;
2022
18.3k
}
2023
2024
isl_bool isl_space_is_wrapping(__isl_keep isl_space *dim)
2025
41.8k
{
2026
41.8k
  if (!dim)
2027
0
    return isl_bool_error;
2028
41.8k
2029
41.8k
  
if (41.8k
!isl_space_is_set(dim)41.8k
)
2030
0
    return isl_bool_false;
2031
41.8k
2032
41.8k
  return dim->nested[1] != NULL;
2033
41.8k
}
2034
2035
/* Is "space" the space of a map where the domain is a wrapped map space?
2036
 */
2037
isl_bool isl_space_domain_is_wrapping(__isl_keep isl_space *space)
2038
33.4k
{
2039
33.4k
  if (!space)
2040
0
    return isl_bool_error;
2041
33.4k
2042
33.4k
  
if (33.4k
isl_space_is_set(space)33.4k
)
2043
0
    return isl_bool_false;
2044
33.4k
2045
33.4k
  return space->nested[0] != NULL;
2046
33.4k
}
2047
2048
/* Is "space" the space of a map where the range is a wrapped map space?
2049
 */
2050
isl_bool isl_space_range_is_wrapping(__isl_keep isl_space *space)
2051
46.8k
{
2052
46.8k
  if (!space)
2053
0
    return isl_bool_error;
2054
46.8k
2055
46.8k
  
if (46.8k
isl_space_is_set(space)46.8k
)
2056
693
    return isl_bool_false;
2057
46.8k
2058
46.1k
  return space->nested[1] != NULL;
2059
46.8k
}
2060
2061
__isl_give isl_space *isl_space_wrap(__isl_take isl_space *dim)
2062
132k
{
2063
132k
  isl_space *wrap;
2064
132k
2065
132k
  if (!dim)
2066
0
    return NULL;
2067
132k
2068
132k
  wrap = isl_space_set_alloc(dim->ctx,
2069
132k
            dim->nparam, dim->n_in + dim->n_out);
2070
132k
2071
132k
  wrap = copy_ids(wrap, isl_dim_param, 0, dim, isl_dim_param);
2072
132k
  wrap = copy_ids(wrap, isl_dim_set, 0, dim, isl_dim_in);
2073
132k
  wrap = copy_ids(wrap, isl_dim_set, dim->n_in, dim, isl_dim_out);
2074
132k
2075
132k
  if (!wrap)
2076
0
    goto error;
2077
132k
2078
132k
  wrap->nested[1] = dim;
2079
132k
2080
132k
  return wrap;
2081
0
error:
2082
0
  isl_space_free(dim);
2083
0
  return NULL;
2084
132k
}
2085
2086
__isl_give isl_space *isl_space_unwrap(__isl_take isl_space *dim)
2087
29.0k
{
2088
29.0k
  isl_space *unwrap;
2089
29.0k
2090
29.0k
  if (!dim)
2091
0
    return NULL;
2092
29.0k
2093
29.0k
  
if (29.0k
!isl_space_is_wrapping(dim)29.0k
)
2094
0
    isl_die(dim->ctx, isl_error_invalid, "not a wrapping space",
2095
29.0k
      goto error);
2096
29.0k
2097
29.0k
  unwrap = isl_space_copy(dim->nested[1]);
2098
29.0k
  isl_space_free(dim);
2099
29.0k
2100
29.0k
  return unwrap;
2101
0
error:
2102
0
  isl_space_free(dim);
2103
0
  return NULL;
2104
29.0k
}
2105
2106
isl_bool isl_space_is_named_or_nested(__isl_keep isl_space *space,
2107
  enum isl_dim_type type)
2108
3.61M
{
2109
3.61M
  if (
type != isl_dim_in && 3.61M
type != isl_dim_out2.59M
)
2110
272k
    return isl_bool_false;
2111
3.33M
  
if (3.33M
!space3.33M
)
2112
1
    return isl_bool_error;
2113
3.33M
  
if (3.33M
space->tuple_id[type - isl_dim_in]3.33M
)
2114
1.45M
    return isl_bool_true;
2115
1.88M
  
if (1.88M
space->nested[type - isl_dim_in]1.88M
)
2116
438k
    return isl_bool_true;
2117
1.44M
  return isl_bool_false;
2118
1.88M
}
2119
2120
isl_bool isl_space_may_be_set(__isl_keep isl_space *space)
2121
271
{
2122
271
  isl_bool nested;
2123
271
2124
271
  if (!space)
2125
0
    return isl_bool_error;
2126
271
  
if (271
isl_space_is_set(space)271
)
2127
166
    return isl_bool_true;
2128
105
  
if (105
isl_space_dim(space, isl_dim_in) != 0105
)
2129
0
    return isl_bool_false;
2130
105
  nested = isl_space_is_named_or_nested(space, isl_dim_in);
2131
105
  if (
nested < 0 || 105
nested105
)
2132
0
    return isl_bool_not(nested);
2133
105
  return isl_bool_true;
2134
105
}
2135
2136
__isl_give isl_space *isl_space_reset(__isl_take isl_space *dim,
2137
  enum isl_dim_type type)
2138
3.29M
{
2139
3.29M
  if (!isl_space_is_named_or_nested(dim, type))
2140
1.54M
    return dim;
2141
3.29M
2142
1.74M
  dim = isl_space_cow(dim);
2143
1.74M
  if (!dim)
2144
2
    return NULL;
2145
1.74M
2146
1.74M
  isl_id_free(dim->tuple_id[type - isl_dim_in]);
2147
1.74M
  dim->tuple_id[type - isl_dim_in] = NULL;
2148
1.74M
  isl_space_free(dim->nested[type - isl_dim_in]);
2149
1.74M
  dim->nested[type - isl_dim_in] = NULL;
2150
1.74M
2151
1.74M
  return dim;
2152
1.74M
}
2153
2154
__isl_give isl_space *isl_space_flatten(__isl_take isl_space *dim)
2155
20.0k
{
2156
20.0k
  if (!dim)
2157
0
    return NULL;
2158
20.0k
  
if (20.0k
!dim->nested[0] && 20.0k
!dim->nested[1]20.0k
)
2159
0
    return dim;
2160
20.0k
2161
20.0k
  
if (20.0k
dim->nested[0]20.0k
)
2162
0
    dim = isl_space_reset(dim, isl_dim_in);
2163
20.0k
  if (
dim && 20.0k
dim->nested[1]20.0k
)
2164
20.0k
    dim = isl_space_reset(dim, isl_dim_out);
2165
20.0k
2166
20.0k
  return dim;
2167
20.0k
}
2168
2169
__isl_give isl_space *isl_space_flatten_domain(__isl_take isl_space *dim)
2170
30
{
2171
30
  if (!dim)
2172
0
    return NULL;
2173
30
  
if (30
!dim->nested[0]30
)
2174
0
    return dim;
2175
30
2176
30
  return isl_space_reset(dim, isl_dim_in);
2177
30
}
2178
2179
__isl_give isl_space *isl_space_flatten_range(__isl_take isl_space *dim)
2180
37.1k
{
2181
37.1k
  if (!dim)
2182
0
    return NULL;
2183
37.1k
  
if (37.1k
!dim->nested[1]37.1k
)
2184
0
    return dim;
2185
37.1k
2186
37.1k
  return isl_space_reset(dim, isl_dim_out);
2187
37.1k
}
2188
2189
/* Replace the dimensions of the given type of dst by those of src.
2190
 */
2191
__isl_give isl_space *isl_space_replace(__isl_take isl_space *dst,
2192
  enum isl_dim_type type, __isl_keep isl_space *src)
2193
104k
{
2194
104k
  dst = isl_space_cow(dst);
2195
104k
2196
104k
  if (
!dst || 104k
!src104k
)
2197
0
    goto error;
2198
104k
2199
104k
  dst = isl_space_drop_dims(dst, type, 0, isl_space_dim(dst, type));
2200
104k
  dst = isl_space_add_dims(dst, type, isl_space_dim(src, type));
2201
104k
  dst = copy_ids(dst, type, 0, src, type);
2202
104k
2203
104k
  if (
dst && 104k
type == isl_dim_param104k
)
{104k
2204
104k
    int i;
2205
313k
    for (i = 0; 
i <= 1313k
;
++i208k
)
{208k
2206
208k
      if (!dst->nested[i])
2207
200k
        continue;
2208
8.77k
      dst->nested[i] = isl_space_replace(dst->nested[i],
2209
8.77k
               type, src);
2210
8.77k
      if (!dst->nested[i])
2211
0
        goto error;
2212
8.77k
    }
2213
104k
  }
2214
104k
2215
104k
  return dst;
2216
0
error:
2217
0
  isl_space_free(dst);
2218
0
  return NULL;
2219
104k
}
2220
2221
/* Given a dimension specification "dim" of a set, create a dimension
2222
 * specification for the lift of the set.  In particular, the result
2223
 * is of the form [dim -> local[..]], with n_local variables in the
2224
 * range of the wrapped map.
2225
 */
2226
__isl_give isl_space *isl_space_lift(__isl_take isl_space *dim, unsigned n_local)
2227
18.6k
{
2228
18.6k
  isl_space *local_dim;
2229
18.6k
2230
18.6k
  if (!dim)
2231
0
    return NULL;
2232
18.6k
2233
18.6k
  local_dim = isl_space_dup(dim);
2234
18.6k
  local_dim = isl_space_drop_dims(local_dim, isl_dim_set, 0, dim->n_out);
2235
18.6k
  local_dim = isl_space_add_dims(local_dim, isl_dim_set, n_local);
2236
18.6k
  local_dim = isl_space_set_tuple_name(local_dim, isl_dim_set, "local");
2237
18.6k
  dim = isl_space_join(isl_space_from_domain(dim),
2238
18.6k
          isl_space_from_range(local_dim));
2239
18.6k
  dim = isl_space_wrap(dim);
2240
18.6k
  dim = isl_space_set_tuple_name(dim, isl_dim_set, "lifted");
2241
18.6k
2242
18.6k
  return dim;
2243
18.6k
}
2244
2245
isl_bool isl_space_can_zip(__isl_keep isl_space *dim)
2246
4.49k
{
2247
4.49k
  if (!dim)
2248
0
    return isl_bool_error;
2249
4.49k
2250
4.49k
  
return dim->nested[0] && 4.49k
dim->nested[1]4.47k
;
2251
4.49k
}
2252
2253
__isl_give isl_space *isl_space_zip(__isl_take isl_space *dim)
2254
1.94k
{
2255
1.94k
  isl_space *dom, *ran;
2256
1.94k
  isl_space *dom_dom, *dom_ran, *ran_dom, *ran_ran;
2257
1.94k
2258
1.94k
  if (!isl_space_can_zip(dim))
2259
0
    isl_die(dim->ctx, isl_error_invalid, "dim cannot be zipped",
2260
1.94k
      goto error);
2261
1.94k
2262
1.94k
  
if (1.94k
!dim1.94k
)
2263
0
    return NULL;
2264
1.94k
  dom = isl_space_unwrap(isl_space_domain(isl_space_copy(dim)));
2265
1.94k
  ran = isl_space_unwrap(isl_space_range(dim));
2266
1.94k
  dom_dom = isl_space_domain(isl_space_copy(dom));
2267
1.94k
  dom_ran = isl_space_range(dom);
2268
1.94k
  ran_dom = isl_space_domain(isl_space_copy(ran));
2269
1.94k
  ran_ran = isl_space_range(ran);
2270
1.94k
  dom = isl_space_join(isl_space_from_domain(dom_dom),
2271
1.94k
         isl_space_from_range(ran_dom));
2272
1.94k
  ran = isl_space_join(isl_space_from_domain(dom_ran),
2273
1.94k
         isl_space_from_range(ran_ran));
2274
1.94k
  return isl_space_join(isl_space_from_domain(isl_space_wrap(dom)),
2275
1.94k
          isl_space_from_range(isl_space_wrap(ran)));
2276
0
error:
2277
0
  isl_space_free(dim);
2278
0
  return NULL;
2279
1.94k
}
2280
2281
/* Can we apply isl_space_curry to "space"?
2282
 * That is, does it have a nested relation in its domain?
2283
 */
2284
isl_bool isl_space_can_curry(__isl_keep isl_space *space)
2285
30.2k
{
2286
30.2k
  if (!space)
2287
0
    return isl_bool_error;
2288
30.2k
2289
30.2k
  return !!space->nested[0];
2290
30.2k
}
2291
2292
/* Given a space (A -> B) -> C, return the corresponding space
2293
 * A -> (B -> C).
2294
 */
2295
__isl_give isl_space *isl_space_curry(__isl_take isl_space *space)
2296
10.0k
{
2297
10.0k
  isl_space *dom, *ran;
2298
10.0k
  isl_space *dom_dom, *dom_ran;
2299
10.0k
2300
10.0k
  if (!space)
2301
0
    return NULL;
2302
10.0k
2303
10.0k
  
if (10.0k
!isl_space_can_curry(space)10.0k
)
2304
0
    isl_die(space->ctx, isl_error_invalid,
2305
10.0k
      "space cannot be curried", goto error);
2306
10.0k
2307
10.0k
  dom = isl_space_unwrap(isl_space_domain(isl_space_copy(space)));
2308
10.0k
  ran = isl_space_range(space);
2309
10.0k
  dom_dom = isl_space_domain(isl_space_copy(dom));
2310
10.0k
  dom_ran = isl_space_range(dom);
2311
10.0k
  ran = isl_space_join(isl_space_from_domain(dom_ran),
2312
10.0k
         isl_space_from_range(ran));
2313
10.0k
  return isl_space_join(isl_space_from_domain(dom_dom),
2314
10.0k
          isl_space_from_range(isl_space_wrap(ran)));
2315
0
error:
2316
0
  isl_space_free(space);
2317
0
  return NULL;
2318
10.0k
}
2319
2320
/* Can isl_space_range_curry be applied to "space"?
2321
 * That is, does it have a nested relation in its range,
2322
 * the domain of which is itself a nested relation?
2323
 */
2324
isl_bool isl_space_can_range_curry(__isl_keep isl_space *space)
2325
20.1k
{
2326
20.1k
  isl_bool can;
2327
20.1k
2328
20.1k
  if (!space)
2329
0
    return isl_bool_error;
2330
20.1k
  can = isl_space_range_is_wrapping(space);
2331
20.1k
  if (
can < 0 || 20.1k
!can20.1k
)
2332
0
    return can;
2333
20.1k
  return isl_space_can_curry(space->nested[1]);
2334
20.1k
}
2335
2336
/* Given a space A -> ((B -> C) -> D), return the corresponding space
2337
 * A -> (B -> (C -> D)).
2338
 */
2339
__isl_give isl_space *isl_space_range_curry(__isl_take isl_space *space)
2340
10.0k
{
2341
10.0k
  if (!space)
2342
0
    return NULL;
2343
10.0k
2344
10.0k
  
if (10.0k
!isl_space_can_range_curry(space)10.0k
)
2345
0
    isl_die(isl_space_get_ctx(space), isl_error_invalid,
2346
10.0k
      "space range cannot be curried",
2347
10.0k
      return isl_space_free(space));
2348
10.0k
2349
10.0k
  space = isl_space_cow(space);
2350
10.0k
  if (!space)
2351
0
    return NULL;
2352
10.0k
  space->nested[1] = isl_space_curry(space->nested[1]);
2353
10.0k
  if (!space->nested[1])
2354
0
    return isl_space_free(space);
2355
10.0k
2356
10.0k
  return space;
2357
10.0k
}
2358
2359
/* Can we apply isl_space_uncurry to "space"?
2360
 * That is, does it have a nested relation in its range?
2361
 */
2362
isl_bool isl_space_can_uncurry(__isl_keep isl_space *space)
2363
258
{
2364
258
  if (!space)
2365
0
    return isl_bool_error;
2366
258
2367
258
  return !!space->nested[1];
2368
258
}
2369
2370
/* Given a space A -> (B -> C), return the corresponding space
2371
 * (A -> B) -> C.
2372
 */
2373
__isl_give isl_space *isl_space_uncurry(__isl_take isl_space *space)
2374
96
{
2375
96
  isl_space *dom, *ran;
2376
96
  isl_space *ran_dom, *ran_ran;
2377
96
2378
96
  if (!space)
2379
0
    return NULL;
2380
96
2381
96
  
if (96
!isl_space_can_uncurry(space)96
)
2382
0
    isl_die(space->ctx, isl_error_invalid,
2383
96
      "space cannot be uncurried",
2384
96
      return isl_space_free(space));
2385
96
2386
96
  dom = isl_space_domain(isl_space_copy(space));
2387
96
  ran = isl_space_unwrap(isl_space_range(space));
2388
96
  ran_dom = isl_space_domain(isl_space_copy(ran));
2389
96
  ran_ran = isl_space_range(ran);
2390
96
  dom = isl_space_join(isl_space_from_domain(dom),
2391
96
         isl_space_from_range(ran_dom));
2392
96
  return isl_space_join(isl_space_from_domain(isl_space_wrap(dom)),
2393
96
          isl_space_from_range(ran_ran));
2394
96
}
2395
2396
isl_bool isl_space_has_named_params(__isl_keep isl_space *space)
2397
327k
{
2398
327k
  int i;
2399
327k
  unsigned off;
2400
327k
2401
327k
  if (!space)
2402
0
    return isl_bool_error;
2403
327k
  
if (327k
space->nparam == 0327k
)
2404
132k
    return isl_bool_true;
2405
194k
  off = isl_space_offset(space, isl_dim_param);
2406
194k
  if (off + space->nparam > space->n_id)
2407
0
    return isl_bool_false;
2408
781k
  
for (i = 0; 194k
i < space->nparam781k
;
++i586k
)
2409
586k
    
if (586k
!space->ids[off + i]586k
)
2410
0
      return isl_bool_false;
2411
194k
  return isl_bool_true;
2412
194k
}
2413
2414
/* Check that "space" has only named parameters, reporting an error
2415
 * if it does not.
2416
 */
2417
isl_stat isl_space_check_named_params(__isl_keep isl_space *space)
2418
137k
{
2419
137k
  isl_bool named;
2420
137k
2421
137k
  named = isl_space_has_named_params(space);
2422
137k
  if (named < 0)
2423
0
    return isl_stat_error;
2424
137k
  
if (137k
!named137k
)
2425
0
    isl_die(isl_space_get_ctx(space), isl_error_invalid,
2426
137k
      "unaligned unnamed parameters", return isl_stat_error);
2427
137k
2428
137k
  return isl_stat_ok;
2429
137k
}
2430
2431
/* Align the initial parameters of dim1 to match the order in dim2.
2432
 */
2433
__isl_give isl_space *isl_space_align_params(__isl_take isl_space *dim1,
2434
  __isl_take isl_space *dim2)
2435
17.1k
{
2436
17.1k
  isl_reordering *exp;
2437
17.1k
2438
17.1k
  if (
!isl_space_has_named_params(dim1) || 17.1k
!isl_space_has_named_params(dim2)17.1k
)
2439
0
    isl_die(isl_space_get_ctx(dim1), isl_error_invalid,
2440
17.1k
      "parameter alignment requires named parameters",
2441
17.1k
      goto error);
2442
17.1k
2443
17.1k
  dim2 = isl_space_params(dim2);
2444
17.1k
  exp = isl_parameter_alignment_reordering(dim1, dim2);
2445
17.1k
  exp = isl_reordering_extend_space(exp, dim1);
2446
17.1k
  isl_space_free(dim2);
2447
17.1k
  if (!exp)
2448
0
    return NULL;
2449
17.1k
  dim1 = isl_space_copy(exp->dim);
2450
17.1k
  isl_reordering_free(exp);
2451
17.1k
  return dim1;
2452
0
error:
2453
0
  isl_space_free(dim1);
2454
0
  isl_space_free(dim2);
2455
0
  return NULL;
2456
17.1k
}
2457
2458
/* Given the space of set (domain), construct a space for a map
2459
 * with as domain the given space and as range the range of "model".
2460
 */
2461
__isl_give isl_space *isl_space_extend_domain_with_range(
2462
  __isl_take isl_space *space, __isl_take isl_space *model)
2463
37.3k
{
2464
37.3k
  if (!model)
2465
0
    goto error;
2466
37.3k
2467
37.3k
  space = isl_space_from_domain(space);
2468
37.3k
  space = isl_space_add_dims(space, isl_dim_out,
2469
37.3k
            isl_space_dim(model, isl_dim_out));
2470
37.3k
  if (isl_space_has_tuple_id(model, isl_dim_out))
2471
8
    space = isl_space_set_tuple_id(space, isl_dim_out,
2472
8
        isl_space_get_tuple_id(model, isl_dim_out));
2473
37.3k
  if (!space)
2474
0
    goto error;
2475
37.3k
  
if (37.3k
model->nested[1]37.3k
)
{1
2476
1
    isl_space *nested = isl_space_copy(model->nested[1]);
2477
1
    int n_nested, n_space;
2478
1
    nested = isl_space_align_params(nested, isl_space_copy(space));
2479
1
    n_nested = isl_space_dim(nested, isl_dim_param);
2480
1
    n_space = isl_space_dim(space, isl_dim_param);
2481
1
    if (n_nested > n_space)
2482
0
      nested = isl_space_drop_dims(nested, isl_dim_param,
2483
0
            n_space, n_nested - n_space);
2484
1
    if (!nested)
2485
0
      goto error;
2486
1
    space->nested[1] = nested;
2487
1
  }
2488
37.3k
  isl_space_free(model);
2489
37.3k
  return space;
2490
0
error:
2491
0
  isl_space_free(model);
2492
0
  isl_space_free(space);
2493
0
  return NULL;
2494
37.3k
}
2495
2496
/* Compare the "type" dimensions of two isl_spaces.
2497
 *
2498
 * The order is fairly arbitrary.
2499
 */
2500
static int isl_space_cmp_type(__isl_keep isl_space *space1,
2501
  __isl_keep isl_space *space2, enum isl_dim_type type)
2502
1.29M
{
2503
1.29M
  int cmp;
2504
1.29M
  isl_space *nested1, *nested2;
2505
1.29M
2506
1.29M
  if (isl_space_dim(space1, type) != isl_space_dim(space2, type))
2507
0
    return isl_space_dim(space1, type) -
2508
0
      isl_space_dim(space2, type);
2509
1.29M
2510
1.29M
  cmp = isl_id_cmp(tuple_id(space1, type), tuple_id(space2, type));
2511
1.29M
  if (cmp != 0)
2512
0
    return cmp;
2513
1.29M
2514
1.29M
  nested1 = nested(space1, type);
2515
1.29M
  nested2 = nested(space2, type);
2516
1.29M
  if (!nested1 != !nested2)
2517
0
    return !nested1 - !nested2;
2518
1.29M
2519
1.29M
  
if (1.29M
nested11.29M
)
2520
58.6k
    return isl_space_cmp(nested1, nested2);
2521
1.29M
2522
1.23M
  return 0;
2523
1.29M
}
2524
2525
/* Compare two isl_spaces.
2526
 *
2527
 * The order is fairly arbitrary.
2528
 */
2529
int isl_space_cmp(__isl_keep isl_space *space1, __isl_keep isl_space *space2)
2530
1.59M
{
2531
1.59M
  int i;
2532
1.59M
  int cmp;
2533
1.59M
2534
1.59M
  if (space1 == space2)
2535
1.16M
    return 0;
2536
430k
  
if (430k
!space1430k
)
2537
0
    return -1;
2538
430k
  
if (430k
!space2430k
)
2539
0
    return 1;
2540
430k
2541
430k
  cmp = isl_space_cmp_type(space1, space2, isl_dim_param);
2542
430k
  if (cmp != 0)
2543
0
    return cmp;
2544
430k
  cmp = isl_space_cmp_type(space1, space2, isl_dim_in);
2545
430k
  if (cmp != 0)
2546
0
    return cmp;
2547
430k
  cmp = isl_space_cmp_type(space1, space2, isl_dim_out);
2548
430k
  if (cmp != 0)
2549
0
    return cmp;
2550
430k
2551
430k
  
if (430k
!space1->ids && 430k
!space2->ids31.6k
)
2552
31.5k
    return 0;
2553
430k
2554
3.63M
  
for (i = 0; 399k
i < n(space1, isl_dim_param)3.63M
;
++i3.23M
)
{3.23M
2555
3.23M
    cmp = isl_id_cmp(get_id(space1, isl_dim_param, i),
2556
3.23M
         get_id(space2, isl_dim_param, i));
2557
3.23M
    if (cmp != 0)
2558
0
      return cmp;
2559
3.23M
  }
2560
399k
2561
399k
  return 0;
2562
399k
}