nexmon – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | /* |
2 | * Copyright 2008-2009 Katholieke Universiteit Leuven |
||
3 | * Copyright 2010 INRIA Saclay |
||
4 | * |
||
5 | * Use of this software is governed by the GNU LGPLv2.1 license |
||
6 | * |
||
7 | * Written by Sven Verdoolaege, K.U.Leuven, Departement |
||
8 | * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium |
||
9 | * and INRIA Saclay - Ile-de-France, Parc Club Orsay Universite, |
||
10 | * ZAC des vignes, 4 rue Jacques Monod, 91893 Orsay, France |
||
11 | */ |
||
12 | |||
13 | #include <stdlib.h> |
||
14 | #include <isl_space_private.h> |
||
15 | #include <isl_id_private.h> |
||
16 | #include <isl_reordering.h> |
||
17 | |||
18 | isl_ctx *isl_space_get_ctx(__isl_keep isl_space *dim) |
||
19 | { |
||
20 | return dim ? dim->ctx : NULL; |
||
21 | } |
||
22 | |||
23 | __isl_give isl_space *isl_space_alloc(isl_ctx *ctx, |
||
24 | unsigned nparam, unsigned n_in, unsigned n_out) |
||
25 | { |
||
26 | isl_space *dim; |
||
27 | |||
28 | dim = isl_alloc_type(ctx, struct isl_space); |
||
29 | if (!dim) |
||
30 | return NULL; |
||
31 | |||
32 | dim->ctx = ctx; |
||
33 | isl_ctx_ref(ctx); |
||
34 | dim->ref = 1; |
||
35 | dim->nparam = nparam; |
||
36 | dim->n_in = n_in; |
||
37 | dim->n_out = n_out; |
||
38 | |||
39 | dim->tuple_id[0] = NULL; |
||
40 | dim->tuple_id[1] = NULL; |
||
41 | |||
42 | dim->nested[0] = NULL; |
||
43 | dim->nested[1] = NULL; |
||
44 | |||
45 | dim->n_id = 0; |
||
46 | dim->ids = NULL; |
||
47 | |||
48 | return dim; |
||
49 | } |
||
50 | |||
51 | /* Mark the space as being that of a set, by setting the domain tuple |
||
52 | * to isl_id_none. |
||
53 | */ |
||
54 | static __isl_give isl_space *mark_as_set(__isl_take isl_space *space) |
||
55 | { |
||
56 | space = isl_space_cow(space); |
||
57 | if (!space) |
||
58 | return NULL; |
||
59 | space = isl_space_set_tuple_id(space, isl_dim_in, &isl_id_none); |
||
60 | return space; |
||
61 | } |
||
62 | |||
63 | /* Is the space that of a set? |
||
64 | */ |
||
65 | int isl_space_is_set(__isl_keep isl_space *space) |
||
66 | { |
||
67 | if (!space) |
||
68 | return -1; |
||
69 | if (space->n_in != 0 || space->nested[0]) |
||
70 | return 0; |
||
71 | if (space->tuple_id[0] != &isl_id_none) |
||
72 | return 0; |
||
73 | return 1; |
||
74 | } |
||
75 | |||
76 | __isl_give isl_space *isl_space_set_alloc(isl_ctx *ctx, |
||
77 | unsigned nparam, unsigned dim) |
||
78 | { |
||
79 | isl_space *space; |
||
80 | space = isl_space_alloc(ctx, nparam, 0, dim); |
||
81 | space = mark_as_set(space); |
||
82 | return space; |
||
83 | } |
||
84 | |||
85 | /* Mark the space as being that of a parameter domain, by setting |
||
86 | * both tuples to isl_id_none. |
||
87 | */ |
||
88 | static __isl_give isl_space *mark_as_params(isl_space *space) |
||
89 | { |
||
90 | if (!space) |
||
91 | return NULL; |
||
92 | space = isl_space_set_tuple_id(space, isl_dim_in, &isl_id_none); |
||
93 | space = isl_space_set_tuple_id(space, isl_dim_out, &isl_id_none); |
||
94 | return space; |
||
95 | } |
||
96 | |||
97 | /* Is the space that of a parameter domain? |
||
98 | */ |
||
99 | int isl_space_is_params(__isl_keep isl_space *space) |
||
100 | { |
||
101 | if (!space) |
||
102 | return -1; |
||
103 | if (space->n_in != 0 || space->nested[0] || |
||
104 | space->n_out != 0 || space->nested[1]) |
||
105 | return 0; |
||
106 | if (space->tuple_id[0] != &isl_id_none) |
||
107 | return 0; |
||
108 | if (space->tuple_id[1] != &isl_id_none) |
||
109 | return 0; |
||
110 | return 1; |
||
111 | } |
||
112 | |||
113 | /* Create a space for a parameter domain. |
||
114 | */ |
||
115 | __isl_give isl_space *isl_space_params_alloc(isl_ctx *ctx, unsigned nparam) |
||
116 | { |
||
117 | isl_space *space; |
||
118 | space = isl_space_alloc(ctx, nparam, 0, 0); |
||
119 | space = mark_as_params(space); |
||
120 | return space; |
||
121 | } |
||
122 | |||
123 | static unsigned global_pos(__isl_keep isl_space *dim, |
||
124 | enum isl_dim_type type, unsigned pos) |
||
125 | { |
||
126 | struct isl_ctx *ctx = dim->ctx; |
||
127 | |||
128 | switch (type) { |
||
129 | case isl_dim_param: |
||
130 | isl_assert(ctx, pos < dim->nparam, |
||
131 | return isl_space_dim(dim, isl_dim_all)); |
||
132 | return pos; |
||
133 | case isl_dim_in: |
||
134 | isl_assert(ctx, pos < dim->n_in, |
||
135 | return isl_space_dim(dim, isl_dim_all)); |
||
136 | return pos + dim->nparam; |
||
137 | case isl_dim_out: |
||
138 | isl_assert(ctx, pos < dim->n_out, |
||
139 | return isl_space_dim(dim, isl_dim_all)); |
||
140 | return pos + dim->nparam + dim->n_in; |
||
141 | default: |
||
142 | isl_assert(ctx, 0, return isl_space_dim(dim, isl_dim_all)); |
||
143 | } |
||
144 | return isl_space_dim(dim, isl_dim_all); |
||
145 | } |
||
146 | |||
147 | /* Extend length of ids array to the total number of dimensions. |
||
148 | */ |
||
149 | static __isl_give isl_space *extend_ids(__isl_take isl_space *dim) |
||
150 | { |
||
151 | isl_id **ids; |
||
152 | int i; |
||
153 | |||
154 | if (isl_space_dim(dim, isl_dim_all) <= dim->n_id) |
||
155 | return dim; |
||
156 | |||
157 | if (!dim->ids) { |
||
158 | dim->ids = isl_calloc_array(dim->ctx, |
||
159 | isl_id *, isl_space_dim(dim, isl_dim_all)); |
||
160 | if (!dim->ids) |
||
161 | goto error; |
||
162 | } else { |
||
163 | ids = isl_realloc_array(dim->ctx, dim->ids, |
||
164 | isl_id *, isl_space_dim(dim, isl_dim_all)); |
||
165 | if (!ids) |
||
166 | goto error; |
||
167 | dim->ids = ids; |
||
168 | for (i = dim->n_id; i < isl_space_dim(dim, isl_dim_all); ++i) |
||
169 | dim->ids[i] = NULL; |
||
170 | } |
||
171 | |||
172 | dim->n_id = isl_space_dim(dim, isl_dim_all); |
||
173 | |||
174 | return dim; |
||
175 | error: |
||
176 | isl_space_free(dim); |
||
177 | return NULL; |
||
178 | } |
||
179 | |||
180 | static __isl_give isl_space *set_id(__isl_take isl_space *dim, |
||
181 | enum isl_dim_type type, unsigned pos, __isl_take isl_id *id) |
||
182 | { |
||
183 | dim = isl_space_cow(dim); |
||
184 | |||
185 | if (!dim) |
||
186 | goto error; |
||
187 | |||
188 | pos = global_pos(dim, type, pos); |
||
189 | if (pos == isl_space_dim(dim, isl_dim_all)) |
||
190 | goto error; |
||
191 | |||
192 | if (pos >= dim->n_id) { |
||
193 | if (!id) |
||
194 | return dim; |
||
195 | dim = extend_ids(dim); |
||
196 | if (!dim) |
||
197 | goto error; |
||
198 | } |
||
199 | |||
200 | dim->ids[pos] = id; |
||
201 | |||
202 | return dim; |
||
203 | error: |
||
204 | isl_id_free(id); |
||
205 | isl_space_free(dim); |
||
206 | return NULL; |
||
207 | } |
||
208 | |||
209 | static __isl_keep isl_id *get_id(__isl_keep isl_space *dim, |
||
210 | enum isl_dim_type type, unsigned pos) |
||
211 | { |
||
212 | if (!dim) |
||
213 | return NULL; |
||
214 | |||
215 | pos = global_pos(dim, type, pos); |
||
216 | if (pos == isl_space_dim(dim, isl_dim_all)) |
||
217 | return NULL; |
||
218 | if (pos >= dim->n_id) |
||
219 | return NULL; |
||
220 | return dim->ids[pos]; |
||
221 | } |
||
222 | |||
223 | static unsigned offset(__isl_keep isl_space *dim, enum isl_dim_type type) |
||
224 | { |
||
225 | switch (type) { |
||
226 | case isl_dim_param: return 0; |
||
227 | case isl_dim_in: return dim->nparam; |
||
228 | case isl_dim_out: return dim->nparam + dim->n_in; |
||
229 | default: return 0; |
||
230 | } |
||
231 | } |
||
232 | |||
233 | static unsigned n(__isl_keep isl_space *dim, enum isl_dim_type type) |
||
234 | { |
||
235 | switch (type) { |
||
236 | case isl_dim_param: return dim->nparam; |
||
237 | case isl_dim_in: return dim->n_in; |
||
238 | case isl_dim_out: return dim->n_out; |
||
239 | case isl_dim_all: return dim->nparam + dim->n_in + dim->n_out; |
||
240 | default: return 0; |
||
241 | } |
||
242 | } |
||
243 | |||
244 | unsigned isl_space_dim(__isl_keep isl_space *dim, enum isl_dim_type type) |
||
245 | { |
||
246 | if (!dim) |
||
247 | return 0; |
||
248 | return n(dim, type); |
||
249 | } |
||
250 | |||
251 | unsigned isl_space_offset(__isl_keep isl_space *dim, enum isl_dim_type type) |
||
252 | { |
||
253 | if (!dim) |
||
254 | return 0; |
||
255 | return offset(dim, type); |
||
256 | } |
||
257 | |||
258 | static __isl_give isl_space *copy_ids(__isl_take isl_space *dst, |
||
259 | enum isl_dim_type dst_type, unsigned offset, __isl_keep isl_space *src, |
||
260 | enum isl_dim_type src_type) |
||
261 | { |
||
262 | int i; |
||
263 | isl_id *id; |
||
264 | |||
265 | if (!dst) |
||
266 | return NULL; |
||
267 | |||
268 | for (i = 0; i < n(src, src_type); ++i) { |
||
269 | id = get_id(src, src_type, i); |
||
270 | if (!id) |
||
271 | continue; |
||
272 | dst = set_id(dst, dst_type, offset + i, isl_id_copy(id)); |
||
273 | if (!dst) |
||
274 | return NULL; |
||
275 | } |
||
276 | return dst; |
||
277 | } |
||
278 | |||
279 | __isl_take isl_space *isl_space_dup(__isl_keep isl_space *dim) |
||
280 | { |
||
281 | isl_space *dup; |
||
282 | if (!dim) |
||
283 | return NULL; |
||
284 | dup = isl_space_alloc(dim->ctx, dim->nparam, dim->n_in, dim->n_out); |
||
285 | if (dim->tuple_id[0] && |
||
286 | !(dup->tuple_id[0] = isl_id_copy(dim->tuple_id[0]))) |
||
287 | goto error; |
||
288 | if (dim->tuple_id[1] && |
||
289 | !(dup->tuple_id[1] = isl_id_copy(dim->tuple_id[1]))) |
||
290 | goto error; |
||
291 | if (dim->nested[0] && !(dup->nested[0] = isl_space_copy(dim->nested[0]))) |
||
292 | goto error; |
||
293 | if (dim->nested[1] && !(dup->nested[1] = isl_space_copy(dim->nested[1]))) |
||
294 | goto error; |
||
295 | if (!dim->ids) |
||
296 | return dup; |
||
297 | dup = copy_ids(dup, isl_dim_param, 0, dim, isl_dim_param); |
||
298 | dup = copy_ids(dup, isl_dim_in, 0, dim, isl_dim_in); |
||
299 | dup = copy_ids(dup, isl_dim_out, 0, dim, isl_dim_out); |
||
300 | return dup; |
||
301 | error: |
||
302 | isl_space_free(dup); |
||
303 | return NULL; |
||
304 | } |
||
305 | |||
306 | __isl_give isl_space *isl_space_cow(__isl_take isl_space *dim) |
||
307 | { |
||
308 | if (!dim) |
||
309 | return NULL; |
||
310 | |||
311 | if (dim->ref == 1) |
||
312 | return dim; |
||
313 | dim->ref--; |
||
314 | return isl_space_dup(dim); |
||
315 | } |
||
316 | |||
317 | __isl_give isl_space *isl_space_copy(__isl_keep isl_space *dim) |
||
318 | { |
||
319 | if (!dim) |
||
320 | return NULL; |
||
321 | |||
322 | dim->ref++; |
||
323 | return dim; |
||
324 | } |
||
325 | |||
326 | void isl_space_free(__isl_take isl_space *dim) |
||
327 | { |
||
328 | int i; |
||
329 | |||
330 | if (!dim) |
||
331 | return; |
||
332 | |||
333 | if (--dim->ref > 0) |
||
334 | return; |
||
335 | |||
336 | isl_id_free(dim->tuple_id[0]); |
||
337 | isl_id_free(dim->tuple_id[1]); |
||
338 | |||
339 | isl_space_free(dim->nested[0]); |
||
340 | isl_space_free(dim->nested[1]); |
||
341 | |||
342 | for (i = 0; i < dim->n_id; ++i) |
||
343 | isl_id_free(dim->ids[i]); |
||
344 | free(dim->ids); |
||
345 | isl_ctx_deref(dim->ctx); |
||
346 | |||
347 | free(dim); |
||
348 | } |
||
349 | |||
350 | /* Check if "s" is a valid dimension or tuple name. |
||
351 | * We currently only forbid names that look like a number. |
||
352 | * |
||
353 | * s is assumed to be non-NULL. |
||
354 | */ |
||
355 | static int name_ok(isl_ctx *ctx, const char *s) |
||
356 | { |
||
357 | char *p; |
||
358 | long dummy; |
||
359 | |||
360 | dummy = strtol(s, &p, 0); |
||
361 | if (p != s) |
||
362 | isl_die(ctx, isl_error_invalid, "name looks like a number", |
||
363 | return 0); |
||
364 | |||
365 | return 1; |
||
366 | } |
||
367 | |||
368 | /* Is it possible for the given dimension type to have a tuple id? |
||
369 | */ |
||
370 | static int space_can_have_id(__isl_keep isl_space *space, |
||
371 | enum isl_dim_type type) |
||
372 | { |
||
373 | if (!space) |
||
374 | return 0; |
||
375 | if (isl_space_is_params(space)) |
||
376 | isl_die(space->ctx, isl_error_invalid, |
||
377 | "parameter spaces don't have tuple ids", return 0); |
||
378 | if (isl_space_is_set(space) && type != isl_dim_set) |
||
379 | isl_die(space->ctx, isl_error_invalid, |
||
380 | "set spaces can only have a set id", return 0); |
||
381 | if (type != isl_dim_in && type != isl_dim_out) |
||
382 | isl_die(space->ctx, isl_error_invalid, |
||
383 | "only input, output and set tuples can have ids", |
||
384 | return 0); |
||
385 | |||
386 | return 1; |
||
387 | } |
||
388 | |||
389 | /* Does the tuple have an id? |
||
390 | */ |
||
391 | int isl_space_has_tuple_id(__isl_keep isl_space *dim, enum isl_dim_type type) |
||
392 | { |
||
393 | if (!space_can_have_id(dim, type)) |
||
394 | return -1; |
||
395 | return dim->tuple_id[type - isl_dim_in] != NULL; |
||
396 | } |
||
397 | |||
398 | __isl_give isl_id *isl_space_get_tuple_id(__isl_keep isl_space *dim, |
||
399 | enum isl_dim_type type) |
||
400 | { |
||
401 | int has_id; |
||
402 | |||
403 | if (!dim) |
||
404 | return NULL; |
||
405 | has_id = isl_space_has_tuple_id(dim, type); |
||
406 | if (has_id < 0) |
||
407 | return NULL; |
||
408 | if (!has_id) |
||
409 | isl_die(dim->ctx, isl_error_invalid, |
||
410 | "tuple has no id", return NULL); |
||
411 | return isl_id_copy(dim->tuple_id[type - isl_dim_in]); |
||
412 | } |
||
413 | |||
414 | __isl_give isl_space *isl_space_set_tuple_id(__isl_take isl_space *dim, |
||
415 | enum isl_dim_type type, __isl_take isl_id *id) |
||
416 | { |
||
417 | dim = isl_space_cow(dim); |
||
418 | if (!dim || !id) |
||
419 | goto error; |
||
420 | if (type != isl_dim_in && type != isl_dim_out) |
||
421 | isl_die(dim->ctx, isl_error_invalid, |
||
422 | "only input, output and set tuples can have names", |
||
423 | goto error); |
||
424 | |||
425 | isl_id_free(dim->tuple_id[type - isl_dim_in]); |
||
426 | dim->tuple_id[type - isl_dim_in] = id; |
||
427 | |||
428 | return dim; |
||
429 | error: |
||
430 | isl_id_free(id); |
||
431 | isl_space_free(dim); |
||
432 | return NULL; |
||
433 | } |
||
434 | |||
435 | __isl_give isl_space *isl_space_reset_tuple_id(__isl_take isl_space *dim, |
||
436 | enum isl_dim_type type) |
||
437 | { |
||
438 | dim = isl_space_cow(dim); |
||
439 | if (!dim) |
||
440 | return NULL; |
||
441 | if (type != isl_dim_in && type != isl_dim_out) |
||
442 | isl_die(dim->ctx, isl_error_invalid, |
||
443 | "only input, output and set tuples can have names", |
||
444 | goto error); |
||
445 | |||
446 | isl_id_free(dim->tuple_id[type - isl_dim_in]); |
||
447 | dim->tuple_id[type - isl_dim_in] = NULL; |
||
448 | |||
449 | return dim; |
||
450 | error: |
||
451 | isl_space_free(dim); |
||
452 | return NULL; |
||
453 | } |
||
454 | |||
455 | /* Set the id of the given dimension of "space" to "id". |
||
456 | * If the dimension already has an id, then it is replaced. |
||
457 | * If the dimension is a parameter, then we need to change it |
||
458 | * in the nested spaces (if any) as well. |
||
459 | */ |
||
460 | __isl_give isl_space *isl_space_set_dim_id(__isl_take isl_space *space, |
||
461 | enum isl_dim_type type, unsigned pos, __isl_take isl_id *id) |
||
462 | { |
||
463 | space = isl_space_cow(space); |
||
464 | if (!space || !id) |
||
465 | goto error; |
||
466 | |||
467 | if (type == isl_dim_param) { |
||
468 | int i; |
||
469 | |||
470 | for (i = 0; i < 2; ++i) { |
||
471 | if (!space->nested[i]) |
||
472 | continue; |
||
473 | space->nested[i] = |
||
474 | isl_space_set_dim_id(space->nested[i], |
||
475 | type, pos, isl_id_copy(id)); |
||
476 | if (!space->nested[i]) |
||
477 | goto error; |
||
478 | } |
||
479 | } |
||
480 | |||
481 | isl_id_free(get_id(space, type, pos)); |
||
482 | return set_id(space, type, pos, id); |
||
483 | error: |
||
484 | isl_id_free(id); |
||
485 | isl_space_free(space); |
||
486 | return NULL; |
||
487 | } |
||
488 | |||
489 | /* Reset the id of the given dimension of "space". |
||
490 | * If the dimension already has an id, then it is removed. |
||
491 | * If the dimension is a parameter, then we need to reset it |
||
492 | * in the nested spaces (if any) as well. |
||
493 | */ |
||
494 | __isl_give isl_space *isl_space_reset_dim_id(__isl_take isl_space *space, |
||
495 | enum isl_dim_type type, unsigned pos) |
||
496 | { |
||
497 | space = isl_space_cow(space); |
||
498 | if (!space) |
||
499 | goto error; |
||
500 | |||
501 | if (type == isl_dim_param) { |
||
502 | int i; |
||
503 | |||
504 | for (i = 0; i < 2; ++i) { |
||
505 | if (!space->nested[i]) |
||
506 | continue; |
||
507 | space->nested[i] = |
||
508 | isl_space_reset_dim_id(space->nested[i], |
||
509 | type, pos); |
||
510 | if (!space->nested[i]) |
||
511 | goto error; |
||
512 | } |
||
513 | } |
||
514 | |||
515 | isl_id_free(get_id(space, type, pos)); |
||
516 | return set_id(space, type, pos, NULL); |
||
517 | error: |
||
518 | isl_space_free(space); |
||
519 | return NULL; |
||
520 | } |
||
521 | |||
522 | int isl_space_has_dim_id(__isl_keep isl_space *dim, |
||
523 | enum isl_dim_type type, unsigned pos) |
||
524 | { |
||
525 | if (!dim) |
||
526 | return -1; |
||
527 | return get_id(dim, type, pos) != NULL; |
||
528 | } |
||
529 | |||
530 | __isl_give isl_id *isl_space_get_dim_id(__isl_keep isl_space *dim, |
||
531 | enum isl_dim_type type, unsigned pos) |
||
532 | { |
||
533 | if (!dim) |
||
534 | return NULL; |
||
535 | if (!get_id(dim, type, pos)) |
||
536 | isl_die(dim->ctx, isl_error_invalid, |
||
537 | "dim has no id", return NULL); |
||
538 | return isl_id_copy(get_id(dim, type, pos)); |
||
539 | } |
||
540 | |||
541 | __isl_give isl_space *isl_space_set_tuple_name(__isl_take isl_space *dim, |
||
542 | enum isl_dim_type type, const char *s) |
||
543 | { |
||
544 | isl_id *id; |
||
545 | |||
546 | if (!dim) |
||
547 | return NULL; |
||
548 | |||
549 | if (!s) |
||
550 | return isl_space_reset_tuple_id(dim, type); |
||
551 | |||
552 | if (!name_ok(dim->ctx, s)) |
||
553 | goto error; |
||
554 | |||
555 | id = isl_id_alloc(dim->ctx, s, NULL); |
||
556 | return isl_space_set_tuple_id(dim, type, id); |
||
557 | error: |
||
558 | isl_space_free(dim); |
||
559 | return NULL; |
||
560 | } |
||
561 | |||
562 | /* Does the tuple have a name? |
||
563 | */ |
||
564 | int isl_space_has_tuple_name(__isl_keep isl_space *space, |
||
565 | enum isl_dim_type type) |
||
566 | { |
||
567 | isl_id *id; |
||
568 | |||
569 | if (!space_can_have_id(space, type)) |
||
570 | return -1; |
||
571 | id = space->tuple_id[type - isl_dim_in]; |
||
572 | return id && id->name; |
||
573 | } |
||
574 | |||
575 | const char *isl_space_get_tuple_name(__isl_keep isl_space *dim, |
||
576 | enum isl_dim_type type) |
||
577 | { |
||
578 | isl_id *id; |
||
579 | if (!dim) |
||
580 | return NULL; |
||
581 | if (type != isl_dim_in && type != isl_dim_out) |
||
582 | return NULL; |
||
583 | id = dim->tuple_id[type - isl_dim_in]; |
||
584 | return id ? id->name : NULL; |
||
585 | } |
||
586 | |||
587 | __isl_give isl_space *isl_space_set_dim_name(__isl_take isl_space *dim, |
||
588 | enum isl_dim_type type, unsigned pos, |
||
589 | const char *s) |
||
590 | { |
||
591 | isl_id *id; |
||
592 | |||
593 | if (!dim) |
||
594 | return NULL; |
||
595 | if (!s) |
||
596 | return isl_space_reset_dim_id(dim, type, pos); |
||
597 | if (!name_ok(dim->ctx, s)) |
||
598 | goto error; |
||
599 | id = isl_id_alloc(dim->ctx, s, NULL); |
||
600 | return isl_space_set_dim_id(dim, type, pos, id); |
||
601 | error: |
||
602 | isl_space_free(dim); |
||
603 | return NULL; |
||
604 | } |
||
605 | |||
606 | /* Does the given dimension have a name? |
||
607 | */ |
||
608 | int isl_space_has_dim_name(__isl_keep isl_space *space, |
||
609 | enum isl_dim_type type, unsigned pos) |
||
610 | { |
||
611 | isl_id *id; |
||
612 | |||
613 | if (!space) |
||
614 | return -1; |
||
615 | id = get_id(space, type, pos); |
||
616 | return id && id->name; |
||
617 | } |
||
618 | |||
619 | __isl_keep const char *isl_space_get_dim_name(__isl_keep isl_space *dim, |
||
620 | enum isl_dim_type type, unsigned pos) |
||
621 | { |
||
622 | isl_id *id = get_id(dim, type, pos); |
||
623 | return id ? id->name : NULL; |
||
624 | } |
||
625 | |||
626 | int isl_space_find_dim_by_id(__isl_keep isl_space *dim, enum isl_dim_type type, |
||
627 | __isl_keep isl_id *id) |
||
628 | { |
||
629 | int i; |
||
630 | int offset; |
||
631 | int n; |
||
632 | |||
633 | if (!dim || !id) |
||
634 | return -1; |
||
635 | |||
636 | offset = isl_space_offset(dim, type); |
||
637 | n = isl_space_dim(dim, type); |
||
638 | for (i = 0; i < n && offset + i < dim->n_id; ++i) |
||
639 | if (dim->ids[offset + i] == id) |
||
640 | return i; |
||
641 | |||
642 | return -1; |
||
643 | } |
||
644 | |||
645 | int isl_space_find_dim_by_name(__isl_keep isl_space *space, |
||
646 | enum isl_dim_type type, const char *name) |
||
647 | { |
||
648 | int i; |
||
649 | int offset; |
||
650 | int n; |
||
651 | |||
652 | if (!space || !name) |
||
653 | return -1; |
||
654 | |||
655 | offset = isl_space_offset(space, type); |
||
656 | n = isl_space_dim(space, type); |
||
657 | for (i = 0; i < n && offset + i < space->n_id; ++i) |
||
658 | if (space->ids[offset + i]->name && |
||
659 | !strcmp(space->ids[offset + i]->name, name)) |
||
660 | return i; |
||
661 | |||
662 | return -1; |
||
663 | } |
||
664 | |||
665 | static __isl_keep isl_id *tuple_id(__isl_keep isl_space *dim, |
||
666 | enum isl_dim_type type) |
||
667 | { |
||
668 | if (!dim) |
||
669 | return NULL; |
||
670 | if (type == isl_dim_in) |
||
671 | return dim->tuple_id[0]; |
||
672 | if (type == isl_dim_out) |
||
673 | return dim->tuple_id[1]; |
||
674 | return NULL; |
||
675 | } |
||
676 | |||
677 | static __isl_keep isl_space *nested(__isl_keep isl_space *dim, |
||
678 | enum isl_dim_type type) |
||
679 | { |
||
680 | if (!dim) |
||
681 | return NULL; |
||
682 | if (type == isl_dim_in) |
||
683 | return dim->nested[0]; |
||
684 | if (type == isl_dim_out) |
||
685 | return dim->nested[1]; |
||
686 | return NULL; |
||
687 | } |
||
688 | |||
689 | int isl_space_tuple_match(__isl_keep isl_space *dim1, enum isl_dim_type dim1_type, |
||
690 | __isl_keep isl_space *dim2, enum isl_dim_type dim2_type) |
||
691 | { |
||
692 | isl_id *id1, *id2; |
||
693 | isl_space *nested1, *nested2; |
||
694 | |||
695 | if (!dim1 || !dim2) |
||
696 | return -1; |
||
697 | |||
698 | if (dim1 == dim2 && dim1_type == dim2_type) |
||
699 | return 1; |
||
700 | |||
701 | if (n(dim1, dim1_type) != n(dim2, dim2_type)) |
||
702 | return 0; |
||
703 | id1 = tuple_id(dim1, dim1_type); |
||
704 | id2 = tuple_id(dim2, dim2_type); |
||
705 | if (!id1 ^ !id2) |
||
706 | return 0; |
||
707 | if (id1 && id1 != id2) |
||
708 | return 0; |
||
709 | nested1 = nested(dim1, dim1_type); |
||
710 | nested2 = nested(dim2, dim2_type); |
||
711 | if (!nested1 ^ !nested2) |
||
712 | return 0; |
||
713 | if (nested1 && !isl_space_is_equal(nested1, nested2)) |
||
714 | return 0; |
||
715 | return 1; |
||
716 | } |
||
717 | |||
718 | static int match(__isl_keep isl_space *dim1, enum isl_dim_type dim1_type, |
||
719 | __isl_keep isl_space *dim2, enum isl_dim_type dim2_type) |
||
720 | { |
||
721 | int i; |
||
722 | |||
723 | if (dim1 == dim2 && dim1_type == dim2_type) |
||
724 | return 1; |
||
725 | |||
726 | if (!isl_space_tuple_match(dim1, dim1_type, dim2, dim2_type)) |
||
727 | return 0; |
||
728 | |||
729 | if (!dim1->ids && !dim2->ids) |
||
730 | return 1; |
||
731 | |||
732 | for (i = 0; i < n(dim1, dim1_type); ++i) { |
||
733 | if (get_id(dim1, dim1_type, i) != get_id(dim2, dim2_type, i)) |
||
734 | return 0; |
||
735 | } |
||
736 | return 1; |
||
737 | } |
||
738 | |||
739 | int isl_space_match(__isl_keep isl_space *dim1, enum isl_dim_type dim1_type, |
||
740 | __isl_keep isl_space *dim2, enum isl_dim_type dim2_type) |
||
741 | { |
||
742 | if (!dim1 || !dim2) |
||
743 | return -1; |
||
744 | |||
745 | return match(dim1, dim1_type, dim2, dim2_type); |
||
746 | } |
||
747 | |||
748 | static void get_ids(__isl_keep isl_space *dim, enum isl_dim_type type, |
||
749 | unsigned first, unsigned n, __isl_keep isl_id **ids) |
||
750 | { |
||
751 | int i; |
||
752 | |||
753 | for (i = 0; i < n ; ++i) |
||
754 | ids[i] = get_id(dim, type, first + i); |
||
755 | } |
||
756 | |||
757 | __isl_give isl_space *isl_space_extend(__isl_take isl_space *dim, |
||
758 | unsigned nparam, unsigned n_in, unsigned n_out) |
||
759 | { |
||
760 | isl_id **ids = NULL; |
||
761 | |||
762 | if (!dim) |
||
763 | return NULL; |
||
764 | if (dim->nparam == nparam && dim->n_in == n_in && dim->n_out == n_out) |
||
765 | return dim; |
||
766 | |||
767 | isl_assert(dim->ctx, dim->nparam <= nparam, goto error); |
||
768 | isl_assert(dim->ctx, dim->n_in <= n_in, goto error); |
||
769 | isl_assert(dim->ctx, dim->n_out <= n_out, goto error); |
||
770 | |||
771 | dim = isl_space_cow(dim); |
||
772 | |||
773 | if (dim->ids) { |
||
774 | ids = isl_calloc_array(dim->ctx, isl_id *, |
||
775 | nparam + n_in + n_out); |
||
776 | if (!ids) |
||
777 | goto error; |
||
778 | get_ids(dim, isl_dim_param, 0, dim->nparam, ids); |
||
779 | get_ids(dim, isl_dim_in, 0, dim->n_in, ids + nparam); |
||
780 | get_ids(dim, isl_dim_out, 0, dim->n_out, ids + nparam + n_in); |
||
781 | free(dim->ids); |
||
782 | dim->ids = ids; |
||
783 | dim->n_id = nparam + n_in + n_out; |
||
784 | } |
||
785 | dim->nparam = nparam; |
||
786 | dim->n_in = n_in; |
||
787 | dim->n_out = n_out; |
||
788 | |||
789 | return dim; |
||
790 | error: |
||
791 | free(ids); |
||
792 | isl_space_free(dim); |
||
793 | return NULL; |
||
794 | } |
||
795 | |||
796 | __isl_give isl_space *isl_space_add_dims(__isl_take isl_space *dim, |
||
797 | enum isl_dim_type type, unsigned n) |
||
798 | { |
||
799 | if (!dim) |
||
800 | return NULL; |
||
801 | dim = isl_space_reset(dim, type); |
||
802 | switch (type) { |
||
803 | case isl_dim_param: |
||
804 | dim = isl_space_extend(dim, |
||
805 | dim->nparam + n, dim->n_in, dim->n_out); |
||
806 | if (dim && dim->nested[0] && |
||
807 | !(dim->nested[0] = isl_space_add_dims(dim->nested[0], |
||
808 | isl_dim_param, n))) |
||
809 | goto error; |
||
810 | if (dim && dim->nested[1] && |
||
811 | !(dim->nested[1] = isl_space_add_dims(dim->nested[1], |
||
812 | isl_dim_param, n))) |
||
813 | goto error; |
||
814 | return dim; |
||
815 | case isl_dim_in: |
||
816 | return isl_space_extend(dim, |
||
817 | dim->nparam, dim->n_in + n, dim->n_out); |
||
818 | case isl_dim_out: |
||
819 | return isl_space_extend(dim, |
||
820 | dim->nparam, dim->n_in, dim->n_out + n); |
||
821 | default: |
||
822 | isl_die(dim->ctx, isl_error_invalid, |
||
823 | "cannot add dimensions of specified type", goto error); |
||
824 | } |
||
825 | error: |
||
826 | isl_space_free(dim); |
||
827 | return NULL; |
||
828 | } |
||
829 | |||
830 | static int valid_dim_type(enum isl_dim_type type) |
||
831 | { |
||
832 | switch (type) { |
||
833 | case isl_dim_param: |
||
834 | case isl_dim_in: |
||
835 | case isl_dim_out: |
||
836 | return 1; |
||
837 | default: |
||
838 | return 0; |
||
839 | } |
||
840 | } |
||
841 | |||
842 | /* Insert "n" dimensions of type "type" at position "pos". |
||
843 | * If we are inserting parameters, then they are also inserted in |
||
844 | * any nested spaces. |
||
845 | */ |
||
846 | __isl_give isl_space *isl_space_insert_dims(__isl_take isl_space *dim, |
||
847 | enum isl_dim_type type, unsigned pos, unsigned n) |
||
848 | { |
||
849 | isl_id **ids = NULL; |
||
850 | |||
851 | if (!dim) |
||
852 | return NULL; |
||
853 | if (n == 0) |
||
854 | return isl_space_reset(dim, type); |
||
855 | |||
856 | if (!valid_dim_type(type)) |
||
857 | isl_die(dim->ctx, isl_error_invalid, |
||
858 | "cannot insert dimensions of specified type", |
||
859 | goto error); |
||
860 | |||
861 | isl_assert(dim->ctx, pos <= isl_space_dim(dim, type), goto error); |
||
862 | |||
863 | dim = isl_space_cow(dim); |
||
864 | if (!dim) |
||
865 | return NULL; |
||
866 | |||
867 | if (dim->ids) { |
||
868 | enum isl_dim_type t, o = isl_dim_param; |
||
869 | int off; |
||
870 | int s[3]; |
||
871 | ids = isl_calloc_array(dim->ctx, isl_id *, |
||
872 | dim->nparam + dim->n_in + dim->n_out + n); |
||
873 | if (!ids) |
||
874 | goto error; |
||
875 | off = 0; |
||
876 | s[isl_dim_param - o] = dim->nparam; |
||
877 | s[isl_dim_in - o] = dim->n_in; |
||
878 | s[isl_dim_out - o] = dim->n_out; |
||
879 | for (t = isl_dim_param; t <= isl_dim_out; ++t) { |
||
880 | if (t != type) { |
||
881 | get_ids(dim, t, 0, s[t - o], ids + off); |
||
882 | off += s[t - o]; |
||
883 | } else { |
||
884 | get_ids(dim, t, 0, pos, ids + off); |
||
885 | off += pos + n; |
||
886 | get_ids(dim, t, pos, s[t - o] - pos, ids + off); |
||
887 | off += s[t - o] - pos; |
||
888 | } |
||
889 | } |
||
890 | free(dim->ids); |
||
891 | dim->ids = ids; |
||
892 | dim->n_id = dim->nparam + dim->n_in + dim->n_out + n; |
||
893 | } |
||
894 | switch (type) { |
||
895 | case isl_dim_param: dim->nparam += n; break; |
||
896 | case isl_dim_in: dim->n_in += n; break; |
||
897 | case isl_dim_out: dim->n_out += n; break; |
||
898 | default: ; |
||
899 | } |
||
900 | dim = isl_space_reset(dim, type); |
||
901 | |||
902 | if (type == isl_dim_param) { |
||
903 | if (dim && dim->nested[0] && |
||
904 | !(dim->nested[0] = isl_space_insert_dims(dim->nested[0], |
||
905 | isl_dim_param, pos, n))) |
||
906 | goto error; |
||
907 | if (dim && dim->nested[1] && |
||
908 | !(dim->nested[1] = isl_space_insert_dims(dim->nested[1], |
||
909 | isl_dim_param, pos, n))) |
||
910 | goto error; |
||
911 | } |
||
912 | |||
913 | return dim; |
||
914 | error: |
||
915 | isl_space_free(dim); |
||
916 | return NULL; |
||
917 | } |
||
918 | |||
919 | __isl_give isl_space *isl_space_move_dims(__isl_take isl_space *dim, |
||
920 | enum isl_dim_type dst_type, unsigned dst_pos, |
||
921 | enum isl_dim_type src_type, unsigned src_pos, unsigned n) |
||
922 | { |
||
923 | int i; |
||
924 | |||
925 | if (!dim) |
||
926 | return NULL; |
||
927 | if (n == 0) |
||
928 | return dim; |
||
929 | |||
930 | isl_assert(dim->ctx, src_pos + n <= isl_space_dim(dim, src_type), |
||
931 | goto error); |
||
932 | |||
933 | if (dst_type == src_type && dst_pos == src_pos) |
||
934 | return dim; |
||
935 | |||
936 | isl_assert(dim->ctx, dst_type != src_type, goto error); |
||
937 | |||
938 | dim = isl_space_reset(dim, src_type); |
||
939 | dim = isl_space_reset(dim, dst_type); |
||
940 | |||
941 | dim = isl_space_cow(dim); |
||
942 | if (!dim) |
||
943 | return NULL; |
||
944 | |||
945 | if (dim->ids) { |
||
946 | isl_id **ids; |
||
947 | enum isl_dim_type t, o = isl_dim_param; |
||
948 | int off; |
||
949 | int s[3]; |
||
950 | ids = isl_calloc_array(dim->ctx, isl_id *, |
||
951 | dim->nparam + dim->n_in + dim->n_out); |
||
952 | if (!ids) |
||
953 | goto error; |
||
954 | off = 0; |
||
955 | s[isl_dim_param - o] = dim->nparam; |
||
956 | s[isl_dim_in - o] = dim->n_in; |
||
957 | s[isl_dim_out - o] = dim->n_out; |
||
958 | for (t = isl_dim_param; t <= isl_dim_out; ++t) { |
||
959 | if (t == dst_type) { |
||
960 | get_ids(dim, t, 0, dst_pos, ids + off); |
||
961 | off += dst_pos; |
||
962 | get_ids(dim, src_type, src_pos, n, ids + off); |
||
963 | off += n; |
||
964 | get_ids(dim, t, dst_pos, s[t - o] - dst_pos, |
||
965 | ids + off); |
||
966 | off += s[t - o] - dst_pos; |
||
967 | } else if (t == src_type) { |
||
968 | get_ids(dim, t, 0, src_pos, ids + off); |
||
969 | off += src_pos; |
||
970 | get_ids(dim, t, src_pos + n, |
||
971 | s[t - o] - src_pos - n, ids + off); |
||
972 | off += s[t - o] - src_pos - n; |
||
973 | } else { |
||
974 | get_ids(dim, t, 0, s[t - o], ids + off); |
||
975 | off += s[t - o]; |
||
976 | } |
||
977 | } |
||
978 | free(dim->ids); |
||
979 | dim->ids = ids; |
||
980 | dim->n_id = dim->nparam + dim->n_in + dim->n_out; |
||
981 | } |
||
982 | |||
983 | switch (dst_type) { |
||
984 | case isl_dim_param: dim->nparam += n; break; |
||
985 | case isl_dim_in: dim->n_in += n; break; |
||
986 | case isl_dim_out: dim->n_out += n; break; |
||
987 | default: ; |
||
988 | } |
||
989 | |||
990 | switch (src_type) { |
||
991 | case isl_dim_param: dim->nparam -= n; break; |
||
992 | case isl_dim_in: dim->n_in -= n; break; |
||
993 | case isl_dim_out: dim->n_out -= n; break; |
||
994 | default: ; |
||
995 | } |
||
996 | |||
997 | if (dst_type != isl_dim_param && src_type != isl_dim_param) |
||
998 | return dim; |
||
999 | |||
1000 | for (i = 0; i < 2; ++i) { |
||
1001 | if (!dim->nested[i]) |
||
1002 | continue; |
||
1003 | dim->nested[i] = isl_space_replace(dim->nested[i], |
||
1004 | isl_dim_param, dim); |
||
1005 | if (!dim->nested[i]) |
||
1006 | goto error; |
||
1007 | } |
||
1008 | |||
1009 | return dim; |
||
1010 | error: |
||
1011 | isl_space_free(dim); |
||
1012 | return NULL; |
||
1013 | } |
||
1014 | |||
1015 | __isl_give isl_space *isl_space_join(__isl_take isl_space *left, |
||
1016 | __isl_take isl_space *right) |
||
1017 | { |
||
1018 | isl_space *dim; |
||
1019 | |||
1020 | if (!left || !right) |
||
1021 | goto error; |
||
1022 | |||
1023 | isl_assert(left->ctx, match(left, isl_dim_param, right, isl_dim_param), |
||
1024 | goto error); |
||
1025 | isl_assert(left->ctx, |
||
1026 | isl_space_tuple_match(left, isl_dim_out, right, isl_dim_in), |
||
1027 | goto error); |
||
1028 | |||
1029 | dim = isl_space_alloc(left->ctx, left->nparam, left->n_in, right->n_out); |
||
1030 | if (!dim) |
||
1031 | goto error; |
||
1032 | |||
1033 | dim = copy_ids(dim, isl_dim_param, 0, left, isl_dim_param); |
||
1034 | dim = copy_ids(dim, isl_dim_in, 0, left, isl_dim_in); |
||
1035 | dim = copy_ids(dim, isl_dim_out, 0, right, isl_dim_out); |
||
1036 | |||
1037 | if (dim && left->tuple_id[0] && |
||
1038 | !(dim->tuple_id[0] = isl_id_copy(left->tuple_id[0]))) |
||
1039 | goto error; |
||
1040 | if (dim && right->tuple_id[1] && |
||
1041 | !(dim->tuple_id[1] = isl_id_copy(right->tuple_id[1]))) |
||
1042 | goto error; |
||
1043 | if (dim && left->nested[0] && |
||
1044 | !(dim->nested[0] = isl_space_copy(left->nested[0]))) |
||
1045 | goto error; |
||
1046 | if (dim && right->nested[1] && |
||
1047 | !(dim->nested[1] = isl_space_copy(right->nested[1]))) |
||
1048 | goto error; |
||
1049 | |||
1050 | isl_space_free(left); |
||
1051 | isl_space_free(right); |
||
1052 | |||
1053 | return dim; |
||
1054 | error: |
||
1055 | isl_space_free(left); |
||
1056 | isl_space_free(right); |
||
1057 | return NULL; |
||
1058 | } |
||
1059 | |||
1060 | __isl_give isl_space *isl_space_product(__isl_take isl_space *left, |
||
1061 | __isl_take isl_space *right) |
||
1062 | { |
||
1063 | isl_space *dom1, *dom2, *nest1, *nest2; |
||
1064 | |||
1065 | if (!left || !right) |
||
1066 | goto error; |
||
1067 | |||
1068 | isl_assert(left->ctx, match(left, isl_dim_param, right, isl_dim_param), |
||
1069 | goto error); |
||
1070 | |||
1071 | dom1 = isl_space_domain(isl_space_copy(left)); |
||
1072 | dom2 = isl_space_domain(isl_space_copy(right)); |
||
1073 | nest1 = isl_space_wrap(isl_space_join(isl_space_reverse(dom1), dom2)); |
||
1074 | |||
1075 | dom1 = isl_space_range(left); |
||
1076 | dom2 = isl_space_range(right); |
||
1077 | nest2 = isl_space_wrap(isl_space_join(isl_space_reverse(dom1), dom2)); |
||
1078 | |||
1079 | return isl_space_join(isl_space_reverse(nest1), nest2); |
||
1080 | error: |
||
1081 | isl_space_free(left); |
||
1082 | isl_space_free(right); |
||
1083 | return NULL; |
||
1084 | } |
||
1085 | |||
1086 | /* Given two spaces { A -> C } and { B -> C }, construct the space |
||
1087 | * { [A -> B] -> C } |
||
1088 | */ |
||
1089 | __isl_give isl_space *isl_space_domain_product(__isl_take isl_space *left, |
||
1090 | __isl_take isl_space *right) |
||
1091 | { |
||
1092 | isl_space *ran, *dom1, *dom2, *nest; |
||
1093 | |||
1094 | if (!left || !right) |
||
1095 | goto error; |
||
1096 | |||
1097 | if (!match(left, isl_dim_param, right, isl_dim_param)) |
||
1098 | isl_die(left->ctx, isl_error_invalid, |
||
1099 | "parameters need to match", goto error); |
||
1100 | if (!isl_space_tuple_match(left, isl_dim_out, right, isl_dim_out)) |
||
1101 | isl_die(left->ctx, isl_error_invalid, |
||
1102 | "ranges need to match", goto error); |
||
1103 | |||
1104 | ran = isl_space_range(isl_space_copy(left)); |
||
1105 | |||
1106 | dom1 = isl_space_domain(left); |
||
1107 | dom2 = isl_space_domain(right); |
||
1108 | nest = isl_space_wrap(isl_space_join(isl_space_reverse(dom1), dom2)); |
||
1109 | |||
1110 | return isl_space_join(isl_space_reverse(nest), ran); |
||
1111 | error: |
||
1112 | isl_space_free(left); |
||
1113 | isl_space_free(right); |
||
1114 | return NULL; |
||
1115 | } |
||
1116 | |||
1117 | __isl_give isl_space *isl_space_range_product(__isl_take isl_space *left, |
||
1118 | __isl_take isl_space *right) |
||
1119 | { |
||
1120 | isl_space *dom, *ran1, *ran2, *nest; |
||
1121 | |||
1122 | if (!left || !right) |
||
1123 | goto error; |
||
1124 | |||
1125 | isl_assert(left->ctx, match(left, isl_dim_param, right, isl_dim_param), |
||
1126 | goto error); |
||
1127 | if (!isl_space_tuple_match(left, isl_dim_in, right, isl_dim_in)) |
||
1128 | isl_die(left->ctx, isl_error_invalid, |
||
1129 | "domains need to match", goto error); |
||
1130 | |||
1131 | dom = isl_space_domain(isl_space_copy(left)); |
||
1132 | |||
1133 | ran1 = isl_space_range(left); |
||
1134 | ran2 = isl_space_range(right); |
||
1135 | nest = isl_space_wrap(isl_space_join(isl_space_reverse(ran1), ran2)); |
||
1136 | |||
1137 | return isl_space_join(isl_space_reverse(dom), nest); |
||
1138 | error: |
||
1139 | isl_space_free(left); |
||
1140 | isl_space_free(right); |
||
1141 | return NULL; |
||
1142 | } |
||
1143 | |||
1144 | __isl_give isl_space *isl_space_map_from_set(__isl_take isl_space *dim) |
||
1145 | { |
||
1146 | isl_ctx *ctx; |
||
1147 | isl_id **ids = NULL; |
||
1148 | |||
1149 | if (!dim) |
||
1150 | return NULL; |
||
1151 | ctx = isl_space_get_ctx(dim); |
||
1152 | if (!isl_space_is_set(dim)) |
||
1153 | isl_die(ctx, isl_error_invalid, "not a set space", goto error); |
||
1154 | dim = isl_space_cow(dim); |
||
1155 | if (!dim) |
||
1156 | return NULL; |
||
1157 | if (dim->ids) { |
||
1158 | ids = isl_calloc_array(dim->ctx, isl_id *, |
||
1159 | dim->nparam + dim->n_out + dim->n_out); |
||
1160 | if (!ids) |
||
1161 | goto error; |
||
1162 | get_ids(dim, isl_dim_param, 0, dim->nparam, ids); |
||
1163 | get_ids(dim, isl_dim_out, 0, dim->n_out, ids + dim->nparam); |
||
1164 | } |
||
1165 | dim->n_in = dim->n_out; |
||
1166 | if (ids) { |
||
1167 | free(dim->ids); |
||
1168 | dim->ids = ids; |
||
1169 | dim->n_id = dim->nparam + dim->n_out + dim->n_out; |
||
1170 | dim = copy_ids(dim, isl_dim_out, 0, dim, isl_dim_in); |
||
1171 | } |
||
1172 | isl_id_free(dim->tuple_id[0]); |
||
1173 | dim->tuple_id[0] = isl_id_copy(dim->tuple_id[1]); |
||
1174 | isl_space_free(dim->nested[0]); |
||
1175 | dim->nested[0] = isl_space_copy(dim->nested[1]); |
||
1176 | return dim; |
||
1177 | error: |
||
1178 | isl_space_free(dim); |
||
1179 | return NULL; |
||
1180 | } |
||
1181 | |||
1182 | __isl_give isl_space *isl_space_map_from_domain_and_range( |
||
1183 | __isl_take isl_space *domain, __isl_take isl_space *range) |
||
1184 | { |
||
1185 | if (!domain || !range) |
||
1186 | goto error; |
||
1187 | if (!isl_space_is_set(domain)) |
||
1188 | isl_die(isl_space_get_ctx(domain), isl_error_invalid, |
||
1189 | "domain is not a set space", goto error); |
||
1190 | if (!isl_space_is_set(range)) |
||
1191 | isl_die(isl_space_get_ctx(range), isl_error_invalid, |
||
1192 | "range is not a set space", goto error); |
||
1193 | return isl_space_join(isl_space_reverse(domain), range); |
||
1194 | error: |
||
1195 | isl_space_free(domain); |
||
1196 | isl_space_free(range); |
||
1197 | return NULL; |
||
1198 | } |
||
1199 | |||
1200 | static __isl_give isl_space *set_ids(__isl_take isl_space *dim, |
||
1201 | enum isl_dim_type type, |
||
1202 | unsigned first, unsigned n, __isl_take isl_id **ids) |
||
1203 | { |
||
1204 | int i; |
||
1205 | |||
1206 | for (i = 0; i < n ; ++i) |
||
1207 | dim = set_id(dim, type, first + i, ids[i]); |
||
1208 | |||
1209 | return dim; |
||
1210 | } |
||
1211 | |||
1212 | __isl_give isl_space *isl_space_reverse(__isl_take isl_space *dim) |
||
1213 | { |
||
1214 | unsigned t; |
||
1215 | isl_space *nested; |
||
1216 | isl_id **ids = NULL; |
||
1217 | isl_id *id; |
||
1218 | |||
1219 | if (!dim) |
||
1220 | return NULL; |
||
1221 | if (match(dim, isl_dim_in, dim, isl_dim_out)) |
||
1222 | return dim; |
||
1223 | |||
1224 | dim = isl_space_cow(dim); |
||
1225 | if (!dim) |
||
1226 | return NULL; |
||
1227 | |||
1228 | id = dim->tuple_id[0]; |
||
1229 | dim->tuple_id[0] = dim->tuple_id[1]; |
||
1230 | dim->tuple_id[1] = id; |
||
1231 | |||
1232 | nested = dim->nested[0]; |
||
1233 | dim->nested[0] = dim->nested[1]; |
||
1234 | dim->nested[1] = nested; |
||
1235 | |||
1236 | if (dim->ids) { |
||
1237 | ids = isl_alloc_array(dim->ctx, isl_id *, |
||
1238 | dim->n_in + dim->n_out); |
||
1239 | if (!ids) |
||
1240 | goto error; |
||
1241 | get_ids(dim, isl_dim_in, 0, dim->n_in, ids); |
||
1242 | get_ids(dim, isl_dim_out, 0, dim->n_out, ids + dim->n_in); |
||
1243 | } |
||
1244 | |||
1245 | t = dim->n_in; |
||
1246 | dim->n_in = dim->n_out; |
||
1247 | dim->n_out = t; |
||
1248 | |||
1249 | if (dim->ids) { |
||
1250 | dim = set_ids(dim, isl_dim_out, 0, dim->n_out, ids); |
||
1251 | dim = set_ids(dim, isl_dim_in, 0, dim->n_in, ids + dim->n_out); |
||
1252 | free(ids); |
||
1253 | } |
||
1254 | |||
1255 | return dim; |
||
1256 | error: |
||
1257 | free(ids); |
||
1258 | isl_space_free(dim); |
||
1259 | return NULL; |
||
1260 | } |
||
1261 | |||
1262 | __isl_give isl_space *isl_space_drop_dims(__isl_take isl_space *dim, |
||
1263 | enum isl_dim_type type, unsigned first, unsigned num) |
||
1264 | { |
||
1265 | int i; |
||
1266 | |||
1267 | if (!dim) |
||
1268 | return NULL; |
||
1269 | |||
1270 | if (num == 0) |
||
1271 | return isl_space_reset(dim, type); |
||
1272 | |||
1273 | if (!valid_dim_type(type)) |
||
1274 | isl_die(dim->ctx, isl_error_invalid, |
||
1275 | "cannot drop dimensions of specified type", goto error); |
||
1276 | |||
1277 | isl_assert(dim->ctx, first + num <= n(dim, type), goto error); |
||
1278 | dim = isl_space_cow(dim); |
||
1279 | if (!dim) |
||
1280 | goto error; |
||
1281 | if (dim->ids) { |
||
1282 | dim = extend_ids(dim); |
||
1283 | if (!dim) |
||
1284 | goto error; |
||
1285 | for (i = 0; i < num; ++i) |
||
1286 | isl_id_free(get_id(dim, type, first + i)); |
||
1287 | for (i = first+num; i < n(dim, type); ++i) |
||
1288 | set_id(dim, type, i - num, get_id(dim, type, i)); |
||
1289 | switch (type) { |
||
1290 | case isl_dim_param: |
||
1291 | get_ids(dim, isl_dim_in, 0, dim->n_in, |
||
1292 | dim->ids + offset(dim, isl_dim_in) - num); |
||
1293 | case isl_dim_in: |
||
1294 | get_ids(dim, isl_dim_out, 0, dim->n_out, |
||
1295 | dim->ids + offset(dim, isl_dim_out) - num); |
||
1296 | default: |
||
1297 | ; |
||
1298 | } |
||
1299 | dim->n_id -= num; |
||
1300 | } |
||
1301 | switch (type) { |
||
1302 | case isl_dim_param: dim->nparam -= num; break; |
||
1303 | case isl_dim_in: dim->n_in -= num; break; |
||
1304 | case isl_dim_out: dim->n_out -= num; break; |
||
1305 | default: ; |
||
1306 | } |
||
1307 | dim = isl_space_reset(dim, type); |
||
1308 | if (type == isl_dim_param) { |
||
1309 | if (dim && dim->nested[0] && |
||
1310 | !(dim->nested[0] = isl_space_drop_dims(dim->nested[0], |
||
1311 | isl_dim_param, first, num))) |
||
1312 | goto error; |
||
1313 | if (dim && dim->nested[1] && |
||
1314 | !(dim->nested[1] = isl_space_drop_dims(dim->nested[1], |
||
1315 | isl_dim_param, first, num))) |
||
1316 | goto error; |
||
1317 | } |
||
1318 | return dim; |
||
1319 | error: |
||
1320 | isl_space_free(dim); |
||
1321 | return NULL; |
||
1322 | } |
||
1323 | |||
1324 | __isl_give isl_space *isl_space_drop_inputs(__isl_take isl_space *dim, |
||
1325 | unsigned first, unsigned n) |
||
1326 | { |
||
1327 | if (!dim) |
||
1328 | return NULL; |
||
1329 | return isl_space_drop_dims(dim, isl_dim_in, first, n); |
||
1330 | } |
||
1331 | |||
1332 | __isl_give isl_space *isl_space_drop_outputs(__isl_take isl_space *dim, |
||
1333 | unsigned first, unsigned n) |
||
1334 | { |
||
1335 | if (!dim) |
||
1336 | return NULL; |
||
1337 | return isl_space_drop_dims(dim, isl_dim_out, first, n); |
||
1338 | } |
||
1339 | |||
1340 | __isl_give isl_space *isl_space_domain(__isl_take isl_space *dim) |
||
1341 | { |
||
1342 | if (!dim) |
||
1343 | return NULL; |
||
1344 | dim = isl_space_drop_outputs(dim, 0, dim->n_out); |
||
1345 | dim = isl_space_reverse(dim); |
||
1346 | dim = mark_as_set(dim); |
||
1347 | return dim; |
||
1348 | } |
||
1349 | |||
1350 | __isl_give isl_space *isl_space_from_domain(__isl_take isl_space *dim) |
||
1351 | { |
||
1352 | if (!dim) |
||
1353 | return NULL; |
||
1354 | if (!isl_space_is_set(dim)) |
||
1355 | isl_die(isl_space_get_ctx(dim), isl_error_invalid, |
||
1356 | "not a set space", goto error); |
||
1357 | dim = isl_space_reverse(dim); |
||
1358 | dim = isl_space_reset(dim, isl_dim_out); |
||
1359 | return dim; |
||
1360 | error: |
||
1361 | isl_space_free(dim); |
||
1362 | return NULL; |
||
1363 | } |
||
1364 | |||
1365 | __isl_give isl_space *isl_space_range(__isl_take isl_space *dim) |
||
1366 | { |
||
1367 | if (!dim) |
||
1368 | return NULL; |
||
1369 | dim = isl_space_drop_inputs(dim, 0, dim->n_in); |
||
1370 | dim = mark_as_set(dim); |
||
1371 | return dim; |
||
1372 | } |
||
1373 | |||
1374 | __isl_give isl_space *isl_space_from_range(__isl_take isl_space *dim) |
||
1375 | { |
||
1376 | if (!dim) |
||
1377 | return NULL; |
||
1378 | if (!isl_space_is_set(dim)) |
||
1379 | isl_die(isl_space_get_ctx(dim), isl_error_invalid, |
||
1380 | "not a set space", goto error); |
||
1381 | return isl_space_reset(dim, isl_dim_in); |
||
1382 | error: |
||
1383 | isl_space_free(dim); |
||
1384 | return NULL; |
||
1385 | } |
||
1386 | |||
1387 | __isl_give isl_space *isl_space_params(__isl_take isl_space *space) |
||
1388 | { |
||
1389 | if (isl_space_is_params(space)) |
||
1390 | return space; |
||
1391 | space = isl_space_drop_dims(space, |
||
1392 | isl_dim_in, 0, isl_space_dim(space, isl_dim_in)); |
||
1393 | space = isl_space_drop_dims(space, |
||
1394 | isl_dim_out, 0, isl_space_dim(space, isl_dim_out)); |
||
1395 | space = mark_as_params(space); |
||
1396 | return space; |
||
1397 | } |
||
1398 | |||
1399 | __isl_give isl_space *isl_space_set_from_params(__isl_take isl_space *space) |
||
1400 | { |
||
1401 | if (!space) |
||
1402 | return NULL; |
||
1403 | if (!isl_space_is_params(space)) |
||
1404 | isl_die(isl_space_get_ctx(space), isl_error_invalid, |
||
1405 | "not a parameter space", goto error); |
||
1406 | return isl_space_reset(space, isl_dim_set); |
||
1407 | error: |
||
1408 | isl_space_free(space); |
||
1409 | return NULL; |
||
1410 | } |
||
1411 | |||
1412 | __isl_give isl_space *isl_space_as_set_space(__isl_take isl_space *dim) |
||
1413 | { |
||
1414 | dim = isl_space_cow(dim); |
||
1415 | if (!dim) |
||
1416 | return NULL; |
||
1417 | |||
1418 | dim->n_out += dim->n_in; |
||
1419 | dim->n_in = 0; |
||
1420 | dim = isl_space_reset(dim, isl_dim_in); |
||
1421 | dim = isl_space_reset(dim, isl_dim_out); |
||
1422 | |||
1423 | return dim; |
||
1424 | } |
||
1425 | |||
1426 | __isl_give isl_space *isl_space_underlying(__isl_take isl_space *dim, |
||
1427 | unsigned n_div) |
||
1428 | { |
||
1429 | int i; |
||
1430 | |||
1431 | if (!dim) |
||
1432 | return NULL; |
||
1433 | if (n_div == 0 && |
||
1434 | dim->nparam == 0 && dim->n_in == 0 && dim->n_id == 0) |
||
1435 | return isl_space_reset(isl_space_reset(dim, isl_dim_in), isl_dim_out); |
||
1436 | dim = isl_space_cow(dim); |
||
1437 | if (!dim) |
||
1438 | return NULL; |
||
1439 | dim->n_out += dim->nparam + dim->n_in + n_div; |
||
1440 | dim->nparam = 0; |
||
1441 | dim->n_in = 0; |
||
1442 | |||
1443 | for (i = 0; i < dim->n_id; ++i) |
||
1444 | isl_id_free(get_id(dim, isl_dim_out, i)); |
||
1445 | dim->n_id = 0; |
||
1446 | dim = isl_space_reset(dim, isl_dim_in); |
||
1447 | dim = isl_space_reset(dim, isl_dim_out); |
||
1448 | |||
1449 | return dim; |
||
1450 | } |
||
1451 | |||
1452 | int isl_space_is_equal(__isl_keep isl_space *dim1, __isl_keep isl_space *dim2) |
||
1453 | { |
||
1454 | if (!dim1 || !dim2) |
||
1455 | return -1; |
||
1456 | if (dim1 == dim2) |
||
1457 | return 1; |
||
1458 | return match(dim1, isl_dim_param, dim2, isl_dim_param) && |
||
1459 | isl_space_tuple_match(dim1, isl_dim_in, dim2, isl_dim_in) && |
||
1460 | isl_space_tuple_match(dim1, isl_dim_out, dim2, isl_dim_out); |
||
1461 | } |
||
1462 | |||
1463 | /* Is space1 equal to the domain of space2? |
||
1464 | */ |
||
1465 | int isl_space_is_domain(__isl_keep isl_space *space1, |
||
1466 | __isl_keep isl_space *space2) |
||
1467 | { |
||
1468 | if (!space1 || !space2) |
||
1469 | return -1; |
||
1470 | if (!isl_space_is_set(space1)) |
||
1471 | return 0; |
||
1472 | return match(space1, isl_dim_param, space2, isl_dim_param) && |
||
1473 | isl_space_tuple_match(space1, isl_dim_set, space2, isl_dim_in); |
||
1474 | } |
||
1475 | |||
1476 | int isl_space_compatible(__isl_keep isl_space *dim1, |
||
1477 | __isl_keep isl_space *dim2) |
||
1478 | { |
||
1479 | return dim1->nparam == dim2->nparam && |
||
1480 | dim1->n_in + dim1->n_out == dim2->n_in + dim2->n_out; |
||
1481 | } |
||
1482 | |||
1483 | static uint32_t isl_hash_dim(uint32_t hash, __isl_keep isl_space *dim) |
||
1484 | { |
||
1485 | int i; |
||
1486 | isl_id *id; |
||
1487 | |||
1488 | if (!dim) |
||
1489 | return hash; |
||
1490 | |||
1491 | hash = isl_hash_builtin(hash, dim->nparam); |
||
1492 | hash = isl_hash_builtin(hash, dim->n_in); |
||
1493 | hash = isl_hash_builtin(hash, dim->n_out); |
||
1494 | |||
1495 | for (i = 0; i < dim->nparam; ++i) { |
||
1496 | id = get_id(dim, isl_dim_param, i); |
||
1497 | hash = isl_hash_id(hash, id); |
||
1498 | } |
||
1499 | |||
1500 | id = tuple_id(dim, isl_dim_in); |
||
1501 | hash = isl_hash_id(hash, id); |
||
1502 | id = tuple_id(dim, isl_dim_out); |
||
1503 | hash = isl_hash_id(hash, id); |
||
1504 | |||
1505 | hash = isl_hash_dim(hash, dim->nested[0]); |
||
1506 | hash = isl_hash_dim(hash, dim->nested[1]); |
||
1507 | |||
1508 | return hash; |
||
1509 | } |
||
1510 | |||
1511 | uint32_t isl_space_get_hash(__isl_keep isl_space *dim) |
||
1512 | { |
||
1513 | uint32_t hash; |
||
1514 | |||
1515 | if (!dim) |
||
1516 | return 0; |
||
1517 | |||
1518 | hash = isl_hash_init(); |
||
1519 | hash = isl_hash_dim(hash, dim); |
||
1520 | |||
1521 | return hash; |
||
1522 | } |
||
1523 | |||
1524 | int isl_space_is_wrapping(__isl_keep isl_space *dim) |
||
1525 | { |
||
1526 | if (!dim) |
||
1527 | return -1; |
||
1528 | |||
1529 | if (!isl_space_is_set(dim)) |
||
1530 | return 0; |
||
1531 | |||
1532 | return dim->nested[1] != NULL; |
||
1533 | } |
||
1534 | |||
1535 | __isl_give isl_space *isl_space_wrap(__isl_take isl_space *dim) |
||
1536 | { |
||
1537 | isl_space *wrap; |
||
1538 | |||
1539 | if (!dim) |
||
1540 | return NULL; |
||
1541 | |||
1542 | wrap = isl_space_set_alloc(dim->ctx, |
||
1543 | dim->nparam, dim->n_in + dim->n_out); |
||
1544 | |||
1545 | wrap = copy_ids(wrap, isl_dim_param, 0, dim, isl_dim_param); |
||
1546 | wrap = copy_ids(wrap, isl_dim_set, 0, dim, isl_dim_in); |
||
1547 | wrap = copy_ids(wrap, isl_dim_set, dim->n_in, dim, isl_dim_out); |
||
1548 | |||
1549 | if (!wrap) |
||
1550 | goto error; |
||
1551 | |||
1552 | wrap->nested[1] = dim; |
||
1553 | |||
1554 | return wrap; |
||
1555 | error: |
||
1556 | isl_space_free(dim); |
||
1557 | return NULL; |
||
1558 | } |
||
1559 | |||
1560 | __isl_give isl_space *isl_space_unwrap(__isl_take isl_space *dim) |
||
1561 | { |
||
1562 | isl_space *unwrap; |
||
1563 | |||
1564 | if (!dim) |
||
1565 | return NULL; |
||
1566 | |||
1567 | if (!isl_space_is_wrapping(dim)) |
||
1568 | isl_die(dim->ctx, isl_error_invalid, "not a wrapping space", |
||
1569 | goto error); |
||
1570 | |||
1571 | unwrap = isl_space_copy(dim->nested[1]); |
||
1572 | isl_space_free(dim); |
||
1573 | |||
1574 | return unwrap; |
||
1575 | error: |
||
1576 | isl_space_free(dim); |
||
1577 | return NULL; |
||
1578 | } |
||
1579 | |||
1580 | int isl_space_is_named_or_nested(__isl_keep isl_space *dim, enum isl_dim_type type) |
||
1581 | { |
||
1582 | if (type != isl_dim_in && type != isl_dim_out) |
||
1583 | return 0; |
||
1584 | if (!dim) |
||
1585 | return -1; |
||
1586 | if (dim->tuple_id[type - isl_dim_in]) |
||
1587 | return 1; |
||
1588 | if (dim->nested[type - isl_dim_in]) |
||
1589 | return 1; |
||
1590 | return 0; |
||
1591 | } |
||
1592 | |||
1593 | int isl_space_may_be_set(__isl_keep isl_space *dim) |
||
1594 | { |
||
1595 | if (!dim) |
||
1596 | return -1; |
||
1597 | if (isl_space_is_set(dim)) |
||
1598 | return 1; |
||
1599 | if (isl_space_dim(dim, isl_dim_in) != 0) |
||
1600 | return 0; |
||
1601 | if (isl_space_is_named_or_nested(dim, isl_dim_in)) |
||
1602 | return 0; |
||
1603 | return 1; |
||
1604 | } |
||
1605 | |||
1606 | __isl_give isl_space *isl_space_reset(__isl_take isl_space *dim, |
||
1607 | enum isl_dim_type type) |
||
1608 | { |
||
1609 | if (!isl_space_is_named_or_nested(dim, type)) |
||
1610 | return dim; |
||
1611 | |||
1612 | dim = isl_space_cow(dim); |
||
1613 | if (!dim) |
||
1614 | return NULL; |
||
1615 | |||
1616 | isl_id_free(dim->tuple_id[type - isl_dim_in]); |
||
1617 | dim->tuple_id[type - isl_dim_in] = NULL; |
||
1618 | isl_space_free(dim->nested[type - isl_dim_in]); |
||
1619 | dim->nested[type - isl_dim_in] = NULL; |
||
1620 | |||
1621 | return dim; |
||
1622 | } |
||
1623 | |||
1624 | __isl_give isl_space *isl_space_flatten(__isl_take isl_space *dim) |
||
1625 | { |
||
1626 | if (!dim) |
||
1627 | return NULL; |
||
1628 | if (!dim->nested[0] && !dim->nested[1]) |
||
1629 | return dim; |
||
1630 | |||
1631 | if (dim->nested[0]) |
||
1632 | dim = isl_space_reset(dim, isl_dim_in); |
||
1633 | if (dim && dim->nested[1]) |
||
1634 | dim = isl_space_reset(dim, isl_dim_out); |
||
1635 | |||
1636 | return dim; |
||
1637 | } |
||
1638 | |||
1639 | __isl_give isl_space *isl_space_flatten_domain(__isl_take isl_space *dim) |
||
1640 | { |
||
1641 | if (!dim) |
||
1642 | return NULL; |
||
1643 | if (!dim->nested[0]) |
||
1644 | return dim; |
||
1645 | |||
1646 | return isl_space_reset(dim, isl_dim_in); |
||
1647 | } |
||
1648 | |||
1649 | __isl_give isl_space *isl_space_flatten_range(__isl_take isl_space *dim) |
||
1650 | { |
||
1651 | if (!dim) |
||
1652 | return NULL; |
||
1653 | if (!dim->nested[1]) |
||
1654 | return dim; |
||
1655 | |||
1656 | return isl_space_reset(dim, isl_dim_out); |
||
1657 | } |
||
1658 | |||
1659 | /* Replace the dimensions of the given type of dst by those of src. |
||
1660 | */ |
||
1661 | __isl_give isl_space *isl_space_replace(__isl_take isl_space *dst, |
||
1662 | enum isl_dim_type type, __isl_keep isl_space *src) |
||
1663 | { |
||
1664 | dst = isl_space_cow(dst); |
||
1665 | |||
1666 | if (!dst || !src) |
||
1667 | goto error; |
||
1668 | |||
1669 | dst = isl_space_drop_dims(dst, type, 0, isl_space_dim(dst, type)); |
||
1670 | dst = isl_space_add_dims(dst, type, isl_space_dim(src, type)); |
||
1671 | dst = copy_ids(dst, type, 0, src, type); |
||
1672 | |||
1673 | if (dst && type == isl_dim_param) { |
||
1674 | int i; |
||
1675 | for (i = 0; i <= 1; ++i) { |
||
1676 | if (!dst->nested[i]) |
||
1677 | continue; |
||
1678 | dst->nested[i] = isl_space_replace(dst->nested[i], |
||
1679 | type, src); |
||
1680 | if (!dst->nested[i]) |
||
1681 | goto error; |
||
1682 | } |
||
1683 | } |
||
1684 | |||
1685 | return dst; |
||
1686 | error: |
||
1687 | isl_space_free(dst); |
||
1688 | return NULL; |
||
1689 | } |
||
1690 | |||
1691 | /* Given a dimension specification "dim" of a set, create a dimension |
||
1692 | * specification for the lift of the set. In particular, the result |
||
1693 | * is of the form [dim -> local[..]], with n_local variables in the |
||
1694 | * range of the wrapped map. |
||
1695 | */ |
||
1696 | __isl_give isl_space *isl_space_lift(__isl_take isl_space *dim, unsigned n_local) |
||
1697 | { |
||
1698 | isl_space *local_dim; |
||
1699 | |||
1700 | if (!dim) |
||
1701 | return NULL; |
||
1702 | |||
1703 | local_dim = isl_space_dup(dim); |
||
1704 | local_dim = isl_space_drop_dims(local_dim, isl_dim_set, 0, dim->n_out); |
||
1705 | local_dim = isl_space_add_dims(local_dim, isl_dim_set, n_local); |
||
1706 | local_dim = isl_space_set_tuple_name(local_dim, isl_dim_set, "local"); |
||
1707 | dim = isl_space_join(isl_space_from_domain(dim), |
||
1708 | isl_space_from_range(local_dim)); |
||
1709 | dim = isl_space_wrap(dim); |
||
1710 | dim = isl_space_set_tuple_name(dim, isl_dim_set, "lifted"); |
||
1711 | |||
1712 | return dim; |
||
1713 | } |
||
1714 | |||
1715 | int isl_space_can_zip(__isl_keep isl_space *dim) |
||
1716 | { |
||
1717 | if (!dim) |
||
1718 | return -1; |
||
1719 | |||
1720 | return dim->nested[0] && dim->nested[1]; |
||
1721 | } |
||
1722 | |||
1723 | __isl_give isl_space *isl_space_zip(__isl_take isl_space *dim) |
||
1724 | { |
||
1725 | isl_space *dom, *ran; |
||
1726 | isl_space *dom_dom, *dom_ran, *ran_dom, *ran_ran; |
||
1727 | |||
1728 | if (!isl_space_can_zip(dim)) |
||
1729 | isl_die(dim->ctx, isl_error_invalid, "dim cannot be zipped", |
||
1730 | goto error); |
||
1731 | |||
1732 | if (!dim) |
||
1733 | return NULL; |
||
1734 | dom = isl_space_unwrap(isl_space_domain(isl_space_copy(dim))); |
||
1735 | ran = isl_space_unwrap(isl_space_range(dim)); |
||
1736 | dom_dom = isl_space_domain(isl_space_copy(dom)); |
||
1737 | dom_ran = isl_space_range(dom); |
||
1738 | ran_dom = isl_space_domain(isl_space_copy(ran)); |
||
1739 | ran_ran = isl_space_range(ran); |
||
1740 | dom = isl_space_join(isl_space_from_domain(dom_dom), |
||
1741 | isl_space_from_range(ran_dom)); |
||
1742 | ran = isl_space_join(isl_space_from_domain(dom_ran), |
||
1743 | isl_space_from_range(ran_ran)); |
||
1744 | return isl_space_join(isl_space_from_domain(isl_space_wrap(dom)), |
||
1745 | isl_space_from_range(isl_space_wrap(ran))); |
||
1746 | error: |
||
1747 | isl_space_free(dim); |
||
1748 | return NULL; |
||
1749 | } |
||
1750 | |||
1751 | /* Can we apply isl_space_curry to "space"? |
||
1752 | * That is, does it have a nested relation in its domain? |
||
1753 | */ |
||
1754 | int isl_space_can_curry(__isl_keep isl_space *space) |
||
1755 | { |
||
1756 | if (!space) |
||
1757 | return -1; |
||
1758 | |||
1759 | return !!space->nested[0]; |
||
1760 | } |
||
1761 | |||
1762 | /* Given a space (A -> B) -> C, return the corresponding space |
||
1763 | * A -> (B -> C). |
||
1764 | */ |
||
1765 | __isl_give isl_space *isl_space_curry(__isl_take isl_space *space) |
||
1766 | { |
||
1767 | isl_space *dom, *ran; |
||
1768 | isl_space *dom_dom, *dom_ran; |
||
1769 | |||
1770 | if (!space) |
||
1771 | return NULL; |
||
1772 | |||
1773 | if (!isl_space_can_curry(space)) |
||
1774 | isl_die(space->ctx, isl_error_invalid, |
||
1775 | "space cannot be curried", goto error); |
||
1776 | |||
1777 | dom = isl_space_unwrap(isl_space_domain(isl_space_copy(space))); |
||
1778 | ran = isl_space_range(space); |
||
1779 | dom_dom = isl_space_domain(isl_space_copy(dom)); |
||
1780 | dom_ran = isl_space_range(dom); |
||
1781 | ran = isl_space_join(isl_space_from_domain(dom_ran), |
||
1782 | isl_space_from_range(ran)); |
||
1783 | return isl_space_join(isl_space_from_domain(dom_dom), |
||
1784 | isl_space_from_range(isl_space_wrap(ran))); |
||
1785 | error: |
||
1786 | isl_space_free(space); |
||
1787 | return NULL; |
||
1788 | } |
||
1789 | |||
1790 | int isl_space_has_named_params(__isl_keep isl_space *dim) |
||
1791 | { |
||
1792 | int i; |
||
1793 | unsigned off; |
||
1794 | |||
1795 | if (!dim) |
||
1796 | return -1; |
||
1797 | if (dim->nparam == 0) |
||
1798 | return 1; |
||
1799 | off = isl_space_offset(dim, isl_dim_param); |
||
1800 | if (off + dim->nparam > dim->n_id) |
||
1801 | return 0; |
||
1802 | for (i = 0; i < dim->nparam; ++i) |
||
1803 | if (!dim->ids[off + i]) |
||
1804 | return 0; |
||
1805 | return 1; |
||
1806 | } |
||
1807 | |||
1808 | /* Align the initial parameters of dim1 to match the order in dim2. |
||
1809 | */ |
||
1810 | __isl_give isl_space *isl_space_align_params(__isl_take isl_space *dim1, |
||
1811 | __isl_take isl_space *dim2) |
||
1812 | { |
||
1813 | isl_reordering *exp; |
||
1814 | |||
1815 | if (!isl_space_has_named_params(dim1) || !isl_space_has_named_params(dim2)) |
||
1816 | isl_die(isl_space_get_ctx(dim1), isl_error_invalid, |
||
1817 | "parameter alignment requires named parameters", |
||
1818 | goto error); |
||
1819 | |||
1820 | dim2 = isl_space_params(dim2); |
||
1821 | exp = isl_parameter_alignment_reordering(dim1, dim2); |
||
1822 | exp = isl_reordering_extend_space(exp, dim1); |
||
1823 | isl_space_free(dim2); |
||
1824 | if (!exp) |
||
1825 | return NULL; |
||
1826 | dim1 = isl_space_copy(exp->dim); |
||
1827 | isl_reordering_free(exp); |
||
1828 | return dim1; |
||
1829 | error: |
||
1830 | isl_space_free(dim1); |
||
1831 | isl_space_free(dim2); |
||
1832 | return NULL; |
||
1833 | } |
||
1834 | |||
1835 | /* Given the space of set (domain), construct a space for a map |
||
1836 | * with as domain the given space and as range the range of "model". |
||
1837 | */ |
||
1838 | __isl_give isl_space *isl_space_extend_domain_with_range( |
||
1839 | __isl_take isl_space *domain, __isl_take isl_space *model) |
||
1840 | { |
||
1841 | isl_space *space; |
||
1842 | |||
1843 | space = isl_space_from_domain(domain); |
||
1844 | space = isl_space_add_dims(space, isl_dim_out, |
||
1845 | isl_space_dim(model, isl_dim_out)); |
||
1846 | if (isl_space_has_tuple_id(model, isl_dim_out)) |
||
1847 | space = isl_space_set_tuple_id(space, isl_dim_out, |
||
1848 | isl_space_get_tuple_id(model, isl_dim_out)); |
||
1849 | isl_space_free(model); |
||
1850 | return space; |
||
1851 | } |