Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/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.82M
{
23
1.82M
  return dim ? dim->ctx : NULL;
24
1.82M
}
25
26
__isl_give isl_space *isl_space_alloc(isl_ctx *ctx,
27
      unsigned nparam, unsigned n_in, unsigned n_out)
28
7.07M
{
29
7.07M
  isl_space *dim;
30
7.07M
31
7.07M
  dim = isl_alloc_type(ctx, struct isl_space);
32
7.07M
  if (!dim)
33
12
    return NULL;
34
7.07M
35
7.07M
  dim->ctx = ctx;
36
7.07M
  isl_ctx_ref(ctx);
37
7.07M
  dim->ref = 1;
38
7.07M
  dim->nparam = nparam;
39
7.07M
  dim->n_in = n_in;
40
7.07M
  dim->n_out = n_out;
41
7.07M
42
7.07M
  dim->tuple_id[0] = NULL;
43
7.07M
  dim->tuple_id[1] = NULL;
44
7.07M
45
7.07M
  dim->nested[0] = NULL;
46
7.07M
  dim->nested[1] = NULL;
47
7.07M
48
7.07M
  dim->n_id = 0;
49
7.07M
  dim->ids = NULL;
50
7.07M
51
7.07M
  return dim;
52
7.07M
}
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
2.32M
{
59
2.32M
  space = isl_space_cow(space);
60
2.32M
  if (!space)
61
2
    return NULL;
62
2.32M
  space = isl_space_set_tuple_id(space, isl_dim_in, &isl_id_none);
63
2.32M
  return space;
64
2.32M
}
65
66
/* Is the space that of a set?
67
 */
68
isl_bool isl_space_is_set(__isl_keep isl_space *space)
69
2.03M
{
70
2.03M
  if (!space)
71
0
    return isl_bool_error;
72
2.03M
  if (space->n_in != 0 || 
space->nested[0]1.73M
)
73
312k
    return isl_bool_false;
74
1.72M
  if (space->tuple_id[0] != &isl_id_none)
75
17.0k
    return isl_bool_false;
76
1.70M
  return isl_bool_true;
77
1.70M
}
78
79
/* Is the given space that of a map?
80
 */
81
isl_bool isl_space_is_map(__isl_keep isl_space *space)
82
31.6k
{
83
31.6k
  if (!space)
84
0
    return isl_bool_error;
85
31.6k
  return space->tuple_id[0] != &isl_id_none &&
86
31.6k
    
space->tuple_id[1] != &isl_id_none805
;
87
31.6k
}
88
89
__isl_give isl_space *isl_space_set_alloc(isl_ctx *ctx,
90
      unsigned nparam, unsigned dim)
91
1.04M
{
92
1.04M
  isl_space *space;
93
1.04M
  space = isl_space_alloc(ctx, nparam, 0, dim);
94
1.04M
  space = mark_as_set(space);
95
1.04M
  return space;
96
1.04M
}
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
201k
{
103
201k
  if (!space)
104
0
    return NULL;
105
201k
  space = isl_space_set_tuple_id(space, isl_dim_in, &isl_id_none);
106
201k
  space = isl_space_set_tuple_id(space, isl_dim_out, &isl_id_none);
107
201k
  return space;
108
201k
}
109
110
/* Is the space that of a parameter domain?
111
 */
112
isl_bool isl_space_is_params(__isl_keep isl_space *space)
113
784k
{
114
784k
  if (!space)
115
27
    return isl_bool_error;
116
784k
  if (space->n_in != 0 || 
space->nested[0]635k
||
117
784k
      
space->n_out != 0635k
||
space->nested[1]479k
)
118
305k
    return isl_bool_false;
119
478k
  if (space->tuple_id[0] != &isl_id_none)
120
26.1k
    return isl_bool_false;
121
452k
  if (space->tuple_id[1] != &isl_id_none)
122
39.3k
    return isl_bool_false;
123
413k
  return isl_bool_true;
124
413k
}
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
29.0k
{
130
29.0k
  isl_space *space;
131
29.0k
  space = isl_space_alloc(ctx, nparam, 0, 0);
132
29.0k
  space = mark_as_params(space);
133
29.0k
  return space;
134
29.0k
}
135
136
static unsigned global_pos(__isl_keep isl_space *dim,
137
         enum isl_dim_type type, unsigned pos)
138
56.8M
{
139
56.8M
  struct isl_ctx *ctx = dim->ctx;
140
56.8M
141
56.8M
  switch (type) {
142
56.8M
  case isl_dim_param:
143
36.6M
    isl_assert(ctx, pos < dim->nparam,
144
36.6M
          return isl_space_dim(dim, isl_dim_all));
145
36.6M
    return pos;
146
36.6M
  case isl_dim_in:
147
7.42M
    isl_assert(ctx, pos < dim->n_in,
148
7.42M
          return isl_space_dim(dim, isl_dim_all));
149
7.42M
    return pos + dim->nparam;
150
12.7M
  case isl_dim_out:
151
12.7M
    isl_assert(ctx, pos < dim->n_out,
152
12.7M
          return isl_space_dim(dim, isl_dim_all));
153
12.7M
    return pos + dim->nparam + dim->n_in;
154
12.7M
  default:
155
0
    isl_assert(ctx, 0, return isl_space_dim(dim, isl_dim_all));
156
56.8M
  }
157
56.8M
  
return isl_space_dim(dim, isl_dim_all)0
;
158
56.8M
}
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.34M
{
164
2.34M
  isl_id **ids;
165
2.34M
  int i;
166
2.34M
167
2.34M
  if (isl_space_dim(dim, isl_dim_all) <= dim->n_id)
168
559k
    return dim;
169
1.78M
170
1.78M
  if (!dim->ids) {
171
1.78M
    dim->ids = isl_calloc_array(dim->ctx,
172
1.78M
        isl_id *, isl_space_dim(dim, isl_dim_all));
173
1.78M
    if (!dim->ids)
174
0
      goto error;
175
809
  } else {
176
809
    ids = isl_realloc_array(dim->ctx, dim->ids,
177
809
        isl_id *, isl_space_dim(dim, isl_dim_all));
178
809
    if (!ids)
179
0
      goto error;
180
809
    dim->ids = ids;
181
5.26k
    for (i = dim->n_id; i < isl_space_dim(dim, isl_dim_all); 
++i4.45k
)
182
4.45k
      dim->ids[i] = NULL;
183
809
  }
184
1.78M
185
1.78M
  dim->n_id = isl_space_dim(dim, isl_dim_all);
186
1.78M
187
1.78M
  return dim;
188
0
error:
189
0
  isl_space_free(dim);
190
0
  return NULL;
191
1.78M
}
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
7.42M
{
196
7.42M
  dim = isl_space_cow(dim);
197
7.42M
198
7.42M
  if (!dim)
199
0
    goto error;
200
7.42M
201
7.42M
  pos = global_pos(dim, type, pos);
202
7.42M
  if (pos == isl_space_dim(dim, isl_dim_all))
203
0
    goto error;
204
7.42M
205
7.42M
  if (pos >= dim->n_id) {
206
1.78M
    if (!id)
207
0
      return dim;
208
1.78M
    dim = extend_ids(dim);
209
1.78M
    if (!dim)
210
0
      goto error;
211
7.42M
  }
212
7.42M
213
7.42M
  dim->ids[pos] = id;
214
7.42M
215
7.42M
  return dim;
216
0
error:
217
0
  isl_id_free(id);
218
0
  isl_space_free(dim);
219
0
  return NULL;
220
7.42M
}
221
222
static __isl_keep isl_id *get_id(__isl_keep isl_space *dim,
223
         enum isl_dim_type type, unsigned pos)
224
49.4M
{
225
49.4M
  if (!dim)
226
0
    return NULL;
227
49.4M
228
49.4M
  pos = global_pos(dim, type, pos);
229
49.4M
  if (pos == isl_space_dim(dim, isl_dim_all))
230
0
    return NULL;
231
49.4M
  if (pos >= dim->n_id)
232
3.95M
    return NULL;
233
45.4M
  return dim->ids[pos];
234
45.4M
}
235
236
static unsigned offset(__isl_keep isl_space *dim, enum isl_dim_type type)
237
2.56M
{
238
2.56M
  switch (type) {
239
2.56M
  
case isl_dim_param: return 0759k
;
240
2.56M
  
case isl_dim_in: return dim->nparam549k
;
241
2.56M
  
case isl_dim_out: return dim->nparam + dim->n_in1.25M
;
242
2.56M
  
default: return 00
;
243
2.56M
  }
244
2.56M
}
245
246
static unsigned n(__isl_keep isl_space *dim, enum isl_dim_type type)
247
413M
{
248
413M
  switch (type) {
249
413M
  
case isl_dim_param: return dim->nparam74.0M
;
250
413M
  
case isl_dim_in: return dim->n_in52.2M
;
251
413M
  
case isl_dim_out: return dim->n_out62.2M
;
252
413M
  
case isl_dim_all: return dim->nparam + dim->n_in + dim->n_out224M
;
253
413M
  
default: return 00
;
254
413M
  }
255
413M
}
256
257
unsigned isl_space_dim(__isl_keep isl_space *dim, enum isl_dim_type type)
258
313M
{
259
313M
  if (!dim)
260
4
    return 0;
261
313M
  return n(dim, type);
262
313M
}
263
264
unsigned isl_space_offset(__isl_keep isl_space *dim, enum isl_dim_type type)
265
2.35M
{
266
2.35M
  if (!dim)
267
0
    return 0;
268
2.35M
  return offset(dim, type);
269
2.35M
}
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.34M
{
275
7.34M
  int i;
276
7.34M
  isl_id *id;
277
7.34M
278
7.34M
  if (!dst)
279
0
    return NULL;
280
7.34M
281
21.0M
  
for (i = 0; 7.34M
i < n(src, src_type);
++i13.7M
) {
282
13.7M
    id = get_id(src, src_type, i);
283
13.7M
    if (!id)
284
8.70M
      continue;
285
5.01M
    dst = set_id(dst, dst_type, offset + i, isl_id_copy(id));
286
5.01M
    if (!dst)
287
0
      return NULL;
288
5.01M
  }
289
7.34M
  return dst;
290
7.34M
}
291
292
__isl_take isl_space *isl_space_dup(__isl_keep isl_space *dim)
293
5.02M
{
294
5.02M
  isl_space *dup;
295
5.02M
  if (!dim)
296
0
    return NULL;
297
5.02M
  dup = isl_space_alloc(dim->ctx, dim->nparam, dim->n_in, dim->n_out);
298
5.02M
  if (!dup)
299
12
    return NULL;
300
5.02M
  if (dim->tuple_id[0] &&
301
5.02M
      
!(dup->tuple_id[0] = isl_id_copy(dim->tuple_id[0]))2.70M
)
302
0
    goto error;
303
5.02M
  if (dim->tuple_id[1] &&
304
5.02M
      
!(dup->tuple_id[1] = isl_id_copy(dim->tuple_id[1]))1.01M
)
305
0
    goto error;
306
5.02M
  if (dim->nested[0] && 
!(dup->nested[0] = isl_space_copy(dim->nested[0]))908k
)
307
0
    goto error;
308
5.02M
  if (dim->nested[1] && 
!(dup->nested[1] = isl_space_copy(dim->nested[1]))1.60M
)
309
0
    goto error;
310
5.02M
  if (!dim->ids)
311
3.45M
    return dup;
312
1.56M
  dup = copy_ids(dup, isl_dim_param, 0, dim, isl_dim_param);
313
1.56M
  dup = copy_ids(dup, isl_dim_in, 0, dim, isl_dim_in);
314
1.56M
  dup = copy_ids(dup, isl_dim_out, 0, dim, isl_dim_out);
315
1.56M
  return dup;
316
0
error:
317
0
  isl_space_free(dup);
318
0
  return NULL;
319
1.56M
}
320
321
__isl_give isl_space *isl_space_cow(__isl_take isl_space *dim)
322
23.0M
{
323
23.0M
  if (!dim)
324
11
    return NULL;
325
23.0M
326
23.0M
  if (dim->ref == 1)
327
18.0M
    return dim;
328
5.00M
  dim->ref--;
329
5.00M
  return isl_space_dup(dim);
330
5.00M
}
331
332
__isl_give isl_space *isl_space_copy(__isl_keep isl_space *dim)
333
22.2M
{
334
22.2M
  if (!dim)
335
9.66k
    return NULL;
336
22.2M
337
22.2M
  dim->ref++;
338
22.2M
  return dim;
339
22.2M
}
340
341
__isl_null isl_space *isl_space_free(__isl_take isl_space *space)
342
40.5M
{
343
40.5M
  int i;
344
40.5M
345
40.5M
  if (!space)
346
16.2M
    return NULL;
347
24.3M
348
24.3M
  if (--space->ref > 0)
349
17.2M
    return NULL;
350
7.07M
351
7.07M
  isl_id_free(space->tuple_id[0]);
352
7.07M
  isl_id_free(space->tuple_id[1]);
353
7.07M
354
7.07M
  isl_space_free(space->nested[0]);
355
7.07M
  isl_space_free(space->nested[1]);
356
7.07M
357
14.5M
  for (i = 0; i < space->n_id; 
++i7.51M
)
358
7.51M
    isl_id_free(space->ids[i]);
359
7.07M
  free(space->ids);
360
7.07M
  isl_ctx_deref(space->ctx);
361
7.07M
  
362
7.07M
  free(space);
363
7.07M
364
7.07M
  return NULL;
365
7.07M
}
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
56.7k
{
374
56.7k
  char *p;
375
56.7k
  long dummy;
376
56.7k
377
56.7k
  dummy = strtol(s, &p, 0);
378
56.7k
  if (p != s)
379
56.7k
    
isl_die0
(ctx, isl_error_invalid, "name looks like a number",
380
56.7k
      return 0);
381
56.7k
382
56.7k
  return 1;
383
56.7k
}
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
121k
{
390
121k
  if (!space)
391
0
    return 0;
392
121k
  if (isl_space_is_params(space))
393
121k
    
isl_die0
(space->ctx, isl_error_invalid,
394
121k
      "parameter spaces don't have tuple ids", return 0);
395
121k
  if (isl_space_is_set(space) && 
type != isl_dim_set31.5k
)
396
121k
    
isl_die0
(space->ctx, isl_error_invalid,
397
121k
      "set spaces can only have a set id", return 0);
398
121k
  if (type != isl_dim_in && 
type != isl_dim_out121k
)
399
121k
    
isl_die0
(space->ctx, isl_error_invalid,
400
121k
      "only input, output and set tuples can have ids",
401
121k
      return 0);
402
121k
403
121k
  return 1;
404
121k
}
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
120k
{
411
120k
  if (!space_can_have_id(dim, type))
412
0
    return isl_bool_error;
413
120k
  return dim->tuple_id[type - isl_dim_in] != NULL;
414
120k
}
415
416
__isl_give isl_id *isl_space_get_tuple_id(__isl_keep isl_space *dim,
417
  enum isl_dim_type type)
