Coverage Report

Created: 2017-08-21 19:50

/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
1.11M
{
23
1.11M
  return dim ? dim->ctx : NULL;
24
1.11M
}
25
26
__isl_give isl_space *isl_space_alloc(isl_ctx *ctx,
27
      unsigned nparam, unsigned n_in, unsigned n_out)
28
4.03M
{
29
4.03M
  isl_space *dim;
30
4.03M
31
4.03M
  dim = isl_alloc_type(ctx, struct isl_space);
32
4.03M
  if (!dim)
33
8
    return NULL;
34
4.03M
35
4.03M
  dim->ctx = ctx;
36
4.03M
  isl_ctx_ref(ctx);
37
4.03M
  dim->ref = 1;
38
4.03M
  dim->nparam = nparam;
39
4.03M
  dim->n_in = n_in;
40
4.03M
  dim->n_out = n_out;
41
4.03M
42
4.03M
  dim->tuple_id[0] = NULL;
43
4.03M
  dim->tuple_id[1] = NULL;
44
4.03M
45
4.03M
  dim->nested[0] = NULL;
46
4.03M
  dim->nested[1] = NULL;
47
4.03M
48
4.03M
  dim->n_id = 0;
49
4.03M
  dim->ids = NULL;
50
4.03M
51
4.03M
  return dim;
52
4.03M
}
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
1.23M
{
59
1.23M
  space = isl_space_cow(space);
60
1.23M
  if (!space)
61
0
    return NULL;
62
1.23M
  space = isl_space_set_tuple_id(space, isl_dim_in, &isl_id_none);
63
1.23M
  return space;
64
1.23M
}
65
66
/* Is the space that of a set?
67
 */
68
isl_bool isl_space_is_set(__isl_keep isl_space *space)
69
1.28M
{
70
1.28M
  if (!space)
71
0
    return isl_bool_error;
72
1.28M
  
if (1.28M
space->n_in != 0 || 1.28M
space->nested[0]1.02M
)
73
257k
    return isl_bool_false;
74
1.02M
  
if (1.02M
space->tuple_id[0] != &isl_id_none1.02M
)
75
15.4k
    return isl_bool_false;
76
1.00M
  return isl_bool_true;
77
1.28M
}
78
79
/* Is the given space that of a map?
80
 */
81
isl_bool isl_space_is_map(__isl_keep isl_space *space)
82
16.6k
{
83
16.6k
  if (!space)
84
0
    return isl_bool_error;
85
16.6k
  return space->tuple_id[0] != &isl_id_none &&
86
519
    space->tuple_id[1] != &isl_id_none;
87
16.6k
}
88
89
__isl_give isl_space *isl_space_set_alloc(isl_ctx *ctx,
90
      unsigned nparam, unsigned dim)
91
420k
{
92
420k
  isl_space *space;
93
420k
  space = isl_space_alloc(ctx, nparam, 0, dim);
94
420k
  space = mark_as_set(space);
95
420k
  return space;
96
420k
}
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
116k
{
103
116k
  if (!space)
104
2
    return NULL;
105
116k
  space = isl_space_set_tuple_id(space, isl_dim_in, &isl_id_none);
106
116k
  space = isl_space_set_tuple_id(space, isl_dim_out, &isl_id_none);
107
116k
  return space;
108
116k
}
109
110
/* Is the space that of a parameter domain?
111
 */
112
isl_bool isl_space_is_params(__isl_keep isl_space *space)
113
553k
{
114
553k
  if (!space)
115
16
    return isl_bool_error;
116
553k
  
if (553k
space->n_in != 0 || 553k
space->nested[0]454k
||
117
553k
      
space->n_out != 0453k
||
space->nested[1]352k
)
118
201k
    return isl_bool_false;
119
351k
  
if (351k
space->tuple_id[0] != &isl_id_none351k
)
120
20.0k
    return isl_bool_false;
121
331k
  
if (331k
space->tuple_id[1] != &isl_id_none331k
)
122
23.1k
    return isl_bool_false;
123
308k
  return isl_bool_true;
124
553k
}
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
23.8k
{
130
23.8k
  isl_space *space;
131
23.8k
  space = isl_space_alloc(ctx, nparam, 0, 0);
132
23.8k
  space = mark_as_params(space);
133
23.8k
  return space;
134
23.8k
}
135
136
static unsigned global_pos(__isl_keep isl_space *dim,
137
         enum isl_dim_type type, unsigned pos)
138
59.9M
{
139
59.9M
  struct isl_ctx *ctx = dim->ctx;
140
59.9M
141
59.9M
  switch (type) {
142
59.9M
  case isl_dim_param:
143
29.8M
    isl_assert(ctx, pos < dim->nparam,
144
29.8M
          return isl_space_dim(dim, isl_dim_all));
145
29.8M
    return pos;
146
29.8M
  case isl_dim_in:
147
11.7M
    isl_assert(ctx, pos < dim->n_in,
148
11.7M
          return isl_space_dim(dim, isl_dim_all));
149
11.7M
    return pos + dim->nparam;
150
18.3M
  case isl_dim_out:
151
18.3M
    isl_assert(ctx, pos < dim->n_out,
152
18.3M
          return isl_space_dim(dim, isl_dim_all));
153
18.3M
    return pos + dim->nparam + dim->n_in;
154
18.3M
  default:
155
0
    isl_assert(ctx, 0, return isl_space_dim(dim, isl_dim_all));
156
59.9M
  }
157
0
  return isl_space_dim(dim, isl_dim_all);
158
59.9M
}
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
3.15M
{
164
3.15M
  isl_id **ids;
165
3.15M
  int i;
166
3.15M
167
3.15M
  if (isl_space_dim(dim, isl_dim_all) <= dim->n_id)
168
900k
    return dim;
169
3.15M
170
2.25M
  
if (2.25M
!dim->ids2.25M
)
{2.25M
171
2.25M
    dim->ids = isl_calloc_array(dim->ctx,
172
2.25M
        isl_id *, isl_space_dim(dim, isl_dim_all));
173
2.25M
    if (!dim->ids)
174
0
      goto error;
175
2.25M
  } else {
176
619
    ids = isl_realloc_array(dim->ctx, dim->ids,
177
619
        isl_id *, isl_space_dim(dim, isl_dim_all));
178
619
    if (!ids)
179
0
      goto error;
180
619
    dim->ids = ids;
181
3.32k
    for (i = dim->n_id; 
i < isl_space_dim(dim, isl_dim_all)3.32k
;
++i2.70k
)
182
2.70k
      dim->ids[i] = NULL;
183
2.25M
  }
184
2.25M
185
2.25M
  dim->n_id = isl_space_dim(dim, isl_dim_all);
186
2.25M
187
2.25M
  return dim;
188
2.25M
error:
189
0
  isl_space_free(dim);
190
2.25M
  return NULL;
191
3.15M
}
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
13.1M
{
196
13.1M
  dim = isl_space_cow(dim);
197
13.1M
198
13.1M
  if (!dim)
199
0
    goto error;
200
13.1M
201
13.1M
  pos = global_pos(dim, type, pos);
202
13.1M
  if (pos == isl_space_dim(dim, isl_dim_all))
203
0
    goto error;
204
13.1M
205
13.1M
  
if (13.1M
pos >= dim->n_id13.1M
)
{2.25M
206
2.25M
    if (!id)
207
0
      return dim;
208
2.25M
    dim = extend_ids(dim);
209
2.25M
    if (!dim)
210
0
      goto error;
211
13.1M
  }
212
13.1M
213
13.1M
  dim->ids[pos] = id;
214
13.1M
215
13.1M
  return dim;
216
13.1M
error:
217
0
  isl_id_free(id);
218
0
  isl_space_free(dim);
219
13.1M
  return NULL;
220
13.1M
}
221
222
static __isl_keep isl_id *get_id(__isl_keep isl_space *dim,
223
         enum isl_dim_type type, unsigned pos)
224
46.7M
{
225
46.7M
  if (!dim)
226
0
    return NULL;
227
46.7M
228
46.7M
  pos = global_pos(dim, type, pos);
229
46.7M
  if (pos == isl_space_dim(dim, isl_dim_all))
230
0
    return NULL;
231
46.7M
  
if (46.7M
pos >= dim->n_id46.7M
)
232
1.72M
    return NULL;
233
45.0M
  return dim->ids[pos];
234
46.7M
}
235
236
static unsigned offset(__isl_keep isl_space *dim, enum isl_dim_type type)
237
1.88M
{
238
1.88M
  switch (type) {
239
565k
  case isl_dim_param: return 0;
240
424k
  case isl_dim_in:  return dim->nparam;
241
897k
  case isl_dim_out: return dim->nparam + dim->n_in;
242
0
  default:    return 0;
243
1.88M
  }
244
1.88M
}
245
246
static unsigned n(__isl_keep isl_space *dim, enum isl_dim_type type)
247
262M
{
248
262M
  switch (type) {
249
49.1M
  case isl_dim_param: return dim->nparam;
250
31.8M
  case isl_dim_in:  return dim->n_in;
251
37.2M
  case isl_dim_out: return dim->n_out;
252
144M
  case isl_dim_all: return dim->nparam + dim->n_in + dim->n_out;
253
0
  default:    return 0;
254
262M
  }
255
262M
}
256
257
unsigned isl_space_dim(__isl_keep isl_space *dim, enum isl_dim_type type)
258
188M
{
259
188M
  if (!dim)
260
4
    return 0;
261
188M
  return n(dim, type);
262
188M
}
263
264
unsigned isl_space_offset(__isl_keep isl_space *dim, enum isl_dim_type type)
265
1.50M
{
266
1.50M
  if (!dim)
267
0
    return 0;
268
1.50M
  return offset(dim, type);
269
1.50M
}
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
7.97M
{
275
7.97M
  int i;
276
7.97M
  isl_id *id;
277
7.97M
278
7.97M
  if (!dst)
279
0
    return NULL;
280
7.97M
281
22.2M
  
for (i = 0; 7.97M
i < n(src, src_type)22.2M
;
++i14.2M
)
{14.2M
282
14.2M
    id = get_id(src, src_type, i);
283
14.2M
    if (!id)
284
4.56M
      continue;
285
14.2M
    dst = set_id(dst, dst_type, offset + i, isl_id_copy(id));
286
9.67M
    if (!dst)
287
0
      return NULL;
288
9.67M
  }
289
7.97M
  return dst;
290
7.97M
}
291
292
__isl_take isl_space *isl_space_dup(__isl_keep isl_space *dim)
293
3.04M
{
294
3.04M
  isl_space *dup;
295
3.04M
  if (!dim)
296
0
    return NULL;
297
3.04M
  dup = isl_space_alloc(dim->ctx, dim->nparam, dim->n_in, dim->n_out);
298
3.04M
  if (!dup)
299
8
    return NULL;
300
3.04M
  
if (3.04M
dim->tuple_id[0] &&3.04M
301
1.74M
      !(dup->tuple_id[0] = isl_id_copy(dim->tuple_id[0])))
302
0
    goto error;
303
3.04M
  
if (3.04M
dim->tuple_id[1] &&3.04M
304
743k
      !(dup->tuple_id[1] = isl_id_copy(dim->tuple_id[1])))
305
0
    goto error;
306
3.04M
  
if (3.04M
dim->nested[0] && 3.04M
!(dup->nested[0] = isl_space_copy(dim->nested[0]))533k
)
307
0
    goto error;
308
3.04M
  
if (3.04M
dim->nested[1] && 3.04M
!(dup->nested[1] = isl_space_copy(dim->nested[1]))685k
)
309
0
    goto error;
310
3.04M
  
if (3.04M
!dim->ids3.04M
)
311
1.00M
    return dup;
312
3.04M
  dup = copy_ids(dup, isl_dim_param, 0, dim, isl_dim_param);
313
2.03M
  dup = copy_ids(dup, isl_dim_in, 0, dim, isl_dim_in);
314
2.03M
  dup = copy_ids(dup, isl_dim_out, 0, dim, isl_dim_out);
315
3.04M
  return dup;
316
3.04M
error:
317
0
  isl_space_free(dup);
318
3.04M
  return NULL;
319
3.04M
}
320
321
__isl_give isl_space *isl_space_cow(__isl_take isl_space *dim)
322
22.5M
{
323
22.5M
  if (!dim)
324
7
    return NULL;
325
22.5M
326
22.5M
  
if (22.5M
dim->ref == 122.5M
)
327
19.5M
    return dim;
328
22.5M
  dim->ref--;
329
22.5M
  return isl_space_dup(dim);
330
22.5M
}
331
332
__isl_give isl_space *isl_space_copy(__isl_keep isl_space *dim)
333
13.1M
{
334
13.1M
  if (!dim)
335
7.91k
    return NULL;
336
13.1M
337
13.1M
  dim->ref++;
338
13.1M
  return dim;
339
13.1M
}
340
341
__isl_null isl_space *isl_space_free(__isl_take isl_space *space)
342
23.3M
{
343
23.3M
  int i;
344
23.3M
345
23.3M
  if (!space)
346
9.19M
    return NULL;
347
23.3M
348
14.1M
  
if (14.1M
--space->ref > 014.1M
)
349
10.1M
    return NULL;
350
14.1M
351
14.1M
  isl_id_free(space->tuple_id[0]);
352
4.03M
  isl_id_free(space->tuple_id[1]);
353
4.03M
354
4.03M
  isl_space_free(space->nested[0]);
355
4.03M
  isl_space_free(space->nested[1]);
356
4.03M
357
13.0M
  for (i = 0; 
i < space->n_id13.0M
;
++i9.00M
)
358
9.00M
    isl_id_free(space->ids[i]);
359
4.03M
  free(space->ids);
360
4.03M
  isl_ctx_deref(space->ctx);
361
4.03M
  
362
4.03M
  free(space);
363
4.03M
364
14.1M
  return NULL;
365
23.3M
}
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
51.9k
{
374
51.9k
  char *p;
375
51.9k
  long dummy;
376
51.9k
377
51.9k
  dummy = strtol(s, &p, 0);
378
51.9k
  if (p != s)
379
0
    isl_die(ctx, isl_error_invalid, "name looks like a number",
380
51.9k
      return 0);
381
51.9k
382
51.9k
  return 1;
383
51.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
92.1k
{
390
92.1k
  if (!space)
391
0
    return 0;
392
92.1k
  
if (92.1k
isl_space_is_params(space)92.1k
)
393
0
    isl_die(space->ctx, isl_error_invalid,
394
92.1k
      "parameter spaces don't have tuple ids", return 0);
395
92.1k
  
if (92.1k
isl_space_is_set(space) && 92.1k
type != isl_dim_set21.6k
)
396
0
    isl_die(space->ctx, isl_error_invalid,
397
92.1k
      "set spaces can only have a set id", return 0);
398
92.1k
  
if (92.1k
type != isl_dim_in && 92.1k
type != isl_dim_out91.7k
)
399
0
    isl_die(space->ctx, isl_error_invalid,
400
92.1k
      "only input, output and set tuples can have ids",
401
92.1k
      return 0);
402
92.1k
403
92.1k
  return 1;
404
92.1k
}
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
91.3k
{
411
91.3k
  if (!space_can_have_id(dim, type))
412
0
    return isl_bool_error;
413
91.3k
  return dim->tuple_id[type - isl_dim_in] != NULL;
414
91.3k
}
415
416
__isl_give isl_id *isl_space_get_tuple_id(__isl_keep isl_space *dim,
417
  enum isl_dim_type type)
418
33.1k
{
419
33.1k
  int has_id;
420
33.1k
421
33.1k
  if (!dim)
422
0
    return NULL;
423
33.1k
  has_id = isl_space_has_tuple_id(dim, type);
424
33.1k
  if (has_id < 0)
425
0
    return NULL;
426
33.1k
  
if (33.1k
!has_id33.1k
)
427
0
    isl_die(dim->ctx, isl_error_invalid,
428
33.1k
      "tuple has no id", return NULL);
429
33.1k
  return isl_id_copy(dim->tuple_id[type - isl_dim_in]);
430
33.1k
}
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.53M
{
435
1.53M
  dim = isl_space_cow(dim);
436
1.53M
  if (
!dim || 1.53M
!id1.53M
)
437
1
    goto error;
438
1.53M
  
if (1.53M
type != isl_dim_in && 1.53M
type != isl_dim_out175k
)
439
0
    isl_die(dim->ctx, isl_error_invalid,
440
1.53M
      "only input, output and set tuples can have names",
441
1.53M
      goto error);
442
1.53M
443
1.53M
  isl_id_free(dim->tuple_id[type - isl_dim_in]);
444
1.53M
  dim->tuple_id[type - isl_dim_in] = id;
445
1.53M
446
1.53M
  return dim;
447
1.53M
error:
448
1
  isl_id_free(id);
449
1
  isl_space_free(dim);
450
1.53M
  return NULL;
451
1.53M
}
452
453
__isl_give isl_space *isl_space_reset_tuple_id(__isl_take isl_space *dim,
454
  enum isl_dim_type type)
455
5.70k
{
456
5.70k
  dim = isl_space_cow(dim);
457
5.70k
  if (!dim)
458
0
    return NULL;
459
5.70k
  
if (5.70k
type != isl_dim_in && 5.70k
type != isl_dim_out5.70k
)
460
0
    isl_die(dim->ctx, isl_error_invalid,
461
5.70k
      "only input, output and set tuples can have names",
462
5.70k
      goto error);
463
5.70k
464
5.70k
  isl_id_free(dim->tuple_id[type - isl_dim_in]);
465
5.70k
  dim->tuple_id[type - isl_dim_in] = NULL;
466
5.70k
467
5.70k
  return dim;
468
5.70k
error:
469
0
  isl_space_free(dim);
470
5.70k
  return NULL;
471
5.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
80.9k
{
481
80.9k
  space = isl_space_cow(space);
482
80.9k
  if (
!space || 80.9k
!id80.9k
)
483
0
    goto error;
484
80.9k
485
80.9k
  
if (80.9k
type == isl_dim_param80.9k
)
{59.4k
486
59.4k
    int i;
487
59.4k
488
178k
    for (i = 0; 
i < 2178k
;
++i118k
)
{118k
489
118k
      if (!space->nested[i])
490
118k
        continue;
491
118k
      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
59.4k
    }
497
80.9k
  }
498
80.9k
499
80.9k
  isl_id_free(get_id(space, type, pos));
500
80.9k
  return set_id(space, type, pos, id);
501
80.9k
error:
502
0
  isl_id_free(id);
503
0
  isl_space_free(space);
504
80.9k
  return NULL;
505
80.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
950
{
543
950
  if (!dim)
544
0
    return isl_bool_error;
545
950
  return get_id(dim, type, pos) != NULL;
546
950
}
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
786k
{
551
786k
  if (!dim)
552
0
    return NULL;
553
786k
  
if (786k
!get_id(dim, type, pos)786k
)
554
0
    isl_die(dim->ctx, isl_error_invalid,
555
786k
      "dim has no id", return NULL);
556
786k
  return isl_id_copy(get_id(dim, type, pos));
557
786k
}
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
46.6k
{
562
46.6k
  isl_id *id;
563
46.6k
564
46.6k
  if (!dim)
565
0
    return NULL;
566
46.6k
567
46.6k
  
if (46.6k
!s46.6k
)
568
0
    return isl_space_reset_tuple_id(dim, type);
569
46.6k
570
46.6k
  
if (46.6k
!name_ok(dim->ctx, s)46.6k
)
571
0
    goto error;
572
46.6k
573
46.6k
  id = isl_id_alloc(dim->ctx, s, NULL);
574
46.6k
  return isl_space_set_tuple_id(dim, type, id);
575
46.6k
error:
576
0
  isl_space_free(dim);
577
46.6k
  return NULL;
578
46.6k
}
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
822
{
585
822
  isl_id *id;
586
822
587
822
  if (!space_can_have_id(space, type))
588
0
    return isl_bool_error;
589
822
  id = space->tuple_id[type - isl_dim_in];
590
178
  return id && id->name;
591
822
}
592
593
__isl_keep const char *isl_space_get_tuple_name(__isl_keep isl_space *dim,
594
   enum isl_dim_type type)
595
9.26k
{
596
9.26k
  isl_id *id;
597
9.26k
  if (!dim)
598
0
    return NULL;
599
9.26k
  
if (9.26k
type != isl_dim_in && 9.26k
type != isl_dim_out5.49k
)
600
0
    return NULL;
601
9.26k
  id = dim->tuple_id[type - isl_dim_in];
602
9.26k
  return id ? id->name : NULL;
603
9.26k
}
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
5.35k
{
609
5.35k
  isl_id *id;
610
5.35k
611
5.35k
  if (!dim)
612
0
    return NULL;
613
5.35k
  
if (5.35k
!s5.35k
)
614
0
    return isl_space_reset_dim_id(dim, type, pos);
615
5.35k
  
if (5.35k
!name_ok(dim->ctx, s)5.35k
)
616
0
    goto error;
617
5.35k
  id = isl_id_alloc(dim->ctx, s, NULL);
618
5.35k
  return isl_space_set_dim_id(dim, type, pos, id);
619
5.35k
error:
620
0
  isl_space_free(dim);
621
5.35k
  return NULL;
622
5.35k
}
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
5.68k
{
629
5.68k
  isl_id *id;
630
5.68k
631
5.68k
  if (!space)
632
0
    return isl_bool_error;
633
5.68k
  id = get_id(space, type, pos);
634
1.07k
  return id && id->name;
635
5.68k
}
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
306k
{
640
306k
  isl_id *id = get_id(dim, type, pos);
641
274k
  return id ? id->name : NULL;
642
306k
}
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
380
{
647
380
  int i;
648
380
  int offset;
649
380
  int n;
650
380
651
380
  if (
!dim || 380
!id380
)
652
0
    return -1;
653
380
654
380
  offset = isl_space_offset(dim, type);
655
380
  n = isl_space_dim(dim, type);
656
501
  for (i = 0; 
i < n && 501
offset + i < dim->n_id500
;
++i121
)
657
500
    
if (500
dim->ids[offset + i] == id500
)
658
379
      return i;
659
380
660
1
  return -1;
661
380
}
662
663
int isl_space_find_dim_by_name(__isl_keep isl_space *space,
664
  enum isl_dim_type type, const char *name)
665
854
{
666
854
  int i;
667
854
  int offset;
668
854
  int n;
669
854
670
854
  if (
!space || 854
!name854
)
671
0
    return -1;
672
854
673
854
  offset = isl_space_offset(space, type);
674
854
  n = isl_space_dim(space, type);
675
1.35k
  for (i = 0; 
i < n && 1.35k
offset + i < space->n_id496
;
++i496
)
{496
676
496
    isl_id *id = get_id(space, type, i);
677
496
    if (
id && 496
id->name496
&&
!strcmp(id->name, name)496
)
678
0
      return i;
679
854
  }
680
854
681
854
  return -1;
682
854
}
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
34.2M
{
746
34.2M
  if (!dim)
747
0
    return NULL;
748
34.2M
  
if (34.2M
type == isl_dim_in34.2M
)
749
10.7M
    return dim->tuple_id[0];
750
23.5M
  
if (23.5M
type == isl_dim_out23.5M
)
751
9.76M
    return dim->tuple_id[1];
752
13.7M
  return NULL;
753
34.2M
}
754
755
static __isl_keep isl_space *nested(__isl_keep isl_space *dim,
756
  enum isl_dim_type type)
757
31.7M
{
758
31.7M
  if (!dim)
759
0
    return NULL;
760
31.7M
  
if (31.7M
type == isl_dim_in31.7M
)
761
9.12M
    return dim->nested[0];
762
22.6M
  
if (22.6M
type == isl_dim_out22.6M
)
763
8.84M
    return dim->nested[1];
764
13.7M
  return NULL;
765
31.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
5.28M
{
772
5.28M
  if (
!space1 || 5.28M
!space25.28M
)
773
0
    return isl_bool_error;
774
5.28M
  
if (5.28M
space1 == space25.28M
)
775
1.54M
    return isl_bool_true;
776
5.28M
  return isl_space_tuple_is_equal(space1, isl_dim_in,
777
3.73M
          space2, isl_dim_in) &&
778
3.73M
         isl_space_tuple_is_equal(space1, isl_dim_out,
779
5.28M
          space2, isl_dim_out);
780
5.28M
}
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
16.7M
{
798
16.7M
  isl_id *id1, *id2;
799
16.7M
  isl_space *nested1, *nested2;
800
16.7M
801
16.7M
  if (
!space1 || 16.7M
!space216.7M
)
802
0
    return isl_bool_error;
803
16.7M
804
16.7M
  
if (16.7M
space1 == space2 && 16.7M
type1 == type21.47M
)
805
6.81k
    return isl_bool_true;
806
16.7M
807
16.7M
  
if (16.7M
n(space1, type1) != n(space2, type2)16.7M
)
808
1.62M
    return isl_bool_false;
809
16.7M
  id1 = tuple_id(space1, type1);
810
15.1M
  id2 = tuple_id(space2, type2);
811
15.1M
  if (!id1 ^ !id2)
812
508k
    return isl_bool_false;
813
14.6M
  
if (14.6M
id1 && 14.6M
id1 != id23.27M
)
814
127k
    return isl_bool_false;
815
14.6M
  nested1 = nested(space1, type1);
816
14.5M
  nested2 = nested(space2, type2);
817
14.5M
  if (!nested1 ^ !nested2)
818
50.2k
    return isl_bool_false;
819
14.4M
  
if (14.4M
nested1 && 14.4M
!isl_space_has_equal_tuples(nested1, nested2)2.53M
)
820
18.4k
    return isl_bool_false;
821
14.4M
  return isl_bool_true;
822
16.7M
}
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
9.03M
{
836
9.03M
  int i;
837
9.03M
838
9.03M
  if (
space1 == space2 && 9.03M
type1 == type22.28M
)
839
825k
    return isl_bool_true;
840
9.03M
841
8.21M
  
if (8.21M
!isl_space_tuple_is_equal(space1, type1, space2, type2)8.21M
)
842
1.54M
    return isl_bool_false;
843
8.21M
844
6.66M
  
if (6.66M
!space1->ids && 6.66M
!space2->ids1.50M
)
845
1.37M
    return isl_bool_true;
846
6.66M
847
12.3M
  
for (i = 0; 5.29M
i < n(space1, type1)12.3M
;
++i7.05M
)
{7.09M
848
7.09M
    if (get_id(space1, type1, i) != get_id(space2, type2, i))
849
45.2k
      return isl_bool_false;
850
7.09M
  }
851
5.25M
  return isl_bool_true;
852
9.03M
}
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
7.21M
{
859
7.21M
  if (
!space1 || 7.21M
!space27.21M
)
860
1
    return isl_bool_error;
861
7.21M
862
7.21M
  return match(space1, isl_dim_param, space2, isl_dim_param);
863
7.21M
}
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
182k
{
871
182k
  isl_bool equal;
872
182k
873
182k
  if (
!space1 || 182k
!space2182k
)
874
0
    return isl_bool_error;
875
182k
876
182k
  equal = match(space1, isl_dim_in, space2, isl_dim_in);
877
182k
  if (
equal < 0 || 182k
!equal182k
)
878
137
    return equal;
879
181k
  return match(space1, isl_dim_out, space2, isl_dim_out);
880
182k
}
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
3.60M
{
894
3.60M
  int i;
895
3.60M
896
9.35M
  for (i = 0; 
i < n9.35M
;
++i5.75M
)
897
5.75M
    ids[i] = get_id(dim, type, first + i);
898
3.60M
}
899
900
static __isl_give isl_space *space_extend(__isl_take isl_space *space,
901
      unsigned nparam, unsigned n_in, unsigned n_out)
902
593k
{
903
593k
  isl_id **ids = NULL;
904
593k
905
593k
  if (!space)
906
0
    return NULL;
907
593k
  
if (593k
space->nparam == nparam &&593k
908
593k
      
space->n_in == n_in439k
&&
space->n_out == n_out433k
)
909
27.4k
    return space;
910
593k
911
565k
  
isl_assert565k
(space->ctx, space->nparam <= nparam, goto error);565k
912
565k
  
isl_assert565k
(space->ctx, space->n_in <= n_in, goto error);565k
913
565k
  
isl_assert565k
(space->ctx, space->n_out <= n_out, goto error);565k
914
565k
915
565k
  space = isl_space_cow(space);
916
565k
  if (!space)
917
0
    goto error;
918
565k
919
565k
  
if (565k
space->ids565k
)
{303k
920
303k
    unsigned n;
921
303k
    n = nparam + n_in + n_out;
922
303k
    if (
n < nparam || 303k
n < n_in303k
||
n < n_out303k
)
923
0
      isl_die(isl_space_get_ctx(space), isl_error_invalid,
924
303k
        "overflow in total number of dimensions",
925
303k
        goto error);
926
303k
    
ids = 303k
isl_calloc_array303k
(space->ctx, isl_id *, n);
927
303k
    if (!ids)
928
0
      goto error;
929
303k
    get_ids(space, isl_dim_param, 0, space->nparam, ids);
930
303k
    get_ids(space, isl_dim_in, 0, space->n_in, ids + nparam);
931
303k
    get_ids(space, isl_dim_out, 0, space->n_out,
932
303k
      ids + nparam + n_in);
933
303k
    free(space->ids);
934
303k
    space->ids = ids;
935
303k
    space->n_id = nparam + n_in + n_out;
936
565k
  }
937
565k
  space->nparam = nparam;
938
565k
  space->n_in = n_in;
939
565k
  space->n_out = n_out;
940
565k
941
565k
  return space;
942
565k
error:
943
0
  free(ids);
944
0
  isl_space_free(space);
945
565k
  return NULL;
946
593k
}
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
593k
{
957
593k
  space = isl_space_reset(space, type);
958
593k
  if (!space)
959
6
    return NULL;
960
593k
  switch (type) {
961
593k
  case isl_dim_param:
962
180k
    space = space_extend(space,
963
180k
        space->nparam + n, space->n_in, space->n_out);
964
180k
    if (
space && 180k
space->nested[0]180k
&&
965
180k
        !(space->nested[0] = isl_space_add_dims(space->nested[0],
966
180k
                isl_dim_param, n)))
967
0
      goto error;
968
180k
    
if (180k
space && 180k
space->nested[1]180k
&&
969
180k
        !(space->nested[1] = isl_space_add_dims(space->nested[1],
970
180k
                isl_dim_param, n)))
971
0
      goto error;
972
180k
    return space;
973
180k
  case isl_dim_in:
974
6.91k
    return space_extend(space,
975
180k
        space->nparam, space->n_in + n, space->n_out);
976
405k
  case isl_dim_out:
977
405k
    return space_extend(space,
978
405k
        space->nparam, space->n_in, space->n_out + n);
979
180k
  default:
980
0
    isl_die(space->ctx, isl_error_invalid,
981
593k
      "cannot add dimensions of specified type", goto error);
982
593k
  }
983
593k
error:
984
0
  isl_space_free(space);
985
593k
  return NULL;
986
593k
}
987
988
static int valid_dim_type(enum isl_dim_type type)
989
1.65M
{
990
1.65M
  switch (type) {
991
1.65M
  case isl_dim_param:
992
1.65M
  case isl_dim_in:
993
1.65M
  case isl_dim_out:
994
1.65M
    return 1;
995
1.65M
  default:
996
1.65M
    return 0;
997
1.65M
  }
998
1.65M
}
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
142k
{
1007
142k
  isl_id **ids = NULL;
1008
142k
1009
142k
  if (!dim)
1010
0
    return NULL;
1011
142k
  
if (142k
n == 0142k
)
1012
2
    return isl_space_reset(dim, type);
1013
142k
1014
142k
  
if (142k
!valid_dim_type(type)142k
)
1015
0
    isl_die(dim->ctx, isl_error_invalid,
1016
142k
      "cannot insert dimensions of specified type",
1017
142k
      goto error);
1018
142k
1019
142k
  
isl_assert142k
(dim->ctx, pos <= isl_space_dim(dim, type), goto error);142k
1020
142k
1021
142k
  dim = isl_space_cow(dim);
1022
142k
  if (!dim)
1023
0
    return NULL;
1024
142k
1025
142k
  
if (142k
dim->ids142k
)
{85.5k
1026
85.5k
    enum isl_dim_type t, o = isl_dim_param;
1027
85.5k
    int off;
1028
85.5k
    int s[3];
1029
85.5k
    ids = isl_calloc_array(dim->ctx, isl_id *,
1030
85.5k
             dim->nparam + dim->n_in + dim->n_out + n);
1031
85.5k
    if (!ids)
1032
0
      goto error;
1033
85.5k
    off = 0;
1034
85.5k
    s[isl_dim_param - o] = dim->nparam;
1035
85.5k
    s[isl_dim_in - o] = dim->n_in;
1036
85.5k
    s[isl_dim_out - o] = dim->n_out;
1037
342k
    for (t = isl_dim_param; 
t <= isl_dim_out342k
;
++t256k
)
{256k
1038
256k
      if (
t != type256k
)
{171k
1039
171k
        get_ids(dim, t, 0, s[t - o], ids + off);
1040
171k
        off += s[t - o];
1041
256k
      } else {
1042
85.5k
        get_ids(dim, t, 0, pos, ids + off);
1043
85.5k
        off += pos + n;
1044
85.5k
        get_ids(dim, t, pos, s[t - o] - pos, ids + off);
1045
85.5k
        off += s[t - o] - pos;
1046
256k
      }
1047
256k
    }
1048
85.5k
    free(dim->ids);
1049
85.5k
    dim->ids = ids;
1050
85.5k
    dim->n_id = dim->nparam + dim->n_in + dim->n_out + n;
1051
142k
  }
1052
142k
  switch (type) {
1053
2.29k
  case isl_dim_param: dim->nparam += n; break;
1054
8.55k
  case isl_dim_in:  dim->n_in += n; break;
1055
131k
  case isl_dim_out: dim->n_out += n; break;
1056
0
  default:    ;
1057
142k
  }
1058
142k
  dim = isl_space_reset(dim, type);
1059
142k
1060
142k
  if (
type == isl_dim_param142k
)
{2.29k
1061
2.29k
    if (
dim && 2.29k
dim->nested[0]2.29k
&&
1062
2.29k
        !(dim->nested[0] = isl_space_insert_dims(dim->nested[0],
1063
2.29k
                isl_dim_param, pos, n)))
1064
0
      goto error;
1065
2.29k
    
if (2.29k
dim && 2.29k
dim->nested[1]2.29k
&&
1066
2.29k
        !(dim->nested[1] = isl_space_insert_dims(dim->nested[1],
1067
2.29k
                isl_dim_param, pos, n)))
1068
0
      goto error;
1069
142k
  }
1070
142k
1071
142k
  return dim;
1072
142k
error:
1073
0
  isl_space_free(dim);
1074
142k
  return NULL;
1075
142k
}
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
1.11k
{
1081
1.11k
  int i;
1082
1.11k
1083
1.11k
  space = isl_space_reset(space, src_type);
1084
1.11k
  space = isl_space_reset(space, dst_type);
1085
1.11k
  if (!space)
1086
0
    return NULL;
1087
1.11k
  
if (1.11k
n == 01.11k
)
1088
299
    return space;
1089
1.11k
1090
814
  
isl_assert814
(space->ctx, src_pos + n <= isl_space_dim(space, src_type),814
1091
814
    goto error);
1092
814
1093
814
  
if (814
dst_type == src_type && 814
dst_pos == src_pos0
)
1094
0
    return space;
1095
814
1096
814
  
isl_assert814
(space->ctx, dst_type != src_type, goto error);814
1097
814
1098
814
  space = isl_space_cow(space);
1099
814
  if (!space)
1100
0
    return NULL;
1101
814
1102
814
  
if (814
space->ids814
)
{474
1103
474
    isl_id **ids;
1104
474
    enum isl_dim_type t, o = isl_dim_param;
1105
474
    int off;
1106
474
    int s[3];
1107
474
    ids = isl_calloc_array(space->ctx, isl_id *,
1108
474
         space->nparam + space->n_in + space->n_out);
1109
474
    if (!ids)
1110
0
      goto error;
1111
474
    off = 0;
1112
474
    s[isl_dim_param - o] = space->nparam;
1113
474
    s[isl_dim_in - o] = space->n_in;
1114
474
    s[isl_dim_out - o] = space->n_out;
1115
1.89k
    for (t = isl_dim_param; 
t <= isl_dim_out1.89k
;
++t1.42k
)
{1.42k
1116
1.42k
      if (
t == dst_type1.42k
)
{474
1117
474
        get_ids(space, t, 0, dst_pos, ids + off);
1118
474
        off += dst_pos;
1119
474
        get_ids(space, src_type, src_pos, n, ids + off);
1120
474
        off += n;
1121
474
        get_ids(space, t, dst_pos, s[t - o] - dst_pos,
1122
474
            ids + off);
1123
474
        off += s[t - o] - dst_pos;
1124
1.42k
      } else 
if (948
t == src_type948
)
{474
1125
474
        get_ids(space, t, 0, src_pos, ids + off);
1126
474
        off += src_pos;
1127
474
        get_ids(space, t, src_pos + n,
1128
474
              s[t - o] - src_pos - n, ids + off);
1129
474
        off += s[t - o] - src_pos - n;
1130
948
      } else {
1131
474
        get_ids(space, t, 0, s[t - o], ids + off);
1132
474
        off += s[t - o];
1133
1.42k
      }
1134
1.42k
    }
1135
474
    free(space->ids);
1136
474
    space->ids = ids;
1137
474
    space->n_id = space->nparam + space->n_in + space->n_out;
1138
814
  }
1139
814
1140
814
  switch (dst_type) {
1141
86
  case isl_dim_param: space->nparam += n; break;
1142
321
  case isl_dim_in:  space->n_in += n; break;
1143
407
  case isl_dim_out: space->n_out += n; break;
1144
0
  default:    ;
1145
814
  }
1146
814
1147
814
  switch (src_type) {
1148
234
  case isl_dim_param: space->nparam -= n; break;
1149
191
  case isl_dim_in:  space->n_in -= n; break;
1150
389
  case isl_dim_out: space->n_out -= n; break;
1151
0
  default:    ;
1152
814
  }
1153
814
1154
814
  
if (814
dst_type != isl_dim_param && 814
src_type != isl_dim_param728
)
1155
494
    return space;
1156
814
1157
960
  
for (i = 0; 320
i < 2960
;
++i640
)
{640
1158
640
    if (!space->nested[i])
1159
623
      continue;
1160
640
    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
320
  }
1165
320
1166
320
  return space;
1167
320
error:
1168
0
  isl_space_free(space);
1169
320
  return NULL;
1170
1.11k
}
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
495k
{
1178
495k
  isl_bool equal;
1179
495k
1180
495k
  equal = isl_space_has_equal_params(space1, space2);
1181
495k
  if (equal < 0)
1182
1
    return isl_stat_error;
1183
495k
  
if (495k
!equal495k
)
1184
0
    isl_die(isl_space_get_ctx(space1), isl_error_invalid,
1185
495k
      "parameters need to match", return isl_stat_error);
1186
495k
  return isl_stat_ok;
1187
495k
}
1188
1189
__isl_give isl_space *isl_space_join(__isl_take isl_space *left,
1190
  __isl_take isl_space *right)
1191
417k
{
1192
417k
  isl_space *dim;
1193
417k
1194
417k
  if (isl_space_check_equal_params(left, right) < 0)
1195
1
    goto error;
1196
417k
1197
417k
  
isl_assert417k
(left->ctx,417k
1198
417k
    isl_space_tuple_is_equal(left, isl_dim_out, right, isl_dim_in),
1199
417k
    goto error);
1200
417k
1201
417k
  dim = isl_space_alloc(left->ctx, left->nparam, left->n_in, right->n_out);
1202
417k
  if (!dim)
1203
0
    goto error;
1204
417k
1205
417k
  dim = copy_ids(dim, isl_dim_param, 0, left, isl_dim_param);
1206
417k
  dim = copy_ids(dim, isl_dim_in, 0, left, isl_dim_in);
1207
417k
  dim = copy_ids(dim, isl_dim_out, 0, right, isl_dim_out);
1208
417k
1209
417k
  if (
dim && 417k
left->tuple_id[0]417k
&&
1210
142k
      !(dim->tuple_id[0] = isl_id_copy(left->tuple_id[0])))
1211
0
    goto error;
1212
417k
  
if (417k
dim && 417k
right->tuple_id[1]417k
&&
1213
120k
      !(dim->tuple_id[1] = isl_id_copy(right->tuple_id[1])))
1214
0
    goto error;
1215
417k
  
if (417k
dim && 417k
left->nested[0]417k
&&
1216
152k
      !(dim->nested[0] = isl_space_copy(left->nested[0])))
1217
0
    goto error;
1218
417k
  
if (417k
dim && 417k
right->nested[1]417k
&&
1219
190k
      !(dim->nested[1] = isl_space_copy(right->nested[1])))
1220
0
    goto error;
1221
417k
1222
417k
  isl_space_free(left);
1223
417k
  isl_space_free(right);
1224
417k
1225
417k
  return dim;
1226
417k
error:
1227
1
  isl_space_free(left);
1228
1
  isl_space_free(right);
1229
417k
  return NULL;
1230
417k
}
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
2.45k
{
1239
2.45k
  isl_space *dom1, *dom2, *nest1, *nest2;
1240
2.45k
  int is_set;
1241
2.45k
1242
2.45k
  if (
!left || 2.45k
!right2.45k
)
1243
0
    goto error;
1244
2.45k
1245
2.45k
  is_set = isl_space_is_set(left);
1246
2.45k
  if (is_set != isl_space_is_set(right))
1247
0
    isl_die(isl_space_get_ctx(left), isl_error_invalid,
1248
2.45k
      "expecting either two set spaces or two map spaces",
1249
2.45k
      goto error);
1250
2.45k
  
if (2.45k
is_set2.45k
)
1251
220
    return isl_space_range_product(left, right);
1252
2.45k
1253
2.23k
  
if (2.23k
isl_space_check_equal_params(left, right) < 02.23k
)
1254
0
    goto error;
1255
2.23k
1256
2.23k
  dom1 = isl_space_domain(isl_space_copy(left));
1257
2.23k
  dom2 = isl_space_domain(isl_space_copy(right));
1258
2.23k
  nest1 = isl_space_wrap(isl_space_join(isl_space_reverse(dom1), dom2));
1259
2.23k
1260
2.23k
  dom1 = isl_space_range(left);
1261
2.23k
  dom2 = isl_space_range(right);
1262
2.23k
  nest2 = isl_space_wrap(isl_space_join(isl_space_reverse(dom1), dom2));
1263
2.23k
1264
2.23k
  return isl_space_join(isl_space_reverse(nest1), nest2);
1265
2.23k
error:
1266
0
  isl_space_free(left);
1267
0
  isl_space_free(right);
1268
2.23k
  return NULL;
1269
2.45k
}
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.72k
{
1277
1.72k
  isl_space *ran, *dom1, *dom2, *nest;
1278
1.72k
1279
1.72k
  if (isl_space_check_equal_params(left, right) < 0)
1280
0
    goto error;
1281
1.72k
1282
1.72k
  
if (1.72k
!isl_space_tuple_is_equal(left, isl_dim_out, right, isl_dim_out)1.72k
)
1283
0
    isl_die(left->ctx, isl_error_invalid,
1284
1.72k
      "ranges need to match", goto error);
1285
1.72k
1286
1.72k
  ran = isl_space_range(isl_space_copy(left));
1287
1.72k
1288
1.72k
  dom1 = isl_space_domain(left);
1289
1.72k
  dom2 = isl_space_domain(right);
1290
1.72k
  nest = isl_space_wrap(isl_space_join(isl_space_reverse(dom1), dom2));
1291
1.72k
1292
1.72k
  return isl_space_join(isl_space_reverse(nest), ran);
1293
1.72k
error:
1294
0
  isl_space_free(left);
1295
0
  isl_space_free(right);
1296
1.72k
  return NULL;
1297
1.72k
}
1298
1299
__isl_give isl_space *isl_space_range_product(__isl_take isl_space *left,
1300
  __isl_take isl_space *right)
1301
74.3k
{
1302
74.3k
  isl_space *dom, *ran1, *ran2, *nest;
1303
74.3k
1304
74.3k
  if (isl_space_check_equal_params(left, right) < 0)
1305
0
    goto error;
1306
74.3k
1307
74.3k
  
if (74.3k
!isl_space_tuple_is_equal(left, isl_dim_in, right, isl_dim_in)74.3k
)
1308
0
    isl_die(left->ctx, isl_error_invalid,
1309
74.3k
      "domains need to match", goto error);
1310
74.3k
1311
74.3k
  dom = isl_space_domain(isl_space_copy(left));
1312
74.3k
1313
74.3k
  ran1 = isl_space_range(left);
1314
74.3k
  ran2 = isl_space_range(right);
1315
74.3k
  nest = isl_space_wrap(isl_space_join(isl_space_reverse(ran1), ran2));
1316
74.3k
1317
74.3k
  return isl_space_join(isl_space_reverse(dom), nest);
1318
74.3k
error:
1319
0
  isl_space_free(left);
1320
0
  isl_space_free(right);
1321
74.3k
  return NULL;
1322
74.3k
}
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
12
{
1328
12
  space = isl_space_domain_factor_domain(space);
1329
12
  space = isl_space_range_factor_domain(space);
1330
12
  return space;
1331
12
}
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
571
{
1338
571
  isl_space *nested;
1339
571
  isl_space *domain;
1340
571
1341
571
  if (!space)
1342
0
    return NULL;
1343
571
  
if (571
!isl_space_domain_is_wrapping(space)571
)
1344
0
    isl_die(isl_space_get_ctx(space), isl_error_invalid,
1345
571
      "domain not a product", return isl_space_free(space));
1346
571
1347
571
  nested = space->nested[0];
1348
571
  domain = isl_space_copy(space);
1349
571
  domain = isl_space_drop_dims(domain, isl_dim_in,
1350
571
          nested->n_in, nested->n_out);
1351
571
  if (!domain)
1352
0
    return isl_space_free(space);
1353
571
  
if (571
nested->tuple_id[0]571
)
{302
1354
302
    domain->tuple_id[0] = isl_id_copy(nested->tuple_id[0]);
1355
302
    if (!domain->tuple_id[0])
1356
0
      goto error;
1357
571
  }
1358
571
  
if (571
nested->nested[0]571
)
{269
1359
269
    domain->nested[0] = isl_space_copy(nested->nested[0]);
1360
269
    if (!domain->nested[0])
1361
0
      goto error;
1362
571
  }
1363
571
1364
571
  isl_space_free(space);
1365
571
  return domain;
1366
571
error:
1367
0
  isl_space_free(space);
1368
0
  isl_space_free(domain);
1369
571
  return NULL;
1370
571
}
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
18.4k
{
1377
18.4k
  isl_space *nested;
1378
18.4k
  isl_space *range;
1379
18.4k
1380
18.4k
  if (!space)
1381
0
    return NULL;
1382
18.4k
  
if (18.4k
!isl_space_domain_is_wrapping(space)18.4k
)
1383
0
    isl_die(isl_space_get_ctx(space), isl_error_invalid,
1384
18.4k
      "domain not a product", return isl_space_free(space));
1385
18.4k
1386
18.4k
  nested = space->nested[0];
1387
18.4k
  range = isl_space_copy(space);
1388
18.4k
  range = isl_space_drop_dims(range, isl_dim_in, 0, nested->n_in);
1389
18.4k
  if (!range)
1390
0
    return isl_space_free(space);
1391
18.4k
  
if (18.4k
nested->tuple_id[1]18.4k
)
{11.4k
1392
11.4k
    range->tuple_id[0] = isl_id_copy(nested->tuple_id[1]);
1393
11.4k
    if (!range->tuple_id[0])
1394
0
      goto error;
1395
18.4k
  }
1396
18.4k
  
if (18.4k
nested->nested[1]18.4k
)
{7.03k
1397
7.03k
    range->nested[0] = isl_space_copy(nested->nested[1]);
1398
7.03k
    if (!range->nested[0])
1399
0
      goto error;
1400
18.4k
  }
1401
18.4k
1402
18.4k
  isl_space_free(space);
1403
18.4k
  return range;
1404
18.4k
error:
1405
0
  isl_space_free(space);
1406
0
  isl_space_free(range);
1407
18.4k
  return NULL;
1408
18.4k
}
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.79k
{
1415
1.79k
  isl_space *nested;
1416
1.79k
  isl_space *domain;
1417
1.79k
1418
1.79k
  if (!space)
1419
0
    return NULL;
1420
1.79k
  
if (1.79k
!isl_space_range_is_wrapping(space)1.79k
)
1421
0
    isl_die(isl_space_get_ctx(space), isl_error_invalid,
1422
1.79k
      "range not a product", return isl_space_free(space));
1423
1.79k
1424
1.79k
  nested = space->nested[1];
1425
1.79k
  domain = isl_space_copy(space);
1426
1.79k
  domain = isl_space_drop_dims(domain, isl_dim_out,
1427
1.79k
          nested->n_in, nested->n_out);
1428
1.79k
  if (!domain)
1429
0
    return isl_space_free(space);
1430
1.79k
  
if (1.79k
nested->tuple_id[0]1.79k
)
{1.04k
1431
1.04k
    domain->tuple_id[1] = isl_id_copy(nested->tuple_id[0]);
1432
1.04k
    if (!domain->tuple_id[1])
1433
0
      goto error;
1434
1.79k
  }
1435
1.79k
  
if (1.79k
nested->nested[0]1.79k
)
{733
1436
733
    domain->nested[1] = isl_space_copy(nested->nested[0]);
1437
733
    if (!domain->nested[1])
1438
0
      goto error;
1439
1.79k
  }
1440
1.79k
1441
1.79k
  isl_space_free(space);
1442
1.79k
  return domain;
1443
1.79k
error:
1444
0
  isl_space_free(space);
1445
0
  isl_space_free(domain);
1446
1.79k
  return NULL;
1447
1.79k
}
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
11.9k
{
1456
11.9k
  isl_space *nested;
1457
11.9k
  isl_space *range;
1458
11.9k
1459
11.9k
  if (!space)
1460
0
    return NULL;
1461
11.9k
1462
11.9k
  nested = space->nested[1];
1463
11.9k
  range = isl_space_copy(space);
1464
11.9k
  range = isl_space_drop_dims(range, isl_dim_out, 0, nested->n_in);
1465
11.9k
  if (!range)
1466
0
    return isl_space_free(space);
1467
11.9k
  
if (11.9k
nested->tuple_id[1]11.9k
)
{595
1468
595
    range->tuple_id[1] = isl_id_copy(nested->tuple_id[1]);
1469
595
    if (!range->tuple_id[1])
1470
0
      goto error;
1471
11.9k
  }
1472
11.9k
  
if (11.9k
nested->nested[1]11.9k
)
{11.3k
1473
11.3k
    range->nested[1] = isl_space_copy(nested->nested[1]);
1474
11.3k
    if (!range->nested[1])
1475
0
      goto error;
1476
11.9k
  }
1477
11.9k
1478
11.9k
  isl_space_free(space);
1479
11.9k
  return range;
1480
11.9k
error:
1481
0
  isl_space_free(space);
1482
0
  isl_space_free(range);
1483
11.9k
  return NULL;
1484
11.9k
}
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
11.9k
{
1491
11.9k
  if (!space)
1492
0
    return NULL;
1493
11.9k
  
if (11.9k
!isl_space_range_is_wrapping(space)11.9k
)
1494
0
    isl_die(isl_space_get_ctx(space), isl_error_invalid,
1495
11.9k
      "range not a product", return isl_space_free(space));
1496
11.9k
1497
11.9k
  return range_factor_range(space);
1498
11.9k
}
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
11.3k
{
1518
11.3k
  if (!space)
1519
0
    return NULL;
1520
11.3k
  
if (11.3k
isl_space_is_set(space)11.3k
)
1521
0
    return set_factor_range(space);
1522
11.3k
  space = isl_space_domain_factor_range(space);
1523
11.3k
  space = isl_space_range_factor_range(space);
1524
11.3k
  return space;
1525
11.3k
}
1526
1527
__isl_give isl_space *isl_space_map_from_set(__isl_take isl_space *space)
1528
10.1k
{
1529
10.1k
  isl_ctx *ctx;
1530
10.1k
  isl_id **ids = NULL;
1531
10.1k
  int n_id;
1532
10.1k
1533
10.1k
  if (!space)
1534
3
    return NULL;
1535
10.1k
  ctx = isl_space_get_ctx(space);
1536
10.1k
  if (!isl_space_is_set(space))
1537
0
    isl_die(ctx, isl_error_invalid, "not a set space", goto error);
1538
10.1k
  space = isl_space_cow(space);
1539
10.1k
  if (!space)
1540
0
    return NULL;
1541
10.1k
  n_id = space->nparam + space->n_out + space->n_out;
1542
10.1k
  if (
n_id > 0 && 10.1k
space->ids9.63k
)
{7.88k
1543
7.88k
    ids = isl_calloc_array(space->ctx, isl_id *, n_id);
1544
7.88k
    if (!ids)
1545
0
      goto error;
1546
7.88k
    get_ids(space, isl_dim_param, 0, space->nparam, ids);
1547
7.88k
    get_ids(space, isl_dim_out, 0, space->n_out,
1548
7.88k
      ids + space->nparam);
1549
10.1k
  }
1550
10.1k
  space->n_in = space->n_out;
1551
10.1k
  if (
ids10.1k
)
{7.88k
1552
7.88k
    free(space->ids);
1553
7.88k
    space->ids = ids;
1554
7.88k
    space->n_id = n_id;
1555
7.88k
    space = copy_ids(space, isl_dim_out, 0, space, isl_dim_in);
1556
10.1k
  }
1557
10.1k
  isl_id_free(space->tuple_id[0]);
1558
10.1k
  space->tuple_id[0] = isl_id_copy(space->tuple_id[1]);
1559
10.1k
  isl_space_free(space->nested[0]);
1560
10.1k
  space->nested[0] = isl_space_copy(space->nested[1]);
1561
10.1k
  return space;
1562
10.1k
error:
1563
0
  isl_space_free(space);
1564
10.1k
  return NULL;
1565
10.1k
}
1566
1567
__isl_give isl_space *isl_space_map_from_domain_and_range(
1568
  __isl_take isl_space *domain, __isl_take isl_space *range)
1569
60.5k
{
1570
60.5k
  if (
!domain || 60.5k
!range60.5k
)
1571
1
    goto error;
1572
60.5k
  
if (60.5k
!isl_space_is_set(domain)60.5k
)
1573
0
    isl_die(isl_space_get_ctx(domain), isl_error_invalid,
1574
60.5k
      "domain is not a set space", goto error);
1575
60.5k
  
if (60.5k
!isl_space_is_set(range)60.5k
)
1576
0
    isl_die(isl_space_get_ctx(range), isl_error_invalid,
1577
60.5k
      "range is not a set space", goto error);
1578
60.5k
  return isl_space_join(isl_space_reverse(domain), range);
1579
60.5k
error:
1580
1
  isl_space_free(domain);
1581
1
  isl_space_free(range);
1582
60.5k
  return NULL;
1583
60.5k
}
1584
1585
static __isl_give isl_space *set_ids(__isl_take isl_space *dim,
1586
  enum isl_dim_type type,
1587
  unsigned first, unsigned n, __isl_take isl_id **ids)
1588
1.94M
{
1589
1.94M
  int i;
1590
1.94M
1591
5.26M
  for (i = 0; 
i < n5.26M
;
++i3.31M
)
1592
3.31M
    dim = set_id(dim, type, first + i, ids[i]);
1593
1.94M
1594
1.94M
  return dim;
1595
1.94M
}
1596
1597
__isl_give isl_space *isl_space_reverse(__isl_take isl_space *dim)
1598
1.46M
{
1599
1.46M
  unsigned t;
1600
1.46M
  isl_space *nested;
1601
1.46M
  isl_id **ids = NULL;
1602
1.46M
  isl_id *id;
1603
1.46M
1604
1.46M
  if (!dim)
1605
0
    return NULL;
1606
1.46M
  
if (1.46M
match(dim, isl_dim_in, dim, isl_dim_out)1.46M
)
1607
90.3k
    return dim;
1608
1.46M
1609
1.46M
  dim = isl_space_cow(dim);
1610
1.37M
  if (!dim)
1611
1
    return NULL;
1612
1.37M
1613
1.37M
  id = dim->tuple_id[0];
1614
1.37M
  dim->tuple_id[0] = dim->tuple_id[1];
1615
1.37M
  dim->tuple_id[1] = id;
1616
1.37M
1617
1.37M
  nested = dim->nested[0];
1618
1.37M
  dim->nested[0] = dim->nested[1];
1619
1.37M
  dim->nested[1] = nested;
1620
1.37M
1621
1.37M
  if (
dim->ids1.37M
)
{973k
1622
973k
    int n_id = dim->n_in + dim->n_out;
1623
973k
    ids = isl_alloc_array(dim->ctx, isl_id *, n_id);
1624
973k
    if (
n_id && 973k
!ids841k
)
1625
0
      goto error;
1626
973k
    get_ids(dim, isl_dim_in, 0, dim->n_in, ids);
1627
973k
    get_ids(dim, isl_dim_out, 0, dim->n_out, ids + dim->n_in);
1628
1.37M
  }
1629
1.37M
1630
1.37M
  t = dim->n_in;
1631
1.37M
  dim->n_in = dim->n_out;
1632
1.37M
  dim->n_out = t;
1633
1.37M
1634
1.37M
  if (
dim->ids1.37M
)
{973k
1635
973k
    dim = set_ids(dim, isl_dim_out, 0, dim->n_out, ids);
1636
973k
    dim = set_ids(dim, isl_dim_in, 0, dim->n_in, ids + dim->n_out);
1637
973k
    free(ids);
1638
1.37M
  }
1639
1.37M
1640
1.37M
  return dim;
1641
1.37M
error:
1642
0
  free(ids);
1643
0
  isl_space_free(dim);
1644
1.37M
  return NULL;
1645
1.46M
}
1646
1647
__isl_give isl_space *isl_space_drop_dims(__isl_take isl_space *dim,
1648
  enum isl_dim_type type, unsigned first, unsigned num)
1649
1.87M
{
1650
1.87M
  int i;
1651
1.87M
1652
1.87M
  if (!dim)
1653
2
    return NULL;
1654
1.87M
1655
1.87M
  
if (1.87M
num == 01.87M
)
1656
362k
    return isl_space_reset(dim, type);
1657
1.87M
1658
1.51M
  
if (1.51M
!valid_dim_type(type)1.51M
)
1659
0
    isl_die(dim->ctx, isl_error_invalid,
1660
1.51M
      "cannot drop dimensions of specified type", goto error);
1661
1.51M
1662
1.51M
  
if (1.51M
first + num > n(dim, type) || 1.51M
first + num < first1.51M
)
1663
0
    isl_die(isl_space_get_ctx(dim), isl_error_invalid,
1664
1.51M
      "index out of bounds", return isl_space_free(dim));
1665
1.51M
  dim = isl_space_cow(dim);
1666
1.51M
  if (!dim)
1667
0
    goto error;
1668
1.51M
  
if (1.51M
dim->ids1.51M
)
{901k
1669
901k
    dim = extend_ids(dim);
1670
901k
    if (!dim)
1671
0
      goto error;
1672
3.40M
    
for (i = 0; 901k
i < num3.40M
;
++i2.50M
)
1673
2.50M
      isl_id_free(get_id(dim, type, first + i));
1674
1.00M
    for (i = first+num; 
i < n(dim, type)1.00M
;
++i106k
)
1675
106k
      set_id(dim, type, i - num, get_id(dim, type, i));
1676
901k
    switch (type) {
1677
901k
    case isl_dim_param:
1678
68.4k
      get_ids(dim, isl_dim_in, 0, dim->n_in,
1679
68.4k
        dim->ids + offset(dim, isl_dim_in) - num);
1680
312k
    case isl_dim_in:
1681
312k
      get_ids(dim, isl_dim_out, 0, dim->n_out,
1682
312k
        dim->ids + offset(dim, isl_dim_out) - num);
1683
901k
    default:
1684
901k
      ;
1685
901k
    }
1686
901k
    dim->n_id -= num;
1687
1.51M
  }
1688
1.51M
  switch (type) {
1689
68.5k
  case isl_dim_param: dim->nparam -= num; break;
1690
310k
  case isl_dim_in:  dim->n_in -= num; break;
1691
1.13M
  case isl_dim_out: dim->n_out -= num; break;
1692
0
  default:    ;
1693
1.51M
  }
1694
1.51M
  dim = isl_space_reset(dim, type);
1695
1.51M
  if (
type == isl_dim_param1.51M
)
{68.5k
1696
68.5k
    if (
dim && 68.5k
dim->nested[0]68.5k
&&
1697
68.5k
        !(dim->nested[0] = isl_space_drop_dims(dim->nested[0],
1698
68.5k
                isl_dim_param, first, num)))
1699
0
      goto error;
1700
68.5k
    
if (68.5k
dim && 68.5k
dim->nested[1]68.5k
&&
1701
68.5k
        !(dim->nested[1] = isl_space_drop_dims(dim->nested[1],
1702
68.5k
                isl_dim_param, first, num)))
1703
0
      goto error;
1704
1.51M
  }
1705
1.51M
  return dim;
1706
1.51M
error:
1707
0
  isl_space_free(dim);
1708
1.51M
  return NULL;
1709
1.87M
}
1710
1711
__isl_give isl_space *isl_space_drop_inputs(__isl_take isl_space *dim,
1712
    unsigned first, unsigned n)
1713
0
{
1714
0
  if (!dim)
1715
0
    return NULL;
1716
0
  return isl_space_drop_dims(dim, isl_dim_in, first, n);
1717
0
}
1718
1719
__isl_give isl_space *isl_space_drop_outputs(__isl_take isl_space *dim,
1720
    unsigned first, unsigned n)
1721
0
{
1722
0
  if (!dim)
1723
0
    return NULL;
1724
0
  return isl_space_drop_dims(dim, isl_dim_out, first, n);
1725
0
}
1726
1727
__isl_give isl_space *isl_space_domain(__isl_take isl_space *space)
1728
548k
{
1729
548k
  if (!space)
1730
0
    return NULL;
1731
548k
  space = isl_space_drop_dims(space, isl_dim_out, 0, space->n_out);
1732
548k
  space = isl_space_reverse(space);
1733
548k
  space = mark_as_set(space);
1734
548k
  return space;
1735
548k
}
1736
1737
__isl_give isl_space *isl_space_from_domain(__isl_take isl_space *dim)
1738
468k
{
1739
468k
  if (!dim)
1740
0
    return NULL;
1741
468k
  
if (468k
!isl_space_is_set(dim)468k
)
1742
0
    isl_die(isl_space_get_ctx(dim), isl_error_invalid,
1743
468k
      "not a set space", goto error);
1744
468k
  dim = isl_space_reverse(dim);
1745
468k
  dim = isl_space_reset(dim, isl_dim_out);
1746
468k
  return dim;
1747
468k
error:
1748
0
  isl_space_free(dim);
1749
468k
  return NULL;
1750
468k
}
1751
1752
__isl_give isl_space *isl_space_range(__isl_take isl_space *space)
1753
270k
{
1754
270k
  if (!space)
1755
0
    return NULL;
1756
270k
  space = isl_space_drop_dims(space, isl_dim_in, 0, space->n_in);
1757
270k
  space = mark_as_set(space);
1758
270k
  return space;
1759
270k
}
1760
1761
__isl_give isl_space *isl_space_from_range(__isl_take isl_space *dim)
1762
171k
{
1763
171k
  if (!dim)
1764
4
    return NULL;
1765
171k
  
if (171k
!isl_space_is_set(dim)171k
)
1766
0
    isl_die(isl_space_get_ctx(dim), isl_error_invalid,
1767
171k
      "not a set space", goto error);
1768
171k
  return isl_space_reset(dim, isl_dim_in);
1769
171k
error:
1770
0
  isl_space_free(dim);
1771
171k
  return NULL;
1772
171k
}
1773
1774
/* Given a map space A -> B, return the map space [A -> B] -> A.
1775
 */
1776
__isl_give isl_space *isl_space_domain_map(__isl_take isl_space *space)
1777
1.23k
{
1778
1.23k
  isl_space *domain;
1779
1.23k
1780
1.23k
  domain = isl_space_from_range(isl_space_domain(isl_space_copy(space)));
1781
1.23k
  space = isl_space_from_domain(isl_space_wrap(space));
1782
1.23k
  space = isl_space_join(space, domain);
1783
1.23k
1784
1.23k
  return space;
1785
1.23k
}
1786
1787
/* Given a map space A -> B, return the map space [A -> B] -> B.
1788
 */
1789
__isl_give isl_space *isl_space_range_map(__isl_take isl_space *space)
1790
2
{
1791
2
  isl_space *range;
1792
2
1793
2
  range = isl_space_from_range(isl_space_range(isl_space_copy(space)));
1794
2
  space = isl_space_from_domain(isl_space_wrap(space));
1795
2
  space = isl_space_join(space, range);
1796
2
1797
2
  return space;
1798
2
}
1799
1800
__isl_give isl_space *isl_space_params(__isl_take isl_space *space)
1801
381k
{
1802
381k
  if (isl_space_is_params(space))
1803
289k
    return space;
1804
381k
  space = isl_space_drop_dims(space,
1805
92.2k
          isl_dim_in, 0, isl_space_dim(space, isl_dim_in));
1806
92.2k
  space = isl_space_drop_dims(space,
1807
92.2k
          isl_dim_out, 0, isl_space_dim(space, isl_dim_out));
1808
92.2k
  space = mark_as_params(space);
1809
381k
  return space;
1810
381k
}
1811
1812
__isl_give isl_space *isl_space_set_from_params(__isl_take isl_space *space)
1813
13.3k
{
1814
13.3k
  if (!space)
1815
0
    return NULL;
1816
13.3k
  
if (13.3k
!isl_space_is_params(space)13.3k
)
1817
0
    isl_die(isl_space_get_ctx(space), isl_error_invalid,
1818
13.3k
      "not a parameter space", goto error);
1819
13.3k
  return isl_space_reset(space, isl_dim_set);
1820
13.3k
error:
1821
0
  isl_space_free(space);
1822
13.3k
  return NULL;
1823
13.3k
}
1824
1825
__isl_give isl_space *isl_space_underlying(__isl_take isl_space *dim,
1826
  unsigned n_div)
1827
366k
{
1828
366k
  int i;
1829
366k
1830
366k
  if (!dim)
1831
0
    return NULL;
1832
366k
  
if (366k
n_div == 0 &&366k
1833
366k
      
dim->nparam == 0354k
&&
dim->n_in == 0186k
&&
dim->n_id == 0150k
)
1834
80.4k
    return isl_space_reset(isl_space_reset(dim, isl_dim_in), isl_dim_out);
1835
366k
  dim = isl_space_cow(dim);
1836
286k
  if (!dim)
1837
0
    return NULL;
1838
286k
  dim->n_out += dim->nparam + dim->n_in + n_div;
1839
286k
  dim->nparam = 0;
1840
286k
  dim->n_in = 0;
1841
286k
1842
1.73M
  for (i = 0; 
i < dim->n_id1.73M
;
++i1.45M
)
1843
1.45M
    isl_id_free(get_id(dim, isl_dim_out, i));
1844
286k
  dim->n_id = 0;
1845
286k
  dim = isl_space_reset(dim, isl_dim_in);
1846
286k
  dim = isl_space_reset(dim, isl_dim_out);
1847
286k
1848
286k
  return dim;
1849
366k
}
1850
1851
/* Are the two spaces the same, including positions and names of parameters?
1852
 */
1853
isl_bool isl_space_is_equal(__isl_keep isl_space *space1,
1854
  __isl_keep isl_space *space2)
1855
6.36M
{
1856
6.36M
  isl_bool equal;
1857
6.36M
1858
6.36M
  if (
!space1 || 6.36M
!space26.36M
)
1859
0
    return isl_bool_error;
1860
6.36M
  
if (6.36M
space1 == space26.36M
)
1861
3.55M
    return isl_bool_true;
1862
6.36M
  equal = isl_space_has_equal_params(space1, space2);
1863
2.80M
  if (
equal < 0 || 2.80M
!equal2.80M
)
1864
60.1k
    return equal;
1865
2.74M
  return isl_space_has_equal_tuples(space1, space2);
1866
6.36M
}
1867
1868
/* Is space1 equal to the domain of space2?
1869
 *
1870
 * In the internal version we also allow space2 to be the space of a set,
1871
 * provided space1 is a parameter space.
1872
 */
1873
isl_bool isl_space_is_domain_internal(__isl_keep isl_space *space1,
1874
  __isl_keep isl_space *space2)
1875
53
{
1876
53
  isl_bool equal_params;
1877
53
1878
53
  if (
!space1 || 53
!space253
)
1879
0
    return isl_bool_error;
1880
53
  
if (53
!isl_space_is_set(space1)53
)
1881
0
    return isl_bool_false;
1882
53
  equal_params = isl_space_has_equal_params(space1, space2);
1883
53
  if (
equal_params < 0 || 53
!equal_params53
)
1884
0
    return equal_params;
1885
53
  return isl_space_tuple_is_equal(space1, isl_dim_set,
1886
53
          space2, isl_dim_in);
1887
53
}
1888
1889
/* Is space1 equal to the domain of space2?
1890
 */
1891
isl_bool isl_space_is_domain(__isl_keep isl_space *space1,
1892
  __isl_keep isl_space *space2)
1893
25
{
1894
25
  if (!space2)
1895
0
    return isl_bool_error;
1896
25
  
if (25
!isl_space_is_map(space2)25
)
1897
0
    return isl_bool_false;
1898
25
  return isl_space_is_domain_internal(space1, space2);
1899
25
}
1900
1901
/* Is space1 equal to the range of space2?
1902
 *
1903
 * In the internal version, space2 is allowed to be the space of a set,
1904
 * in which case it should be equal to space1.
1905
 */
1906
isl_bool isl_space_is_range_internal(__isl_keep isl_space *space1,
1907
  __isl_keep isl_space *space2)
1908
13.3k
{
1909
13.3k
  isl_bool equal_params;
1910
13.3k
1911
13.3k
  if (
!space1 || 13.3k
!space213.3k
)
1912
0
    return isl_bool_error;
1913
13.3k
  
if (13.3k
!isl_space_is_set(space1)13.3k
)
1914
0
    return isl_bool_false;
1915
13.3k
  equal_params = isl_space_has_equal_params(space1, space2);
1916
13.3k
  if (
equal_params < 0 || 13.3k
!equal_params13.3k
)
1917
0
    return equal_params;
1918
13.3k
  return isl_space_tuple_is_equal(space1, isl_dim_set,
1919
13.3k
          space2, isl_dim_out);
1920
13.3k
}
1921
1922
/* Is space1 equal to the range of space2?
1923
 */
1924
isl_bool isl_space_is_range(__isl_keep isl_space *space1,
1925
  __isl_keep isl_space *space2)
1926
0
{
1927
0
  if (!space2)
1928
0
    return isl_bool_error;
1929
0
  
if (0
!isl_space_is_map(space2)0
)
1930
0
    return isl_bool_false;
1931
0
  return isl_space_is_range_internal(space1, space2);
1932
0
}
1933
1934
/* Update "hash" by hashing in the parameters of "space".
1935
 */
1936
static uint32_t isl_hash_params(uint32_t hash, __isl_keep isl_space *space)
1937
426k
{
1938
426k
  int i;
1939
426k
  isl_id *id;
1940
426k
1941
426k
  if (!space)
1942
0
    return hash;
1943
426k
1944
426k
  
isl_hash_byte426k
(hash, space->nparam % 256);426k
1945
426k
1946
1.04M
  for (i = 0; 
i < space->nparam1.04M
;
++i616k
)
{616k
1947
616k
    id = get_id(space, isl_dim_param, i);
1948
616k
    hash = isl_hash_id(hash, id);
1949
616k
  }
1950
426k
1951
426k
  return hash;
1952
426k
}
1953
1954
/* Update "hash" by hashing in the tuples of "space".
1955
 * Changes in this function should be reflected in isl_hash_tuples_domain.
1956
 */
1957
static uint32_t isl_hash_tuples(uint32_t hash, __isl_keep isl_space *space)
1958
1.64M
{
1959
1.64M
  isl_id *id;
1960
1.64M
1961
1.64M
  if (!space)
1962
1.03M
    return hash;
1963
1.64M
1964
609k
  
isl_hash_byte609k
(hash, space->n_in % 256);609k
1965
609k
  isl_hash_byte(hash, space->n_out % 256);
1966
609k
1967
609k
  id = tuple_id(space, isl_dim_in);
1968
609k
  hash = isl_hash_id(hash, id);
1969
609k
  id = tuple_id(space, isl_dim_out);
1970
609k
  hash = isl_hash_id(hash, id);
1971
609k
1972
609k
  hash = isl_hash_tuples(hash, space->nested[0]);
1973
609k
  hash = isl_hash_tuples(hash, space->nested[1]);
1974
609k
1975
1.64M
  return hash;
1976
1.64M
}
1977
1978
/* Update "hash" by hashing in the domain tuple of "space".
1979
 * The result of this function is equal to the result of applying
1980
 * isl_hash_tuples to the domain of "space".
1981
 */
1982
static uint32_t isl_hash_tuples_domain(uint32_t hash,
1983
  __isl_keep isl_space *space)
1984
28.6k
{
1985
28.6k
  isl_id *id;
1986
28.6k
1987
28.6k
  if (!space)
1988
0
    return hash;
1989
28.6k
1990
28.6k
  
isl_hash_byte28.6k
(hash, 0);28.6k
1991
28.6k
  isl_hash_byte(hash, space->n_in % 256);
1992
28.6k
1993
28.6k
  hash = isl_hash_id(hash, &isl_id_none);
1994
28.6k
  id = tuple_id(space, isl_dim_in);
1995
28.6k
  hash = isl_hash_id(hash, id);
1996
28.6k
1997
28.6k
  hash = isl_hash_tuples(hash, space->nested[0]);
1998
28.6k
1999
28.6k
  return hash;
2000
28.6k
}
2001
2002
/* Return a hash value that digests the tuples of "space",
2003
 * i.e., that ignores the parameters.
2004
 */
2005
uint32_t isl_space_get_tuple_hash(__isl_keep isl_space *space)
2006
2.01k
{
2007
2.01k
  uint32_t hash;
2008
2.01k
2009
2.01k
  if (!space)
2010
0
    return 0;
2011
2.01k
2012
2.01k
  
hash = 2.01k
isl_hash_init2.01k
();
2013
2.01k
  hash = isl_hash_tuples(hash, space);
2014
2.01k
2015
2.01k
  return hash;
2016
2.01k
}
2017
2018
uint32_t isl_space_get_hash(__isl_keep isl_space *space)
2019
397k
{
2020
397k
  uint32_t hash;
2021
397k
2022
397k
  if (!space)
2023
0
    return 0;
2024
397k
2025
397k
  
hash = 397k
isl_hash_init397k
();
2026
397k
  hash = isl_hash_params(hash, space);
2027
397k
  hash = isl_hash_tuples(hash, space);
2028
397k
2029
397k
  return hash;
2030
397k
}
2031
2032
/* Return the hash value of the domain of "space".
2033
 * That is, isl_space_get_domain_hash(space) is equal to
2034
 * isl_space_get_hash(isl_space_domain(space)).
2035
 */
2036
uint32_t isl_space_get_domain_hash(__isl_keep isl_space *space)
2037
28.6k
{
2038
28.6k
  uint32_t hash;
2039
28.6k
2040
28.6k
  if (!space)
2041
0
    return 0;
2042
28.6k
2043
28.6k
  
hash = 28.6k
isl_hash_init28.6k
();
2044
28.6k
  hash = isl_hash_params(hash, space);
2045
28.6k
  hash = isl_hash_tuples_domain(hash, space);
2046
28.6k
2047
28.6k
  return hash;
2048
28.6k
}
2049
2050
isl_bool isl_space_is_wrapping(__isl_keep isl_space *dim)
2051
49.0k
{
2052
49.0k
  if (!dim)
2053
0
    return isl_bool_error;
2054
49.0k
2055
49.0k
  
if (49.0k
!isl_space_is_set(dim)49.0k
)
2056
0
    return isl_bool_false;
2057
49.0k
2058
49.0k
  return dim->nested[1] != NULL;
2059
49.0k
}
2060
2061
/* Is "space" the space of a map where the domain is a wrapped map space?
2062
 */
2063
isl_bool isl_space_domain_is_wrapping(__isl_keep isl_space *space)
2064
43.9k
{
2065
43.9k
  if (!space)
2066
0
    return isl_bool_error;
2067
43.9k
2068
43.9k
  
if (43.9k
isl_space_is_set(space)43.9k
)
2069
0
    return isl_bool_false;
2070
43.9k
2071
43.9k
  return space->nested[0] != NULL;
2072
43.9k
}
2073
2074
/* Is "space" the space of a map where the range is a wrapped map space?
2075
 */
2076
isl_bool isl_space_range_is_wrapping(__isl_keep isl_space *space)
2077
58.7k
{
2078
58.7k
  if (!space)
2079
0
    return isl_bool_error;
2080
58.7k
2081
58.7k
  
if (58.7k
isl_space_is_set(space)58.7k
)
2082
761
    return isl_bool_false;
2083
58.7k
2084
57.9k
  return space->nested[1] != NULL;
2085
58.7k
}
2086
2087
/* Is "space" a product of two spaces?
2088
 * That is, is it a wrapping set space or a map space
2089
 * with wrapping domain and range?
2090
 */
2091
isl_bool isl_space_is_product(__isl_keep isl_space *space)
2092
5.25k
{
2093
5.25k
  isl_bool is_set;
2094
5.25k
  isl_bool is_product;
2095
5.25k
2096
5.25k
  is_set = isl_space_is_set(space);
2097
5.25k
  if (is_set < 0)
2098
0
    return isl_bool_error;
2099
5.25k
  
if (5.25k
is_set5.25k
)
2100
0
    return isl_space_is_wrapping(space);
2101
5.25k
  is_product = isl_space_domain_is_wrapping(space);
2102
5.25k
  if (
is_product < 0 || 5.25k
!is_product5.25k
)
2103
34
    return is_product;
2104
5.22k
  return isl_space_range_is_wrapping(space);
2105
5.25k
}
2106
2107
__isl_give isl_space *isl_space_wrap(__isl_take isl_space *dim)
2108
164k
{
2109
164k
  isl_space *wrap;
2110
164k
2111
164k
  if (!dim)
2112
0
    return NULL;
2113
164k
2114
164k
  wrap = isl_space_set_alloc(dim->ctx,
2115
164k
            dim->nparam, dim->n_in + dim->n_out);
2116
164k
2117
164k
  wrap = copy_ids(wrap, isl_dim_param, 0, dim, isl_dim_param);
2118
164k
  wrap = copy_ids(wrap, isl_dim_set, 0, dim, isl_dim_in);
2119
164k
  wrap = copy_ids(wrap, isl_dim_set, dim->n_in, dim, isl_dim_out);
2120
164k
2121
164k
  if (!wrap)
2122
0
    goto error;
2123
164k
2124
164k
  wrap->nested[1] = dim;
2125
164k
2126
164k
  return wrap;
2127
164k
error:
2128
0
  isl_space_free(dim);
2129
164k
  return NULL;
2130
164k
}
2131
2132
__isl_give isl_space *isl_space_unwrap(__isl_take isl_space *dim)
2133
33.9k
{
2134
33.9k
  isl_space *unwrap;
2135
33.9k
2136
33.9k
  if (!dim)
2137
0
    return NULL;
2138
33.9k
2139
33.9k
  
if (33.9k
!isl_space_is_wrapping(dim)33.9k
)
2140
0
    isl_die(dim->ctx, isl_error_invalid, "not a wrapping space",
2141
33.9k
      goto error);
2142
33.9k
2143
33.9k
  unwrap = isl_space_copy(dim->nested[1]);
2144
33.9k
  isl_space_free(dim);
2145
33.9k
2146
33.9k
  return unwrap;
2147
33.9k
error:
2148
0
  isl_space_free(dim);
2149
33.9k
  return NULL;
2150
33.9k
}
2151
2152
isl_bool isl_space_is_named_or_nested(__isl_keep isl_space *space,
2153
  enum isl_dim_type type)
2154
4.49M
{
2155
4.49M
  if (
type != isl_dim_in && 4.49M
type != isl_dim_out3.23M
)
2156
312k
    return isl_bool_false;
2157
4.18M
  
if (4.18M
!space4.18M
)
2158
6
    return isl_bool_error;
2159
4.18M
  
if (4.18M
space->tuple_id[type - isl_dim_in]4.18M
)
2160
1.79M
    return isl_bool_true;
2161
2.39M
  
if (2.39M
space->nested[type - isl_dim_in]2.39M
)
2162
570k
    return isl_bool_true;
2163
1.82M
  return isl_bool_false;
2164
4.49M
}
2165
2166
isl_bool isl_space_may_be_set(__isl_keep isl_space *space)
2167
272
{
2168
272
  isl_bool nested;
2169
272
2170
272
  if (!space)
2171
0
    return isl_bool_error;
2172
272
  
if (272
isl_space_is_set(space)272
)
2173
167
    return isl_bool_true;
2174
105
  
if (105
isl_space_dim(space, isl_dim_in) != 0105
)
2175
0
    return isl_bool_false;
2176
105
  nested = isl_space_is_named_or_nested(space, isl_dim_in);
2177
105
  if (
nested < 0 || 105
nested105
)
2178
0
    return isl_bool_not(nested);
2179
105
  return isl_bool_true;
2180
272
}
2181
2182
__isl_give isl_space *isl_space_reset(__isl_take isl_space *dim,
2183
  enum isl_dim_type type)
2184
4.10M
{
2185
4.10M
  if (!isl_space_is_named_or_nested(dim, type))
2186
1.92M
    return dim;
2187
4.10M
2188
4.10M
  dim = isl_space_cow(dim);
2189
2.18M
  if (!dim)
2190
13
    return NULL;
2191
2.18M
2192
2.18M
  isl_id_free(dim->tuple_id[type - isl_dim_in]);
2193
2.18M
  dim->tuple_id[type - isl_dim_in] = NULL;
2194
2.18M
  isl_space_free(dim->nested[type - isl_dim_in]);
2195
2.18M
  dim->nested[type - isl_dim_in] = NULL;
2196
2.18M
2197
2.18M
  return dim;
2198
4.10M
}
2199
2200
__isl_give isl_space *isl_space_flatten(__isl_take isl_space *dim)
2201
22.0k
{
2202
22.0k
  if (!dim)
2203
0
    return NULL;
2204
22.0k
  
if (22.0k
!dim->nested[0] && 22.0k
!dim->nested[1]22.0k
)
2205
0
    return dim;
2206
22.0k
2207
22.0k
  
if (22.0k
dim->nested[0]22.0k
)
2208
0
    dim = isl_space_reset(dim, isl_dim_in);
2209
22.0k
  if (
dim && 22.0k
dim->nested[1]22.0k
)
2210
22.0k
    dim = isl_space_reset(dim, isl_dim_out);
2211
22.0k
2212
22.0k
  return dim;
2213
22.0k
}
2214
2215
__isl_give isl_space *isl_space_flatten_domain(__isl_take isl_space *dim)
2216
33
{
2217
33
  if (!dim)
2218
0
    return NULL;
2219
33
  
if (33
!dim->nested[0]33
)
2220
0
    return dim;
2221
33
2222
33
  return isl_space_reset(dim, isl_dim_in);
2223
33
}
2224
2225
__isl_give isl_space *isl_space_flatten_range(__isl_take isl_space *dim)
2226
50.2k
{
2227
50.2k
  if (!dim)
2228
0
    return NULL;
2229
50.2k
  
if (50.2k
!dim->nested[1]50.2k
)
2230
0
    return dim;
2231
50.2k
2232
50.2k
  return isl_space_reset(dim, isl_dim_out);
2233
50.2k
}
2234
2235
/* Replace the dimensions of the given type of dst by those of src.
2236
 */
2237
__isl_give isl_space *isl_space_replace(__isl_take isl_space *dst,
2238
  enum isl_dim_type type, __isl_keep isl_space *src)
2239
111k
{
2240
111k
  dst = isl_space_cow(dst);
2241
111k
2242
111k
  if (
!dst || 111k
!src111k
)
2243
0
    goto error;
2244
111k
2245
111k
  dst = isl_space_drop_dims(dst, type, 0, isl_space_dim(dst, type));
2246
111k
  dst = isl_space_add_dims(dst, type, isl_space_dim(src, type));
2247
111k
  dst = copy_ids(dst, type, 0, src, type);
2248
111k
2249
111k
  if (
dst && 111k
type == isl_dim_param111k
)
{111k
2250
111k
    int i;
2251
334k
    for (i = 0; 
i <= 1334k
;
++i222k
)
{222k
2252
222k
      if (!dst->nested[i])
2253
211k
        continue;
2254
222k
      dst->nested[i] = isl_space_replace(dst->nested[i],
2255
11.1k
               type, src);
2256
11.1k
      if (!dst->nested[i])
2257
0
        goto error;
2258
111k
    }
2259
111k
  }
2260
111k
2261
111k
  return dst;
2262
111k
error:
2263
0
  isl_space_free(dst);
2264
111k
  return NULL;
2265
111k
}
2266
2267
/* Given a dimension specification "dim" of a set, create a dimension
2268
 * specification for the lift of the set.  In particular, the result
2269
 * is of the form [dim -> local[..]], with n_local variables in the
2270
 * range of the wrapped map.
2271
 */
2272
__isl_give isl_space *isl_space_lift(__isl_take isl_space *dim, unsigned n_local)
2273
20.2k
{
2274
20.2k
  isl_space *local_dim;
2275
20.2k
2276
20.2k
  if (!dim)
2277
0
    return NULL;
2278
20.2k
2279
20.2k
  local_dim = isl_space_dup(dim);
2280
20.2k
  local_dim = isl_space_drop_dims(local_dim, isl_dim_set, 0, dim->n_out);
2281
20.2k
  local_dim = isl_space_add_dims(local_dim, isl_dim_set, n_local);
2282
20.2k
  local_dim = isl_space_set_tuple_name(local_dim, isl_dim_set, "local");
2283
20.2k
  dim = isl_space_join(isl_space_from_domain(dim),
2284
20.2k
          isl_space_from_range(local_dim));
2285
20.2k
  dim = isl_space_wrap(dim);
2286
20.2k
  dim = isl_space_set_tuple_name(dim, isl_dim_set, "lifted");
2287
20.2k
2288
20.2k
  return dim;
2289
20.2k
}
2290
2291
isl_bool isl_space_can_zip(__isl_keep isl_space *space)
2292
5.16k
{
2293
5.16k
  isl_bool is_set;
2294
5.16k
2295
5.16k
  is_set = isl_space_is_set(space);
2296
5.16k
  if (is_set < 0)
2297
0
    return isl_bool_error;
2298
5.16k
  
if (5.16k
is_set5.16k
)
2299
0
    return isl_bool_false;
2300
5.16k
  return isl_space_is_product(space);
2301
5.16k
}
2302
2303
__isl_give isl_space *isl_space_zip(__isl_take isl_space *dim)
2304
2.24k
{
2305
2.24k
  isl_space *dom, *ran;
2306
2.24k
  isl_space *dom_dom, *dom_ran, *ran_dom, *ran_ran;
2307
2.24k
2308
2.24k
  if (!isl_space_can_zip(dim))
2309
0
    isl_die(dim->ctx, isl_error_invalid, "dim cannot be zipped",
2310
2.24k
      goto error);
2311
2.24k
2312
2.24k
  
if (2.24k
!dim2.24k
)
2313
0
    return NULL;
2314
2.24k
  dom = isl_space_unwrap(isl_space_domain(isl_space_copy(dim)));
2315
2.24k
  ran = isl_space_unwrap(isl_space_range(dim));
2316
2.24k
  dom_dom = isl_space_domain(isl_space_copy(dom));
2317
2.24k
  dom_ran = isl_space_range(dom);
2318
2.24k
  ran_dom = isl_space_domain(isl_space_copy(ran));
2319
2.24k
  ran_ran = isl_space_range(ran);
2320
2.24k
  dom = isl_space_join(isl_space_from_domain(dom_dom),
2321
2.24k
         isl_space_from_range(ran_dom));
2322
2.24k
  ran = isl_space_join(isl_space_from_domain(dom_ran),
2323
2.24k
         isl_space_from_range(ran_ran));
2324
2.24k
  return isl_space_join(isl_space_from_domain(isl_space_wrap(dom)),
2325
2.24k
          isl_space_from_range(isl_space_wrap(ran)));
2326
2.24k
error:
2327
0
  isl_space_free(dim);
2328
2.24k
  return NULL;
2329
2.24k
}
2330
2331
/* Can we apply isl_space_curry to "space"?
2332
 * That is, does it have a nested relation in its domain?
2333
 */
2334
isl_bool isl_space_can_curry(__isl_keep isl_space *space)
2335
35.0k
{
2336
35.0k
  if (!space)
2337
0
    return isl_bool_error;
2338
35.0k
2339
35.0k
  return !!space->nested[0];
2340
35.0k
}
2341
2342
/* Given a space (A -> B) -> C, return the corresponding space
2343
 * A -> (B -> C).
2344
 */
2345
__isl_give isl_space *isl_space_curry(__isl_take isl_space *space)
2346
11.6k
{
2347
11.6k
  isl_space *dom, *ran;
2348
11.6k
  isl_space *dom_dom, *dom_ran;
2349
11.6k
2350
11.6k
  if (!space)
2351
0
    return NULL;
2352
11.6k
2353
11.6k
  
if (11.6k
!isl_space_can_curry(space)11.6k
)
2354
0
    isl_die(space->ctx, isl_error_invalid,
2355
11.6k
      "space cannot be curried", goto error);
2356
11.6k
2357
11.6k
  dom = isl_space_unwrap(isl_space_domain(isl_space_copy(space)));
2358
11.6k
  ran = isl_space_range(space);
2359
11.6k
  dom_dom = isl_space_domain(isl_space_copy(dom));
2360
11.6k
  dom_ran = isl_space_range(dom);
2361
11.6k
  ran = isl_space_join(isl_space_from_domain(dom_ran),
2362
11.6k
         isl_space_from_range(ran));
2363
11.6k
  return isl_space_join(isl_space_from_domain(dom_dom),
2364
11.6k
          isl_space_from_range(isl_space_wrap(ran)));
2365
11.6k
error:
2366
0
  isl_space_free(space);
2367
11.6k
  return NULL;
2368
11.6k
}
2369
2370
/* Can isl_space_range_curry be applied to "space"?
2371
 * That is, does it have a nested relation in its range,
2372
 * the domain of which is itself a nested relation?
2373
 */
2374
isl_bool isl_space_can_range_curry(__isl_keep isl_space *space)
2375
22.7k
{
2376
22.7k
  isl_bool can;
2377
22.7k
2378
22.7k
  if (!space)
2379
0
    return isl_bool_error;
2380
22.7k
  can = isl_space_range_is_wrapping(space);
2381
22.7k
  if (
can < 0 || 22.7k
!can22.7k
)
2382
0
    return can;
2383
22.7k
  return isl_space_can_curry(space->nested[1]);
2384
22.7k
}
2385
2386
/* Given a space A -> ((B -> C) -> D), return the corresponding space
2387
 * A -> (B -> (C -> D)).
2388
 */
2389
__isl_give isl_space *isl_space_range_curry(__isl_take isl_space *space)
2390
11.3k
{
2391
11.3k
  if (!space)
2392
0
    return NULL;
2393
11.3k
2394
11.3k
  
if (11.3k
!isl_space_can_range_curry(space)11.3k
)
2395
0
    isl_die(isl_space_get_ctx(space), isl_error_invalid,
2396
11.3k
      "space range cannot be curried",
2397
11.3k
      return isl_space_free(space));
2398
11.3k
2399
11.3k
  space = isl_space_cow(space);
2400
11.3k
  if (!space)
2401
0
    return NULL;
2402
11.3k
  space->nested[1] = isl_space_curry(space->nested[1]);
2403
11.3k
  if (!space->nested[1])
2404
0
    return isl_space_free(space);
2405
11.3k
2406
11.3k
  return space;
2407
11.3k
}
2408
2409
/* Can we apply isl_space_uncurry to "space"?
2410
 * That is, does it have a nested relation in its range?
2411
 */
2412
isl_bool isl_space_can_uncurry(__isl_keep isl_space *space)
2413
999
{
2414
999
  if (!space)
2415
0
    return isl_bool_error;
2416
999
2417
999
  return !!space->nested[1];
2418
999
}
2419
2420
/* Given a space A -> (B -> C), return the corresponding space
2421
 * (A -> B) -> C.
2422
 */
2423
__isl_give isl_space *isl_space_uncurry(__isl_take isl_space *space)
2424
360
{
2425
360
  isl_space *dom, *ran;
2426
360
  isl_space *ran_dom, *ran_ran;
2427
360
2428
360
  if (!space)
2429
0
    return NULL;
2430
360
2431
360
  
if (360
!isl_space_can_uncurry(space)360
)
2432
0
    isl_die(space->ctx, isl_error_invalid,
2433
360
      "space cannot be uncurried",
2434
360
      return isl_space_free(space));
2435
360
2436
360
  dom = isl_space_domain(isl_space_copy(space));
2437
360
  ran = isl_space_unwrap(isl_space_range(space));
2438
360
  ran_dom = isl_space_domain(isl_space_copy(ran));
2439
360
  ran_ran = isl_space_range(ran);
2440
360
  dom = isl_space_join(isl_space_from_domain(dom),
2441
360
         isl_space_from_range(ran_dom));
2442
360
  return isl_space_join(isl_space_from_domain(isl_space_wrap(dom)),
2443
360
          isl_space_from_range(ran_ran));
2444
360
}
2445
2446
isl_bool isl_space_has_named_params(__isl_keep isl_space *space)
2447
407k
{
2448
407k
  int i;
2449
407k
  unsigned off;
2450
407k
2451
407k
  if (!space)
2452
0
    return isl_bool_error;
2453
407k
  
if (407k
space->nparam == 0407k
)
2454
170k
    return isl_bool_true;
2455
407k
  off = isl_space_offset(space, isl_dim_param);
2456
237k
  if (off + space->nparam > space->n_id)
2457
0
    return isl_bool_false;
2458
980k
  
for (i = 0; 237k
i < space->nparam980k
;
++i742k
)
2459
742k
    
if (742k
!space->ids[off + i]742k
)
2460
0
      return isl_bool_false;
2461
237k
  return isl_bool_true;
2462
407k
}
2463
2464
/* Check that "space" has only named parameters, reporting an error
2465
 * if it does not.
2466
 */
2467
isl_stat isl_space_check_named_params(__isl_keep isl_space *space)
2468
164k
{
2469
164k
  isl_bool named;
2470
164k
2471
164k
  named = isl_space_has_named_params(space);
2472
164k
  if (named < 0)
2473
0
    return isl_stat_error;
2474
164k
  
if (164k
!named164k
)
2475
0
    isl_die(isl_space_get_ctx(space), isl_error_invalid,
2476
164k
      "unaligned unnamed parameters", return isl_stat_error);
2477
164k
2478
164k
  return isl_stat_ok;
2479
164k
}
2480
2481
/* Align the initial parameters of dim1 to match the order in dim2.
2482
 */
2483
__isl_give isl_space *isl_space_align_params(__isl_take isl_space *dim1,
2484
  __isl_take isl_space *dim2)
2485
21.6k
{
2486
21.6k
  isl_reordering *exp;
2487
21.6k
2488
21.6k
  if (
!isl_space_has_named_params(dim1) || 21.6k
!isl_space_has_named_params(dim2)21.6k
)
2489
0
    isl_die(isl_space_get_ctx(dim1), isl_error_invalid,
2490
21.6k
      "parameter alignment requires named parameters",
2491
21.6k
      goto error);
2492
21.6k
2493
21.6k
  dim2 = isl_space_params(dim2);
2494
21.6k
  exp = isl_parameter_alignment_reordering(dim1, dim2);
2495
21.6k
  exp = isl_reordering_extend_space(exp, dim1);
2496
21.6k
  isl_space_free(dim2);
2497
21.6k
  if (!exp)
2498
0
    return NULL;
2499
21.6k
  dim1 = isl_space_copy(exp->dim);
2500
21.6k
  isl_reordering_free(exp);
2501
21.6k
  return dim1;
2502
21.6k
error:
2503
0
  isl_space_free(dim1);
2504
0
  isl_space_free(dim2);
2505
21.6k
  return NULL;
2506
21.6k
}
2507
2508
/* Given the space of set (domain), construct a space for a map
2509
 * with as domain the given space and as range the range of "model".
2510
 */
2511
__isl_give isl_space *isl_space_extend_domain_with_range(
2512
  __isl_take isl_space *space, __isl_take isl_space *model)
2513
52.7k
{
2514
52.7k
  if (!model)
2515
0
    goto error;
2516
52.7k
2517
52.7k
  space = isl_space_from_domain(space);
2518
52.7k
  space = isl_space_add_dims(space, isl_dim_out,
2519
52.7k
            isl_space_dim(model, isl_dim_out));
2520
52.7k
  if (isl_space_has_tuple_id(model, isl_dim_out))
2521
52.7k
    space = isl_space_set_tuple_id(space, isl_dim_out,
2522
52.7k
        isl_space_get_tuple_id(model, isl_dim_out));
2523
52.7k
  if (!space)
2524
0
    goto error;
2525
52.7k
  
if (52.7k
model->nested[1]52.7k
)
{1
2526
1
    isl_space *nested = isl_space_copy(model->nested[1]);
2527
1
    int n_nested, n_space;
2528
1
    nested = isl_space_align_params(nested, isl_space_copy(space));
2529
1
    n_nested = isl_space_dim(nested, isl_dim_param);
2530
1
    n_space = isl_space_dim(space, isl_dim_param);
2531
1
    if (n_nested > n_space)
2532
1
      nested = isl_space_drop_dims(nested, isl_dim_param,
2533
1
            n_space, n_nested - n_space);
2534
1
    if (!nested)
2535
0
      goto error;
2536
1
    space->nested[1] = nested;
2537
52.7k
  }
2538
52.7k
  isl_space_free(model);
2539
52.7k
  return space;
2540
52.7k
error:
2541
0
  isl_space_free(model);
2542
0
  isl_space_free(space);
2543
52.7k
  return NULL;
2544
52.7k
}
2545
2546
/* Compare the "type" dimensions of two isl_spaces.
2547
 *
2548
 * The order is fairly arbitrary.
2549
 */
2550
static int isl_space_cmp_type(__isl_keep isl_space *space1,
2551
  __isl_keep isl_space *space2, enum isl_dim_type type)
2552
1.34M
{
2553
1.34M
  int cmp;
2554
1.34M
  isl_space *nested1, *nested2;
2555
1.34M
2556
1.34M
  if (isl_space_dim(space1, type) != isl_space_dim(space2, type))
2557
1.34M
    return isl_space_dim(space1, type) -
2558
1.34M
      isl_space_dim(space2, type);
2559
1.34M
2560
1.34M
  cmp = isl_id_cmp(tuple_id(space1, type), tuple_id(space2, type));
2561
1.34M
  if (cmp != 0)
2562
0
    return cmp;
2563
1.34M
2564
1.34M
  nested1 = nested(space1, type);
2565
1.34M
  nested2 = nested(space2, type);
2566
1.34M
  if (!nested1 != !nested2)
2567
0
    return !nested1 - !nested2;
2568
1.34M
2569
1.34M
  
if (1.34M
nested11.34M
)
2570
87.7k
    return isl_space_cmp(nested1, nested2);
2571
1.34M
2572
1.25M
  return 0;
2573
1.34M
}
2574
2575
/* Compare two isl_spaces.
2576
 *
2577
 * The order is fairly arbitrary.
2578
 */
2579
int isl_space_cmp(__isl_keep isl_space *space1, __isl_keep isl_space *space2)
2580
1.56M
{
2581
1.56M
  int i;
2582
1.56M
  int cmp;
2583
1.56M
2584
1.56M
  if (space1 == space2)
2585
1.11M
    return 0;
2586
448k
  
if (448k
!space1448k
)
2587
0
    return -1;
2588
448k
  
if (448k
!space2448k
)
2589
0
    return 1;
2590
448k
2591
448k
  cmp = isl_space_cmp_type(space1, space2, isl_dim_param);
2592
448k
  if (cmp != 0)
2593
0
    return cmp;
2594
448k
  cmp = isl_space_cmp_type(space1, space2, isl_dim_in);
2595
448k
  if (cmp != 0)
2596
0
    return cmp;
2597
448k
  cmp = isl_space_cmp_type(space1, space2, isl_dim_out);
2598
448k
  if (cmp != 0)
2599
0
    return cmp;
2600
448k
2601
448k
  
if (448k
!space1->ids && 448k
!space2->ids36.4k
)
2602
36.2k
    return 0;
2603
448k
2604
3.37M
  
for (i = 0; 412k
i < n(space1, isl_dim_param)3.37M
;
++i2.95M
)
{2.95M
2605
2.95M
    cmp = isl_id_cmp(get_id(space1, isl_dim_param, i),
2606
2.95M
         get_id(space2, isl_dim_param, i));
2607
2.95M
    if (cmp != 0)
2608
0
      return cmp;
2609
2.95M
  }
2610
412k
2611
412k
  return 0;
2612
1.56M
}