418
38.6k
{
419
38.6k
  int has_id;
420
38.6k
421
38.6k
  if (!dim)
422
0
    return NULL;
423
38.6k
  has_id = isl_space_has_tuple_id(dim, type);
424
38.6k
  if (has_id < 0)
425
0
    return NULL;
426
38.6k
  if (!has_id)
427
38.6k
    
isl_die0
(dim->ctx, isl_error_invalid,
428
38.6k
      "tuple has no id", return NULL);
429
38.6k
  return isl_id_copy(dim->tuple_id[type - isl_dim_in]);
430
38.6k
}
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
2.79M
{
435
2.79M
  dim = isl_space_cow(dim);
436
2.79M
  if (!dim || !id)
437
0
    goto error;
438
2.79M
  if (type != isl_dim_in && 
type != isl_dim_out266k
)
439
2.79M
    
isl_die0
(dim->ctx, isl_error_invalid,
440
2.79M
      "only input, output and set tuples can have names",
441
2.79M
      goto error);
442
2.79M
443
2.79M
  isl_id_free(dim->tuple_id[type - isl_dim_in]);
444
2.79M
  dim->tuple_id[type - isl_dim_in] = id;
445
2.79M
446
2.79M
  return dim;
447
0
error:
448
0
  isl_id_free(id);
449
0
  isl_space_free(dim);
450
0
  return NULL;
451
2.79M
}
452
453
__isl_give isl_space *isl_space_reset_tuple_id(__isl_take isl_space *dim,
454
  enum isl_dim_type type)
455
6.00k
{
456
6.00k
  dim = isl_space_cow(dim);
457
6.00k
  if (!dim)
458
0
    return NULL;
459
6.00k
  if (type != isl_dim_in && type != isl_dim_out)
460
6.00k
    
isl_die0
(dim->ctx, isl_error_invalid,
461
6.00k
      "only input, output and set tuples can have names",
462
6.00k
      goto error);
463
6.00k
464
6.00k
  isl_id_free(dim->tuple_id[type - isl_dim_in]);
465
6.00k
  dim->tuple_id[type - isl_dim_in] = NULL;
466
6.00k
467
6.00k
  return dim;
468
0
error:
469
0
  isl_space_free(dim);
470
0
  return NULL;
471
6.00k
}
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
83.3k
{
481
83.3k
  space = isl_space_cow(space);
482
83.3k
  if (!space || !id)
483
0
    goto error;
484
83.3k
485
83.3k
  if (type == isl_dim_param) {
486
61.3k
    int i;
487
61.3k
488
184k
    for (i = 0; i < 2; 
++i122k
) {
489
122k
      if (!space->nested[i])
490
122k
        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
61.3k
  }
498
83.3k
499
83.3k
  isl_id_free(get_id(space, type, pos));
500
83.3k
  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
83.3k
}
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 (type == isl_dim_param) {
520
0
    int i;
521
0
522
0
    for (i = 0; i < 2; ++i) {
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
1.26k
{
543
1.26k
  if (!dim)
544
0
    return isl_bool_error;
545
1.26k
  return get_id(dim, type, pos) != NULL;
546
1.26k
}
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
781k
{
551
781k
  if (!dim)
552
0
    return NULL;
553
781k
  if (!get_id(dim, type, pos))
554
781k
    
isl_die0
(dim->ctx, isl_error_invalid,
555
781k
      "dim has no id", return NULL);
556
781k
  return isl_id_copy(get_id(dim, type, pos));
557
781k
}
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
50.2k
{
562
50.2k
  isl_id *id;
563
50.2k
564
50.2k
  if (!dim)
565
0
    return NULL;
566
50.2k
567
50.2k
  if (!s)
568
0
    return isl_space_reset_tuple_id(dim, type);
569
50.2k
570
50.2k
  if (!name_ok(dim->ctx, s))
571
0
    goto error;
572
50.2k
573
50.2k
  id = isl_id_alloc(dim->ctx, s, NULL);
574
50.2k
  return isl_space_set_tuple_id(dim, type, id);
575
0
error:
576
0
  isl_space_free(dim);
577
0
  return NULL;
578
50.2k
}
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
1.18k
{
585
1.18k
  isl_id *id;
586
1.18k
587
1.18k
  if (!space_can_have_id(space, type))
588
0
    return isl_bool_error;
589
1.18k
  id = space->tuple_id[type - isl_dim_in];
590
1.18k
  return id && 
id->name256
;
591
1.18k
}
592
593
__isl_keep const char *isl_space_get_tuple_name(__isl_keep isl_space *dim,
594
   enum isl_dim_type type)
595
10.9k
{
596
10.9k
  isl_id *id;
597
10.9k
  if (!dim)
598
0
    return NULL;
599
10.9k
  if (type != isl_dim_in && 
type != isl_dim_out6.48k
)
600
0
    return NULL;
601
10.9k
  id = dim->tuple_id[type - isl_dim_in];
602
10.9k
  return id ? 
id->name9.46k
: NULL;
603
10.9k
}
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
6.54k
{
609
6.54k
  isl_id *id;
610
6.54k
611
6.54k
  if (!dim)
612
0
    return NULL;
613
6.54k
  if (!s)
614
0
    return isl_space_reset_dim_id(dim, type, pos);
615
6.54k
  if (!name_ok(dim->ctx, s))
616
0
    goto error;
617
6.54k
  id = isl_id_alloc(dim->ctx, s, NULL);
618
6.54k
  return isl_space_set_dim_id(dim, type, pos, id);
619
0
error:
620
0
  isl_space_free(dim);
621
0
  return NULL;
622
6.54k
}
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
6.69k
{
629
6.69k
  isl_id *id;
630
6.69k
631
6.69k
  if (!space)
632
0
    return isl_bool_error;
633
6.69k
  id = get_id(space, type, pos);
634
6.69k
  return id && 
id->name1.02k
;
635
6.69k
}
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
314k
{
640
314k
  isl_id *id = get_id(dim, type, pos);
641
314k
  return id ? 
id->name261k
: NULL;
642
314k
}
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
398
{
647
398
  int i;
648
398
  int offset;
649
398
  int n;
650
398
651
398
  if (!dim || !id)
652
0
    return -1;
653
398
654
398
  offset = isl_space_offset(dim, type);
655
398
  n = isl_space_dim(dim, type);
656
522
  for (i = 0; i < n && 
offset + i < dim->n_id520
;
++i124
)
657
520
    if (dim->ids[offset + i] == id)
658
396
      return i;
659
398
660
398
  
return -12
;
661
398
}
662
663
int isl_space_find_dim_by_name(__isl_keep isl_space *space,
664
  enum isl_dim_type type, const char *name)
665
941
{
666
941
  int i;
667
941
  int offset;
668
941
  int n;
669
941
670
941
  if (!space || !name)
671
0
    return -1;
672
941
673
941
  offset = isl_space_offset(space, type);
674
941
  n = isl_space_dim(space, type);
675
1.65k
  for (i = 0; i < n && 
offset + i < space->n_id716
;
++i716
) {
676
716
    isl_id *id = get_id(space, type, i);
677
716
    if (id && id->name && !strcmp(id->name, name))
678
0
      return i;
679
716
  }
680
941
681
941
  return -1;
682
941
}
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 && i < space->n_id; ++i) {
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; i < 2; ++i) {
714
0
    if (!space->tuple_id[i])
715
0
      continue;
716
0
    if (!isl_id_get_user(space->tuple_id[i]))
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; i < 2; ++i) {
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
59.6M
{
746
59.6M
  if (!dim)
747
0
    return NULL;
748
59.6M
  if (type == isl_dim_in)
749
18.6M
    return dim->tuple_id[0];
750
40.9M
  if (type == isl_dim_out)
751
16.8M
    return dim->tuple_id[1];
752
24.1M
  return NULL;
753
24.1M
}
754
755
static __isl_keep isl_space *nested(__isl_keep isl_space *dim,
756
  enum isl_dim_type type)
757
55.8M
{
758
55.8M
  if (!dim)
759
0
    return NULL;
760
55.8M
  if (type == isl_dim_in)
761
16.1M
    return dim->nested[0];
762
39.7M
  if (type == isl_dim_out)
763
15.5M
    return dim->nested[1];
764
24.1M
  return NULL;
765
24.1M
}
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
10.0M
{
772
10.0M
  if (!space1 || !space2)
773
0
    return isl_bool_error;
774
10.0M
  if (space1 == space2)
775
3.54M
    return isl_bool_true;
776
6.52M
  return isl_space_tuple_is_equal(space1, isl_dim_in,
777
6.52M
          space2, isl_dim_in) &&
778
6.52M
         isl_space_tuple_is_equal(space1, isl_dim_out,
779
5.50M
          space2, isl_dim_out);
780
6.52M
}
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
29.3M
{
798
29.3M
  isl_id *id1, *id2;
799
29.3M
  isl_space *nested1, *nested2;
800
29.3M
801
29.3M
  if (!space1 || !space2)
802
0
    return isl_bool_error;
803
29.3M
804
29.3M
  if (space1 == space2 && 
type1 == type22.34M
)
805
6.46k
    return isl_bool_true;
806
29.3M
807
29.3M
  if (n(space1, type1) != n(space2, type2))
808
2.74M
    return isl_bool_false;
809
26.5M
  id1 = tuple_id(space1, type1);
810
26.5M
  id2 = tuple_id(space2, type2);
811
26.5M
  if (!id1 ^ !id2)
812
902k
    return isl_bool_false;
813
25.6M
  if (id1 && 
id1 != id24.85M
)
814
150k
    return isl_bool_false;
815
25.5M
  nested1 = nested(space1, type1);
816
25.5M
  nested2 = nested(space2, type2);
817
25.5M
  if (!nested1 ^ !nested2)
818
80.8k
    return isl_bool_false;
819
25.4M
  if (nested1 && 
!isl_space_has_equal_tuples(nested1, nested2)5.55M
)
820
26.2k
    return isl_bool_false;
821
25.3M
  return isl_bool_true;
822
25.3M
}
823
824
static isl_bool match(__isl_keep isl_space *space1, enum isl_dim_type type1,
825
  __isl_keep isl_space *space2, enum isl_dim_type type2)
826
15.0M
{
827
15.0M
  int i;
828
15.0M
829
15.0M
  if (space1 == space2 && 
type1 == type23.31M
)
830
984k
    return isl_bool_true;
831
14.0M
832
14.0M
  if (!isl_space_tuple_is_equal(space1, type1, space2, type2))
833
2.41M
    return isl_bool_false;
834
11.6M
835
11.6M
  if (!space1->ids && 
!space2->ids8.30M
)
836
8.26M
    return isl_bool_true;
837
3.37M
838
12.6M
  
for (i = 0; 3.37M
i < n(space1, type1);
++i9.23M
) {
839
9.30M
    if (get_id(space1, type1, i) != get_id(space2, type2, i))
840
67.6k
      return isl_bool_false;
841
9.30M
  }
842
3.37M
  
return isl_bool_true3.30M
;
843
3.37M
}
844
845
/* Do "space1" and "space2" have the same parameters?
846
 */
847
isl_bool isl_space_has_equal_params(__isl_keep isl_space *space1,
848
  __isl_keep isl_space *space2)
849
12.2M
{
850
12.2M
  if (!space1 || 
!space212.2M
)
851
2
    return isl_bool_error;
852
12.2M
853
12.2M
  return match(space1, isl_dim_param, space2, isl_dim_param);
854
12.2M
}
855
856
/* Do "space1" and "space2" have the same identifiers for all
857
 * the tuple variables?
858
 */
859
isl_bool isl_space_has_equal_ids(__isl_keep isl_space *space1,
860
  __isl_keep isl_space *space2)
861
213k
{
862
213k
  isl_bool equal;
863
213k
864
213k
  if (!space1 || !space2)
865
0
    return isl_bool_error;
866
213k
867
213k
  equal = match(space1, isl_dim_in, space2, isl_dim_in);
868
213k
  if (equal < 0 || !equal)
869
132
    return equal;
870
213k
  return match(space1, isl_dim_out, space2, isl_dim_out);
871
213k
}
872
873
isl_bool isl_space_match(__isl_keep isl_space *space1, enum isl_dim_type type1,
874
  __isl_keep isl_space *space2, enum isl_dim_type type2)
875
0
{
876
0
  if (!space1 || !space2)
877
0
    return isl_bool_error;
878
0
879
0
  return match(space1, type1, space2, type2);
880
0
}
881
882
static void get_ids(__isl_keep isl_space *dim, enum isl_dim_type type,
883
  unsigned first, unsigned n, __isl_keep isl_id **ids)
884
2.89M
{
885
2.89M
  int i;
886
2.89M
887
7.44M
  for (i = 0; i < n ; 
++i4.55M
)
888
4.55M
    ids[i] = get_id(dim, type, first + i);
889
2.89M
}
890
891
static __isl_give isl_space *space_extend(__isl_take isl_space *space,
892
      unsigned nparam, unsigned n_in, unsigned n_out)
893
762k
{
894
762k
  isl_id **ids = NULL;
895
762k
896
762k
  if (!space)
897
0
    return NULL;
898
762k
  if (space->nparam == nparam &&
899
762k
      
space->n_in == n_in638k
&&
space->n_out == n_out630k
)
900
1.46k
    return space;
901
760k
902
760k
  isl_assert(space->ctx, space->nparam <= nparam, goto error);
903
760k
  isl_assert(space->ctx, space->n_in <= n_in, goto error);
904
760k
  isl_assert(space->ctx, space->n_out <= n_out, goto error);
905
760k
906
760k
  space = isl_space_cow(space);
907
760k
  if (!space)
908
0
    goto error;
909
760k
910
760k
  if (space->ids) {
911
311k
    unsigned n;
912
311k
    n = nparam + n_in + n_out;
913
311k
    if (n < nparam || n < n_in || n < n_out)
914
311k
      
isl_die0
(isl_space_get_ctx(space), isl_error_invalid,
915
311k
        "overflow in total number of dimensions",
916
311k
        goto error);
917
311k
    ids = isl_calloc_array(space->ctx, isl_id *, n);
918
311k
    if (!ids)
919
0
      goto error;
920
311k
    get_ids(space, isl_dim_param, 0, space->nparam, ids);
921
311k
    get_ids(space, isl_dim_in, 0, space->n_in, ids + nparam);
922
311k
    get_ids(space, isl_dim_out, 0, space->n_out,
923
311k
      ids + nparam + n_in);
924
311k
    free(space->ids);
925
311k
    space->ids = ids;
926
311k
    space->n_id = nparam + n_in + n_out;
927
311k
  }
928
760k
  space->nparam = nparam;
929
760k
  space->n_in = n_in;
930
760k
  space->n_out = n_out;
931
760k
932
760k
  return space;
933
0
error:
934
0
  free(ids);
935
0
  isl_space_free(space);
936
0
  return NULL;
937
760k
}
938
939
__isl_give isl_space *isl_space_extend(__isl_take isl_space *space,
940
  unsigned nparam, unsigned n_in, unsigned n_out)
941
0
{
942
0
  return space_extend(space, nparam, n_in, n_out);
943
0
}
944
945
__isl_give isl_space *isl_space_add_dims(__isl_take isl_space *space,
946
  enum isl_dim_type type, unsigned n)
947
762k
{
948
762k
  space = isl_space_reset(space, type);
949
762k
  if (!space)
950
9
    return NULL;
951
762k
  switch (type) {
952
762k
  case isl_dim_param:
953
124k
    space = space_extend(space,
954
124k
        space->nparam + n, space->n_in, space->n_out);
955
124k
    if (space && space->nested[0] &&
956
124k
        !(space->nested[0] = isl_space_add_dims(space->nested[0],
957
125
                isl_dim_param, n)))
958
0
      goto error;
959
124k
    if (space && space->nested[1] &&
960
124k
        !(space->nested[1] = isl_space_add_dims(space->nested[1],
961
470
                isl_dim_param, n)))
962
0
      goto error;
963
124k
    return space;
964
124k
  case isl_dim_in:
965
8.99k
    return space_extend(space,
966
8.99k
        space->nparam, space->n_in + n, space->n_out);
967
629k
  case isl_dim_out:
968
629k
    return space_extend(space,
969
629k
        space->nparam, space->n_in, space->n_out + n);
970
124k
  default:
971
0
    isl_die(space->ctx, isl_error_invalid,
972
762k
      "cannot add dimensions of specified type", goto error);
973
762k
  }
974
762k
error:
975
0
  isl_space_free(space);
976
0
  return NULL;
977
762k
}
978
979
/* Add a parameter with identifier "id" to "space", provided
980
 * it does not already appear in "space".
981
 */
982
__isl_give isl_space *isl_space_add_param_id(__isl_take isl_space *space,
983
  __isl_take isl_id *id)
984
1
{
985
1
  int pos;
986
1
987
1
  if (!space || !id)
988
0
    goto error;
989
1
990
1
  if (isl_space_find_dim_by_id(space, isl_dim_param, id) >= 0) {
991
0
    isl_id_free(id);
992
0
    return space;
993
0
  }
994
1
995
1
  pos = isl_space_dim(space, isl_dim_param);
996
1
  space = isl_space_add_dims(space, isl_dim_param, 1);
997
1
  space = isl_space_set_dim_id(space, isl_dim_param, pos, id);
998
1
999
1
  return space;
1000
0
error:
1001
0
  isl_space_free(space);
1002
0
  isl_id_free(id);
1003
0
  return NULL;
1004
1
}
1005
1006
static int valid_dim_type(enum isl_dim_type type)
1007
2.72M
{
1008
2.72M
  switch (type) {
1009
2.72M
  case isl_dim_param:
1010
2.72M
  case isl_dim_in:
1011
2.72M
  case isl_dim_out:
1012
2.72M
    return 1;
1013
2.72M
  default:
1014
0
    return 0;
1015
2.72M
  }
1016
2.72M
}
1017
1018
/* Insert "n" dimensions of type "type" at position "pos".
1019
 * If we are inserting parameters, then they are also inserted in
1020
 * any nested spaces.
1021
 */
1022
__isl_give isl_space *isl_space_insert_dims(__isl_take isl_space *space,
1023
  enum isl_dim_type type, unsigned pos, unsigned n)
1024
200k
{
1025
200k
  isl_ctx *ctx;
1026
200k
  isl_id **ids = NULL;
1027
200k
  unsigned total;
1028
200k
1029
200k
  if (!space)
1030
0
    return NULL;
1031
200k
  if (n == 0)
1032
6
    return isl_space_reset(space, type);
1033
200k
1034
200k
  ctx = isl_space_get_ctx(space);
1035
200k
  if (!valid_dim_type(type))
1036
200k
    
isl_die0
(ctx, isl_error_invalid,
1037
200k
      "cannot insert dimensions of specified type",
1038
200k
      goto error);
1039
200k
1040
200k
  total = isl_space_dim(space, isl_dim_all);
1041
200k
  if (total + n < total)
1042
200k
    
isl_die0
(ctx, isl_error_invalid,
1043
200k
      "overflow in total number of dimensions",
1044
200k
      return isl_space_free(space));
1045
200k
  isl_assert(ctx, pos <= isl_space_dim(space, type), goto error);
1046
200k
1047
200k
  space = isl_space_cow(space);
1048
200k
  if (!space)
1049
0
    return NULL;
1050
200k
1051
200k
  if (space->ids) {
1052
56.7k
    enum isl_dim_type t, o = isl_dim_param;
1053
56.7k
    int off;
1054
56.7k
    int s[3];
1055
56.7k
    ids = isl_calloc_array(ctx, isl_id *,
1056
56.7k
           space->nparam + space->n_in + space->n_out + n);
1057
56.7k
    if (!ids)
1058
0
      goto error;
1059
56.7k
    off = 0;
1060
56.7k
    s[isl_dim_param - o] = space->nparam;
1061
56.7k
    s[isl_dim_in - o] = space->n_in;
1062
56.7k
    s[isl_dim_out - o] = space->n_out;
1063
226k
    for (t = isl_dim_param; t <= isl_dim_out; 
++t170k
) {
1064
170k
      if (t != type) {
1065
113k
        get_ids(space, t, 0, s[t - o], ids + off);
1066
113k
        off += s[t - o];
1067
113k
      } else {
1068
56.7k
        get_ids(space, t, 0, pos, ids + off);
1069
56.7k
        off += pos + n;
1070
56.7k
        get_ids(space, t, pos, s[t - o] - pos,
1071
56.7k
          ids + off);
1072
56.7k
        off += s[t - o] - pos;
1073
56.7k
      }
1074
170k
    }
1075
56.7k
    free(space->ids);
1076
56.7k
    space->ids = ids;
1077
56.7k
    space->n_id = space->nparam + space->n_in + space->n_out + n;
1078
56.7k
  }
1079
200k
  switch (type) {
1080
200k
  
case isl_dim_param: space->nparam += n; break2.83k
;
1081
200k
  
case isl_dim_in: space->n_in += n; break10.6k
;
1082
200k
  
case isl_dim_out: space->n_out += n; break187k
;
1083
200k
  
default: ;0
1084
200k
  }
1085
200k
  space = isl_space_reset(space, type);
1086
200k
1087
200k
  if (type == isl_dim_param) {
1088
2.83k
    if (space && space->nested[0] &&
1089
2.83k
        !(space->nested[0] = isl_space_insert_dims(space->nested[0],
1090
0
                isl_dim_param, pos, n)))
1091
0
      goto error;
1092
2.83k
    if (space && space->nested[1] &&
1093
2.83k
        !(space->nested[1] = isl_space_insert_dims(space->nested[1],
1094
1
                isl_dim_param, pos, n)))
1095
0
      goto error;
1096
200k
  }
1097
200k
1098
200k
  return space;
1099
0
error:
1100
0
  isl_space_free(space);
1101
0
  return NULL;
1102
200k
}
1103
1104
__isl_give isl_space *isl_space_move_dims(__isl_take isl_space *space,
1105
  enum isl_dim_type dst_type, unsigned dst_pos,
1106
  enum isl_dim_type src_type, unsigned src_pos, unsigned n)
1107
1.39k
{
1108
1.39k
  int i;
1109
1.39k
1110
1.39k
  space = isl_space_reset(space, src_type);
1111
1.39k
  space = isl_space_reset(space, dst_type);
1112
1.39k
  if (!space)
1113
0
    return NULL;
1114
1.39k
  if (n == 0)
1115
294
    return space;
1116
1.10k
1117
1.10k
  isl_assert(space->ctx, src_pos + n <= isl_space_dim(space, src_type),
1118
1.10k
    goto error);
1119
1.10k
1120
1.10k
  if (dst_type == src_type && 
dst_pos == src_pos0
)
1121
0
    return space;
1122
1.10k
1123
1.10k
  isl_assert(space->ctx, dst_type != src_type, goto error);
1124
1.10k
1125
1.10k
  space = isl_space_cow(space);
1126
1.10k
  if (!space)
1127
0
    return NULL;
1128
1.10k
1129
1.10k
  if (space->ids) {
1130
339
    isl_id **ids;
1131
339
    enum isl_dim_type t, o = isl_dim_param;
1132
339
    int off;
1133
339
    int s[3];
1134
339
    ids = isl_calloc_array(space->ctx, isl_id *,
1135
339
         space->nparam + space->n_in + space->n_out);
1136
339
    if (!ids)
1137
0
      goto error;
1138
339
    off = 0;
1139
339
    s[isl_dim_param - o] = space->nparam;
1140
339
    s[isl_dim_in - o] = space->n_in;
1141
339
    s[isl_dim_out - o] = space->n_out;
1142
1.35k
    for (t = isl_dim_param; t <= isl_dim_out; 
++t1.01k
) {
1143
1.01k
      if (t == dst_type) {
1144
339
        get_ids(space, t, 0, dst_pos, ids + off);
1145
339
        off += dst_pos;
1146
339
        get_ids(space, src_type, src_pos, n, ids + off);
1147
339
        off += n;
1148
339
        get_ids(space, t, dst_pos, s[t - o] - dst_pos,
1149
339
            ids + off);
1150
339
        off += s[t - o] - dst_pos;
1151
678
      } else if (t == src_type) {
1152
339
        get_ids(space, t, 0, src_pos, ids + off);
1153
339
        off += src_pos;
1154
339
        get_ids(space, t, src_pos + n,
1155
339
              s[t - o] - src_pos - n, ids + off);
1156
339
        off += s[t - o] - src_pos - n;
1157
339
      } else {
1158
339
        get_ids(space, t, 0, s[t - o], ids + off);
1159
339
        off += s[t - o];
1160
339
      }
1161
1.01k
    }
1162
339
    free(space->ids);
1163
339
    space->ids = ids;
1164
339
    space->n_id = space->nparam + space->n_in + space->n_out;
1165
339
  }
1166
1.10k
1167
1.10k
  switch (dst_type) {
1168
1.10k
  
case isl_dim_param: space->nparam += n; break96
;
1169
1.10k
  
case isl_dim_in: space->n_in += n; break569
;
1170
1.10k
  
case isl_dim_out: space->n_out += n; break440
;
1171
1.10k
  
default: ;0
1172
1.10k
  }
1173
1.10k
1174
1.10k
  switch (src_type) {
1175
1.10k
  
case isl_dim_param: space->nparam -= n; break252
;
1176
1.10k
  
case isl_dim_in: space->n_in -= n; break206
;
1177
1.10k
  
case isl_dim_out: space->n_out -= n; break647
;
1178
1.10k
  
default: ;0
1179
1.10k
  }
1180
1.10k
1181
1.10k
  if (dst_type != isl_dim_param && 
src_type != isl_dim_param1.00k
)
1182
757
    return space;
1183
348
1184
1.04k
  
for (i = 0; 348
i < 2;
++i696
) {
1185
696
    if (!space->nested[i])
1186
679
      continue;
1187
17
    space->nested[i] = isl_space_replace_params(space->nested[i],
1188
17
                   space);
1189
17
    if (!space->nested[i])
1190
0
      goto error;
1191
17
  }
1192
348
1193
348
  return space;
1194
0
error:
1195
0
  isl_space_free(space);
1196
0
  return NULL;
1197
348
}
1198
1199
/* Check that "space1" and "space2" have the same parameters,
1200
 * reporting an error if they do not.
1201
 */
1202
isl_stat isl_space_check_equal_params(__isl_keep isl_space *space1,
1203
  __isl_keep isl_space *space2)
1204
756k
{
1205
756k
  isl_bool equal;
1206
756k
1207
756k
  equal = isl_space_has_equal_params(space1, space2);
1208
756k
  if (equal < 0)
1209
2
    return isl_stat_error;
1210
756k
  if (!equal)
1211
756k
    
isl_die0
(isl_space_get_ctx(space1), isl_error_invalid,
1212
756k
      "parameters need to match", return isl_stat_error);
1213
756k
  return isl_stat_ok;
1214
756k
}
1215
1216
__isl_give isl_space *isl_space_join(__isl_take isl_space *left,
1217
  __isl_take isl_space *right)
1218
638k
{
1219
638k
  isl_space *dim;
1220
638k
1221
638k
  if (isl_space_check_equal_params(left, right) < 0)
1222
2
    goto error;
1223
638k
1224
638k
  isl_assert(left->ctx,
1225
638k
    isl_space_tuple_is_equal(left, isl_dim_out, right, isl_dim_in),
1226
638k
    goto error);
1227
638k
1228
638k
  dim = isl_space_alloc(left->ctx, left->nparam, left->n_in, right->n_out);
1229
638k
  if (!dim)
1230
0
    goto error;
1231
638k
1232
638k
  dim = copy_ids(dim, isl_dim_param, 0, left, isl_dim_param);
1233
638k
  dim = copy_ids(dim, isl_dim_in, 0, left, isl_dim_in);
1234
638k
  dim = copy_ids(dim, isl_dim_out, 0, right, isl_dim_out);
1235
638k
1236
638k
  if (dim && left->tuple_id[0] &&
1237
638k
      
!(dim->tuple_id[0] = isl_id_copy(left->tuple_id[0]))246k
)
1238
0
    goto error;
1239
638k
  if (dim && right->tuple_id[1] &&
1240
638k
      
!(dim->tuple_id[1] = isl_id_copy(right->tuple_id[1]))164k
)
1241
0
    goto error;
1242
638k
  if (dim && left->nested[0] &&
1243
638k
      
!(dim->nested[0] = isl_space_copy(left->nested[0]))226k
)
1244
0
    goto error;
1245
638k
  if (dim && right->nested[1] &&
1246
638k
      
!(dim->nested[1] = isl_space_copy(right->nested[1]))318k
)
1247
0
    goto error;
1248
638k
1249
638k
  isl_space_free(left);
1250
638k
  isl_space_free(right);
1251
638k
1252
638k
  return dim;
1253
2
error:
1254
2
  isl_space_free(left);
1255
2
  isl_space_free(right);
1256
2
  return NULL;
1257
638k
}
1258
1259
/* Given two map spaces { A -> C } and { B -> D }, construct the space
1260
 * { [A -> B] -> [C -> D] }.
1261
 * Given two set spaces { A } and { B }, construct the space { [A -> B] }.
1262
 */
1263
__isl_give isl_space *isl_space_product(__isl_take isl_space *left,
1264
  __isl_take isl_space *right)
1265
2.95k
{
1266
2.95k
  isl_space *dom1, *dom2, *nest1, *nest2;
1267
2.95k
  int is_set;
1268
2.95k
1269
2.95k
  if (!left || !right)
1270
0
    goto error;
1271
2.95k
1272
2.95k
  is_set = isl_space_is_set(left);
1273
2.95k
  if (is_set != isl_space_is_set(right))
1274
2.95k
    
isl_die0
(isl_space_get_ctx(left), isl_error_invalid,
1275
2.95k
      "expecting either two set spaces or two map spaces",
1276
2.95k
      goto error);
1277
2.95k
  if (is_set)
1278
274
    return isl_space_range_product(left, right);
1279
2.68k
1280
2.68k
  if (isl_space_check_equal_params(left, right) < 0)
1281
0
    goto error;
1282
2.68k
1283
2.68k
  dom1 = isl_space_domain(isl_space_copy(left));
1284
2.68k
  dom2 = isl_space_domain(isl_space_copy(right));
1285
2.68k
  nest1 = isl_space_wrap(isl_space_join(isl_space_reverse(dom1), dom2));
1286
2.68k
1287
2.68k
  dom1 = isl_space_range(left);
1288
2.68k
  dom2 = isl_space_range(right);
1289
2.68k
  nest2 = isl_space_wrap(isl_space_join(isl_space_reverse(dom1), dom2));
1290
2.68k
1291
2.68k
  return isl_space_join(isl_space_reverse(nest1), nest2);
1292
0
error:
1293
0
  isl_space_free(left);
1294
0
  isl_space_free(right);
1295
0
  return NULL;
1296
2.68k
}
1297
1298
/* Given two spaces { A -> C } and { B -> C }, construct the space
1299
 * { [A -> B] -> C }
1300
 */
1301
__isl_give isl_space *isl_space_domain_product(__isl_take isl_space *left,
1302
  __isl_take isl_space *right)
1303
2.27k
{
1304
2.27k
  isl_space *ran, *dom1, *dom2, *nest;
1305
2.27k
1306
2.27k
  if (isl_space_check_equal_params(left, right) < 0)
1307
0
    goto error;
1308
2.27k
1309
2.27k
  if (!isl_space_tuple_is_equal(left, isl_dim_out, right, isl_dim_out))
1310
2.27k
    
isl_die0
(left->ctx, isl_error_invalid,
1311
2.27k
      "ranges need to match", goto error);
1312
2.27k
1313
2.27k
  ran = isl_space_range(isl_space_copy(left));
1314
2.27k
1315
2.27k
  dom1 = isl_space_domain(left);
1316
2.27k
  dom2 = isl_space_domain(right);
1317
2.27k
  nest = isl_space_wrap(isl_space_join(isl_space_reverse(dom1), dom2));
1318
2.27k
1319
2.27k
  return isl_space_join(isl_space_reverse(nest), ran);
1320
0
error:
1321
0
  isl_space_free(left);
1322
0
  isl_space_free(right);
1323
0
  return NULL;
1324
2.27k
}
1325
1326
__isl_give isl_space *isl_space_range_product(__isl_take isl_space *left,
1327
  __isl_take isl_space *right)
1328
112k
{
1329
112k
  isl_space *dom, *ran1, *ran2, *nest;
1330
112k
1331
112k
  if (isl_space_check_equal_params(left, right) < 0)
1332
0
    goto error;
1333
112k
1334
112k
  if (!isl_space_tuple_is_equal(left, isl_dim_in, right, isl_dim_in))
1335
112k
    
isl_die0
(left->ctx, isl_error_invalid,
1336
112k
      "domains need to match", goto error);
1337
112k
1338
112k
  dom = isl_space_domain(isl_space_copy(left));
1339
112k
1340
112k
  ran1 = isl_space_range(left);
1341
112k
  ran2 = isl_space_range(right);
1342
112k
  nest = isl_space_wrap(isl_space_join(isl_space_reverse(ran1), ran2));
1343
112k
1344
112k
  return isl_space_join(isl_space_reverse(dom), nest);
1345
0
error:
1346
0
  isl_space_free(left);
1347
0
  isl_space_free(right);
1348
0
  return NULL;
1349
112k
}
1350
1351
/* Given a space of the form [A -> B] -> C, return the space A -> C.
1352
 */
1353
__isl_give isl_space *isl_space_domain_factor_domain(
1354
  __isl_take isl_space *space)
1355
860
{
1356
860
  isl_space *nested;
1357
860
  isl_space *domain;
1358
860
1359
860
  if (!space)
1360
0
    return NULL;
1361
860
  if (!isl_space_domain_is_wrapping(space))
1362
860
    
isl_die0
(isl_space_get_ctx(space), isl_error_invalid,
1363
860
      "domain not a product", return isl_space_free(space));
1364
860
1365
860
  nested = space->nested[0];
1366
860
  domain = isl_space_copy(space);
1367
860
  domain = isl_space_drop_dims(domain, isl_dim_in,
1368
860
          nested->n_in, nested->n_out);
1369
860
  if (!domain)
1370
0
    return isl_space_free(space);
1371
860
  if (nested->tuple_id[0]) {
1372
541
    domain->tuple_id[0] = isl_id_copy(nested->tuple_id[0]);
1373
541
    if (!domain->tuple_id[0])
1374
0
      goto error;
1375
860
  }
1376
860
  if (nested->nested[0]) {
1377
319
    domain->nested[0] = isl_space_copy(nested->nested[0]);
1378
319
    if (!domain->nested[0])
1379
0
      goto error;
1380
860
  }
1381
860
1382
860
  isl_space_free(space);
1383
860
  return domain;
1384
0
error:
1385
0
  isl_space_free(space);
1386
0
  isl_space_free(domain);
1387
0
  return NULL;
1388
860
}
1389
1390
/* Given a space of the form [A -> B] -> C, return the space B -> C.
1391
 */
1392
__isl_give isl_space *isl_space_domain_factor_range(
1393
  __isl_take isl_space *space)
1394
20.7k
{
1395
20.7k
  isl_space *nested;
1396
20.7k
  isl_space *range;
1397
20.7k
1398
20.7k
  if (!space)
1399
0
    return NULL;
1400
20.7k
  if (!isl_space_domain_is_wrapping(space))
1401
20.7k
    
isl_die0
(isl_space_get_ctx(space), isl_error_invalid,
1402
20.7k
      "domain not a product", return isl_space_free(space));
1403
20.7k
1404
20.7k
  nested = space->nested[0];
1405
20.7k
  range = isl_space_copy(space);
1406
20.7k
  range = isl_space_drop_dims(range, isl_dim_in, 0, nested->n_in);
1407
20.7k
  if (!range)
1408
0
    return isl_space_free(space);
1409
20.7k
  if (nested->tuple_id[1]) {
1410
12.4k
    range->tuple_id[0] = isl_id_copy(nested->tuple_id[1]);
1411
12.4k
    if (!range->tuple_id[0])
1412
0
      goto error;
1413
20.7k
  }
1414
20.7k
  if (nested->nested[1]) {
1415
8.21k
    range->nested[0] = isl_space_copy(nested->nested[1]);
1416
8.21k
    if (!range->nested[0])
1417
0
      goto error;
1418
20.7k
  }
1419
20.7k
1420
20.7k
  isl_space_free(space);
1421
20.7k
  return range;
1422
0
error:
1423
0
  isl_space_free(space);
1424
0
  isl_space_free(range);
1425
0
  return NULL;
1426
20.7k
}
1427
1428
/* Internal function that selects the domain of the map that is
1429
 * embedded in either a set space or the range of a map space.
1430
 * In particular, given a space of the form [A -> B], return the space A.
1431
 * Given a space of the form A -> [B -> C], return the space A -> B.
1432
 */
1433
static __isl_give isl_space *range_factor_domain(__isl_take isl_space *space)
1434
2.22k
{
1435
2.22k
  isl_space *nested;
1436
2.22k
  isl_space *domain;
1437
2.22k
1438
2.22k
  if (!space)
1439
0
    return NULL;
1440
2.22k
1441
2.22k
  nested = space->nested[1];
1442
2.22k
  domain = isl_space_copy(space);
1443
2.22k
  domain = isl_space_drop_dims(domain, isl_dim_out,
1444
2.22k
          nested->n_in, nested->n_out);
1445
2.22k
  if (!domain)
1446
0
    return isl_space_free(space);
1447
2.22k
  if (nested->tuple_id[0]) {
1448
1.26k
    domain->tuple_id[1] = isl_id_copy(nested->tuple_id[0]);
1449
1.26k
    if (!domain->tuple_id[1])
1450
0
      goto error;
1451
2.22k
  }
1452
2.22k
  if (nested->nested[0]) {
1453
940
    domain->nested[1] = isl_space_copy(nested->nested[0]);
1454
940
    if (!domain->nested[1])
1455
0
      goto error;
1456
2.22k
  }
1457
2.22k
1458
2.22k
  isl_space_free(space);
1459
2.22k
  return domain;
1460
0
error:
1461
0
  isl_space_free(space);
1462
0
  isl_space_free(domain);
1463
0
  return NULL;
1464
2.22k
}
1465
1466
/* Given a space of the form A -> [B -> C], return the space A -> B.
1467
 */
1468
__isl_give isl_space *isl_space_range_factor_domain(
1469
  __isl_take isl_space *space)
1470
2.22k
{
1471
2.22k
  if (!space)
1472
0
    return NULL;
1473
2.22k
  if (!isl_space_range_is_wrapping(space))
1474
2.22k
    
isl_die0
(isl_space_get_ctx(space), isl_error_invalid,
1475
2.22k
      "range not a product", return isl_space_free(space));
1476
2.22k
1477
2.22k
  return range_factor_domain(space);
1478
2.22k
}
1479
1480
/* Given a space of the form [A -> B], return the space A.
1481
 */
1482
static __isl_give isl_space *set_factor_domain(__isl_take isl_space *space)
1483
0
{
1484
0
  if (!space)
1485
0
    return NULL;
1486
0
  if (!isl_space_is_wrapping(space))
1487
0
    isl_die(isl_space_get_ctx(space), isl_error_invalid,
1488
0
      "not a product", return isl_space_free(space));
1489
0
1490
0
  return range_factor_domain(space);
1491
0
}
1492
1493
/* Given a space of the form [A -> B] -> [C -> D], return the space A -> C.
1494
 * Given a space of the form [A -> B], return the space A.
1495
 */
1496
__isl_give isl_space *isl_space_factor_domain(__isl_take isl_space *space)
1497
132
{
1498
132
  if (!space)
1499
0
    return NULL;
1500
132
  if (isl_space_is_set(space))
1501
0
    return set_factor_domain(space);
1502
132
  space = isl_space_domain_factor_domain(space);
1503
132
  space = isl_space_range_factor_domain(space);
1504
132
  return space;
1505
132
}
1506
1507
/* Internal function that selects the range of the map that is
1508
 * embedded in either a set space or the range of a map space.
1509
 * In particular, given a space of the form [A -> B], return the space B.
1510
 * Given a space of the form A -> [B -> C], return the space A -> C.
1511
 */
1512
static __isl_give isl_space *range_factor_range(__isl_take isl_space *space)
1513
13.4k
{
1514
13.4k
  isl_space *nested;
1515
13.4k
  isl_space *range;
1516
13.4k
1517
13.4k
  if (!space)
1518
0
    return NULL;
1519
13.4k
1520
13.4k
  nested = space->nested[1];
1521
13.4k
  range = isl_space_copy(space);
1522
13.4k
  range = isl_space_drop_dims(range, isl_dim_out, 0, nested->n_in);
1523
13.4k
  if (!range)
1524
0
    return isl_space_free(space);
1525
13.4k
  if (nested->tuple_id[1]) {
1526
744
    range->tuple_id[1] = isl_id_copy(nested->tuple_id[1]);
1527
744
    if (!range->tuple_id[1])
1528
0
      goto error;
1529
13.4k
  }
1530
13.4k
  if (nested->nested[1]) {
1531
12.6k
    range->nested[1] = isl_space_copy(nested->nested[1]);
1532
12.6k
    if (!range->nested[1])
1533
0
      goto error;
1534
13.4k
  }
1535
13.4k
1536
13.4k
  isl_space_free(space);
1537
13.4k
  return range;
1538
0
error:
1539
0
  isl_space_free(space);
1540
0
  isl_space_free(range);
1541
0
  return NULL;
1542
13.4k
}
1543
1544
/* Given a space of the form A -> [B -> C], return the space A -> C.
1545
 */
1546
__isl_give isl_space *isl_space_range_factor_range(
1547
  __isl_take isl_space *space)
1548
13.4k
{
1549
13.4k
  if (!space)
1550
0
    return NULL;
1551
13.4k
  if (!isl_space_range_is_wrapping(space))
1552
13.4k
    
isl_die0
(isl_space_get_ctx(space), isl_error_invalid,
1553
13.4k
      "range not a product", return isl_space_free(space));
1554
13.4k
1555
13.4k
  return range_factor_range(space);
1556
13.4k
}
1557
1558
/* Given a space of the form [A -> B], return the space B.
1559
 */
1560
static __isl_give isl_space *set_factor_range(__isl_take isl_space *space)
1561
9
{
1562
9
  if (!space)
1563
0
    return NULL;
1564
9
  if (!isl_space_is_wrapping(space))
1565
9
    
isl_die0
(isl_space_get_ctx(space), isl_error_invalid,
1566
9
      "not a product", return isl_space_free(space));
1567
9
1568
9
  return range_factor_range(space);
1569
9
}
1570
1571
/* Given a space of the form [A -> B] -> [C -> D], return the space B -> D.
1572
 * Given a space of the form [A -> B], return the space B.
1573
 */
1574
__isl_give isl_space *isl_space_factor_range(__isl_take isl_space *space)
1575
12.6k
{
1576
12.6k
  if (!space)
1577
0
    return NULL;
1578
12.6k
  if (isl_space_is_set(space))
1579
9
    return set_factor_range(space);
1580
12.6k
  space = isl_space_domain_factor_range(space);
1581
12.6k
  space = isl_space_range_factor_range(space);
1582
12.6k
  return space;
1583
12.6k
}
1584
1585
__isl_give isl_space *isl_space_map_from_set(__isl_take isl_space *space)
1586
13.2k
{
1587
13.2k
  isl_ctx *ctx;
1588
13.2k
  isl_id **ids = NULL;
1589
13.2k
  int n_id;
1590
13.2k
1591
13.2k
  if (!space)
1592
7
    return NULL;
1593
13.1k
  ctx = isl_space_get_ctx(space);
1594
13.1k
  if (!isl_space_is_set(space))
1595
13.1k
    
isl_die0
(ctx, isl_error_invalid, "not a set space", goto error);
1596
13.1k
  space = isl_space_cow(space);
1597
13.1k
  if (!space)
1598
0
    return NULL;
1599
13.1k
  n_id = space->nparam + space->n_out + space->n_out;
1600
13.1k
  if (n_id > 0 && 
space->ids12.6k
) {
1601
3.81k
    ids = isl_calloc_array(space->ctx, isl_id *, n_id);
1602
3.81k
    if (!ids)
1603
0
      goto error;
1604
3.81k
    get_ids(space, isl_dim_param, 0, space->nparam, ids);
1605
3.81k
    get_ids(space, isl_dim_out, 0, space->n_out,
1606
3.81k
      ids + space->nparam);
1607
3.81k
  }
1608
13.1k
  space->n_in = space->n_out;
1609
13.1k
  if (ids) {
1610
3.81k
    free(space->ids);
1611
3.81k
    space->ids = ids;
1612
3.81k
    space->n_id = n_id;
1613
3.81k
    space = copy_ids(space, isl_dim_out, 0, space, isl_dim_in);
1614
3.81k
  }
1615
13.1k
  isl_id_free(space->tuple_id[0]);
1616
13.1k
  space->tuple_id[0] = isl_id_copy(space->tuple_id[1]);
1617
13.1k
  isl_space_free(space->nested[0]);
1618
13.1k
  space->nested[0] = isl_space_copy(space->nested[1]);
1619
13.1k
  return space;
1620
0
error:
1621
0
  isl_space_free(space);
1622
0
  return NULL;
1623
13.1k
}
1624
1625
__isl_give isl_space *isl_space_map_from_domain_and_range(
1626
  __isl_take isl_space *domain, __isl_take isl_space *range)
1627
149k
{
1628
149k
  if (!domain || !range)
1629
0
    goto error;
1630
149k
  if (!isl_space_is_set(domain))
1631
149k
    
isl_die0
(isl_space_get_ctx(domain), isl_error_invalid,
1632
149k
      "domain is not a set space", goto error);
1633
149k
  if (!isl_space_is_set(range))
1634
149k
    
isl_die0
(isl_space_get_ctx(range), isl_error_invalid,
1635
149k
      "range is not a set space", goto error);
1636
149k
  return isl_space_join(isl_space_reverse(domain), range);
1637
0
error:
1638
0
  isl_space_free(domain);
1639
0
  isl_space_free(range);
1640
0
  return NULL;
1641
149k
}
1642
1643
static __isl_give isl_space *set_ids(__isl_take isl_space *dim,
1644
  enum isl_dim_type type,
1645
  unsigned first, unsigned n, __isl_take isl_id **ids)
1646
1.50M
{
1647
1.50M
  int i;
1648
1.50M
1649
3.76M
  for (i = 0; i < n ; 
++i2.25M
)
1650
2.25M
    dim = set_id(dim, type, first + i, ids[i]);
1651
1.50M
1652
1.50M
  return dim;
1653
1.50M
}
1654
1655
__isl_give isl_space *isl_space_reverse(__isl_take isl_space *dim)
1656
2.33M
{
1657
2.33M
  unsigned t;
1658
2.33M
  isl_space *nested;
1659
2.33M
  isl_id **ids = NULL;
1660
2.33M
  isl_id *id;
1661
2.33M
1662
2.33M
  if (!dim)
1663
1
    return NULL;
1664
2.33M
  if (match(dim, isl_dim_in, dim, isl_dim_out))
1665
171k
    return dim;
1666
2.16M
1667
2.16M
  dim = isl_space_cow(dim);
1668
2.16M
  if (!dim)
1669
0
    return NULL;
1670
2.16M
1671
2.16M
  id = dim->tuple_id[0];
1672
2.16M
  dim->tuple_id[0] = dim->tuple_id[1];
1673
2.16M
  dim->tuple_id[1] = id;
1674
2.16M
1675
2.16M
  nested = dim->nested[0];
1676
2.16M
  dim->nested[0] = dim->nested[1];
1677
2.16M
  dim->nested[1] = nested;
1678
2.16M
1679
2.16M
  if (dim->ids) {
1680
753k
    int n_id = dim->n_in + dim->n_out;
1681
753k
    ids = isl_alloc_array(dim->ctx, isl_id *, n_id);
1682
753k
    if (n_id && 
!ids634k
)
1683
0
      goto error;
1684
753k
    get_ids(dim, isl_dim_in, 0, dim->n_in, ids);
1685
753k
    get_ids(dim, isl_dim_out, 0, dim->n_out, ids + dim->n_in);
1686
753k
  }
1687
2.16M
1688
2.16M
  t = dim->n_in;
1689
2.16M
  dim->n_in = dim->n_out;
1690
2.16M
  dim->n_out = t;
1691
2.16M
1692
2.16M
  if (dim->ids) {
1693
753k
    dim = set_ids(dim, isl_dim_out, 0, dim->n_out, ids);
1694
753k
    dim = set_ids(dim, isl_dim_in, 0, dim->n_in, ids + dim->n_out);
1695
753k
    free(ids);
1696
753k
  }
1697
2.16M
1698
2.16M
  return dim;
1699
0
error:
1700
0
  free(ids);
1701
0
  isl_space_free(dim);
1702
0
  return NULL;
1703
2.16M
}
1704
1705
__isl_give isl_space *isl_space_drop_dims(__isl_take isl_space *dim,
1706
  enum isl_dim_type type, unsigned first, unsigned num)
1707
2.91M
{
1708
2.91M
  int i;
1709
2.91M
1710
2.91M
  if (!dim)
1711
2
    return NULL;
1712
2.91M
1713
2.91M
  if (num == 0)
1714
388k
    return isl_space_reset(dim, type);
1715
2.52M
1716
2.52M
  if (!valid_dim_type(type))
1717
2.52M
    
isl_die0
(dim->ctx, isl_error_invalid,
1718
2.52M
      "cannot drop dimensions of specified type", goto error);
1719
2.52M
1720
2.52M
  if (first + num > n(dim, type) || first + num < first)
1721
2.52M
    
isl_die0
(isl_space_get_ctx(dim), isl_error_invalid,
1722
2.52M
      "index out of bounds", return isl_space_free(dim));
1723
2.52M
  dim = isl_space_cow(dim);
1724
2.52M
  if (!dim)
1725
2
    goto error;
1726
2.52M
  if (dim->ids) {
1727
560k
    dim = extend_ids(dim);
1728
560k
    if (!dim)
1729
0
      goto error;
1730
1.89M
    
for (i = 0; 560k
i < num;
++i1.33M
)
1731
1.33M
      isl_id_free(get_id(dim, type, first + i));
1732
620k
    for (i = first+num; i < n(dim, type); 
++i59.9k
)
1733
59.9k
      set_id(dim, type, i - num, get_id(dim, type, i));
1734
560k
    switch (type) {
1735
560k
    case isl_dim_param:
1736
30.5k
      get_ids(dim, isl_dim_in, 0, dim->n_in,
1737
30.5k
        dim->ids + offset(dim, isl_dim_in) - num);
1738
182k
    case isl_dim_in:
1739
182k
      get_ids(dim, isl_dim_out, 0, dim->n_out,
1740
182k
        dim->ids + offset(dim, isl_dim_out) - num);
1741
560k
    default:
1742
560k
      ;
1743
560k
    }
1744
560k
    dim->n_id -= num;
1745
560k
  }
1746
2.52M
  switch (type) {
1747
2.52M
  
case isl_dim_param: dim->nparam -= num; break31.3k
;
1748
2.52M
  
case isl_dim_in: dim->n_in -= num; break439k
;
1749
2.52M
  
case isl_dim_out: dim->n_out -= num; break2.05M
;
1750
2.52M
  
default: ;0
1751
2.52M
  }
1752
2.52M
  dim = isl_space_reset(dim, type);
1753
2.52M
  if (type == isl_dim_param) {
1754
31.3k
    if (dim && dim->nested[0] &&
1755
31.3k
        !(dim->nested[0] = isl_space_drop_dims(dim->nested[0],
1756
122
                isl_dim_param, first, num)))
1757
0
      goto error;
1758
31.3k
    if (dim && dim->nested[1] &&
1759
31.3k
        !(dim->nested[1] = isl_space_drop_dims(dim->nested[1],
1760
673
                isl_dim_param, first, num)))
1761
0
      goto error;
1762
2.52M
  }
1763
2.52M
  return dim;
1764
2
error:
1765
2
  isl_space_free(dim);
1766
2
  return NULL;
1767
2.52M
}
1768
1769
__isl_give isl_space *isl_space_drop_inputs(__isl_take isl_space *dim,
1770
    unsigned first, unsigned n)
1771
0
{
1772
0
  if (!dim)
1773
0
    return NULL;
1774
0
  return isl_space_drop_dims(dim, isl_dim_in, first, n);
1775
0
}
1776
1777
__isl_give isl_space *isl_space_drop_outputs(__isl_take isl_space *dim,
1778
    unsigned first, unsigned n)
1779
0
{
1780
0
  if (!dim)
1781
0
    return NULL;
1782
0
  return isl_space_drop_dims(dim, isl_dim_out, first, n);
1783
0
}
1784
1785
__isl_give isl_space *isl_space_domain(__isl_take isl_space *space)
1786
893k
{
1787
893k
  if (!space)
1788
1
    return NULL;
1789
893k
  space = isl_space_drop_dims(space, isl_dim_out, 0, space->n_out);
1790
893k
  space = isl_space_reverse(space);
1791
893k
  space = mark_as_set(space);
1792
893k
  return space;
1793
893k
}
1794
1795
__isl_give isl_space *isl_space_from_domain(__isl_take isl_space *dim)
1796
670k
{
1797
670k
  if (!dim)
1798
2
    return NULL;
1799
670k
  if (!isl_space_is_set(dim))
1800
670k
    
isl_die0
(isl_space_get_ctx(dim), isl_error_invalid,
1801
670k
      "not a set space", goto error);
1802
670k
  dim = isl_space_reverse(dim);
1803
670k
  dim = isl_space_reset(dim, isl_dim_out);
1804
670k
  return dim;
1805
0
error:
1806
0
  isl_space_free(dim);
1807
0
  return NULL;
1808
670k
}
1809
1810
__isl_give isl_space *isl_space_range(__isl_take isl_space *space)
1811
381k
{
1812
381k
  if (!space)
1813
3
    return NULL;
1814
381k
  space = isl_space_drop_dims(space, isl_dim_in, 0, space->n_in);
1815
381k
  space = mark_as_set(space);
1816
381k
  return space;
1817
381k
}
1818
1819
__isl_give isl_space *isl_space_from_range(__isl_take isl_space *dim)
1820
304k
{
1821
304k
  if (!dim)
1822
5
    return NULL;
1823
304k
  if (!isl_space_is_set(dim))
1824
304k
    
isl_die0
(isl_space_get_ctx(dim), isl_error_invalid,
1825
304k
      "not a set space", goto error);
1826
304k
  return isl_space_reset(dim, isl_dim_in);
1827
0
error:
1828
0
  isl_space_free(dim);
1829
0
  return NULL;
1830
304k
}
1831
1832
/* Given a map space A -> B, return the map space [A -> B] -> A.
1833
 */
1834
__isl_give isl_space *isl_space_domain_map(__isl_take isl_space *space)
1835
1.91k
{
1836
1.91k
  isl_space *domain;
1837
1.91k
1838
1.91k
  domain = isl_space_from_range(isl_space_domain(isl_space_copy(space)));
1839
1.91k
  space = isl_space_from_domain(isl_space_wrap(space));
1840
1.91k
  space = isl_space_join(space, domain);
1841
1.91k
1842
1.91k
  return space;
1843
1.91k
}
1844
1845
/* Given a map space A -> B, return the map space [A -> B] -> B.
1846
 */
1847
__isl_give isl_space *isl_space_range_map(__isl_take isl_space *space)
1848
16
{
1849
16
  isl_space *range;
1850
16
1851
16
  range = isl_space_from_range(isl_space_range(isl_space_copy(space)));
1852
16
  space = isl_space_from_domain(isl_space_wrap(space));
1853
16
  space = isl_space_join(space, range);
1854
16
1855
16
  return space;
1856
16
}
1857
1858
__isl_give isl_space *isl_space_params(__isl_take isl_space *space)
1859
559k
{
1860
559k
  if (isl_space_is_params(space))
1861
387k
    return space;
1862
172k
  space = isl_space_drop_dims(space,
1863
172k
          isl_dim_in, 0, isl_space_dim(space, isl_dim_in));
1864
172k
  space = isl_space_drop_dims(space,
1865
172k
          isl_dim_out, 0, isl_space_dim(space, isl_dim_out));
1866
172k
  space = mark_as_params(space);
1867
172k
  return space;
1868
172k
}
1869
1870
__isl_give isl_space *isl_space_set_from_params(__isl_take isl_space *space)
1871
17.8k
{
1872
17.8k
  if (!space)
1873
0
    return NULL;
1874
17.8k
  if (!isl_space_is_params(space))
1875
17.8k
    
isl_die0
(isl_space_get_ctx(space), isl_error_invalid,
1876
17.8k
      "not a parameter space", goto error);
1877
17.8k
  return isl_space_reset(space, isl_dim_set);
1878
0
error:
1879
0
  isl_space_free(space);
1880
0
  return NULL;
1881
17.8k
}
1882
1883
__isl_give isl_space *isl_space_underlying(__isl_take isl_space *dim,
1884
  unsigned n_div)
1885
757k
{
1886
757k
  int i;
1887
757k
1888
757k
  if (!dim)
1889
0
    return NULL;
1890
757k
  if (n_div == 0 &&
1891
757k
      
dim->nparam == 0728k
&&
dim->n_in == 0526k
&&
dim->n_id == 0471k
)
1892
454k
    return isl_space_reset(isl_space_reset(dim, isl_dim_in), isl_dim_out);
1893
302k
  dim = isl_space_cow(dim);
1894
302k
  if (!dim)
1895
0
    return NULL;
1896
302k
  dim->n_out += dim->nparam + dim->n_in + n_div;
1897
302k
  dim->nparam = 0;
1898
302k
  dim->n_in = 0;
1899
302k
1900
1.71M
  for (i = 0; i < dim->n_id; 
++i1.41M
)
1901
1.41M
    isl_id_free(get_id(dim, isl_dim_out, i));
1902
302k
  dim->n_id = 0;
1903
302k
  dim = isl_space_reset(dim, isl_dim_in);
1904
302k
  dim = isl_space_reset(dim, isl_dim_out);
1905
302k
1906
302k
  return dim;
1907
302k
}
1908
1909
/* Are the two spaces the same, including positions and names of parameters?
1910
 */
1911
isl_bool isl_space_is_equal(__isl_keep isl_space *space1,
1912
  __isl_keep isl_space *space2)
1913
10.4M
{
1914
10.4M
  isl_bool equal;
1915
10.4M
1916
10.4M
  if (!space1 || !space2)
1917
1
    return isl_bool_error;
1918
10.4M
  if (space1 == space2)
1919
5.90M
    return isl_bool_true;
1920
4.59M
  equal = isl_space_has_equal_params(space1, space2);
1921
4.59M
  if (equal < 0 || !equal)
1922
71.8k
    return equal;
1923
4.52M
  return isl_space_has_equal_tuples(space1, space2);
1924
4.52M
}
1925
1926
/* Do the tuples of "space1" correspond to those of the domain of "space2"?
1927
 * That is, is "space1" eqaul to the domain of "space2", ignoring parameters.
1928
 *
1929
 * "space2" is allowed to be a set space, in which case "space1"
1930
 * should be a parameter space.
1931
 */
1932
isl_bool isl_space_has_domain_tuples(__isl_keep isl_space *space1,
1933
  __isl_keep isl_space *space2)
1934
108k
{
1935
108k
  isl_bool is_set;
1936
108k
1937
108k
  is_set = isl_space_is_set(space1);
1938
108k
  if (is_set < 0 || !is_set)
1939
0
    return is_set;
1940
108k
  return isl_space_tuple_is_equal(space1, isl_dim_set,
1941
108k
          space2, isl_dim_in);
1942
108k
}
1943
1944
/* Is space1 equal to the domain of space2?
1945
 *
1946
 * In the internal version we also allow space2 to be the space of a set,
1947
 * provided space1 is a parameter space.
1948
 */
1949
isl_bool isl_space_is_domain_internal(__isl_keep isl_space *space1,
1950
  __isl_keep isl_space *space2)
1951
108k
{
1952
108k
  isl_bool equal_params;
1953
108k
1954
108k
  if (!space1 || !space2)
1955
0
    return isl_bool_error;
1956
108k
  equal_params = isl_space_has_equal_params(space1, space2);
1957
108k
  if (equal_params < 0 || !equal_params)
1958
0
    return equal_params;
1959
108k
  return isl_space_has_domain_tuples(space1, space2);
1960
108k
}
1961
1962
/* Is space1 equal to the domain of space2?
1963
 */
1964
isl_bool isl_space_is_domain(__isl_keep isl_space *space1,
1965
  __isl_keep isl_space *space2)
1966
25
{
1967
25
  if (!space2)
1968
0
    return isl_bool_error;
1969
25
  if (!isl_space_is_map(space2))
1970
0
    return isl_bool_false;
1971
25
  return isl_space_is_domain_internal(space1, space2);
1972
25
}
1973
1974
/* Is space1 equal to the range of space2?
1975
 *
1976
 * In the internal version, space2 is allowed to be the space of a set,
1977
 * in which case it should be equal to space1.
1978
 */
1979
isl_bool isl_space_is_range_internal(__isl_keep isl_space *space1,
1980
  __isl_keep isl_space *space2)
1981
18.6k
{
1982
18.6k
  isl_bool equal_params;
1983
18.6k
1984
18.6k
  if (!space1 || !space2)
1985
0
    return isl_bool_error;
1986
18.6k
  if (!isl_space_is_set(space1))
1987
0
    return isl_bool_false;
1988
18.6k
  equal_params = isl_space_has_equal_params(space1, space2);
1989
18.6k
  if (equal_params < 0 || !equal_params)
1990
0
    return equal_params;
1991
18.6k
  return isl_space_tuple_is_equal(space1, isl_dim_set,
1992
18.6k
          space2, isl_dim_out);
1993
18.6k
}
1994
1995
/* Is space1 equal to the range of space2?
1996
 */
1997
isl_bool isl_space_is_range(__isl_keep isl_space *space1,
1998
  __isl_keep isl_space *space2)
1999
0
{
2000
0
  if (!space2)
2001
0
    return isl_bool_error;
2002
0
  if (!isl_space_is_map(space2))
2003
0
    return isl_bool_false;
2004
0
  return isl_space_is_range_internal(space1, space2);
2005
0
}
2006
2007
/* Update "hash" by hashing in the parameters of "space".
2008
 */
2009
static uint32_t isl_hash_params(uint32_t hash, __isl_keep isl_space *space)
2010
559k
{
2011
559k
  int i;
2012
559k
  isl_id *id;
2013
559k
2014
559k
  if (!space)
2015
0
    return hash;
2016
559k
2017
559k
  isl_hash_byte(hash, space->nparam % 256);
2018
559k
2019
1.30M
  for (i = 0; i < space->nparam; 
++i745k
) {
2020
745k
    id = get_id(space, isl_dim_param, i);
2021
745k
    hash = isl_hash_id(hash, id);
2022
745k
  }
2023
559k
2024
559k
  return hash;
2025
559k
}
2026
2027
/* Update "hash" by hashing in the tuples of "space".
2028
 * Changes in this function should be reflected in isl_hash_tuples_domain.
2029
 */
2030
static uint32_t isl_hash_tuples(uint32_t hash, __isl_keep isl_space *space)
2031
2.17M
{
2032
2.17M
  isl_id *id;
2033
2.17M
2034
2.17M
  if (!space)
2035
1.36M
    return hash;
2036
804k
2037
804k
  isl_hash_byte(hash, space->n_in % 256);
2038
804k
  isl_hash_byte(hash, space->n_out % 256);
2039
804k
2040
804k
  id = tuple_id(space, isl_dim_in);
2041
804k
  hash = isl_hash_id(hash, id);
2042
804k
  id = tuple_id(space, isl_dim_out);
2043
804k
  hash = isl_hash_id(hash, id);
2044
804k
2045
804k
  hash = isl_hash_tuples(hash, space->nested[0]);
2046
804k
  hash = isl_hash_tuples(hash, space->nested[1]);
2047
804k
2048
804k
  return hash;
2049
804k
}
2050
2051
/* Update "hash" by hashing in the domain tuple of "space".
2052
 * The result of this function is equal to the result of applying
2053
 * isl_hash_tuples to the domain of "space".
2054
 */
2055
static uint32_t isl_hash_tuples_domain(uint32_t hash,
2056
  __isl_keep isl_space *space)
2057
47.1k
{
2058
47.1k
  isl_id *id;
2059
47.1k
2060
47.1k
  if (!space)
2061
0
    return hash;
2062
47.1k
2063
47.1k
  isl_hash_byte(hash, 0);
2064
47.1k
  isl_hash_byte(hash, space->n_in % 256);
2065
47.1k
2066
47.1k
  hash = isl_hash_id(hash, &isl_id_none);
2067
47.1k
  id = tuple_id(space, isl_dim_in);
2068
47.1k
  hash = isl_hash_id(hash, id);
2069
47.1k
2070
47.1k
  hash = isl_hash_tuples(hash, space->nested[0]);
2071
47.1k
2072
47.1k
  return hash;
2073
47.1k
}
2074
2075
/* Return a hash value that digests the tuples of "space",
2076
 * i.e., that ignores the parameters.
2077
 */
2078
uint32_t isl_space_get_tuple_hash(__isl_keep isl_space *space)
2079
2.24k
{
2080
2.24k
  uint32_t hash;
2081
2.24k
2082
2.24k
  if (!space)
2083
0
    return 0;
2084
2.24k
2085
2.24k
  hash = isl_hash_init();
2086
2.24k
  hash = isl_hash_tuples(hash, space);
2087
2.24k
2088
2.24k
  return hash;
2089
2.24k
}
2090
2091
uint32_t isl_space_get_hash(__isl_keep isl_space *space)
2092
512k
{
2093
512k
  uint32_t hash;
2094
512k
2095
512k
  if (!space)
2096
0
    return 0;
2097
512k
2098
512k
  hash = isl_hash_init();
2099
512k
  hash = isl_hash_params(hash, space);
2100
512k
  hash = isl_hash_tuples(hash, space);
2101
512k
2102
512k
  return hash;
2103
512k
}
2104
2105
/* Return the hash value of the domain of "space".
2106
 * That is, isl_space_get_domain_hash(space) is equal to
2107
 * isl_space_get_hash(isl_space_domain(space)).
2108
 */
2109
uint32_t isl_space_get_domain_hash(__isl_keep isl_space *space)
2110
47.1k
{
2111
47.1k
  uint32_t hash;
2112
47.1k
2113
47.1k
  if (!space)
2114
0
    return 0;
2115
47.1k
2116
47.1k
  hash = isl_hash_init();
2117
47.1k
  hash = isl_hash_params(hash, space);
2118
47.1k
  hash = isl_hash_tuples_domain(hash, space);
2119
47.1k
2120
47.1k
  return hash;
2121
47.1k
}
2122
2123
isl_bool isl_space_is_wrapping(__isl_keep isl_space *dim)
2124
58.4k
{
2125
58.4k
  if (!dim)
2126
0
    return isl_bool_error;
2127
58.4k
2128
58.4k
  if (!isl_space_is_set(dim))
2129
0
    return isl_bool_false;
2130
58.4k
2131
58.4k
  return dim->nested[1] != NULL;
2132
58.4k
}
2133
2134
/* Is "space" the space of a map where the domain is a wrapped map space?
2135
 */
2136
isl_bool isl_space_domain_is_wrapping(__isl_keep isl_space *space)
2137
50.1k
{
2138
50.1k
  if (!space)
2139
0
    return isl_bool_error;
2140
50.1k
2141
50.1k
  if (isl_space_is_set(space))
2142
0
    return isl_bool_false;
2143
50.1k
2144
50.1k
  return space->nested[0] != NULL;
2145
50.1k
}
2146
2147
/* Is "space" the space of a map where the range is a wrapped map space?
2148
 */
2149
isl_bool isl_space_range_is_wrapping(__isl_keep isl_space *space)
2150
66.7k
{
2151
66.7k
  if (!space)
2152
0
    return isl_bool_error;
2153
66.7k
2154
66.7k
  if (isl_space_is_set(space))
2155
785
    return isl_bool_false;
2156
65.9k
2157
65.9k
  return space->nested[1] != NULL;
2158
65.9k
}
2159
2160
/* Is "space" a product of two spaces?
2161
 * That is, is it a wrapping set space or a map space
2162
 * with wrapping domain and range?
2163
 */
2164
isl_bool isl_space_is_product(__isl_keep isl_space *space)
2165
6.23k
{
2166
6.23k
  isl_bool is_set;
2167
6.23k
  isl_bool is_product;
2168
6.23k
2169
6.23k
  is_set = isl_space_is_set(space);
2170
6.23k
  if (is_set < 0)
2171
0
    return isl_bool_error;
2172
6.23k
  if (is_set)
2173
0
    return isl_space_is_wrapping(space);
2174
6.23k
  is_product = isl_space_domain_is_wrapping(space);
2175
6.23k
  if (is_product < 0 || !is_product)
2176
35
    return is_product;
2177
6.20k
  return isl_space_range_is_wrapping(space);
2178
6.20k
}
2179
2180
__isl_give isl_space *isl_space_wrap(__isl_take isl_space *dim)
2181
218k
{
2182
218k
  isl_space *wrap;
2183
218k
2184
218k
  if (!dim)
2185
1
    return NULL;
2186
218k
2187
218k
  wrap = isl_space_set_alloc(dim->ctx,
2188
218k
            dim->nparam, dim->n_in + dim->n_out);
2189
218k
2190
218k
  wrap = copy_ids(wrap, isl_dim_param, 0, dim, isl_dim_param);
2191
218k
  wrap = copy_ids(wrap, isl_dim_set, 0, dim, isl_dim_in);
2192
218k
  wrap = copy_ids(wrap, isl_dim_set, dim->n_in, dim, isl_dim_out);
2193
218k
2194
218k
  if (!wrap)
2195
0
    goto error;
2196
218k
2197
218k
  wrap->nested[1] = dim;
2198
218k
2199
218k
  return wrap;
2200
0
error:
2201
0
  isl_space_free(dim);
2202
0
  return NULL;
2203
218k
}
2204
2205
__isl_give isl_space *isl_space_unwrap(__isl_take isl_space *dim)
2206
40.3k
{
2207
40.3k
  isl_space *unwrap;
2208
40.3k
2209
40.3k
  if (!dim)
2210
1
    return NULL;
2211
40.3k
2212
40.3k
  if (!isl_space_is_wrapping(dim))
2213
40.3k
    
isl_die0
(dim->ctx, isl_error_invalid, "not a wrapping space",
2214
40.3k
      goto error);
2215
40.3k
2216
40.3k
  unwrap = isl_space_copy(dim->nested[1]);
2217
40.3k
  isl_space_free(dim);
2218
40.3k
2219
40.3k
  return unwrap;
2220
0
error:
2221
0
  isl_space_free(dim);
2222
0
  return NULL;
2223
40.3k
}
2224
2225
isl_bool isl_space_is_named_or_nested(__isl_keep isl_space *space,
2226
  enum isl_dim_type type)
2227
7.41M
{
2228
7.41M
  if (type != isl_dim_in && 
type != isl_dim_out5.14M
)
2229
210k
    return isl_bool_false;
2230
7.20M
  if (!space)
2231
9
    return isl_bool_error;
2232
7.20M
  if (space->tuple_id[type - isl_dim_in])
2233
3.05M
    return isl_bool_true;
2234
4.15M
  if (space->nested[type - isl_dim_in])
2235
1.25M
    return isl_bool_true;
2236
2.90M
  return isl_bool_false;
2237
2.90M
}
2238
2239
isl_bool isl_space_may_be_set(__isl_keep isl_space *space)
2240
278
{
2241
278
  isl_bool nested;
2242
278
2243
278
  if (!space)
2244
0
    return isl_bool_error;
2245
278
  if (isl_space_is_set(space))
2246
173
    return isl_bool_true;
2247
105
  if (isl_space_dim(space, isl_dim_in) != 0)
2248
0
    return isl_bool_false;
2249
105
  nested = isl_space_is_named_or_nested(space, isl_dim_in);
2250
105
  if (nested < 0 || nested)
2251
0
    return isl_bool_not(nested);
2252
105
  return isl_bool_true;
2253
105
}
2254
2255
__isl_give isl_space *isl_space_reset(__isl_take isl_space *dim,
2256
  enum isl_dim_type type)
2257
6.53M
{
2258
6.53M
  if (!isl_space_is_named_or_nested(dim, type))
2259
2.73M
    return dim;
2260
3.79M
2261
3.79M
  dim = isl_space_cow(dim);
2262
3.79M
  if (!dim)
2263
19
    return NULL;
2264
3.79M
2265
3.79M
  isl_id_free(dim->tuple_id[type - isl_dim_in]);
2266
3.79M
  dim->tuple_id[type - isl_dim_in] = NULL;
2267
3.79M
  isl_space_free(dim->nested[type - isl_dim_in]);
2268
3.79M
  dim->nested[type - isl_dim_in] = NULL;
2269
3.79M
2270
3.79M
  return dim;
2271
3.79M
}
2272
2273
__isl_give isl_space *isl_space_flatten(__isl_take isl_space *dim)
2274
23.2k
{
2275
23.2k
  if (!dim)
2276
0
    return NULL;
2277
23.2k
  if (!dim->nested[0] && !dim->nested[1])
2278
0
    return dim;
2279
23.2k
2280
23.2k
  if (dim->nested[0])
2281
0
    dim = isl_space_reset(dim, isl_dim_in);
2282
23.2k
  if (dim && dim->nested[1])
2283
23.2k
    dim = isl_space_reset(dim, isl_dim_out);
2284
23.2k
2285
23.2k
  return dim;
2286
23.2k
}
2287
2288
__isl_give isl_space *isl_space_flatten_domain(__isl_take isl_space *space)
2289
36
{
2290
36
  if (!space)
2291
0
    return NULL;
2292
36
  if (!space->nested[0])
2293
0
    return space;
2294
36
2295
36
  return isl_space_reset(space, isl_dim_in);
2296
36
}
2297
2298
__isl_give isl_space *isl_space_flatten_range(__isl_take isl_space *space)
2299
79.4k
{
2300
79.4k
  if (!space)
2301
0
    return NULL;
2302
79.4k
  if (!space->nested[1])
2303
0
    return space;
2304
79.4k
2305
79.4k
  return isl_space_reset(space, isl_dim_out);
2306
79.4k
}
2307
2308
/* Replace the parameters of dst by those of src.
2309
 */
2310
__isl_give isl_space *isl_space_replace_params(__isl_take isl_space *dst,
2311
  __isl_keep isl_space *src)
2312
125k
{
2313
125k
  isl_bool equal_params;
2314
125k
  enum isl_dim_type type = isl_dim_param;
2315
125k
2316
125k
  equal_params = isl_space_has_equal_params(dst, src);
2317
125k
  if (equal_params < 0)
2318
0
    return isl_space_free(dst);
2319
125k
  if (equal_params)
2320
58.7k
    return dst;
2321
66.5k
2322
66.5k
  dst = isl_space_cow(dst);
2323
66.5k
2324
66.5k
  if (!dst || !src)
2325
0
    goto error;
2326
66.5k
2327
66.5k
  dst = isl_space_drop_dims(dst, type, 0, isl_space_dim(dst, type));
2328
66.5k
  dst = isl_space_add_dims(dst, type, isl_space_dim(src, type));
2329
66.5k
  dst = copy_ids(dst, type, 0, src, type);
2330
66.5k
2331
66.5k
  if (dst) {
2332
66.5k
    int i;
2333
199k
    for (i = 0; i <= 1; 
++i133k
) {
2334
133k
      if (!dst->nested[i])
2335
132k
        continue;
2336
544
      dst->nested[i] = isl_space_replace_params(
2337
544
              dst->nested[i], src);
2338
544
      if (!dst->nested[i])
2339
0
        goto error;
2340
544
    }
2341
66.5k
  }
2342
66.5k
2343
66.5k
  return dst;
2344
0
error:
2345
0
  isl_space_free(dst);
2346
0
  return NULL;
2347
66.5k
}
2348
2349
/* Given a dimension specification "dim" of a set, create a dimension
2350
 * specification for the lift of the set.  In particular, the result
2351
 * is of the form [dim -> local[..]], with n_local variables in the
2352
 * range of the wrapped map.
2353
 */
2354
__isl_give isl_space *isl_space_lift(__isl_take isl_space *dim, unsigned n_local)
2355
20.8k
{
2356
20.8k
  isl_space *local_dim;
2357
20.8k
2358
20.8k
  if (!dim)
2359
0
    return NULL;
2360
20.8k
2361
20.8k
  local_dim = isl_space_dup(dim);
2362
20.8k
  local_dim = isl_space_drop_dims(local_dim, isl_dim_set, 0, dim->n_out);
2363
20.8k
  local_dim = isl_space_add_dims(local_dim, isl_dim_set, n_local);
2364
20.8k
  local_dim = isl_space_set_tuple_name(local_dim, isl_dim_set, "local");
2365
20.8k
  dim = isl_space_join(isl_space_from_domain(dim),
2366
20.8k
          isl_space_from_range(local_dim));
2367
20.8k
  dim = isl_space_wrap(dim);
2368
20.8k
  dim = isl_space_set_tuple_name(dim, isl_dim_set, "lifted");
2369
20.8k
2370
20.8k
  return dim;
2371
20.8k
}
2372
2373
isl_bool isl_space_can_zip(__isl_keep isl_space *space)
2374
6.14k
{
2375
6.14k
  isl_bool is_set;
2376
6.14k
2377
6.14k
  is_set = isl_space_is_set(space);
2378
6.14k
  if (is_set < 0)
2379
0
    return isl_bool_error;
2380
6.14k
  if (is_set)
2381
0
    return isl_bool_false;
2382
6.14k
  return isl_space_is_product(space);
2383
6.14k
}
2384
2385
__isl_give isl_space *isl_space_zip(__isl_take isl_space *dim)
2386
2.63k
{
2387
2.63k
  isl_space *dom, *ran;
2388
2.63k
  isl_space *dom_dom, *dom_ran, *ran_dom, *ran_ran;
2389
2.63k
2390
2.63k
  if (!isl_space_can_zip(dim))
2391
2.63k
    
isl_die0
(dim->ctx, isl_error_invalid, "dim cannot be zipped",
2392
2.63k
      goto error);
2393
2.63k
2394
2.63k
  if (!dim)
2395
0
    return NULL;
2396
2.63k
  dom = isl_space_unwrap(isl_space_domain(isl_space_copy(dim)));
2397
2.63k
  ran = isl_space_unwrap(isl_space_range(dim));
2398
2.63k
  dom_dom = isl_space_domain(isl_space_copy(dom));
2399
2.63k
  dom_ran = isl_space_range(dom);
2400
2.63k
  ran_dom = isl_space_domain(isl_space_copy(ran));
2401
2.63k
  ran_ran = isl_space_range(ran);
2402
2.63k
  dom = isl_space_join(isl_space_from_domain(dom_dom),
2403
2.63k
         isl_space_from_range(ran_dom));
2404
2.63k
  ran = isl_space_join(isl_space_from_domain(dom_ran),
2405
2.63k
         isl_space_from_range(ran_ran));
2406
2.63k
  return isl_space_join(isl_space_from_domain(isl_space_wrap(dom)),
2407
2.63k
          isl_space_from_range(isl_space_wrap(ran)));
2408
0
error:
2409
0
  isl_space_free(dim);
2410
0
  return NULL;
2411
2.63k
}
2412
2413
/* Can we apply isl_space_curry to "space"?
2414
 * That is, does it have a nested relation in its domain?
2415
 */
2416
isl_bool isl_space_can_curry(__isl_keep isl_space *space)
2417
41.4k
{
2418
41.4k
  if (!space)
2419
0
    return isl_bool_error;
2420
41.4k
2421
41.4k
  return !!space->nested[0];
2422
41.4k
}
2423
2424
/* Given a space (A -> B) -> C, return the corresponding space
2425
 * A -> (B -> C).
2426
 */
2427
__isl_give isl_space *isl_space_curry(__isl_take isl_space *space)
2428
13.4k
{
2429
13.4k
  isl_space *dom, *ran;
2430
13.4k
  isl_space *dom_dom, *dom_ran;
2431
13.4k
2432
13.4k
  if (!space)
2433
0
    return NULL;
2434
13.4k
2435
13.4k
  if (!isl_space_can_curry(space))
2436
13.4k
    
isl_die0
(space->ctx, isl_error_invalid,
2437
13.4k
      "space cannot be curried", goto error);
2438
13.4k
2439
13.4k
  dom = isl_space_unwrap(isl_space_domain(isl_space_copy(space)));
2440
13.4k
  ran = isl_space_range(space);
2441
13.4k
  dom_dom = isl_space_domain(isl_space_copy(dom));
2442
13.4k
  dom_ran = isl_space_range(dom);
2443
13.4k
  ran = isl_space_join(isl_space_from_domain(dom_ran),
2444
13.4k
         isl_space_from_range(ran));
2445
13.4k
  return isl_space_join(isl_space_from_domain(dom_dom),
2446
13.4k
          isl_space_from_range(isl_space_wrap(ran)));
2447
0
error:
2448
0
  isl_space_free(space);
2449
0
  return NULL;
2450
13.4k
}
2451
2452
/* Can isl_space_range_curry be applied to "space"?
2453
 * That is, does it have a nested relation in its range,
2454
 * the domain of which is itself a nested relation?
2455
 */
2456
isl_bool isl_space_can_range_curry(__isl_keep isl_space *space)
2457
25.4k
{
2458
25.4k
  isl_bool can;
2459
25.4k
2460
25.4k
  if (!space)
2461
0
    return isl_bool_error;
2462
25.4k
  can = isl_space_range_is_wrapping(space);
2463
25.4k
  if (can < 0 || !can)
2464
0
    return can;
2465
25.4k
  return isl_space_can_curry(space->nested[1]);
2466
25.4k
}
2467
2468
/* Given a space A -> ((B -> C) -> D), return the corresponding space
2469
 * A -> (B -> (C -> D)).
2470
 */
2471
__isl_give isl_space *isl_space_range_curry(__isl_take isl_space *space)
2472
12.6k
{
2473
12.6k
  if (!space)
2474
0
    return NULL;
2475
12.6k
2476
12.6k
  if (!isl_space_can_range_curry(space))
2477
12.6k
    
isl_die0
(isl_space_get_ctx(space), isl_error_invalid,
2478
12.6k
      "space range cannot be curried",
2479
12.6k
      return isl_space_free(space));
2480
12.6k
2481
12.6k
  space = isl_space_cow(space);
2482
12.6k
  if (!space)
2483
0
    return NULL;
2484
12.6k
  space->nested[1] = isl_space_curry(space->nested[1]);
2485
12.6k
  if (!space->nested[1])
2486
0
    return isl_space_free(space);
2487
12.6k
2488
12.6k
  return space;
2489
12.6k
}
2490
2491
/* Can we apply isl_space_uncurry to "space"?
2492
 * That is, does it have a nested relation in its range?
2493
 */
2494
isl_bool isl_space_can_uncurry(__isl_keep isl_space *space)
2495
1.71k
{
2496
1.71k
  if (!space)
2497
0
    return isl_bool_error;
2498
1.71k
2499
1.71k
  return !!space->nested[1];
2500
1.71k
}
2501
2502
/* Given a space A -> (B -> C), return the corresponding space
2503
 * (A -> B) -> C.
2504
 */
2505
__isl_give isl_space *isl_space_uncurry(__isl_take isl_space *space)
2506
601
{
2507
601
  isl_space *dom, *ran;
2508
601
  isl_space *ran_dom, *ran_ran;
2509
601
2510
601
  if (!space)
2511
0
    return NULL;
2512
601
2513
601
  if (!isl_space_can_uncurry(space))
2514
601
    
isl_die0
(space->ctx, isl_error_invalid,
2515
601
      "space cannot be uncurried",
2516
601
      return isl_space_free(space));
2517
601
2518
601
  dom = isl_space_domain(isl_space_copy(space));
2519
601
  ran = isl_space_unwrap(isl_space_range(space));
2520
601
  ran_dom = isl_space_domain(isl_space_copy(ran));
2521
601
  ran_ran = isl_space_range(ran);
2522
601
  dom = isl_space_join(isl_space_from_domain(dom),
2523
601
         isl_space_from_range(ran_dom));
2524
601
  return isl_space_join(isl_space_from_domain(isl_space_wrap(dom)),
2525
601
          isl_space_from_range(ran_ran));
2526
601
}
2527
2528
isl_bool isl_space_has_named_params(__isl_keep isl_space *space)
2529
532k
{
2530
532k
  int i;
2531
532k
  unsigned off;
2532
532k
2533
532k
  if (!space)
2534
2
    return isl_bool_error;
2535
532k
  if (space->nparam == 0)
2536
257k
    return isl_bool_true;
2537
275k
  off = isl_space_offset(space, isl_dim_param);
2538
275k
  if (off + space->nparam > space->n_id)
2539
0
    return isl_bool_false;
2540
1.10M
  
for (i = 0; 275k
i < space->nparam;
++i834k
)
2541
834k
    if (!space->ids[off + i])
2542
0
      return isl_bool_false;
2543
275k
  return isl_bool_true;
2544
275k
}
2545
2546
/* Check that "space" has only named parameters, reporting an error
2547
 * if it does not.
2548
 */
2549
isl_stat isl_space_check_named_params(__isl_keep isl_space *space)
2550
342k
{
2551
342k
  isl_bool named;
2552
342k
2553
342k
  named = isl_space_has_named_params(space);
2554
342k
  if (named < 0)
2555
2
    return isl_stat_error;
2556
342k
  if (!named)
2557
342k
    
isl_die0
(isl_space_get_ctx(space), isl_error_invalid,
2558
342k
      "unexpected unnamed parameters", return isl_stat_error);
2559
342k
2560
342k
  return isl_stat_ok;
2561
342k
}
2562
2563
/* Align the initial parameters of space1 to match the order in space2.
2564
 */
2565
__isl_give isl_space *isl_space_align_params(__isl_take isl_space *space1,
2566
  __isl_take isl_space *space2)
2567
36.2k
{
2568
36.2k
  isl_reordering *exp;
2569
36.2k
2570
36.2k
  if (isl_space_check_named_params(space1) < 0 ||
2571
36.2k
      
isl_space_check_named_params(space2) < 036.2k
)
2572
2
    goto error;
2573
36.2k
2574
36.2k
  exp = isl_parameter_alignment_reordering(space1, space2);
2575
36.2k
  exp = isl_reordering_extend_space(exp, space1);
2576
36.2k
  isl_space_free(space2);
2577
36.2k
  space1 = isl_reordering_get_space(exp);
2578
36.2k
  isl_reordering_free(exp);
2579
36.2k
  return space1;
2580
2
error:
2581
2
  isl_space_free(space1);
2582
2
  isl_space_free(space2);
2583
2
  return NULL;
2584
36.2k
}
2585
2586
/* Given the space of set (domain), construct a space for a map
2587
 * with as domain the given space and as range the range of "model".
2588
 */
2589
__isl_give isl_space *isl_space_extend_domain_with_range(
2590
  __isl_take isl_space *space, __isl_take isl_space *model)
2591
75.7k
{
2592
75.7k
  if (!model)
2593
0
    goto error;
2594
75.7k
2595
75.7k
  space = isl_space_from_domain(space);
2596
75.7k
  space = isl_space_add_dims(space, isl_dim_out,
2597
75.7k
            isl_space_dim(model, isl_dim_out));
2598
75.7k
  if (isl_space_has_tuple_id(model, isl_dim_out))
2599
125
    space = isl_space_set_tuple_id(space, isl_dim_out,
2600
125
        isl_space_get_tuple_id(model, isl_dim_out));
2601
75.7k
  if (!space)
2602
0
    goto error;
2603
75.7k
  if (model->nested[1]) {
2604
1
    isl_space *nested = isl_space_copy(model->nested[1]);
2605
1
    int n_nested, n_space;
2606
1
    nested = isl_space_align_params(nested, isl_space_copy(space));
2607
1
    n_nested = isl_space_dim(nested, isl_dim_param);
2608
1
    n_space = isl_space_dim(space, isl_dim_param);
2609
1
    if (n_nested > n_space)
2610
0
      nested = isl_space_drop_dims(nested, isl_dim_param,
2611
0
            n_space, n_nested - n_space);
2612
1
    if (!nested)
2613
0
      goto error;
2614
1
    space->nested[1] = nested;
2615
1
  }
2616
75.7k
  isl_space_free(model);
2617
75.7k
  return space;
2618
0
error:
2619
0
  isl_space_free(model);
2620
0
  isl_space_free(space);
2621
0
  return NULL;
2622
75.7k
}
2623
2624
/* Compare the "type" dimensions of two isl_spaces.
2625
 *
2626
 * The order is fairly arbitrary.
2627
 */
2628
static int isl_space_cmp_type(__isl_keep isl_space *space1,
2629
  __isl_keep isl_space *space2, enum isl_dim_type type)
2630
2.42M
{
2631
2.42M
  int cmp;
2632
2.42M
  isl_space *nested1, *nested2;
2633
2.42M
2634
2.42M
  if (isl_space_dim(space1, type) != isl_space_dim(space2, type))
2635
0
    return isl_space_dim(space1, type) -
2636
0
      isl_space_dim(space2, type);
2637
2.42M
2638
2.42M
  cmp = isl_id_cmp(tuple_id(space1, type), tuple_id(space2, type));
2639
2.42M
  if (cmp != 0)
2640
0
    return cmp;
2641
2.42M
2642
2.42M
  nested1 = nested(space1, type);
2643
2.42M
  nested2 = nested(space2, type);
2644
2.42M
  if (!nested1 != !nested2)
2645
0
    return !nested1 - !nested2;
2646
2.42M
2647
2.42M
  if (nested1)
2648
416k
    return isl_space_cmp(nested1, nested2);
2649
2.00M
2650
2.00M
  return 0;
2651
2.00M
}
2652
2653
/* Compare two isl_spaces.
2654
 *
2655
 * The order is fairly arbitrary.
2656
 */
2657
int isl_space_cmp(__isl_keep isl_space *space1, __isl_keep isl_space *space2)
2658
2.24M
{
2659
2.24M
  int i;
2660
2.24M
  int cmp;
2661
2.24M
2662
2.24M
  if (space1 == space2)
2663
1.43M
    return 0;
2664
807k
  if (!space1)
2665
0
    return -1;
2666
807k
  if (!space2)
2667
0
    return 1;
2668
807k
2669
807k
  cmp = isl_space_cmp_type(space1, space2, isl_dim_param);
2670
807k
  if (cmp != 0)
2671
0
    return cmp;
2672
807k
  cmp = isl_space_cmp_type(space1, space2, isl_dim_in);
2673
807k
  if (cmp != 0)
2674
0
    return cmp;
2675
807k
  cmp = isl_space_cmp_type(space1, space2, isl_dim_out);
2676
807k
  if (cmp != 0)
2677
0
    return cmp;
2678
807k
2679
807k
  if (!space1->ids && 
!space2->ids360k
)
2680
360k
    return 0;
2681
446k
2682
3.95M
  
for (i = 0; 446k
i < n(space1, isl_dim_param);
++i3.51M
) {
2683
3.51M
    cmp = isl_id_cmp(get_id(space1, isl_dim_param, i),
2684
3.51M
         get_id(space2, isl_dim_param, i));
2685
3.51M
    if (cmp != 0)
2686
0
      return cmp;
2687
3.51M
  }
2688
446k
2689
446k
  return 0;
2690
446k
}