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 <string.h> |
||
14 | #include <isl_ctx_private.h> |
||
15 | #include <isl_map_private.h> |
||
16 | #include <isl/blk.h> |
||
17 | #include "isl_space_private.h" |
||
18 | #include "isl_equalities.h" |
||
19 | #include <isl_list_private.h> |
||
20 | #include <isl/lp.h> |
||
21 | #include <isl/seq.h> |
||
22 | #include <isl/set.h> |
||
23 | #include <isl/map.h> |
||
24 | #include "isl_map_piplib.h" |
||
25 | #include <isl_reordering.h> |
||
26 | #include "isl_sample.h" |
||
27 | #include "isl_tab.h" |
||
28 | #include <isl/vec.h> |
||
29 | #include <isl_mat_private.h> |
||
30 | #include <isl_dim_map.h> |
||
31 | #include <isl_local_space_private.h> |
||
32 | #include <isl_aff_private.h> |
||
33 | #include <isl_options_private.h> |
||
34 | |||
35 | static unsigned n(__isl_keep isl_space *dim, enum isl_dim_type type) |
||
36 | { |
||
37 | switch (type) { |
||
38 | case isl_dim_param: return dim->nparam; |
||
39 | case isl_dim_in: return dim->n_in; |
||
40 | case isl_dim_out: return dim->n_out; |
||
41 | case isl_dim_all: return dim->nparam + dim->n_in + dim->n_out; |
||
42 | default: return 0; |
||
43 | } |
||
44 | } |
||
45 | |||
46 | static unsigned pos(__isl_keep isl_space *dim, enum isl_dim_type type) |
||
47 | { |
||
48 | switch (type) { |
||
49 | case isl_dim_param: return 1; |
||
50 | case isl_dim_in: return 1 + dim->nparam; |
||
51 | case isl_dim_out: return 1 + dim->nparam + dim->n_in; |
||
52 | default: return 0; |
||
53 | } |
||
54 | } |
||
55 | |||
56 | unsigned isl_basic_map_dim(__isl_keep isl_basic_map *bmap, |
||
57 | enum isl_dim_type type) |
||
58 | { |
||
59 | if (!bmap) |
||
60 | return 0; |
||
61 | switch (type) { |
||
62 | case isl_dim_cst: return 1; |
||
63 | case isl_dim_param: |
||
64 | case isl_dim_in: |
||
65 | case isl_dim_out: return isl_space_dim(bmap->dim, type); |
||
66 | case isl_dim_div: return bmap->n_div; |
||
67 | case isl_dim_all: return isl_basic_map_total_dim(bmap); |
||
68 | default: return 0; |
||
69 | } |
||
70 | } |
||
71 | |||
72 | unsigned isl_map_dim(__isl_keep isl_map *map, enum isl_dim_type type) |
||
73 | { |
||
74 | return map ? n(map->dim, type) : 0; |
||
75 | } |
||
76 | |||
77 | unsigned isl_set_dim(__isl_keep isl_set *set, enum isl_dim_type type) |
||
78 | { |
||
79 | return set ? n(set->dim, type) : 0; |
||
80 | } |
||
81 | |||
82 | unsigned isl_basic_map_offset(struct isl_basic_map *bmap, |
||
83 | enum isl_dim_type type) |
||
84 | { |
||
85 | isl_space *dim = bmap->dim; |
||
86 | switch (type) { |
||
87 | case isl_dim_cst: return 0; |
||
88 | case isl_dim_param: return 1; |
||
89 | case isl_dim_in: return 1 + dim->nparam; |
||
90 | case isl_dim_out: return 1 + dim->nparam + dim->n_in; |
||
91 | case isl_dim_div: return 1 + dim->nparam + dim->n_in + dim->n_out; |
||
92 | default: return 0; |
||
93 | } |
||
94 | } |
||
95 | |||
96 | unsigned isl_basic_set_offset(struct isl_basic_set *bset, |
||
97 | enum isl_dim_type type) |
||
98 | { |
||
99 | return isl_basic_map_offset(bset, type); |
||
100 | } |
||
101 | |||
102 | static unsigned map_offset(struct isl_map *map, enum isl_dim_type type) |
||
103 | { |
||
104 | return pos(map->dim, type); |
||
105 | } |
||
106 | |||
107 | unsigned isl_basic_set_dim(__isl_keep isl_basic_set *bset, |
||
108 | enum isl_dim_type type) |
||
109 | { |
||
110 | return isl_basic_map_dim(bset, type); |
||
111 | } |
||
112 | |||
113 | unsigned isl_basic_set_n_dim(__isl_keep isl_basic_set *bset) |
||
114 | { |
||
115 | return isl_basic_set_dim(bset, isl_dim_set); |
||
116 | } |
||
117 | |||
118 | unsigned isl_basic_set_n_param(__isl_keep isl_basic_set *bset) |
||
119 | { |
||
120 | return isl_basic_set_dim(bset, isl_dim_param); |
||
121 | } |
||
122 | |||
123 | unsigned isl_basic_set_total_dim(const struct isl_basic_set *bset) |
||
124 | { |
||
125 | if (!bset) |
||
126 | return 0; |
||
127 | return isl_space_dim(bset->dim, isl_dim_all) + bset->n_div; |
||
128 | } |
||
129 | |||
130 | unsigned isl_set_n_dim(__isl_keep isl_set *set) |
||
131 | { |
||
132 | return isl_set_dim(set, isl_dim_set); |
||
133 | } |
||
134 | |||
135 | unsigned isl_set_n_param(__isl_keep isl_set *set) |
||
136 | { |
||
137 | return isl_set_dim(set, isl_dim_param); |
||
138 | } |
||
139 | |||
140 | unsigned isl_basic_map_n_in(const struct isl_basic_map *bmap) |
||
141 | { |
||
142 | return bmap ? bmap->dim->n_in : 0; |
||
143 | } |
||
144 | |||
145 | unsigned isl_basic_map_n_out(const struct isl_basic_map *bmap) |
||
146 | { |
||
147 | return bmap ? bmap->dim->n_out : 0; |
||
148 | } |
||
149 | |||
150 | unsigned isl_basic_map_n_param(const struct isl_basic_map *bmap) |
||
151 | { |
||
152 | return bmap ? bmap->dim->nparam : 0; |
||
153 | } |
||
154 | |||
155 | unsigned isl_basic_map_n_div(const struct isl_basic_map *bmap) |
||
156 | { |
||
157 | return bmap ? bmap->n_div : 0; |
||
158 | } |
||
159 | |||
160 | unsigned isl_basic_map_total_dim(const struct isl_basic_map *bmap) |
||
161 | { |
||
162 | return bmap ? isl_space_dim(bmap->dim, isl_dim_all) + bmap->n_div : 0; |
||
163 | } |
||
164 | |||
165 | unsigned isl_map_n_in(const struct isl_map *map) |
||
166 | { |
||
167 | return map ? map->dim->n_in : 0; |
||
168 | } |
||
169 | |||
170 | unsigned isl_map_n_out(const struct isl_map *map) |
||
171 | { |
||
172 | return map ? map->dim->n_out : 0; |
||
173 | } |
||
174 | |||
175 | unsigned isl_map_n_param(const struct isl_map *map) |
||
176 | { |
||
177 | return map ? map->dim->nparam : 0; |
||
178 | } |
||
179 | |||
180 | int isl_map_compatible_domain(struct isl_map *map, struct isl_set *set) |
||
181 | { |
||
182 | int m; |
||
183 | if (!map || !set) |
||
184 | return -1; |
||
185 | m = isl_space_match(map->dim, isl_dim_param, set->dim, isl_dim_param); |
||
186 | if (m < 0 || !m) |
||
187 | return m; |
||
188 | return isl_space_tuple_match(map->dim, isl_dim_in, set->dim, isl_dim_set); |
||
189 | } |
||
190 | |||
191 | int isl_basic_map_compatible_domain(struct isl_basic_map *bmap, |
||
192 | struct isl_basic_set *bset) |
||
193 | { |
||
194 | int m; |
||
195 | if (!bmap || !bset) |
||
196 | return -1; |
||
197 | m = isl_space_match(bmap->dim, isl_dim_param, bset->dim, isl_dim_param); |
||
198 | if (m < 0 || !m) |
||
199 | return m; |
||
200 | return isl_space_tuple_match(bmap->dim, isl_dim_in, bset->dim, isl_dim_set); |
||
201 | } |
||
202 | |||
203 | int isl_map_compatible_range(__isl_keep isl_map *map, __isl_keep isl_set *set) |
||
204 | { |
||
205 | int m; |
||
206 | if (!map || !set) |
||
207 | return -1; |
||
208 | m = isl_space_match(map->dim, isl_dim_param, set->dim, isl_dim_param); |
||
209 | if (m < 0 || !m) |
||
210 | return m; |
||
211 | return isl_space_tuple_match(map->dim, isl_dim_out, set->dim, isl_dim_set); |
||
212 | } |
||
213 | |||
214 | int isl_basic_map_compatible_range(struct isl_basic_map *bmap, |
||
215 | struct isl_basic_set *bset) |
||
216 | { |
||
217 | int m; |
||
218 | if (!bmap || !bset) |
||
219 | return -1; |
||
220 | m = isl_space_match(bmap->dim, isl_dim_param, bset->dim, isl_dim_param); |
||
221 | if (m < 0 || !m) |
||
222 | return m; |
||
223 | return isl_space_tuple_match(bmap->dim, isl_dim_out, bset->dim, isl_dim_set); |
||
224 | } |
||
225 | |||
226 | isl_ctx *isl_basic_map_get_ctx(__isl_keep isl_basic_map *bmap) |
||
227 | { |
||
228 | return bmap ? bmap->ctx : NULL; |
||
229 | } |
||
230 | |||
231 | isl_ctx *isl_basic_set_get_ctx(__isl_keep isl_basic_set *bset) |
||
232 | { |
||
233 | return bset ? bset->ctx : NULL; |
||
234 | } |
||
235 | |||
236 | isl_ctx *isl_map_get_ctx(__isl_keep isl_map *map) |
||
237 | { |
||
238 | return map ? map->ctx : NULL; |
||
239 | } |
||
240 | |||
241 | isl_ctx *isl_set_get_ctx(__isl_keep isl_set *set) |
||
242 | { |
||
243 | return set ? set->ctx : NULL; |
||
244 | } |
||
245 | |||
246 | __isl_give isl_space *isl_basic_map_get_space(__isl_keep isl_basic_map *bmap) |
||
247 | { |
||
248 | if (!bmap) |
||
249 | return NULL; |
||
250 | return isl_space_copy(bmap->dim); |
||
251 | } |
||
252 | |||
253 | __isl_give isl_space *isl_basic_set_get_space(__isl_keep isl_basic_set *bset) |
||
254 | { |
||
255 | if (!bset) |
||
256 | return NULL; |
||
257 | return isl_space_copy(bset->dim); |
||
258 | } |
||
259 | |||
260 | /* Extract the divs in "bmap" as a matrix. |
||
261 | */ |
||
262 | __isl_give isl_mat *isl_basic_map_get_divs(__isl_keep isl_basic_map *bmap) |
||
263 | { |
||
264 | int i; |
||
265 | isl_ctx *ctx; |
||
266 | isl_mat *div; |
||
267 | unsigned total; |
||
268 | unsigned cols; |
||
269 | |||
270 | if (!bmap) |
||
271 | return NULL; |
||
272 | |||
273 | ctx = isl_basic_map_get_ctx(bmap); |
||
274 | total = isl_space_dim(bmap->dim, isl_dim_all); |
||
275 | cols = 1 + 1 + total + bmap->n_div; |
||
276 | div = isl_mat_alloc(ctx, bmap->n_div, cols); |
||
277 | if (!div) |
||
278 | return NULL; |
||
279 | |||
280 | for (i = 0; i < bmap->n_div; ++i) |
||
281 | isl_seq_cpy(div->row[i], bmap->div[i], cols); |
||
282 | |||
283 | return div; |
||
284 | } |
||
285 | |||
286 | __isl_give isl_local_space *isl_basic_map_get_local_space( |
||
287 | __isl_keep isl_basic_map *bmap) |
||
288 | { |
||
289 | isl_mat *div; |
||
290 | |||
291 | if (!bmap) |
||
292 | return NULL; |
||
293 | |||
294 | div = isl_basic_map_get_divs(bmap); |
||
295 | return isl_local_space_alloc_div(isl_space_copy(bmap->dim), div); |
||
296 | } |
||
297 | |||
298 | __isl_give isl_local_space *isl_basic_set_get_local_space( |
||
299 | __isl_keep isl_basic_set *bset) |
||
300 | { |
||
301 | return isl_basic_map_get_local_space(bset); |
||
302 | } |
||
303 | |||
304 | __isl_give isl_basic_map *isl_basic_map_from_local_space( |
||
305 | __isl_take isl_local_space *ls) |
||
306 | { |
||
307 | int i; |
||
308 | int n_div; |
||
309 | isl_basic_map *bmap; |
||
310 | |||
311 | if (!ls) |
||
312 | return NULL; |
||
313 | |||
314 | n_div = isl_local_space_dim(ls, isl_dim_div); |
||
315 | bmap = isl_basic_map_alloc_space(isl_local_space_get_space(ls), |
||
316 | n_div, 0, 2 * n_div); |
||
317 | |||
318 | for (i = 0; i < n_div; ++i) |
||
319 | if (isl_basic_map_alloc_div(bmap) < 0) |
||
320 | goto error; |
||
321 | |||
322 | for (i = 0; i < n_div; ++i) { |
||
323 | isl_seq_cpy(bmap->div[i], ls->div->row[i], ls->div->n_col); |
||
324 | if (isl_basic_map_add_div_constraints(bmap, i) < 0) |
||
325 | goto error; |
||
326 | } |
||
327 | |||
328 | isl_local_space_free(ls); |
||
329 | return bmap; |
||
330 | error: |
||
331 | isl_local_space_free(ls); |
||
332 | isl_basic_map_free(bmap); |
||
333 | return NULL; |
||
334 | } |
||
335 | |||
336 | __isl_give isl_basic_set *isl_basic_set_from_local_space( |
||
337 | __isl_take isl_local_space *ls) |
||
338 | { |
||
339 | return isl_basic_map_from_local_space(ls); |
||
340 | } |
||
341 | |||
342 | __isl_give isl_space *isl_map_get_space(__isl_keep isl_map *map) |
||
343 | { |
||
344 | if (!map) |
||
345 | return NULL; |
||
346 | return isl_space_copy(map->dim); |
||
347 | } |
||
348 | |||
349 | __isl_give isl_space *isl_set_get_space(__isl_keep isl_set *set) |
||
350 | { |
||
351 | if (!set) |
||
352 | return NULL; |
||
353 | return isl_space_copy(set->dim); |
||
354 | } |
||
355 | |||
356 | __isl_give isl_basic_map *isl_basic_map_set_tuple_name( |
||
357 | __isl_take isl_basic_map *bmap, enum isl_dim_type type, const char *s) |
||
358 | { |
||
359 | bmap = isl_basic_map_cow(bmap); |
||
360 | if (!bmap) |
||
361 | return NULL; |
||
362 | bmap->dim = isl_space_set_tuple_name(bmap->dim, type, s); |
||
363 | if (!bmap->dim) |
||
364 | goto error; |
||
365 | bmap = isl_basic_map_finalize(bmap); |
||
366 | return bmap; |
||
367 | error: |
||
368 | isl_basic_map_free(bmap); |
||
369 | return NULL; |
||
370 | } |
||
371 | |||
372 | __isl_give isl_basic_set *isl_basic_set_set_tuple_name( |
||
373 | __isl_take isl_basic_set *bset, const char *s) |
||
374 | { |
||
375 | return isl_basic_map_set_tuple_name(bset, isl_dim_set, s); |
||
376 | } |
||
377 | |||
378 | const char *isl_basic_map_get_tuple_name(__isl_keep isl_basic_map *bmap, |
||
379 | enum isl_dim_type type) |
||
380 | { |
||
381 | return bmap ? isl_space_get_tuple_name(bmap->dim, type) : NULL; |
||
382 | } |
||
383 | |||
384 | __isl_give isl_map *isl_map_set_tuple_name(__isl_take isl_map *map, |
||
385 | enum isl_dim_type type, const char *s) |
||
386 | { |
||
387 | int i; |
||
388 | |||
389 | map = isl_map_cow(map); |
||
390 | if (!map) |
||
391 | return NULL; |
||
392 | |||
393 | map->dim = isl_space_set_tuple_name(map->dim, type, s); |
||
394 | if (!map->dim) |
||
395 | goto error; |
||
396 | |||
397 | for (i = 0; i < map->n; ++i) { |
||
398 | map->p[i] = isl_basic_map_set_tuple_name(map->p[i], type, s); |
||
399 | if (!map->p[i]) |
||
400 | goto error; |
||
401 | } |
||
402 | |||
403 | return map; |
||
404 | error: |
||
405 | isl_map_free(map); |
||
406 | return NULL; |
||
407 | } |
||
408 | |||
409 | const char *isl_map_get_tuple_name(__isl_keep isl_map *map, |
||
410 | enum isl_dim_type type) |
||
411 | { |
||
412 | return map ? isl_space_get_tuple_name(map->dim, type) : NULL; |
||
413 | } |
||
414 | |||
415 | __isl_give isl_set *isl_set_set_tuple_name(__isl_take isl_set *set, |
||
416 | const char *s) |
||
417 | { |
||
418 | return (isl_set *)isl_map_set_tuple_name((isl_map *)set, isl_dim_set, s); |
||
419 | } |
||
420 | |||
421 | __isl_give isl_map *isl_map_set_tuple_id(__isl_take isl_map *map, |
||
422 | enum isl_dim_type type, __isl_take isl_id *id) |
||
423 | { |
||
424 | map = isl_map_cow(map); |
||
425 | if (!map) |
||
426 | return isl_id_free(id); |
||
427 | |||
428 | map->dim = isl_space_set_tuple_id(map->dim, type, id); |
||
429 | |||
430 | return isl_map_reset_space(map, isl_space_copy(map->dim)); |
||
431 | } |
||
432 | |||
433 | __isl_give isl_set *isl_set_set_tuple_id(__isl_take isl_set *set, |
||
434 | __isl_take isl_id *id) |
||
435 | { |
||
436 | return isl_map_set_tuple_id(set, isl_dim_set, id); |
||
437 | } |
||
438 | |||
439 | __isl_give isl_map *isl_map_reset_tuple_id(__isl_take isl_map *map, |
||
440 | enum isl_dim_type type) |
||
441 | { |
||
442 | map = isl_map_cow(map); |
||
443 | if (!map) |
||
444 | return NULL; |
||
445 | |||
446 | map->dim = isl_space_reset_tuple_id(map->dim, type); |
||
447 | |||
448 | return isl_map_reset_space(map, isl_space_copy(map->dim)); |
||
449 | } |
||
450 | |||
451 | __isl_give isl_set *isl_set_reset_tuple_id(__isl_take isl_set *set) |
||
452 | { |
||
453 | return isl_map_reset_tuple_id(set, isl_dim_set); |
||
454 | } |
||
455 | |||
456 | int isl_map_has_tuple_id(__isl_keep isl_map *map, enum isl_dim_type type) |
||
457 | { |
||
458 | return map ? isl_space_has_tuple_id(map->dim, type) : -1; |
||
459 | } |
||
460 | |||
461 | __isl_give isl_id *isl_map_get_tuple_id(__isl_keep isl_map *map, |
||
462 | enum isl_dim_type type) |
||
463 | { |
||
464 | return map ? isl_space_get_tuple_id(map->dim, type) : NULL; |
||
465 | } |
||
466 | |||
467 | int isl_set_has_tuple_id(__isl_keep isl_set *set) |
||
468 | { |
||
469 | return isl_map_has_tuple_id(set, isl_dim_set); |
||
470 | } |
||
471 | |||
472 | __isl_give isl_id *isl_set_get_tuple_id(__isl_keep isl_set *set) |
||
473 | { |
||
474 | return isl_map_get_tuple_id(set, isl_dim_set); |
||
475 | } |
||
476 | |||
477 | /* Does the set tuple have a name? |
||
478 | */ |
||
479 | int isl_set_has_tuple_name(__isl_keep isl_set *set) |
||
480 | { |
||
481 | return set ? isl_space_has_tuple_name(set->dim, isl_dim_set) : -1; |
||
482 | } |
||
483 | |||
484 | |||
485 | const char *isl_basic_set_get_tuple_name(__isl_keep isl_basic_set *bset) |
||
486 | { |
||
487 | return bset ? isl_space_get_tuple_name(bset->dim, isl_dim_set) : NULL; |
||
488 | } |
||
489 | |||
490 | const char *isl_set_get_tuple_name(__isl_keep isl_set *set) |
||
491 | { |
||
492 | return set ? isl_space_get_tuple_name(set->dim, isl_dim_set) : NULL; |
||
493 | } |
||
494 | |||
495 | const char *isl_basic_map_get_dim_name(__isl_keep isl_basic_map *bmap, |
||
496 | enum isl_dim_type type, unsigned pos) |
||
497 | { |
||
498 | return bmap ? isl_space_get_dim_name(bmap->dim, type, pos) : NULL; |
||
499 | } |
||
500 | |||
501 | const char *isl_basic_set_get_dim_name(__isl_keep isl_basic_set *bset, |
||
502 | enum isl_dim_type type, unsigned pos) |
||
503 | { |
||
504 | return bset ? isl_space_get_dim_name(bset->dim, type, pos) : NULL; |
||
505 | } |
||
506 | |||
507 | const char *isl_map_get_dim_name(__isl_keep isl_map *map, |
||
508 | enum isl_dim_type type, unsigned pos) |
||
509 | { |
||
510 | return map ? isl_space_get_dim_name(map->dim, type, pos) : NULL; |
||
511 | } |
||
512 | |||
513 | const char *isl_set_get_dim_name(__isl_keep isl_set *set, |
||
514 | enum isl_dim_type type, unsigned pos) |
||
515 | { |
||
516 | return set ? isl_space_get_dim_name(set->dim, type, pos) : NULL; |
||
517 | } |
||
518 | |||
519 | /* Does the given dimension have a name? |
||
520 | */ |
||
521 | int isl_set_has_dim_name(__isl_keep isl_set *set, |
||
522 | enum isl_dim_type type, unsigned pos) |
||
523 | { |
||
524 | return set ? isl_space_has_dim_name(set->dim, type, pos) : -1; |
||
525 | } |
||
526 | |||
527 | __isl_give isl_basic_map *isl_basic_map_set_dim_name( |
||
528 | __isl_take isl_basic_map *bmap, |
||
529 | enum isl_dim_type type, unsigned pos, const char *s) |
||
530 | { |
||
531 | bmap = isl_basic_map_cow(bmap); |
||
532 | if (!bmap) |
||
533 | return NULL; |
||
534 | bmap->dim = isl_space_set_dim_name(bmap->dim, type, pos, s); |
||
535 | if (!bmap->dim) |
||
536 | goto error; |
||
537 | return isl_basic_map_finalize(bmap); |
||
538 | error: |
||
539 | isl_basic_map_free(bmap); |
||
540 | return NULL; |
||
541 | } |
||
542 | |||
543 | __isl_give isl_map *isl_map_set_dim_name(__isl_take isl_map *map, |
||
544 | enum isl_dim_type type, unsigned pos, const char *s) |
||
545 | { |
||
546 | int i; |
||
547 | |||
548 | map = isl_map_cow(map); |
||
549 | if (!map) |
||
550 | return NULL; |
||
551 | |||
552 | map->dim = isl_space_set_dim_name(map->dim, type, pos, s); |
||
553 | if (!map->dim) |
||
554 | goto error; |
||
555 | |||
556 | for (i = 0; i < map->n; ++i) { |
||
557 | map->p[i] = isl_basic_map_set_dim_name(map->p[i], type, pos, s); |
||
558 | if (!map->p[i]) |
||
559 | goto error; |
||
560 | } |
||
561 | |||
562 | return map; |
||
563 | error: |
||
564 | isl_map_free(map); |
||
565 | return NULL; |
||
566 | } |
||
567 | |||
568 | __isl_give isl_basic_set *isl_basic_set_set_dim_name( |
||
569 | __isl_take isl_basic_set *bset, |
||
570 | enum isl_dim_type type, unsigned pos, const char *s) |
||
571 | { |
||
572 | return (isl_basic_set *)isl_basic_map_set_dim_name( |
||
573 | (isl_basic_map *)bset, type, pos, s); |
||
574 | } |
||
575 | |||
576 | __isl_give isl_set *isl_set_set_dim_name(__isl_take isl_set *set, |
||
577 | enum isl_dim_type type, unsigned pos, const char *s) |
||
578 | { |
||
579 | return (isl_set *)isl_map_set_dim_name((isl_map *)set, type, pos, s); |
||
580 | } |
||
581 | |||
582 | int isl_basic_map_has_dim_id(__isl_keep isl_basic_map *bmap, |
||
583 | enum isl_dim_type type, unsigned pos) |
||
584 | { |
||
585 | return bmap ? isl_space_has_dim_id(bmap->dim, type, pos) : -1; |
||
586 | } |
||
587 | |||
588 | __isl_give isl_id *isl_basic_set_get_dim_id(__isl_keep isl_basic_set *bset, |
||
589 | enum isl_dim_type type, unsigned pos) |
||
590 | { |
||
591 | return bset ? isl_space_get_dim_id(bset->dim, type, pos) : NULL; |
||
592 | } |
||
593 | |||
594 | int isl_map_has_dim_id(__isl_keep isl_map *map, |
||
595 | enum isl_dim_type type, unsigned pos) |
||
596 | { |
||
597 | return map ? isl_space_has_dim_id(map->dim, type, pos) : -1; |
||
598 | } |
||
599 | |||
600 | __isl_give isl_id *isl_map_get_dim_id(__isl_keep isl_map *map, |
||
601 | enum isl_dim_type type, unsigned pos) |
||
602 | { |
||
603 | return map ? isl_space_get_dim_id(map->dim, type, pos) : NULL; |
||
604 | } |
||
605 | |||
606 | int isl_set_has_dim_id(__isl_keep isl_set *set, |
||
607 | enum isl_dim_type type, unsigned pos) |
||
608 | { |
||
609 | return isl_map_has_dim_id(set, type, pos); |
||
610 | } |
||
611 | |||
612 | __isl_give isl_id *isl_set_get_dim_id(__isl_keep isl_set *set, |
||
613 | enum isl_dim_type type, unsigned pos) |
||
614 | { |
||
615 | return isl_map_get_dim_id(set, type, pos); |
||
616 | } |
||
617 | |||
618 | __isl_give isl_map *isl_map_set_dim_id(__isl_take isl_map *map, |
||
619 | enum isl_dim_type type, unsigned pos, __isl_take isl_id *id) |
||
620 | { |
||
621 | map = isl_map_cow(map); |
||
622 | if (!map) |
||
623 | return isl_id_free(id); |
||
624 | |||
625 | map->dim = isl_space_set_dim_id(map->dim, type, pos, id); |
||
626 | |||
627 | return isl_map_reset_space(map, isl_space_copy(map->dim)); |
||
628 | } |
||
629 | |||
630 | __isl_give isl_set *isl_set_set_dim_id(__isl_take isl_set *set, |
||
631 | enum isl_dim_type type, unsigned pos, __isl_take isl_id *id) |
||
632 | { |
||
633 | return isl_map_set_dim_id(set, type, pos, id); |
||
634 | } |
||
635 | |||
636 | int isl_map_find_dim_by_id(__isl_keep isl_map *map, enum isl_dim_type type, |
||
637 | __isl_keep isl_id *id) |
||
638 | { |
||
639 | if (!map) |
||
640 | return -1; |
||
641 | return isl_space_find_dim_by_id(map->dim, type, id); |
||
642 | } |
||
643 | |||
644 | int isl_set_find_dim_by_id(__isl_keep isl_set *set, enum isl_dim_type type, |
||
645 | __isl_keep isl_id *id) |
||
646 | { |
||
647 | return isl_map_find_dim_by_id(set, type, id); |
||
648 | } |
||
649 | |||
650 | int isl_map_find_dim_by_name(__isl_keep isl_map *map, enum isl_dim_type type, |
||
651 | const char *name) |
||
652 | { |
||
653 | if (!map) |
||
654 | return -1; |
||
655 | return isl_space_find_dim_by_name(map->dim, type, name); |
||
656 | } |
||
657 | |||
658 | int isl_set_find_dim_by_name(__isl_keep isl_set *set, enum isl_dim_type type, |
||
659 | const char *name) |
||
660 | { |
||
661 | return isl_map_find_dim_by_name(set, type, name); |
||
662 | } |
||
663 | |||
664 | int isl_basic_map_is_rational(__isl_keep isl_basic_map *bmap) |
||
665 | { |
||
666 | if (!bmap) |
||
667 | return -1; |
||
668 | return ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL); |
||
669 | } |
||
670 | |||
671 | int isl_basic_set_is_rational(__isl_keep isl_basic_set *bset) |
||
672 | { |
||
673 | return isl_basic_map_is_rational(bset); |
||
674 | } |
||
675 | |||
676 | /* Is this basic set a parameter domain? |
||
677 | */ |
||
678 | int isl_basic_set_is_params(__isl_keep isl_basic_set *bset) |
||
679 | { |
||
680 | if (!bset) |
||
681 | return -1; |
||
682 | return isl_space_is_params(bset->dim); |
||
683 | } |
||
684 | |||
685 | /* Is this set a parameter domain? |
||
686 | */ |
||
687 | int isl_set_is_params(__isl_keep isl_set *set) |
||
688 | { |
||
689 | if (!set) |
||
690 | return -1; |
||
691 | return isl_space_is_params(set->dim); |
||
692 | } |
||
693 | |||
694 | /* Is this map actually a parameter domain? |
||
695 | * Users should never call this function. Outside of isl, |
||
696 | * a map can never be a parameter domain. |
||
697 | */ |
||
698 | int isl_map_is_params(__isl_keep isl_map *map) |
||
699 | { |
||
700 | if (!map) |
||
701 | return -1; |
||
702 | return isl_space_is_params(map->dim); |
||
703 | } |
||
704 | |||
705 | static struct isl_basic_map *basic_map_init(struct isl_ctx *ctx, |
||
706 | struct isl_basic_map *bmap, unsigned extra, |
||
707 | unsigned n_eq, unsigned n_ineq) |
||
708 | { |
||
709 | int i; |
||
710 | size_t row_size = 1 + isl_space_dim(bmap->dim, isl_dim_all) + extra; |
||
711 | |||
712 | bmap->ctx = ctx; |
||
713 | isl_ctx_ref(ctx); |
||
714 | |||
715 | bmap->block = isl_blk_alloc(ctx, (n_ineq + n_eq) * row_size); |
||
716 | if (isl_blk_is_error(bmap->block)) |
||
717 | goto error; |
||
718 | |||
719 | bmap->ineq = isl_alloc_array(ctx, isl_int *, n_ineq + n_eq); |
||
720 | if (!bmap->ineq) |
||
721 | goto error; |
||
722 | |||
723 | if (extra == 0) { |
||
724 | bmap->block2 = isl_blk_empty(); |
||
725 | bmap->div = NULL; |
||
726 | } else { |
||
727 | bmap->block2 = isl_blk_alloc(ctx, extra * (1 + row_size)); |
||
728 | if (isl_blk_is_error(bmap->block2)) |
||
729 | goto error; |
||
730 | |||
731 | bmap->div = isl_alloc_array(ctx, isl_int *, extra); |
||
732 | if (!bmap->div) |
||
733 | goto error; |
||
734 | } |
||
735 | |||
736 | for (i = 0; i < n_ineq + n_eq; ++i) |
||
737 | bmap->ineq[i] = bmap->block.data + i * row_size; |
||
738 | |||
739 | for (i = 0; i < extra; ++i) |
||
740 | bmap->div[i] = bmap->block2.data + i * (1 + row_size); |
||
741 | |||
742 | bmap->ref = 1; |
||
743 | bmap->flags = 0; |
||
744 | bmap->c_size = n_eq + n_ineq; |
||
745 | bmap->eq = bmap->ineq + n_ineq; |
||
746 | bmap->extra = extra; |
||
747 | bmap->n_eq = 0; |
||
748 | bmap->n_ineq = 0; |
||
749 | bmap->n_div = 0; |
||
750 | bmap->sample = NULL; |
||
751 | |||
752 | return bmap; |
||
753 | error: |
||
754 | isl_basic_map_free(bmap); |
||
755 | return NULL; |
||
756 | } |
||
757 | |||
758 | struct isl_basic_set *isl_basic_set_alloc(struct isl_ctx *ctx, |
||
759 | unsigned nparam, unsigned dim, unsigned extra, |
||
760 | unsigned n_eq, unsigned n_ineq) |
||
761 | { |
||
762 | struct isl_basic_map *bmap; |
||
763 | isl_space *space; |
||
764 | |||
765 | space = isl_space_set_alloc(ctx, nparam, dim); |
||
766 | if (!space) |
||
767 | return NULL; |
||
768 | |||
769 | bmap = isl_basic_map_alloc_space(space, extra, n_eq, n_ineq); |
||
770 | return (struct isl_basic_set *)bmap; |
||
771 | } |
||
772 | |||
773 | struct isl_basic_set *isl_basic_set_alloc_space(__isl_take isl_space *dim, |
||
774 | unsigned extra, unsigned n_eq, unsigned n_ineq) |
||
775 | { |
||
776 | struct isl_basic_map *bmap; |
||
777 | if (!dim) |
||
778 | return NULL; |
||
779 | isl_assert(dim->ctx, dim->n_in == 0, goto error); |
||
780 | bmap = isl_basic_map_alloc_space(dim, extra, n_eq, n_ineq); |
||
781 | return (struct isl_basic_set *)bmap; |
||
782 | error: |
||
783 | isl_space_free(dim); |
||
784 | return NULL; |
||
785 | } |
||
786 | |||
787 | struct isl_basic_map *isl_basic_map_alloc_space(__isl_take isl_space *dim, |
||
788 | unsigned extra, unsigned n_eq, unsigned n_ineq) |
||
789 | { |
||
790 | struct isl_basic_map *bmap; |
||
791 | |||
792 | if (!dim) |
||
793 | return NULL; |
||
794 | bmap = isl_calloc_type(dim->ctx, struct isl_basic_map); |
||
795 | if (!bmap) |
||
796 | goto error; |
||
797 | bmap->dim = dim; |
||
798 | |||
799 | return basic_map_init(dim->ctx, bmap, extra, n_eq, n_ineq); |
||
800 | error: |
||
801 | isl_space_free(dim); |
||
802 | return NULL; |
||
803 | } |
||
804 | |||
805 | struct isl_basic_map *isl_basic_map_alloc(struct isl_ctx *ctx, |
||
806 | unsigned nparam, unsigned in, unsigned out, unsigned extra, |
||
807 | unsigned n_eq, unsigned n_ineq) |
||
808 | { |
||
809 | struct isl_basic_map *bmap; |
||
810 | isl_space *dim; |
||
811 | |||
812 | dim = isl_space_alloc(ctx, nparam, in, out); |
||
813 | if (!dim) |
||
814 | return NULL; |
||
815 | |||
816 | bmap = isl_basic_map_alloc_space(dim, extra, n_eq, n_ineq); |
||
817 | return bmap; |
||
818 | } |
||
819 | |||
820 | static void dup_constraints( |
||
821 | struct isl_basic_map *dst, struct isl_basic_map *src) |
||
822 | { |
||
823 | int i; |
||
824 | unsigned total = isl_basic_map_total_dim(src); |
||
825 | |||
826 | for (i = 0; i < src->n_eq; ++i) { |
||
827 | int j = isl_basic_map_alloc_equality(dst); |
||
828 | isl_seq_cpy(dst->eq[j], src->eq[i], 1+total); |
||
829 | } |
||
830 | |||
831 | for (i = 0; i < src->n_ineq; ++i) { |
||
832 | int j = isl_basic_map_alloc_inequality(dst); |
||
833 | isl_seq_cpy(dst->ineq[j], src->ineq[i], 1+total); |
||
834 | } |
||
835 | |||
836 | for (i = 0; i < src->n_div; ++i) { |
||
837 | int j = isl_basic_map_alloc_div(dst); |
||
838 | isl_seq_cpy(dst->div[j], src->div[i], 1+1+total); |
||
839 | } |
||
840 | ISL_F_SET(dst, ISL_BASIC_SET_FINAL); |
||
841 | } |
||
842 | |||
843 | struct isl_basic_map *isl_basic_map_dup(struct isl_basic_map *bmap) |
||
844 | { |
||
845 | struct isl_basic_map *dup; |
||
846 | |||
847 | if (!bmap) |
||
848 | return NULL; |
||
849 | dup = isl_basic_map_alloc_space(isl_space_copy(bmap->dim), |
||
850 | bmap->n_div, bmap->n_eq, bmap->n_ineq); |
||
851 | if (!dup) |
||
852 | return NULL; |
||
853 | dup_constraints(dup, bmap); |
||
854 | dup->flags = bmap->flags; |
||
855 | dup->sample = isl_vec_copy(bmap->sample); |
||
856 | return dup; |
||
857 | } |
||
858 | |||
859 | struct isl_basic_set *isl_basic_set_dup(struct isl_basic_set *bset) |
||
860 | { |
||
861 | struct isl_basic_map *dup; |
||
862 | |||
863 | dup = isl_basic_map_dup((struct isl_basic_map *)bset); |
||
864 | return (struct isl_basic_set *)dup; |
||
865 | } |
||
866 | |||
867 | struct isl_basic_set *isl_basic_set_copy(struct isl_basic_set *bset) |
||
868 | { |
||
869 | if (!bset) |
||
870 | return NULL; |
||
871 | |||
872 | if (ISL_F_ISSET(bset, ISL_BASIC_SET_FINAL)) { |
||
873 | bset->ref++; |
||
874 | return bset; |
||
875 | } |
||
876 | return isl_basic_set_dup(bset); |
||
877 | } |
||
878 | |||
879 | struct isl_set *isl_set_copy(struct isl_set *set) |
||
880 | { |
||
881 | if (!set) |
||
882 | return NULL; |
||
883 | |||
884 | set->ref++; |
||
885 | return set; |
||
886 | } |
||
887 | |||
888 | struct isl_basic_map *isl_basic_map_copy(struct isl_basic_map *bmap) |
||
889 | { |
||
890 | if (!bmap) |
||
891 | return NULL; |
||
892 | |||
893 | if (ISL_F_ISSET(bmap, ISL_BASIC_SET_FINAL)) { |
||
894 | bmap->ref++; |
||
895 | return bmap; |
||
896 | } |
||
897 | bmap = isl_basic_map_dup(bmap); |
||
898 | if (bmap) |
||
899 | ISL_F_SET(bmap, ISL_BASIC_SET_FINAL); |
||
900 | return bmap; |
||
901 | } |
||
902 | |||
903 | struct isl_map *isl_map_copy(struct isl_map *map) |
||
904 | { |
||
905 | if (!map) |
||
906 | return NULL; |
||
907 | |||
908 | map->ref++; |
||
909 | return map; |
||
910 | } |
||
911 | |||
912 | void isl_basic_map_free(struct isl_basic_map *bmap) |
||
913 | { |
||
914 | if (!bmap) |
||
915 | return; |
||
916 | |||
917 | if (--bmap->ref > 0) |
||
918 | return; |
||
919 | |||
920 | isl_ctx_deref(bmap->ctx); |
||
921 | free(bmap->div); |
||
922 | isl_blk_free(bmap->ctx, bmap->block2); |
||
923 | free(bmap->ineq); |
||
924 | isl_blk_free(bmap->ctx, bmap->block); |
||
925 | isl_vec_free(bmap->sample); |
||
926 | isl_space_free(bmap->dim); |
||
927 | free(bmap); |
||
928 | } |
||
929 | |||
930 | void isl_basic_set_free(struct isl_basic_set *bset) |
||
931 | { |
||
932 | isl_basic_map_free((struct isl_basic_map *)bset); |
||
933 | } |
||
934 | |||
935 | static int room_for_con(struct isl_basic_map *bmap, unsigned n) |
||
936 | { |
||
937 | return bmap->n_eq + bmap->n_ineq + n <= bmap->c_size; |
||
938 | } |
||
939 | |||
940 | __isl_give isl_map *isl_map_align_params_map_map_and( |
||
941 | __isl_take isl_map *map1, __isl_take isl_map *map2, |
||
942 | __isl_give isl_map *(*fn)(__isl_take isl_map *map1, |
||
943 | __isl_take isl_map *map2)) |
||
944 | { |
||
945 | if (!map1 || !map2) |
||
946 | goto error; |
||
947 | if (isl_space_match(map1->dim, isl_dim_param, map2->dim, isl_dim_param)) |
||
948 | return fn(map1, map2); |
||
949 | if (!isl_space_has_named_params(map1->dim) || |
||
950 | !isl_space_has_named_params(map2->dim)) |
||
951 | isl_die(map1->ctx, isl_error_invalid, |
||
952 | "unaligned unnamed parameters", goto error); |
||
953 | map1 = isl_map_align_params(map1, isl_map_get_space(map2)); |
||
954 | map2 = isl_map_align_params(map2, isl_map_get_space(map1)); |
||
955 | return fn(map1, map2); |
||
956 | error: |
||
957 | isl_map_free(map1); |
||
958 | isl_map_free(map2); |
||
959 | return NULL; |
||
960 | } |
||
961 | |||
962 | int isl_map_align_params_map_map_and_test(__isl_keep isl_map *map1, |
||
963 | __isl_keep isl_map *map2, |
||
964 | int (*fn)(__isl_keep isl_map *map1, __isl_keep isl_map *map2)) |
||
965 | { |
||
966 | int r; |
||
967 | |||
968 | if (!map1 || !map2) |
||
969 | return -1; |
||
970 | if (isl_space_match(map1->dim, isl_dim_param, map2->dim, isl_dim_param)) |
||
971 | return fn(map1, map2); |
||
972 | if (!isl_space_has_named_params(map1->dim) || |
||
973 | !isl_space_has_named_params(map2->dim)) |
||
974 | isl_die(map1->ctx, isl_error_invalid, |
||
975 | "unaligned unnamed parameters", return -1); |
||
976 | map1 = isl_map_copy(map1); |
||
977 | map2 = isl_map_copy(map2); |
||
978 | map1 = isl_map_align_params(map1, isl_map_get_space(map2)); |
||
979 | map2 = isl_map_align_params(map2, isl_map_get_space(map1)); |
||
980 | r = fn(map1, map2); |
||
981 | isl_map_free(map1); |
||
982 | isl_map_free(map2); |
||
983 | return r; |
||
984 | } |
||
985 | |||
986 | int isl_basic_map_alloc_equality(struct isl_basic_map *bmap) |
||
987 | { |
||
988 | struct isl_ctx *ctx; |
||
989 | if (!bmap) |
||
990 | return -1; |
||
991 | ctx = bmap->ctx; |
||
992 | isl_assert(ctx, room_for_con(bmap, 1), return -1); |
||
993 | isl_assert(ctx, (bmap->eq - bmap->ineq) + bmap->n_eq <= bmap->c_size, |
||
994 | return -1); |
||
995 | ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED); |
||
996 | ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT); |
||
997 | ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_IMPLICIT); |
||
998 | ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES); |
||
999 | ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS); |
||
1000 | if ((bmap->eq - bmap->ineq) + bmap->n_eq == bmap->c_size) { |
||
1001 | isl_int *t; |
||
1002 | int j = isl_basic_map_alloc_inequality(bmap); |
||
1003 | if (j < 0) |
||
1004 | return -1; |
||
1005 | t = bmap->ineq[j]; |
||
1006 | bmap->ineq[j] = bmap->ineq[bmap->n_ineq - 1]; |
||
1007 | bmap->ineq[bmap->n_ineq - 1] = bmap->eq[-1]; |
||
1008 | bmap->eq[-1] = t; |
||
1009 | bmap->n_eq++; |
||
1010 | bmap->n_ineq--; |
||
1011 | bmap->eq--; |
||
1012 | return 0; |
||
1013 | } |
||
1014 | isl_seq_clr(bmap->eq[bmap->n_eq] + 1 + isl_basic_map_total_dim(bmap), |
||
1015 | bmap->extra - bmap->n_div); |
||
1016 | return bmap->n_eq++; |
||
1017 | } |
||
1018 | |||
1019 | int isl_basic_set_alloc_equality(struct isl_basic_set *bset) |
||
1020 | { |
||
1021 | return isl_basic_map_alloc_equality((struct isl_basic_map *)bset); |
||
1022 | } |
||
1023 | |||
1024 | int isl_basic_map_free_equality(struct isl_basic_map *bmap, unsigned n) |
||
1025 | { |
||
1026 | if (!bmap) |
||
1027 | return -1; |
||
1028 | isl_assert(bmap->ctx, n <= bmap->n_eq, return -1); |
||
1029 | bmap->n_eq -= n; |
||
1030 | return 0; |
||
1031 | } |
||
1032 | |||
1033 | int isl_basic_set_free_equality(struct isl_basic_set *bset, unsigned n) |
||
1034 | { |
||
1035 | return isl_basic_map_free_equality((struct isl_basic_map *)bset, n); |
||
1036 | } |
||
1037 | |||
1038 | int isl_basic_map_drop_equality(struct isl_basic_map *bmap, unsigned pos) |
||
1039 | { |
||
1040 | isl_int *t; |
||
1041 | if (!bmap) |
||
1042 | return -1; |
||
1043 | isl_assert(bmap->ctx, pos < bmap->n_eq, return -1); |
||
1044 | |||
1045 | if (pos != bmap->n_eq - 1) { |
||
1046 | t = bmap->eq[pos]; |
||
1047 | bmap->eq[pos] = bmap->eq[bmap->n_eq - 1]; |
||
1048 | bmap->eq[bmap->n_eq - 1] = t; |
||
1049 | } |
||
1050 | bmap->n_eq--; |
||
1051 | return 0; |
||
1052 | } |
||
1053 | |||
1054 | int isl_basic_set_drop_equality(struct isl_basic_set *bset, unsigned pos) |
||
1055 | { |
||
1056 | return isl_basic_map_drop_equality((struct isl_basic_map *)bset, pos); |
||
1057 | } |
||
1058 | |||
1059 | void isl_basic_map_inequality_to_equality( |
||
1060 | struct isl_basic_map *bmap, unsigned pos) |
||
1061 | { |
||
1062 | isl_int *t; |
||
1063 | |||
1064 | t = bmap->ineq[pos]; |
||
1065 | bmap->ineq[pos] = bmap->ineq[bmap->n_ineq - 1]; |
||
1066 | bmap->ineq[bmap->n_ineq - 1] = bmap->eq[-1]; |
||
1067 | bmap->eq[-1] = t; |
||
1068 | bmap->n_eq++; |
||
1069 | bmap->n_ineq--; |
||
1070 | bmap->eq--; |
||
1071 | ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT); |
||
1072 | ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED); |
||
1073 | ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS); |
||
1074 | ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES); |
||
1075 | } |
||
1076 | |||
1077 | static int room_for_ineq(struct isl_basic_map *bmap, unsigned n) |
||
1078 | { |
||
1079 | return bmap->n_ineq + n <= bmap->eq - bmap->ineq; |
||
1080 | } |
||
1081 | |||
1082 | int isl_basic_map_alloc_inequality(struct isl_basic_map *bmap) |
||
1083 | { |
||
1084 | struct isl_ctx *ctx; |
||
1085 | if (!bmap) |
||
1086 | return -1; |
||
1087 | ctx = bmap->ctx; |
||
1088 | isl_assert(ctx, room_for_ineq(bmap, 1), return -1); |
||
1089 | ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_IMPLICIT); |
||
1090 | ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT); |
||
1091 | ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED); |
||
1092 | ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES); |
||
1093 | isl_seq_clr(bmap->ineq[bmap->n_ineq] + |
||
1094 | 1 + isl_basic_map_total_dim(bmap), |
||
1095 | bmap->extra - bmap->n_div); |
||
1096 | return bmap->n_ineq++; |
||
1097 | } |
||
1098 | |||
1099 | int isl_basic_set_alloc_inequality(struct isl_basic_set *bset) |
||
1100 | { |
||
1101 | return isl_basic_map_alloc_inequality((struct isl_basic_map *)bset); |
||
1102 | } |
||
1103 | |||
1104 | int isl_basic_map_free_inequality(struct isl_basic_map *bmap, unsigned n) |
||
1105 | { |
||
1106 | if (!bmap) |
||
1107 | return -1; |
||
1108 | isl_assert(bmap->ctx, n <= bmap->n_ineq, return -1); |
||
1109 | bmap->n_ineq -= n; |
||
1110 | return 0; |
||
1111 | } |
||
1112 | |||
1113 | int isl_basic_set_free_inequality(struct isl_basic_set *bset, unsigned n) |
||
1114 | { |
||
1115 | return isl_basic_map_free_inequality((struct isl_basic_map *)bset, n); |
||
1116 | } |
||
1117 | |||
1118 | int isl_basic_map_drop_inequality(struct isl_basic_map *bmap, unsigned pos) |
||
1119 | { |
||
1120 | isl_int *t; |
||
1121 | if (!bmap) |
||
1122 | return -1; |
||
1123 | isl_assert(bmap->ctx, pos < bmap->n_ineq, return -1); |
||
1124 | |||
1125 | if (pos != bmap->n_ineq - 1) { |
||
1126 | t = bmap->ineq[pos]; |
||
1127 | bmap->ineq[pos] = bmap->ineq[bmap->n_ineq - 1]; |
||
1128 | bmap->ineq[bmap->n_ineq - 1] = t; |
||
1129 | ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED); |
||
1130 | } |
||
1131 | bmap->n_ineq--; |
||
1132 | return 0; |
||
1133 | } |
||
1134 | |||
1135 | int isl_basic_set_drop_inequality(struct isl_basic_set *bset, unsigned pos) |
||
1136 | { |
||
1137 | return isl_basic_map_drop_inequality((struct isl_basic_map *)bset, pos); |
||
1138 | } |
||
1139 | |||
1140 | __isl_give isl_basic_map *isl_basic_map_add_eq(__isl_take isl_basic_map *bmap, |
||
1141 | isl_int *eq) |
||
1142 | { |
||
1143 | int k; |
||
1144 | |||
1145 | bmap = isl_basic_map_extend_constraints(bmap, 1, 0); |
||
1146 | if (!bmap) |
||
1147 | return NULL; |
||
1148 | k = isl_basic_map_alloc_equality(bmap); |
||
1149 | if (k < 0) |
||
1150 | goto error; |
||
1151 | isl_seq_cpy(bmap->eq[k], eq, 1 + isl_basic_map_total_dim(bmap)); |
||
1152 | return bmap; |
||
1153 | error: |
||
1154 | isl_basic_map_free(bmap); |
||
1155 | return NULL; |
||
1156 | } |
||
1157 | |||
1158 | __isl_give isl_basic_set *isl_basic_set_add_eq(__isl_take isl_basic_set *bset, |
||
1159 | isl_int *eq) |
||
1160 | { |
||
1161 | return (isl_basic_set *) |
||
1162 | isl_basic_map_add_eq((isl_basic_map *)bset, eq); |
||
1163 | } |
||
1164 | |||
1165 | __isl_give isl_basic_map *isl_basic_map_add_ineq(__isl_take isl_basic_map *bmap, |
||
1166 | isl_int *ineq) |
||
1167 | { |
||
1168 | int k; |
||
1169 | |||
1170 | bmap = isl_basic_map_extend_constraints(bmap, 0, 1); |
||
1171 | if (!bmap) |
||
1172 | return NULL; |
||
1173 | k = isl_basic_map_alloc_inequality(bmap); |
||
1174 | if (k < 0) |
||
1175 | goto error; |
||
1176 | isl_seq_cpy(bmap->ineq[k], ineq, 1 + isl_basic_map_total_dim(bmap)); |
||
1177 | return bmap; |
||
1178 | error: |
||
1179 | isl_basic_map_free(bmap); |
||
1180 | return NULL; |
||
1181 | } |
||
1182 | |||
1183 | __isl_give isl_basic_set *isl_basic_set_add_ineq(__isl_take isl_basic_set *bset, |
||
1184 | isl_int *ineq) |
||
1185 | { |
||
1186 | return (isl_basic_set *) |
||
1187 | isl_basic_map_add_ineq((isl_basic_map *)bset, ineq); |
||
1188 | } |
||
1189 | |||
1190 | int isl_basic_map_alloc_div(struct isl_basic_map *bmap) |
||
1191 | { |
||
1192 | if (!bmap) |
||
1193 | return -1; |
||
1194 | isl_assert(bmap->ctx, bmap->n_div < bmap->extra, return -1); |
||
1195 | isl_seq_clr(bmap->div[bmap->n_div] + |
||
1196 | 1 + 1 + isl_basic_map_total_dim(bmap), |
||
1197 | bmap->extra - bmap->n_div); |
||
1198 | ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS); |
||
1199 | return bmap->n_div++; |
||
1200 | } |
||
1201 | |||
1202 | int isl_basic_set_alloc_div(struct isl_basic_set *bset) |
||
1203 | { |
||
1204 | return isl_basic_map_alloc_div((struct isl_basic_map *)bset); |
||
1205 | } |
||
1206 | |||
1207 | int isl_basic_map_free_div(struct isl_basic_map *bmap, unsigned n) |
||
1208 | { |
||
1209 | if (!bmap) |
||
1210 | return -1; |
||
1211 | isl_assert(bmap->ctx, n <= bmap->n_div, return -1); |
||
1212 | bmap->n_div -= n; |
||
1213 | return 0; |
||
1214 | } |
||
1215 | |||
1216 | int isl_basic_set_free_div(struct isl_basic_set *bset, unsigned n) |
||
1217 | { |
||
1218 | return isl_basic_map_free_div((struct isl_basic_map *)bset, n); |
||
1219 | } |
||
1220 | |||
1221 | /* Copy constraint from src to dst, putting the vars of src at offset |
||
1222 | * dim_off in dst and the divs of src at offset div_off in dst. |
||
1223 | * If both sets are actually map, then dim_off applies to the input |
||
1224 | * variables. |
||
1225 | */ |
||
1226 | static void copy_constraint(struct isl_basic_map *dst_map, isl_int *dst, |
||
1227 | struct isl_basic_map *src_map, isl_int *src, |
||
1228 | unsigned in_off, unsigned out_off, unsigned div_off) |
||
1229 | { |
||
1230 | unsigned src_nparam = isl_basic_map_n_param(src_map); |
||
1231 | unsigned dst_nparam = isl_basic_map_n_param(dst_map); |
||
1232 | unsigned src_in = isl_basic_map_n_in(src_map); |
||
1233 | unsigned dst_in = isl_basic_map_n_in(dst_map); |
||
1234 | unsigned src_out = isl_basic_map_n_out(src_map); |
||
1235 | unsigned dst_out = isl_basic_map_n_out(dst_map); |
||
1236 | isl_int_set(dst[0], src[0]); |
||
1237 | isl_seq_cpy(dst+1, src+1, isl_min(dst_nparam, src_nparam)); |
||
1238 | if (dst_nparam > src_nparam) |
||
1239 | isl_seq_clr(dst+1+src_nparam, |
||
1240 | dst_nparam - src_nparam); |
||
1241 | isl_seq_clr(dst+1+dst_nparam, in_off); |
||
1242 | isl_seq_cpy(dst+1+dst_nparam+in_off, |
||
1243 | src+1+src_nparam, |
||
1244 | isl_min(dst_in-in_off, src_in)); |
||
1245 | if (dst_in-in_off > src_in) |
||
1246 | isl_seq_clr(dst+1+dst_nparam+in_off+src_in, |
||
1247 | dst_in - in_off - src_in); |
||
1248 | isl_seq_clr(dst+1+dst_nparam+dst_in, out_off); |
||
1249 | isl_seq_cpy(dst+1+dst_nparam+dst_in+out_off, |
||
1250 | src+1+src_nparam+src_in, |
||
1251 | isl_min(dst_out-out_off, src_out)); |
||
1252 | if (dst_out-out_off > src_out) |
||
1253 | isl_seq_clr(dst+1+dst_nparam+dst_in+out_off+src_out, |
||
1254 | dst_out - out_off - src_out); |
||
1255 | isl_seq_clr(dst+1+dst_nparam+dst_in+dst_out, div_off); |
||
1256 | isl_seq_cpy(dst+1+dst_nparam+dst_in+dst_out+div_off, |
||
1257 | src+1+src_nparam+src_in+src_out, |
||
1258 | isl_min(dst_map->extra-div_off, src_map->n_div)); |
||
1259 | if (dst_map->n_div-div_off > src_map->n_div) |
||
1260 | isl_seq_clr(dst+1+dst_nparam+dst_in+dst_out+ |
||
1261 | div_off+src_map->n_div, |
||
1262 | dst_map->n_div - div_off - src_map->n_div); |
||
1263 | } |
||
1264 | |||
1265 | static void copy_div(struct isl_basic_map *dst_map, isl_int *dst, |
||
1266 | struct isl_basic_map *src_map, isl_int *src, |
||
1267 | unsigned in_off, unsigned out_off, unsigned div_off) |
||
1268 | { |
||
1269 | isl_int_set(dst[0], src[0]); |
||
1270 | copy_constraint(dst_map, dst+1, src_map, src+1, in_off, out_off, div_off); |
||
1271 | } |
||
1272 | |||
1273 | static struct isl_basic_map *add_constraints(struct isl_basic_map *bmap1, |
||
1274 | struct isl_basic_map *bmap2, unsigned i_pos, unsigned o_pos) |
||
1275 | { |
||
1276 | int i; |
||
1277 | unsigned div_off; |
||
1278 | |||
1279 | if (!bmap1 || !bmap2) |
||
1280 | goto error; |
||
1281 | |||
1282 | div_off = bmap1->n_div; |
||
1283 | |||
1284 | for (i = 0; i < bmap2->n_eq; ++i) { |
||
1285 | int i1 = isl_basic_map_alloc_equality(bmap1); |
||
1286 | if (i1 < 0) |
||
1287 | goto error; |
||
1288 | copy_constraint(bmap1, bmap1->eq[i1], bmap2, bmap2->eq[i], |
||
1289 | i_pos, o_pos, div_off); |
||
1290 | } |
||
1291 | |||
1292 | for (i = 0; i < bmap2->n_ineq; ++i) { |
||
1293 | int i1 = isl_basic_map_alloc_inequality(bmap1); |
||
1294 | if (i1 < 0) |
||
1295 | goto error; |
||
1296 | copy_constraint(bmap1, bmap1->ineq[i1], bmap2, bmap2->ineq[i], |
||
1297 | i_pos, o_pos, div_off); |
||
1298 | } |
||
1299 | |||
1300 | for (i = 0; i < bmap2->n_div; ++i) { |
||
1301 | int i1 = isl_basic_map_alloc_div(bmap1); |
||
1302 | if (i1 < 0) |
||
1303 | goto error; |
||
1304 | copy_div(bmap1, bmap1->div[i1], bmap2, bmap2->div[i], |
||
1305 | i_pos, o_pos, div_off); |
||
1306 | } |
||
1307 | |||
1308 | isl_basic_map_free(bmap2); |
||
1309 | |||
1310 | return bmap1; |
||
1311 | |||
1312 | error: |
||
1313 | isl_basic_map_free(bmap1); |
||
1314 | isl_basic_map_free(bmap2); |
||
1315 | return NULL; |
||
1316 | } |
||
1317 | |||
1318 | struct isl_basic_set *isl_basic_set_add_constraints(struct isl_basic_set *bset1, |
||
1319 | struct isl_basic_set *bset2, unsigned pos) |
||
1320 | { |
||
1321 | return (struct isl_basic_set *) |
||
1322 | add_constraints((struct isl_basic_map *)bset1, |
||
1323 | (struct isl_basic_map *)bset2, 0, pos); |
||
1324 | } |
||
1325 | |||
1326 | struct isl_basic_map *isl_basic_map_extend_space(struct isl_basic_map *base, |
||
1327 | __isl_take isl_space *dim, unsigned extra, |
||
1328 | unsigned n_eq, unsigned n_ineq) |
||
1329 | { |
||
1330 | struct isl_basic_map *ext; |
||
1331 | unsigned flags; |
||
1332 | int dims_ok; |
||
1333 | |||
1334 | if (!dim) |
||
1335 | goto error; |
||
1336 | |||
1337 | if (!base) |
||
1338 | goto error; |
||
1339 | |||
1340 | dims_ok = isl_space_is_equal(base->dim, dim) && |
||
1341 | base->extra >= base->n_div + extra; |
||
1342 | |||
1343 | if (dims_ok && room_for_con(base, n_eq + n_ineq) && |
||
1344 | room_for_ineq(base, n_ineq)) { |
||
1345 | isl_space_free(dim); |
||
1346 | return base; |
||
1347 | } |
||
1348 | |||
1349 | isl_assert(base->ctx, base->dim->nparam <= dim->nparam, goto error); |
||
1350 | isl_assert(base->ctx, base->dim->n_in <= dim->n_in, goto error); |
||
1351 | isl_assert(base->ctx, base->dim->n_out <= dim->n_out, goto error); |
||
1352 | extra += base->extra; |
||
1353 | n_eq += base->n_eq; |
||
1354 | n_ineq += base->n_ineq; |
||
1355 | |||
1356 | ext = isl_basic_map_alloc_space(dim, extra, n_eq, n_ineq); |
||
1357 | dim = NULL; |
||
1358 | if (!ext) |
||
1359 | goto error; |
||
1360 | |||
1361 | if (dims_ok) |
||
1362 | ext->sample = isl_vec_copy(base->sample); |
||
1363 | flags = base->flags; |
||
1364 | ext = add_constraints(ext, base, 0, 0); |
||
1365 | if (ext) { |
||
1366 | ext->flags = flags; |
||
1367 | ISL_F_CLR(ext, ISL_BASIC_SET_FINAL); |
||
1368 | } |
||
1369 | |||
1370 | return ext; |
||
1371 | |||
1372 | error: |
||
1373 | isl_space_free(dim); |
||
1374 | isl_basic_map_free(base); |
||
1375 | return NULL; |
||
1376 | } |
||
1377 | |||
1378 | struct isl_basic_set *isl_basic_set_extend_space(struct isl_basic_set *base, |
||
1379 | __isl_take isl_space *dim, unsigned extra, |
||
1380 | unsigned n_eq, unsigned n_ineq) |
||
1381 | { |
||
1382 | return (struct isl_basic_set *) |
||
1383 | isl_basic_map_extend_space((struct isl_basic_map *)base, dim, |
||
1384 | extra, n_eq, n_ineq); |
||
1385 | } |
||
1386 | |||
1387 | struct isl_basic_map *isl_basic_map_extend_constraints( |
||
1388 | struct isl_basic_map *base, unsigned n_eq, unsigned n_ineq) |
||
1389 | { |
||
1390 | if (!base) |
||
1391 | return NULL; |
||
1392 | return isl_basic_map_extend_space(base, isl_space_copy(base->dim), |
||
1393 | 0, n_eq, n_ineq); |
||
1394 | } |
||
1395 | |||
1396 | struct isl_basic_map *isl_basic_map_extend(struct isl_basic_map *base, |
||
1397 | unsigned nparam, unsigned n_in, unsigned n_out, unsigned extra, |
||
1398 | unsigned n_eq, unsigned n_ineq) |
||
1399 | { |
||
1400 | struct isl_basic_map *bmap; |
||
1401 | isl_space *dim; |
||
1402 | |||
1403 | if (!base) |
||
1404 | return NULL; |
||
1405 | dim = isl_space_alloc(base->ctx, nparam, n_in, n_out); |
||
1406 | if (!dim) |
||
1407 | goto error; |
||
1408 | |||
1409 | bmap = isl_basic_map_extend_space(base, dim, extra, n_eq, n_ineq); |
||
1410 | return bmap; |
||
1411 | error: |
||
1412 | isl_basic_map_free(base); |
||
1413 | return NULL; |
||
1414 | } |
||
1415 | |||
1416 | struct isl_basic_set *isl_basic_set_extend(struct isl_basic_set *base, |
||
1417 | unsigned nparam, unsigned dim, unsigned extra, |
||
1418 | unsigned n_eq, unsigned n_ineq) |
||
1419 | { |
||
1420 | return (struct isl_basic_set *) |
||
1421 | isl_basic_map_extend((struct isl_basic_map *)base, |
||
1422 | nparam, 0, dim, extra, n_eq, n_ineq); |
||
1423 | } |
||
1424 | |||
1425 | struct isl_basic_set *isl_basic_set_extend_constraints( |
||
1426 | struct isl_basic_set *base, unsigned n_eq, unsigned n_ineq) |
||
1427 | { |
||
1428 | return (struct isl_basic_set *) |
||
1429 | isl_basic_map_extend_constraints((struct isl_basic_map *)base, |
||
1430 | n_eq, n_ineq); |
||
1431 | } |
||
1432 | |||
1433 | struct isl_basic_set *isl_basic_set_cow(struct isl_basic_set *bset) |
||
1434 | { |
||
1435 | return (struct isl_basic_set *) |
||
1436 | isl_basic_map_cow((struct isl_basic_map *)bset); |
||
1437 | } |
||
1438 | |||
1439 | struct isl_basic_map *isl_basic_map_cow(struct isl_basic_map *bmap) |
||
1440 | { |
||
1441 | if (!bmap) |
||
1442 | return NULL; |
||
1443 | |||
1444 | if (bmap->ref > 1) { |
||
1445 | bmap->ref--; |
||
1446 | bmap = isl_basic_map_dup(bmap); |
||
1447 | } |
||
1448 | if (bmap) |
||
1449 | ISL_F_CLR(bmap, ISL_BASIC_SET_FINAL); |
||
1450 | return bmap; |
||
1451 | } |
||
1452 | |||
1453 | struct isl_set *isl_set_cow(struct isl_set *set) |
||
1454 | { |
||
1455 | if (!set) |
||
1456 | return NULL; |
||
1457 | |||
1458 | if (set->ref == 1) |
||
1459 | return set; |
||
1460 | set->ref--; |
||
1461 | return isl_set_dup(set); |
||
1462 | } |
||
1463 | |||
1464 | struct isl_map *isl_map_cow(struct isl_map *map) |
||
1465 | { |
||
1466 | if (!map) |
||
1467 | return NULL; |
||
1468 | |||
1469 | if (map->ref == 1) |
||
1470 | return map; |
||
1471 | map->ref--; |
||
1472 | return isl_map_dup(map); |
||
1473 | } |
||
1474 | |||
1475 | static void swap_vars(struct isl_blk blk, isl_int *a, |
||
1476 | unsigned a_len, unsigned b_len) |
||
1477 | { |
||
1478 | isl_seq_cpy(blk.data, a+a_len, b_len); |
||
1479 | isl_seq_cpy(blk.data+b_len, a, a_len); |
||
1480 | isl_seq_cpy(a, blk.data, b_len+a_len); |
||
1481 | } |
||
1482 | |||
1483 | static __isl_give isl_basic_map *isl_basic_map_swap_vars( |
||
1484 | __isl_take isl_basic_map *bmap, unsigned pos, unsigned n1, unsigned n2) |
||
1485 | { |
||
1486 | int i; |
||
1487 | struct isl_blk blk; |
||
1488 | |||
1489 | if (!bmap) |
||
1490 | goto error; |
||
1491 | |||
1492 | isl_assert(bmap->ctx, |
||
1493 | pos + n1 + n2 <= 1 + isl_basic_map_total_dim(bmap), goto error); |
||
1494 | |||
1495 | if (n1 == 0 || n2 == 0) |
||
1496 | return bmap; |
||
1497 | |||
1498 | bmap = isl_basic_map_cow(bmap); |
||
1499 | if (!bmap) |
||
1500 | return NULL; |
||
1501 | |||
1502 | blk = isl_blk_alloc(bmap->ctx, n1 + n2); |
||
1503 | if (isl_blk_is_error(blk)) |
||
1504 | goto error; |
||
1505 | |||
1506 | for (i = 0; i < bmap->n_eq; ++i) |
||
1507 | swap_vars(blk, |
||
1508 | bmap->eq[i] + pos, n1, n2); |
||
1509 | |||
1510 | for (i = 0; i < bmap->n_ineq; ++i) |
||
1511 | swap_vars(blk, |
||
1512 | bmap->ineq[i] + pos, n1, n2); |
||
1513 | |||
1514 | for (i = 0; i < bmap->n_div; ++i) |
||
1515 | swap_vars(blk, |
||
1516 | bmap->div[i]+1 + pos, n1, n2); |
||
1517 | |||
1518 | isl_blk_free(bmap->ctx, blk); |
||
1519 | |||
1520 | ISL_F_CLR(bmap, ISL_BASIC_SET_NORMALIZED); |
||
1521 | bmap = isl_basic_map_gauss(bmap, NULL); |
||
1522 | return isl_basic_map_finalize(bmap); |
||
1523 | error: |
||
1524 | isl_basic_map_free(bmap); |
||
1525 | return NULL; |
||
1526 | } |
||
1527 | |||
1528 | static __isl_give isl_basic_set *isl_basic_set_swap_vars( |
||
1529 | __isl_take isl_basic_set *bset, unsigned n) |
||
1530 | { |
||
1531 | unsigned dim; |
||
1532 | unsigned nparam; |
||
1533 | |||
1534 | nparam = isl_basic_set_n_param(bset); |
||
1535 | dim = isl_basic_set_n_dim(bset); |
||
1536 | isl_assert(bset->ctx, n <= dim, goto error); |
||
1537 | |||
1538 | return isl_basic_map_swap_vars(bset, 1 + nparam, n, dim - n); |
||
1539 | error: |
||
1540 | isl_basic_set_free(bset); |
||
1541 | return NULL; |
||
1542 | } |
||
1543 | |||
1544 | struct isl_basic_map *isl_basic_map_set_to_empty(struct isl_basic_map *bmap) |
||
1545 | { |
||
1546 | int i = 0; |
||
1547 | unsigned total; |
||
1548 | if (!bmap) |
||
1549 | goto error; |
||
1550 | total = isl_basic_map_total_dim(bmap); |
||
1551 | isl_basic_map_free_div(bmap, bmap->n_div); |
||
1552 | isl_basic_map_free_inequality(bmap, bmap->n_ineq); |
||
1553 | if (bmap->n_eq > 0) |
||
1554 | isl_basic_map_free_equality(bmap, bmap->n_eq-1); |
||
1555 | else { |
||
1556 | i = isl_basic_map_alloc_equality(bmap); |
||
1557 | if (i < 0) |
||
1558 | goto error; |
||
1559 | } |
||
1560 | isl_int_set_si(bmap->eq[i][0], 1); |
||
1561 | isl_seq_clr(bmap->eq[i]+1, total); |
||
1562 | ISL_F_SET(bmap, ISL_BASIC_MAP_EMPTY); |
||
1563 | isl_vec_free(bmap->sample); |
||
1564 | bmap->sample = NULL; |
||
1565 | return isl_basic_map_finalize(bmap); |
||
1566 | error: |
||
1567 | isl_basic_map_free(bmap); |
||
1568 | return NULL; |
||
1569 | } |
||
1570 | |||
1571 | struct isl_basic_set *isl_basic_set_set_to_empty(struct isl_basic_set *bset) |
||
1572 | { |
||
1573 | return (struct isl_basic_set *) |
||
1574 | isl_basic_map_set_to_empty((struct isl_basic_map *)bset); |
||
1575 | } |
||
1576 | |||
1577 | void isl_basic_map_swap_div(struct isl_basic_map *bmap, int a, int b) |
||
1578 | { |
||
1579 | int i; |
||
1580 | unsigned off = isl_space_dim(bmap->dim, isl_dim_all); |
||
1581 | isl_int *t = bmap->div[a]; |
||
1582 | bmap->div[a] = bmap->div[b]; |
||
1583 | bmap->div[b] = t; |
||
1584 | |||
1585 | for (i = 0; i < bmap->n_eq; ++i) |
||
1586 | isl_int_swap(bmap->eq[i][1+off+a], bmap->eq[i][1+off+b]); |
||
1587 | |||
1588 | for (i = 0; i < bmap->n_ineq; ++i) |
||
1589 | isl_int_swap(bmap->ineq[i][1+off+a], bmap->ineq[i][1+off+b]); |
||
1590 | |||
1591 | for (i = 0; i < bmap->n_div; ++i) |
||
1592 | isl_int_swap(bmap->div[i][1+1+off+a], bmap->div[i][1+1+off+b]); |
||
1593 | ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED); |
||
1594 | } |
||
1595 | |||
1596 | /* Eliminate the specified n dimensions starting at first from the |
||
1597 | * constraints using Fourier-Motzkin. The dimensions themselves |
||
1598 | * are not removed. |
||
1599 | */ |
||
1600 | __isl_give isl_map *isl_map_eliminate(__isl_take isl_map *map, |
||
1601 | enum isl_dim_type type, unsigned first, unsigned n) |
||
1602 | { |
||
1603 | int i; |
||
1604 | |||
1605 | if (!map) |
||
1606 | return NULL; |
||
1607 | if (n == 0) |
||
1608 | return map; |
||
1609 | |||
1610 | map = isl_map_cow(map); |
||
1611 | if (!map) |
||
1612 | return NULL; |
||
1613 | |||
1614 | for (i = 0; i < map->n; ++i) { |
||
1615 | map->p[i] = isl_basic_map_eliminate(map->p[i], type, first, n); |
||
1616 | if (!map->p[i]) |
||
1617 | goto error; |
||
1618 | } |
||
1619 | return map; |
||
1620 | error: |
||
1621 | isl_map_free(map); |
||
1622 | return NULL; |
||
1623 | } |
||
1624 | |||
1625 | /* Eliminate the specified n dimensions starting at first from the |
||
1626 | * constraints using Fourier-Motzkin. The dimensions themselves |
||
1627 | * are not removed. |
||
1628 | */ |
||
1629 | __isl_give isl_set *isl_set_eliminate(__isl_take isl_set *set, |
||
1630 | enum isl_dim_type type, unsigned first, unsigned n) |
||
1631 | { |
||
1632 | return (isl_set *)isl_map_eliminate((isl_map *)set, type, first, n); |
||
1633 | } |
||
1634 | |||
1635 | /* Eliminate the specified n dimensions starting at first from the |
||
1636 | * constraints using Fourier-Motzkin. The dimensions themselves |
||
1637 | * are not removed. |
||
1638 | */ |
||
1639 | __isl_give isl_set *isl_set_eliminate_dims(__isl_take isl_set *set, |
||
1640 | unsigned first, unsigned n) |
||
1641 | { |
||
1642 | return isl_set_eliminate(set, isl_dim_set, first, n); |
||
1643 | } |
||
1644 | |||
1645 | __isl_give isl_basic_map *isl_basic_map_remove_divs( |
||
1646 | __isl_take isl_basic_map *bmap) |
||
1647 | { |
||
1648 | if (!bmap) |
||
1649 | return NULL; |
||
1650 | bmap = isl_basic_map_eliminate_vars(bmap, |
||
1651 | isl_space_dim(bmap->dim, isl_dim_all), bmap->n_div); |
||
1652 | if (!bmap) |
||
1653 | return NULL; |
||
1654 | bmap->n_div = 0; |
||
1655 | return isl_basic_map_finalize(bmap); |
||
1656 | } |
||
1657 | |||
1658 | __isl_give isl_basic_set *isl_basic_set_remove_divs( |
||
1659 | __isl_take isl_basic_set *bset) |
||
1660 | { |
||
1661 | return (struct isl_basic_set *)isl_basic_map_remove_divs( |
||
1662 | (struct isl_basic_map *)bset); |
||
1663 | } |
||
1664 | |||
1665 | __isl_give isl_map *isl_map_remove_divs(__isl_take isl_map *map) |
||
1666 | { |
||
1667 | int i; |
||
1668 | |||
1669 | if (!map) |
||
1670 | return NULL; |
||
1671 | if (map->n == 0) |
||
1672 | return map; |
||
1673 | |||
1674 | map = isl_map_cow(map); |
||
1675 | if (!map) |
||
1676 | return NULL; |
||
1677 | |||
1678 | for (i = 0; i < map->n; ++i) { |
||
1679 | map->p[i] = isl_basic_map_remove_divs(map->p[i]); |
||
1680 | if (!map->p[i]) |
||
1681 | goto error; |
||
1682 | } |
||
1683 | return map; |
||
1684 | error: |
||
1685 | isl_map_free(map); |
||
1686 | return NULL; |
||
1687 | } |
||
1688 | |||
1689 | __isl_give isl_set *isl_set_remove_divs(__isl_take isl_set *set) |
||
1690 | { |
||
1691 | return isl_map_remove_divs(set); |
||
1692 | } |
||
1693 | |||
1694 | struct isl_basic_map *isl_basic_map_remove_dims(struct isl_basic_map *bmap, |
||
1695 | enum isl_dim_type type, unsigned first, unsigned n) |
||
1696 | { |
||
1697 | if (!bmap) |
||
1698 | return NULL; |
||
1699 | isl_assert(bmap->ctx, first + n <= isl_basic_map_dim(bmap, type), |
||
1700 | goto error); |
||
1701 | if (n == 0 && !isl_space_is_named_or_nested(bmap->dim, type)) |
||
1702 | return bmap; |
||
1703 | bmap = isl_basic_map_eliminate_vars(bmap, |
||
1704 | isl_basic_map_offset(bmap, type) - 1 + first, n); |
||
1705 | if (!bmap) |
||
1706 | return bmap; |
||
1707 | if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY) && type == isl_dim_div) |
||
1708 | return bmap; |
||
1709 | bmap = isl_basic_map_drop(bmap, type, first, n); |
||
1710 | return bmap; |
||
1711 | error: |
||
1712 | isl_basic_map_free(bmap); |
||
1713 | return NULL; |
||
1714 | } |
||
1715 | |||
1716 | /* Return true if the definition of the given div (recursively) involves |
||
1717 | * any of the given variables. |
||
1718 | */ |
||
1719 | static int div_involves_vars(__isl_keep isl_basic_map *bmap, int div, |
||
1720 | unsigned first, unsigned n) |
||
1721 | { |
||
1722 | int i; |
||
1723 | unsigned div_offset = isl_basic_map_offset(bmap, isl_dim_div); |
||
1724 | |||
1725 | if (isl_int_is_zero(bmap->div[div][0])) |
||
1726 | return 0; |
||
1727 | if (isl_seq_first_non_zero(bmap->div[div] + 1 + first, n) >= 0) |
||
1728 | return 1; |
||
1729 | |||
1730 | for (i = bmap->n_div - 1; i >= 0; --i) { |
||
1731 | if (isl_int_is_zero(bmap->div[div][1 + div_offset + i])) |
||
1732 | continue; |
||
1733 | if (div_involves_vars(bmap, i, first, n)) |
||
1734 | return 1; |
||
1735 | } |
||
1736 | |||
1737 | return 0; |
||
1738 | } |
||
1739 | |||
1740 | /* Remove all divs (recursively) involving any of the given dimensions |
||
1741 | * in their definitions. |
||
1742 | */ |
||
1743 | __isl_give isl_basic_map *isl_basic_map_remove_divs_involving_dims( |
||
1744 | __isl_take isl_basic_map *bmap, |
||
1745 | enum isl_dim_type type, unsigned first, unsigned n) |
||
1746 | { |
||
1747 | int i; |
||
1748 | |||
1749 | if (!bmap) |
||
1750 | return NULL; |
||
1751 | isl_assert(bmap->ctx, first + n <= isl_basic_map_dim(bmap, type), |
||
1752 | goto error); |
||
1753 | first += isl_basic_map_offset(bmap, type); |
||
1754 | |||
1755 | for (i = bmap->n_div - 1; i >= 0; --i) { |
||
1756 | if (!div_involves_vars(bmap, i, first, n)) |
||
1757 | continue; |
||
1758 | bmap = isl_basic_map_remove_dims(bmap, isl_dim_div, i, 1); |
||
1759 | if (!bmap) |
||
1760 | return NULL; |
||
1761 | i = bmap->n_div; |
||
1762 | } |
||
1763 | |||
1764 | return bmap; |
||
1765 | error: |
||
1766 | isl_basic_map_free(bmap); |
||
1767 | return NULL; |
||
1768 | } |
||
1769 | |||
1770 | __isl_give isl_map *isl_map_remove_divs_involving_dims(__isl_take isl_map *map, |
||
1771 | enum isl_dim_type type, unsigned first, unsigned n) |
||
1772 | { |
||
1773 | int i; |
||
1774 | |||
1775 | if (!map) |
||
1776 | return NULL; |
||
1777 | if (map->n == 0) |
||
1778 | return map; |
||
1779 | |||
1780 | map = isl_map_cow(map); |
||
1781 | if (!map) |
||
1782 | return NULL; |
||
1783 | |||
1784 | for (i = 0; i < map->n; ++i) { |
||
1785 | map->p[i] = isl_basic_map_remove_divs_involving_dims(map->p[i], |
||
1786 | type, first, n); |
||
1787 | if (!map->p[i]) |
||
1788 | goto error; |
||
1789 | } |
||
1790 | return map; |
||
1791 | error: |
||
1792 | isl_map_free(map); |
||
1793 | return NULL; |
||
1794 | } |
||
1795 | |||
1796 | __isl_give isl_set *isl_set_remove_divs_involving_dims(__isl_take isl_set *set, |
||
1797 | enum isl_dim_type type, unsigned first, unsigned n) |
||
1798 | { |
||
1799 | return (isl_set *)isl_map_remove_divs_involving_dims((isl_map *)set, |
||
1800 | type, first, n); |
||
1801 | } |
||
1802 | |||
1803 | /* Does the desciption of "bmap" depend on the specified dimensions? |
||
1804 | * We also check whether the dimensions appear in any of the div definitions. |
||
1805 | * In principle there is no need for this check. If the dimensions appear |
||
1806 | * in a div definition, they also appear in the defining constraints of that |
||
1807 | * div. |
||
1808 | */ |
||
1809 | int isl_basic_map_involves_dims(__isl_keep isl_basic_map *bmap, |
||
1810 | enum isl_dim_type type, unsigned first, unsigned n) |
||
1811 | { |
||
1812 | int i; |
||
1813 | |||
1814 | if (!bmap) |
||
1815 | return -1; |
||
1816 | |||
1817 | if (first + n > isl_basic_map_dim(bmap, type)) |
||
1818 | isl_die(bmap->ctx, isl_error_invalid, |
||
1819 | "index out of bounds", return -1); |
||
1820 | |||
1821 | first += isl_basic_map_offset(bmap, type); |
||
1822 | for (i = 0; i < bmap->n_eq; ++i) |
||
1823 | if (isl_seq_first_non_zero(bmap->eq[i] + first, n) >= 0) |
||
1824 | return 1; |
||
1825 | for (i = 0; i < bmap->n_ineq; ++i) |
||
1826 | if (isl_seq_first_non_zero(bmap->ineq[i] + first, n) >= 0) |
||
1827 | return 1; |
||
1828 | for (i = 0; i < bmap->n_div; ++i) { |
||
1829 | if (isl_int_is_zero(bmap->div[i][0])) |
||
1830 | continue; |
||
1831 | if (isl_seq_first_non_zero(bmap->div[i] + 1 + first, n) >= 0) |
||
1832 | return 1; |
||
1833 | } |
||
1834 | |||
1835 | return 0; |
||
1836 | } |
||
1837 | |||
1838 | int isl_map_involves_dims(__isl_keep isl_map *map, |
||
1839 | enum isl_dim_type type, unsigned first, unsigned n) |
||
1840 | { |
||
1841 | int i; |
||
1842 | |||
1843 | if (!map) |
||
1844 | return -1; |
||
1845 | |||
1846 | if (first + n > isl_map_dim(map, type)) |
||
1847 | isl_die(map->ctx, isl_error_invalid, |
||
1848 | "index out of bounds", return -1); |
||
1849 | |||
1850 | for (i = 0; i < map->n; ++i) { |
||
1851 | int involves = isl_basic_map_involves_dims(map->p[i], |
||
1852 | type, first, n); |
||
1853 | if (involves < 0 || involves) |
||
1854 | return involves; |
||
1855 | } |
||
1856 | |||
1857 | return 0; |
||
1858 | } |
||
1859 | |||
1860 | int isl_basic_set_involves_dims(__isl_keep isl_basic_set *bset, |
||
1861 | enum isl_dim_type type, unsigned first, unsigned n) |
||
1862 | { |
||
1863 | return isl_basic_map_involves_dims(bset, type, first, n); |
||
1864 | } |
||
1865 | |||
1866 | int isl_set_involves_dims(__isl_keep isl_set *set, |
||
1867 | enum isl_dim_type type, unsigned first, unsigned n) |
||
1868 | { |
||
1869 | return isl_map_involves_dims(set, type, first, n); |
||
1870 | } |
||
1871 | |||
1872 | /* Return true if the definition of the given div is unknown or depends |
||
1873 | * on unknown divs. |
||
1874 | */ |
||
1875 | static int div_is_unknown(__isl_keep isl_basic_map *bmap, int div) |
||
1876 | { |
||
1877 | int i; |
||
1878 | unsigned div_offset = isl_basic_map_offset(bmap, isl_dim_div); |
||
1879 | |||
1880 | if (isl_int_is_zero(bmap->div[div][0])) |
||
1881 | return 1; |
||
1882 | |||
1883 | for (i = bmap->n_div - 1; i >= 0; --i) { |
||
1884 | if (isl_int_is_zero(bmap->div[div][1 + div_offset + i])) |
||
1885 | continue; |
||
1886 | if (div_is_unknown(bmap, i)) |
||
1887 | return 1; |
||
1888 | } |
||
1889 | |||
1890 | return 0; |
||
1891 | } |
||
1892 | |||
1893 | /* Remove all divs that are unknown or defined in terms of unknown divs. |
||
1894 | */ |
||
1895 | __isl_give isl_basic_map *isl_basic_map_remove_unknown_divs( |
||
1896 | __isl_take isl_basic_map *bmap) |
||
1897 | { |
||
1898 | int i; |
||
1899 | |||
1900 | if (!bmap) |
||
1901 | return NULL; |
||
1902 | |||
1903 | for (i = bmap->n_div - 1; i >= 0; --i) { |
||
1904 | if (!div_is_unknown(bmap, i)) |
||
1905 | continue; |
||
1906 | bmap = isl_basic_map_remove_dims(bmap, isl_dim_div, i, 1); |
||
1907 | if (!bmap) |
||
1908 | return NULL; |
||
1909 | i = bmap->n_div; |
||
1910 | } |
||
1911 | |||
1912 | return bmap; |
||
1913 | } |
||
1914 | |||
1915 | __isl_give isl_map *isl_map_remove_unknown_divs(__isl_take isl_map *map) |
||
1916 | { |
||
1917 | int i; |
||
1918 | |||
1919 | if (!map) |
||
1920 | return NULL; |
||
1921 | if (map->n == 0) |
||
1922 | return map; |
||
1923 | |||
1924 | map = isl_map_cow(map); |
||
1925 | if (!map) |
||
1926 | return NULL; |
||
1927 | |||
1928 | for (i = 0; i < map->n; ++i) { |
||
1929 | map->p[i] = isl_basic_map_remove_unknown_divs(map->p[i]); |
||
1930 | if (!map->p[i]) |
||
1931 | goto error; |
||
1932 | } |
||
1933 | return map; |
||
1934 | error: |
||
1935 | isl_map_free(map); |
||
1936 | return NULL; |
||
1937 | } |
||
1938 | |||
1939 | __isl_give isl_set *isl_set_remove_unknown_divs(__isl_take isl_set *set) |
||
1940 | { |
||
1941 | return (isl_set *)isl_map_remove_unknown_divs((isl_map *)set); |
||
1942 | } |
||
1943 | |||
1944 | __isl_give isl_basic_set *isl_basic_set_remove_dims( |
||
1945 | __isl_take isl_basic_set *bset, |
||
1946 | enum isl_dim_type type, unsigned first, unsigned n) |
||
1947 | { |
||
1948 | return (isl_basic_set *) |
||
1949 | isl_basic_map_remove_dims((isl_basic_map *)bset, type, first, n); |
||
1950 | } |
||
1951 | |||
1952 | struct isl_map *isl_map_remove_dims(struct isl_map *map, |
||
1953 | enum isl_dim_type type, unsigned first, unsigned n) |
||
1954 | { |
||
1955 | int i; |
||
1956 | |||
1957 | if (n == 0) |
||
1958 | return map; |
||
1959 | |||
1960 | map = isl_map_cow(map); |
||
1961 | if (!map) |
||
1962 | return NULL; |
||
1963 | isl_assert(map->ctx, first + n <= isl_map_dim(map, type), goto error); |
||
1964 | |||
1965 | for (i = 0; i < map->n; ++i) { |
||
1966 | map->p[i] = isl_basic_map_eliminate_vars(map->p[i], |
||
1967 | isl_basic_map_offset(map->p[i], type) - 1 + first, n); |
||
1968 | if (!map->p[i]) |
||
1969 | goto error; |
||
1970 | } |
||
1971 | map = isl_map_drop(map, type, first, n); |
||
1972 | return map; |
||
1973 | error: |
||
1974 | isl_map_free(map); |
||
1975 | return NULL; |
||
1976 | } |
||
1977 | |||
1978 | __isl_give isl_set *isl_set_remove_dims(__isl_take isl_set *bset, |
||
1979 | enum isl_dim_type type, unsigned first, unsigned n) |
||
1980 | { |
||
1981 | return (isl_set *)isl_map_remove_dims((isl_map *)bset, type, first, n); |
||
1982 | } |
||
1983 | |||
1984 | /* Project out n inputs starting at first using Fourier-Motzkin */ |
||
1985 | struct isl_map *isl_map_remove_inputs(struct isl_map *map, |
||
1986 | unsigned first, unsigned n) |
||
1987 | { |
||
1988 | return isl_map_remove_dims(map, isl_dim_in, first, n); |
||
1989 | } |
||
1990 | |||
1991 | static void dump_term(struct isl_basic_map *bmap, |
||
1992 | isl_int c, int pos, FILE *out) |
||
1993 | { |
||
1994 | const char *name; |
||
1995 | unsigned in = isl_basic_map_n_in(bmap); |
||
1996 | unsigned dim = in + isl_basic_map_n_out(bmap); |
||
1997 | unsigned nparam = isl_basic_map_n_param(bmap); |
||
1998 | if (!pos) |
||
1999 | isl_int_print(out, c, 0); |
||
2000 | else { |
||
2001 | if (!isl_int_is_one(c)) |
||
2002 | isl_int_print(out, c, 0); |
||
2003 | if (pos < 1 + nparam) { |
||
2004 | name = isl_space_get_dim_name(bmap->dim, |
||
2005 | isl_dim_param, pos - 1); |
||
2006 | if (name) |
||
2007 | fprintf(out, "%s", name); |
||
2008 | else |
||
2009 | fprintf(out, "p%d", pos - 1); |
||
2010 | } else if (pos < 1 + nparam + in) |
||
2011 | fprintf(out, "i%d", pos - 1 - nparam); |
||
2012 | else if (pos < 1 + nparam + dim) |
||
2013 | fprintf(out, "o%d", pos - 1 - nparam - in); |
||
2014 | else |
||
2015 | fprintf(out, "e%d", pos - 1 - nparam - dim); |
||
2016 | } |
||
2017 | } |
||
2018 | |||
2019 | static void dump_constraint_sign(struct isl_basic_map *bmap, isl_int *c, |
||
2020 | int sign, FILE *out) |
||
2021 | { |
||
2022 | int i; |
||
2023 | int first; |
||
2024 | unsigned len = 1 + isl_basic_map_total_dim(bmap); |
||
2025 | isl_int v; |
||
2026 | |||
2027 | isl_int_init(v); |
||
2028 | for (i = 0, first = 1; i < len; ++i) { |
||
2029 | if (isl_int_sgn(c[i]) * sign <= 0) |
||
2030 | continue; |
||
2031 | if (!first) |
||
2032 | fprintf(out, " + "); |
||
2033 | first = 0; |
||
2034 | isl_int_abs(v, c[i]); |
||
2035 | dump_term(bmap, v, i, out); |
||
2036 | } |
||
2037 | isl_int_clear(v); |
||
2038 | if (first) |
||
2039 | fprintf(out, "0"); |
||
2040 | } |
||
2041 | |||
2042 | static void dump_constraint(struct isl_basic_map *bmap, isl_int *c, |
||
2043 | const char *op, FILE *out, int indent) |
||
2044 | { |
||
2045 | int i; |
||
2046 | |||
2047 | fprintf(out, "%*s", indent, ""); |
||
2048 | |||
2049 | dump_constraint_sign(bmap, c, 1, out); |
||
2050 | fprintf(out, " %s ", op); |
||
2051 | dump_constraint_sign(bmap, c, -1, out); |
||
2052 | |||
2053 | fprintf(out, "\n"); |
||
2054 | |||
2055 | for (i = bmap->n_div; i < bmap->extra; ++i) { |
||
2056 | if (isl_int_is_zero(c[1+isl_space_dim(bmap->dim, isl_dim_all)+i])) |
||
2057 | continue; |
||
2058 | fprintf(out, "%*s", indent, ""); |
||
2059 | fprintf(out, "ERROR: unused div coefficient not zero\n"); |
||
2060 | abort(); |
||
2061 | } |
||
2062 | } |
||
2063 | |||
2064 | static void dump_constraints(struct isl_basic_map *bmap, |
||
2065 | isl_int **c, unsigned n, |
||
2066 | const char *op, FILE *out, int indent) |
||
2067 | { |
||
2068 | int i; |
||
2069 | |||
2070 | for (i = 0; i < n; ++i) |
||
2071 | dump_constraint(bmap, c[i], op, out, indent); |
||
2072 | } |
||
2073 | |||
2074 | static void dump_affine(struct isl_basic_map *bmap, isl_int *exp, FILE *out) |
||
2075 | { |
||
2076 | int j; |
||
2077 | int first = 1; |
||
2078 | unsigned total = isl_basic_map_total_dim(bmap); |
||
2079 | |||
2080 | for (j = 0; j < 1 + total; ++j) { |
||
2081 | if (isl_int_is_zero(exp[j])) |
||
2082 | continue; |
||
2083 | if (!first && isl_int_is_pos(exp[j])) |
||
2084 | fprintf(out, "+"); |
||
2085 | dump_term(bmap, exp[j], j, out); |
||
2086 | first = 0; |
||
2087 | } |
||
2088 | } |
||
2089 | |||
2090 | static void dump(struct isl_basic_map *bmap, FILE *out, int indent) |
||
2091 | { |
||
2092 | int i; |
||
2093 | |||
2094 | dump_constraints(bmap, bmap->eq, bmap->n_eq, "=", out, indent); |
||
2095 | dump_constraints(bmap, bmap->ineq, bmap->n_ineq, ">=", out, indent); |
||
2096 | |||
2097 | for (i = 0; i < bmap->n_div; ++i) { |
||
2098 | fprintf(out, "%*s", indent, ""); |
||
2099 | fprintf(out, "e%d = [(", i); |
||
2100 | dump_affine(bmap, bmap->div[i]+1, out); |
||
2101 | fprintf(out, ")/"); |
||
2102 | isl_int_print(out, bmap->div[i][0], 0); |
||
2103 | fprintf(out, "]\n"); |
||
2104 | } |
||
2105 | } |
||
2106 | |||
2107 | void isl_basic_set_print_internal(struct isl_basic_set *bset, |
||
2108 | FILE *out, int indent) |
||
2109 | { |
||
2110 | if (!bset) { |
||
2111 | fprintf(out, "null basic set\n"); |
||
2112 | return; |
||
2113 | } |
||
2114 | |||
2115 | fprintf(out, "%*s", indent, ""); |
||
2116 | fprintf(out, "ref: %d, nparam: %d, dim: %d, extra: %d, flags: %x\n", |
||
2117 | bset->ref, bset->dim->nparam, bset->dim->n_out, |
||
2118 | bset->extra, bset->flags); |
||
2119 | dump((struct isl_basic_map *)bset, out, indent); |
||
2120 | } |
||
2121 | |||
2122 | void isl_basic_map_print_internal(struct isl_basic_map *bmap, |
||
2123 | FILE *out, int indent) |
||
2124 | { |
||
2125 | if (!bmap) { |
||
2126 | fprintf(out, "null basic map\n"); |
||
2127 | return; |
||
2128 | } |
||
2129 | |||
2130 | fprintf(out, "%*s", indent, ""); |
||
2131 | fprintf(out, "ref: %d, nparam: %d, in: %d, out: %d, extra: %d, " |
||
2132 | "flags: %x, n_name: %d\n", |
||
2133 | bmap->ref, |
||
2134 | bmap->dim->nparam, bmap->dim->n_in, bmap->dim->n_out, |
||
2135 | bmap->extra, bmap->flags, bmap->dim->n_id); |
||
2136 | dump(bmap, out, indent); |
||
2137 | } |
||
2138 | |||
2139 | int isl_inequality_negate(struct isl_basic_map *bmap, unsigned pos) |
||
2140 | { |
||
2141 | unsigned total; |
||
2142 | if (!bmap) |
||
2143 | return -1; |
||
2144 | total = isl_basic_map_total_dim(bmap); |
||
2145 | isl_assert(bmap->ctx, pos < bmap->n_ineq, return -1); |
||
2146 | isl_seq_neg(bmap->ineq[pos], bmap->ineq[pos], 1 + total); |
||
2147 | isl_int_sub_ui(bmap->ineq[pos][0], bmap->ineq[pos][0], 1); |
||
2148 | ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED); |
||
2149 | return 0; |
||
2150 | } |
||
2151 | |||
2152 | __isl_give isl_set *isl_set_alloc_space(__isl_take isl_space *dim, int n, |
||
2153 | unsigned flags) |
||
2154 | { |
||
2155 | struct isl_set *set; |
||
2156 | |||
2157 | if (!dim) |
||
2158 | return NULL; |
||
2159 | isl_assert(dim->ctx, dim->n_in == 0, goto error); |
||
2160 | isl_assert(dim->ctx, n >= 0, goto error); |
||
2161 | set = isl_alloc(dim->ctx, struct isl_set, |
||
2162 | sizeof(struct isl_set) + |
||
2163 | (n - 1) * sizeof(struct isl_basic_set *)); |
||
2164 | if (!set) |
||
2165 | goto error; |
||
2166 | |||
2167 | set->ctx = dim->ctx; |
||
2168 | isl_ctx_ref(set->ctx); |
||
2169 | set->ref = 1; |
||
2170 | set->size = n; |
||
2171 | set->n = 0; |
||
2172 | set->dim = dim; |
||
2173 | set->flags = flags; |
||
2174 | return set; |
||
2175 | error: |
||
2176 | isl_space_free(dim); |
||
2177 | return NULL; |
||
2178 | } |
||
2179 | |||
2180 | struct isl_set *isl_set_alloc(struct isl_ctx *ctx, |
||
2181 | unsigned nparam, unsigned dim, int n, unsigned flags) |
||
2182 | { |
||
2183 | struct isl_set *set; |
||
2184 | isl_space *dims; |
||
2185 | |||
2186 | dims = isl_space_alloc(ctx, nparam, 0, dim); |
||
2187 | if (!dims) |
||
2188 | return NULL; |
||
2189 | |||
2190 | set = isl_set_alloc_space(dims, n, flags); |
||
2191 | return set; |
||
2192 | } |
||
2193 | |||
2194 | /* Make sure "map" has room for at least "n" more basic maps. |
||
2195 | */ |
||
2196 | struct isl_map *isl_map_grow(struct isl_map *map, int n) |
||
2197 | { |
||
2198 | int i; |
||
2199 | struct isl_map *grown = NULL; |
||
2200 | |||
2201 | if (!map) |
||
2202 | return NULL; |
||
2203 | isl_assert(map->ctx, n >= 0, goto error); |
||
2204 | if (map->n + n <= map->size) |
||
2205 | return map; |
||
2206 | grown = isl_map_alloc_space(isl_map_get_space(map), map->n + n, map->flags); |
||
2207 | if (!grown) |
||
2208 | goto error; |
||
2209 | for (i = 0; i < map->n; ++i) { |
||
2210 | grown->p[i] = isl_basic_map_copy(map->p[i]); |
||
2211 | if (!grown->p[i]) |
||
2212 | goto error; |
||
2213 | grown->n++; |
||
2214 | } |
||
2215 | isl_map_free(map); |
||
2216 | return grown; |
||
2217 | error: |
||
2218 | isl_map_free(grown); |
||
2219 | isl_map_free(map); |
||
2220 | return NULL; |
||
2221 | } |
||
2222 | |||
2223 | /* Make sure "set" has room for at least "n" more basic sets. |
||
2224 | */ |
||
2225 | struct isl_set *isl_set_grow(struct isl_set *set, int n) |
||
2226 | { |
||
2227 | return (struct isl_set *)isl_map_grow((struct isl_map *)set, n); |
||
2228 | } |
||
2229 | |||
2230 | struct isl_set *isl_set_dup(struct isl_set *set) |
||
2231 | { |
||
2232 | int i; |
||
2233 | struct isl_set *dup; |
||
2234 | |||
2235 | if (!set) |
||
2236 | return NULL; |
||
2237 | |||
2238 | dup = isl_set_alloc_space(isl_space_copy(set->dim), set->n, set->flags); |
||
2239 | if (!dup) |
||
2240 | return NULL; |
||
2241 | for (i = 0; i < set->n; ++i) |
||
2242 | dup = isl_set_add_basic_set(dup, isl_basic_set_copy(set->p[i])); |
||
2243 | return dup; |
||
2244 | } |
||
2245 | |||
2246 | struct isl_set *isl_set_from_basic_set(struct isl_basic_set *bset) |
||
2247 | { |
||
2248 | return isl_map_from_basic_map(bset); |
||
2249 | } |
||
2250 | |||
2251 | struct isl_map *isl_map_from_basic_map(struct isl_basic_map *bmap) |
||
2252 | { |
||
2253 | struct isl_map *map; |
||
2254 | |||
2255 | if (!bmap) |
||
2256 | return NULL; |
||
2257 | |||
2258 | map = isl_map_alloc_space(isl_space_copy(bmap->dim), 1, ISL_MAP_DISJOINT); |
||
2259 | return isl_map_add_basic_map(map, bmap); |
||
2260 | } |
||
2261 | |||
2262 | __isl_give isl_set *isl_set_add_basic_set(__isl_take isl_set *set, |
||
2263 | __isl_take isl_basic_set *bset) |
||
2264 | { |
||
2265 | return (struct isl_set *)isl_map_add_basic_map((struct isl_map *)set, |
||
2266 | (struct isl_basic_map *)bset); |
||
2267 | } |
||
2268 | |||
2269 | void isl_set_free(struct isl_set *set) |
||
2270 | { |
||
2271 | int i; |
||
2272 | |||
2273 | if (!set) |
||
2274 | return; |
||
2275 | |||
2276 | if (--set->ref > 0) |
||
2277 | return; |
||
2278 | |||
2279 | isl_ctx_deref(set->ctx); |
||
2280 | for (i = 0; i < set->n; ++i) |
||
2281 | isl_basic_set_free(set->p[i]); |
||
2282 | isl_space_free(set->dim); |
||
2283 | free(set); |
||
2284 | } |
||
2285 | |||
2286 | void isl_set_print_internal(struct isl_set *set, FILE *out, int indent) |
||
2287 | { |
||
2288 | int i; |
||
2289 | |||
2290 | if (!set) { |
||
2291 | fprintf(out, "null set\n"); |
||
2292 | return; |
||
2293 | } |
||
2294 | |||
2295 | fprintf(out, "%*s", indent, ""); |
||
2296 | fprintf(out, "ref: %d, n: %d, nparam: %d, dim: %d, flags: %x\n", |
||
2297 | set->ref, set->n, set->dim->nparam, set->dim->n_out, |
||
2298 | set->flags); |
||
2299 | for (i = 0; i < set->n; ++i) { |
||
2300 | fprintf(out, "%*s", indent, ""); |
||
2301 | fprintf(out, "basic set %d:\n", i); |
||
2302 | isl_basic_set_print_internal(set->p[i], out, indent+4); |
||
2303 | } |
||
2304 | } |
||
2305 | |||
2306 | void isl_map_print_internal(struct isl_map *map, FILE *out, int indent) |
||
2307 | { |
||
2308 | int i; |
||
2309 | |||
2310 | if (!map) { |
||
2311 | fprintf(out, "null map\n"); |
||
2312 | return; |
||
2313 | } |
||
2314 | |||
2315 | fprintf(out, "%*s", indent, ""); |
||
2316 | fprintf(out, "ref: %d, n: %d, nparam: %d, in: %d, out: %d, " |
||
2317 | "flags: %x, n_name: %d\n", |
||
2318 | map->ref, map->n, map->dim->nparam, map->dim->n_in, |
||
2319 | map->dim->n_out, map->flags, map->dim->n_id); |
||
2320 | for (i = 0; i < map->n; ++i) { |
||
2321 | fprintf(out, "%*s", indent, ""); |
||
2322 | fprintf(out, "basic map %d:\n", i); |
||
2323 | isl_basic_map_print_internal(map->p[i], out, indent+4); |
||
2324 | } |
||
2325 | } |
||
2326 | |||
2327 | struct isl_basic_map *isl_basic_map_intersect_domain( |
||
2328 | struct isl_basic_map *bmap, struct isl_basic_set *bset) |
||
2329 | { |
||
2330 | struct isl_basic_map *bmap_domain; |
||
2331 | |||
2332 | if (!bmap || !bset) |
||
2333 | goto error; |
||
2334 | |||
2335 | isl_assert(bset->ctx, isl_space_match(bmap->dim, isl_dim_param, |
||
2336 | bset->dim, isl_dim_param), goto error); |
||
2337 | |||
2338 | if (isl_space_dim(bset->dim, isl_dim_set) != 0) |
||
2339 | isl_assert(bset->ctx, |
||
2340 | isl_basic_map_compatible_domain(bmap, bset), goto error); |
||
2341 | |||
2342 | bmap = isl_basic_map_cow(bmap); |
||
2343 | if (!bmap) |
||
2344 | goto error; |
||
2345 | bmap = isl_basic_map_extend_space(bmap, isl_space_copy(bmap->dim), |
||
2346 | bset->n_div, bset->n_eq, bset->n_ineq); |
||
2347 | bmap_domain = isl_basic_map_from_domain(bset); |
||
2348 | bmap = add_constraints(bmap, bmap_domain, 0, 0); |
||
2349 | |||
2350 | bmap = isl_basic_map_simplify(bmap); |
||
2351 | return isl_basic_map_finalize(bmap); |
||
2352 | error: |
||
2353 | isl_basic_map_free(bmap); |
||
2354 | isl_basic_set_free(bset); |
||
2355 | return NULL; |
||
2356 | } |
||
2357 | |||
2358 | struct isl_basic_map *isl_basic_map_intersect_range( |
||
2359 | struct isl_basic_map *bmap, struct isl_basic_set *bset) |
||
2360 | { |
||
2361 | struct isl_basic_map *bmap_range; |
||
2362 | |||
2363 | if (!bmap || !bset) |
||
2364 | goto error; |
||
2365 | |||
2366 | isl_assert(bset->ctx, isl_space_match(bmap->dim, isl_dim_param, |
||
2367 | bset->dim, isl_dim_param), goto error); |
||
2368 | |||
2369 | if (isl_space_dim(bset->dim, isl_dim_set) != 0) |
||
2370 | isl_assert(bset->ctx, |
||
2371 | isl_basic_map_compatible_range(bmap, bset), goto error); |
||
2372 | |||
2373 | if (isl_basic_set_is_universe(bset)) { |
||
2374 | isl_basic_set_free(bset); |
||
2375 | return bmap; |
||
2376 | } |
||
2377 | |||
2378 | bmap = isl_basic_map_cow(bmap); |
||
2379 | if (!bmap) |
||
2380 | goto error; |
||
2381 | bmap = isl_basic_map_extend_space(bmap, isl_space_copy(bmap->dim), |
||
2382 | bset->n_div, bset->n_eq, bset->n_ineq); |
||
2383 | bmap_range = isl_basic_map_from_basic_set(bset, isl_space_copy(bset->dim)); |
||
2384 | bmap = add_constraints(bmap, bmap_range, 0, 0); |
||
2385 | |||
2386 | bmap = isl_basic_map_simplify(bmap); |
||
2387 | return isl_basic_map_finalize(bmap); |
||
2388 | error: |
||
2389 | isl_basic_map_free(bmap); |
||
2390 | isl_basic_set_free(bset); |
||
2391 | return NULL; |
||
2392 | } |
||
2393 | |||
2394 | int isl_basic_map_contains(struct isl_basic_map *bmap, struct isl_vec *vec) |
||
2395 | { |
||
2396 | int i; |
||
2397 | unsigned total; |
||
2398 | isl_int s; |
||
2399 | |||
2400 | total = 1 + isl_basic_map_total_dim(bmap); |
||
2401 | if (total != vec->size) |
||
2402 | return -1; |
||
2403 | |||
2404 | isl_int_init(s); |
||
2405 | |||
2406 | for (i = 0; i < bmap->n_eq; ++i) { |
||
2407 | isl_seq_inner_product(vec->el, bmap->eq[i], total, &s); |
||
2408 | if (!isl_int_is_zero(s)) { |
||
2409 | isl_int_clear(s); |
||
2410 | return 0; |
||
2411 | } |
||
2412 | } |
||
2413 | |||
2414 | for (i = 0; i < bmap->n_ineq; ++i) { |
||
2415 | isl_seq_inner_product(vec->el, bmap->ineq[i], total, &s); |
||
2416 | if (isl_int_is_neg(s)) { |
||
2417 | isl_int_clear(s); |
||
2418 | return 0; |
||
2419 | } |
||
2420 | } |
||
2421 | |||
2422 | isl_int_clear(s); |
||
2423 | |||
2424 | return 1; |
||
2425 | } |
||
2426 | |||
2427 | int isl_basic_set_contains(struct isl_basic_set *bset, struct isl_vec *vec) |
||
2428 | { |
||
2429 | return isl_basic_map_contains((struct isl_basic_map *)bset, vec); |
||
2430 | } |
||
2431 | |||
2432 | struct isl_basic_map *isl_basic_map_intersect( |
||
2433 | struct isl_basic_map *bmap1, struct isl_basic_map *bmap2) |
||
2434 | { |
||
2435 | struct isl_vec *sample = NULL; |
||
2436 | |||
2437 | if (!bmap1 || !bmap2) |
||
2438 | goto error; |
||
2439 | |||
2440 | isl_assert(bmap1->ctx, isl_space_match(bmap1->dim, isl_dim_param, |
||
2441 | bmap2->dim, isl_dim_param), goto error); |
||
2442 | if (isl_space_dim(bmap1->dim, isl_dim_all) == |
||
2443 | isl_space_dim(bmap1->dim, isl_dim_param) && |
||
2444 | isl_space_dim(bmap2->dim, isl_dim_all) != |
||
2445 | isl_space_dim(bmap2->dim, isl_dim_param)) |
||
2446 | return isl_basic_map_intersect(bmap2, bmap1); |
||
2447 | |||
2448 | if (isl_space_dim(bmap2->dim, isl_dim_all) != |
||
2449 | isl_space_dim(bmap2->dim, isl_dim_param)) |
||
2450 | isl_assert(bmap1->ctx, |
||
2451 | isl_space_is_equal(bmap1->dim, bmap2->dim), goto error); |
||
2452 | |||
2453 | if (bmap1->sample && |
||
2454 | isl_basic_map_contains(bmap1, bmap1->sample) > 0 && |
||
2455 | isl_basic_map_contains(bmap2, bmap1->sample) > 0) |
||
2456 | sample = isl_vec_copy(bmap1->sample); |
||
2457 | else if (bmap2->sample && |
||
2458 | isl_basic_map_contains(bmap1, bmap2->sample) > 0 && |
||
2459 | isl_basic_map_contains(bmap2, bmap2->sample) > 0) |
||
2460 | sample = isl_vec_copy(bmap2->sample); |
||
2461 | |||
2462 | bmap1 = isl_basic_map_cow(bmap1); |
||
2463 | if (!bmap1) |
||
2464 | goto error; |
||
2465 | bmap1 = isl_basic_map_extend_space(bmap1, isl_space_copy(bmap1->dim), |
||
2466 | bmap2->n_div, bmap2->n_eq, bmap2->n_ineq); |
||
2467 | bmap1 = add_constraints(bmap1, bmap2, 0, 0); |
||
2468 | |||
2469 | if (!bmap1) |
||
2470 | isl_vec_free(sample); |
||
2471 | else if (sample) { |
||
2472 | isl_vec_free(bmap1->sample); |
||
2473 | bmap1->sample = sample; |
||
2474 | } |
||
2475 | |||
2476 | bmap1 = isl_basic_map_simplify(bmap1); |
||
2477 | return isl_basic_map_finalize(bmap1); |
||
2478 | error: |
||
2479 | if (sample) |
||
2480 | isl_vec_free(sample); |
||
2481 | isl_basic_map_free(bmap1); |
||
2482 | isl_basic_map_free(bmap2); |
||
2483 | return NULL; |
||
2484 | } |
||
2485 | |||
2486 | struct isl_basic_set *isl_basic_set_intersect( |
||
2487 | struct isl_basic_set *bset1, struct isl_basic_set *bset2) |
||
2488 | { |
||
2489 | return (struct isl_basic_set *) |
||
2490 | isl_basic_map_intersect( |
||
2491 | (struct isl_basic_map *)bset1, |
||
2492 | (struct isl_basic_map *)bset2); |
||
2493 | } |
||
2494 | |||
2495 | __isl_give isl_basic_set *isl_basic_set_intersect_params( |
||
2496 | __isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2) |
||
2497 | { |
||
2498 | return isl_basic_set_intersect(bset1, bset2); |
||
2499 | } |
||
2500 | |||
2501 | /* Special case of isl_map_intersect, where both map1 and map2 |
||
2502 | * are convex, without any divs and such that either map1 or map2 |
||
2503 | * contains a single constraint. This constraint is then simply |
||
2504 | * added to the other map. |
||
2505 | */ |
||
2506 | static __isl_give isl_map *map_intersect_add_constraint( |
||
2507 | __isl_take isl_map *map1, __isl_take isl_map *map2) |
||
2508 | { |
||
2509 | isl_assert(map1->ctx, map1->n == 1, goto error); |
||
2510 | isl_assert(map2->ctx, map1->n == 1, goto error); |
||
2511 | isl_assert(map1->ctx, map1->p[0]->n_div == 0, goto error); |
||
2512 | isl_assert(map2->ctx, map1->p[0]->n_div == 0, goto error); |
||
2513 | |||
2514 | if (map2->p[0]->n_eq + map2->p[0]->n_ineq != 1) |
||
2515 | return isl_map_intersect(map2, map1); |
||
2516 | |||
2517 | isl_assert(map2->ctx, |
||
2518 | map2->p[0]->n_eq + map2->p[0]->n_ineq == 1, goto error); |
||
2519 | |||
2520 | map1 = isl_map_cow(map1); |
||
2521 | if (!map1) |
||
2522 | goto error; |
||
2523 | if (isl_map_plain_is_empty(map1)) { |
||
2524 | isl_map_free(map2); |
||
2525 | return map1; |
||
2526 | } |
||
2527 | map1->p[0] = isl_basic_map_cow(map1->p[0]); |
||
2528 | if (map2->p[0]->n_eq == 1) |
||
2529 | map1->p[0] = isl_basic_map_add_eq(map1->p[0], map2->p[0]->eq[0]); |
||
2530 | else |
||
2531 | map1->p[0] = isl_basic_map_add_ineq(map1->p[0], |
||
2532 | map2->p[0]->ineq[0]); |
||
2533 | |||
2534 | map1->p[0] = isl_basic_map_simplify(map1->p[0]); |
||
2535 | map1->p[0] = isl_basic_map_finalize(map1->p[0]); |
||
2536 | if (!map1->p[0]) |
||
2537 | goto error; |
||
2538 | |||
2539 | if (isl_basic_map_plain_is_empty(map1->p[0])) { |
||
2540 | isl_basic_map_free(map1->p[0]); |
||
2541 | map1->n = 0; |
||
2542 | } |
||
2543 | |||
2544 | isl_map_free(map2); |
||
2545 | |||
2546 | return map1; |
||
2547 | error: |
||
2548 | isl_map_free(map1); |
||
2549 | isl_map_free(map2); |
||
2550 | return NULL; |
||
2551 | } |
||
2552 | |||
2553 | /* map2 may be either a parameter domain or a map living in the same |
||
2554 | * space as map1. |
||
2555 | */ |
||
2556 | static __isl_give isl_map *map_intersect_internal(__isl_take isl_map *map1, |
||
2557 | __isl_take isl_map *map2) |
||
2558 | { |
||
2559 | unsigned flags = 0; |
||
2560 | struct isl_map *result; |
||
2561 | int i, j; |
||
2562 | |||
2563 | if (!map1 || !map2) |
||
2564 | goto error; |
||
2565 | |||
2566 | if (isl_map_plain_is_empty(map1) && |
||
2567 | isl_space_is_equal(map1->dim, map2->dim)) { |
||
2568 | isl_map_free(map2); |
||
2569 | return map1; |
||
2570 | } |
||
2571 | if (isl_map_plain_is_empty(map2) && |
||
2572 | isl_space_is_equal(map1->dim, map2->dim)) { |
||
2573 | isl_map_free(map1); |
||
2574 | return map2; |
||
2575 | } |
||
2576 | |||
2577 | if (map1->n == 1 && map2->n == 1 && |
||
2578 | map1->p[0]->n_div == 0 && map2->p[0]->n_div == 0 && |
||
2579 | isl_space_is_equal(map1->dim, map2->dim) && |
||
2580 | (map1->p[0]->n_eq + map1->p[0]->n_ineq == 1 || |
||
2581 | map2->p[0]->n_eq + map2->p[0]->n_ineq == 1)) |
||
2582 | return map_intersect_add_constraint(map1, map2); |
||
2583 | |||
2584 | if (isl_space_dim(map2->dim, isl_dim_all) != |
||
2585 | isl_space_dim(map2->dim, isl_dim_param)) |
||
2586 | isl_assert(map1->ctx, |
||
2587 | isl_space_is_equal(map1->dim, map2->dim), goto error); |
||
2588 | |||
2589 | if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) && |
||
2590 | ISL_F_ISSET(map2, ISL_MAP_DISJOINT)) |
||
2591 | ISL_FL_SET(flags, ISL_MAP_DISJOINT); |
||
2592 | |||
2593 | result = isl_map_alloc_space(isl_space_copy(map1->dim), |
||
2594 | map1->n * map2->n, flags); |
||
2595 | if (!result) |
||
2596 | goto error; |
||
2597 | for (i = 0; i < map1->n; ++i) |
||
2598 | for (j = 0; j < map2->n; ++j) { |
||
2599 | struct isl_basic_map *part; |
||
2600 | part = isl_basic_map_intersect( |
||
2601 | isl_basic_map_copy(map1->p[i]), |
||
2602 | isl_basic_map_copy(map2->p[j])); |
||
2603 | if (isl_basic_map_is_empty(part)) |
||
2604 | isl_basic_map_free(part); |
||
2605 | else |
||
2606 | result = isl_map_add_basic_map(result, part); |
||
2607 | if (!result) |
||
2608 | goto error; |
||
2609 | } |
||
2610 | isl_map_free(map1); |
||
2611 | isl_map_free(map2); |
||
2612 | return result; |
||
2613 | error: |
||
2614 | isl_map_free(map1); |
||
2615 | isl_map_free(map2); |
||
2616 | return NULL; |
||
2617 | } |
||
2618 | |||
2619 | static __isl_give isl_map *map_intersect(__isl_take isl_map *map1, |
||
2620 | __isl_take isl_map *map2) |
||
2621 | { |
||
2622 | if (!map1 || !map2) |
||
2623 | goto error; |
||
2624 | if (!isl_space_is_equal(map1->dim, map2->dim)) |
||
2625 | isl_die(isl_map_get_ctx(map1), isl_error_invalid, |
||
2626 | "spaces don't match", goto error); |
||
2627 | return map_intersect_internal(map1, map2); |
||
2628 | error: |
||
2629 | isl_map_free(map1); |
||
2630 | isl_map_free(map2); |
||
2631 | return NULL; |
||
2632 | } |
||
2633 | |||
2634 | __isl_give isl_map *isl_map_intersect(__isl_take isl_map *map1, |
||
2635 | __isl_take isl_map *map2) |
||
2636 | { |
||
2637 | return isl_map_align_params_map_map_and(map1, map2, &map_intersect); |
||
2638 | } |
||
2639 | |||
2640 | struct isl_set *isl_set_intersect(struct isl_set *set1, struct isl_set *set2) |
||
2641 | { |
||
2642 | return (struct isl_set *) |
||
2643 | isl_map_intersect((struct isl_map *)set1, |
||
2644 | (struct isl_map *)set2); |
||
2645 | } |
||
2646 | |||
2647 | /* map_intersect_internal accepts intersections |
||
2648 | * with parameter domains, so we can just call that function. |
||
2649 | */ |
||
2650 | static __isl_give isl_map *map_intersect_params(__isl_take isl_map *map, |
||
2651 | __isl_take isl_set *params) |
||
2652 | { |
||
2653 | return map_intersect_internal(map, params); |
||
2654 | } |
||
2655 | |||
2656 | __isl_give isl_map *isl_map_intersect_params(__isl_take isl_map *map1, |
||
2657 | __isl_take isl_map *map2) |
||
2658 | { |
||
2659 | return isl_map_align_params_map_map_and(map1, map2, &map_intersect_params); |
||
2660 | } |
||
2661 | |||
2662 | __isl_give isl_set *isl_set_intersect_params(__isl_take isl_set *set, |
||
2663 | __isl_take isl_set *params) |
||
2664 | { |
||
2665 | return isl_map_intersect_params(set, params); |
||
2666 | } |
||
2667 | |||
2668 | struct isl_basic_map *isl_basic_map_reverse(struct isl_basic_map *bmap) |
||
2669 | { |
||
2670 | isl_space *dim; |
||
2671 | struct isl_basic_set *bset; |
||
2672 | unsigned in; |
||
2673 | |||
2674 | if (!bmap) |
||
2675 | return NULL; |
||
2676 | bmap = isl_basic_map_cow(bmap); |
||
2677 | if (!bmap) |
||
2678 | return NULL; |
||
2679 | dim = isl_space_reverse(isl_space_copy(bmap->dim)); |
||
2680 | in = isl_basic_map_n_in(bmap); |
||
2681 | bset = isl_basic_set_from_basic_map(bmap); |
||
2682 | bset = isl_basic_set_swap_vars(bset, in); |
||
2683 | return isl_basic_map_from_basic_set(bset, dim); |
||
2684 | } |
||
2685 | |||
2686 | static __isl_give isl_basic_map *basic_map_space_reset( |
||
2687 | __isl_take isl_basic_map *bmap, enum isl_dim_type type) |
||
2688 | { |
||
2689 | isl_space *space; |
||
2690 | |||
2691 | if (!isl_space_is_named_or_nested(bmap->dim, type)) |
||
2692 | return bmap; |
||
2693 | |||
2694 | space = isl_basic_map_get_space(bmap); |
||
2695 | space = isl_space_reset(space, type); |
||
2696 | bmap = isl_basic_map_reset_space(bmap, space); |
||
2697 | return bmap; |
||
2698 | } |
||
2699 | |||
2700 | __isl_give isl_basic_map *isl_basic_map_insert(__isl_take isl_basic_map *bmap, |
||
2701 | enum isl_dim_type type, unsigned pos, unsigned n) |
||
2702 | { |
||
2703 | isl_space *res_dim; |
||
2704 | struct isl_basic_map *res; |
||
2705 | struct isl_dim_map *dim_map; |
||
2706 | unsigned total, off; |
||
2707 | enum isl_dim_type t; |
||
2708 | |||
2709 | if (n == 0) |
||
2710 | return basic_map_space_reset(bmap, type); |
||
2711 | |||
2712 | if (!bmap) |
||
2713 | return NULL; |
||
2714 | |||
2715 | res_dim = isl_space_insert_dims(isl_basic_map_get_space(bmap), type, pos, n); |
||
2716 | |||
2717 | total = isl_basic_map_total_dim(bmap) + n; |
||
2718 | dim_map = isl_dim_map_alloc(bmap->ctx, total); |
||
2719 | off = 0; |
||
2720 | for (t = isl_dim_param; t <= isl_dim_out; ++t) { |
||
2721 | if (t != type) { |
||
2722 | isl_dim_map_dim(dim_map, bmap->dim, t, off); |
||
2723 | } else { |
||
2724 | unsigned size = isl_basic_map_dim(bmap, t); |
||
2725 | isl_dim_map_dim_range(dim_map, bmap->dim, t, |
||
2726 | 0, pos, off); |
||
2727 | isl_dim_map_dim_range(dim_map, bmap->dim, t, |
||
2728 | pos, size - pos, off + pos + n); |
||
2729 | } |
||
2730 | off += isl_space_dim(res_dim, t); |
||
2731 | } |
||
2732 | isl_dim_map_div(dim_map, bmap, off); |
||
2733 | |||
2734 | res = isl_basic_map_alloc_space(res_dim, |
||
2735 | bmap->n_div, bmap->n_eq, bmap->n_ineq); |
||
2736 | if (isl_basic_map_is_rational(bmap)) |
||
2737 | res = isl_basic_map_set_rational(res); |
||
2738 | if (isl_basic_map_plain_is_empty(bmap)) { |
||
2739 | isl_basic_map_free(bmap); |
||
2740 | return isl_basic_map_set_to_empty(res); |
||
2741 | } |
||
2742 | res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map); |
||
2743 | return isl_basic_map_finalize(res); |
||
2744 | } |
||
2745 | |||
2746 | __isl_give isl_basic_map *isl_basic_map_add(__isl_take isl_basic_map *bmap, |
||
2747 | enum isl_dim_type type, unsigned n) |
||
2748 | { |
||
2749 | if (!bmap) |
||
2750 | return NULL; |
||
2751 | return isl_basic_map_insert(bmap, type, |
||
2752 | isl_basic_map_dim(bmap, type), n); |
||
2753 | } |
||
2754 | |||
2755 | __isl_give isl_basic_set *isl_basic_set_add(__isl_take isl_basic_set *bset, |
||
2756 | enum isl_dim_type type, unsigned n) |
||
2757 | { |
||
2758 | if (!bset) |
||
2759 | return NULL; |
||
2760 | isl_assert(bset->ctx, type != isl_dim_in, goto error); |
||
2761 | return (isl_basic_set *)isl_basic_map_add((isl_basic_map *)bset, type, n); |
||
2762 | error: |
||
2763 | isl_basic_set_free(bset); |
||
2764 | return NULL; |
||
2765 | } |
||
2766 | |||
2767 | static __isl_give isl_map *map_space_reset(__isl_take isl_map *map, |
||
2768 | enum isl_dim_type type) |
||
2769 | { |
||
2770 | isl_space *space; |
||
2771 | |||
2772 | if (!map || !isl_space_is_named_or_nested(map->dim, type)) |
||
2773 | return map; |
||
2774 | |||
2775 | space = isl_map_get_space(map); |
||
2776 | space = isl_space_reset(space, type); |
||
2777 | map = isl_map_reset_space(map, space); |
||
2778 | return map; |
||
2779 | } |
||
2780 | |||
2781 | __isl_give isl_map *isl_map_insert_dims(__isl_take isl_map *map, |
||
2782 | enum isl_dim_type type, unsigned pos, unsigned n) |
||
2783 | { |
||
2784 | int i; |
||
2785 | |||
2786 | if (n == 0) |
||
2787 | return map_space_reset(map, type); |
||
2788 | |||
2789 | map = isl_map_cow(map); |
||
2790 | if (!map) |
||
2791 | return NULL; |
||
2792 | |||
2793 | map->dim = isl_space_insert_dims(map->dim, type, pos, n); |
||
2794 | if (!map->dim) |
||
2795 | goto error; |
||
2796 | |||
2797 | for (i = 0; i < map->n; ++i) { |
||
2798 | map->p[i] = isl_basic_map_insert(map->p[i], type, pos, n); |
||
2799 | if (!map->p[i]) |
||
2800 | goto error; |
||
2801 | } |
||
2802 | |||
2803 | return map; |
||
2804 | error: |
||
2805 | isl_map_free(map); |
||
2806 | return NULL; |
||
2807 | } |
||
2808 | |||
2809 | __isl_give isl_set *isl_set_insert_dims(__isl_take isl_set *set, |
||
2810 | enum isl_dim_type type, unsigned pos, unsigned n) |
||
2811 | { |
||
2812 | return isl_map_insert_dims(set, type, pos, n); |
||
2813 | } |
||
2814 | |||
2815 | __isl_give isl_map *isl_map_add_dims(__isl_take isl_map *map, |
||
2816 | enum isl_dim_type type, unsigned n) |
||
2817 | { |
||
2818 | if (!map) |
||
2819 | return NULL; |
||
2820 | return isl_map_insert_dims(map, type, isl_map_dim(map, type), n); |
||
2821 | } |
||
2822 | |||
2823 | __isl_give isl_set *isl_set_add_dims(__isl_take isl_set *set, |
||
2824 | enum isl_dim_type type, unsigned n) |
||
2825 | { |
||
2826 | if (!set) |
||
2827 | return NULL; |
||
2828 | isl_assert(set->ctx, type != isl_dim_in, goto error); |
||
2829 | return (isl_set *)isl_map_add_dims((isl_map *)set, type, n); |
||
2830 | error: |
||
2831 | isl_set_free(set); |
||
2832 | return NULL; |
||
2833 | } |
||
2834 | |||
2835 | __isl_give isl_basic_map *isl_basic_map_move_dims( |
||
2836 | __isl_take isl_basic_map *bmap, |
||
2837 | enum isl_dim_type dst_type, unsigned dst_pos, |
||
2838 | enum isl_dim_type src_type, unsigned src_pos, unsigned n) |
||
2839 | { |
||
2840 | struct isl_dim_map *dim_map; |
||
2841 | struct isl_basic_map *res; |
||
2842 | enum isl_dim_type t; |
||
2843 | unsigned total, off; |
||
2844 | |||
2845 | if (!bmap) |
||
2846 | return NULL; |
||
2847 | if (n == 0) |
||
2848 | return bmap; |
||
2849 | |||
2850 | isl_assert(bmap->ctx, src_pos + n <= isl_basic_map_dim(bmap, src_type), |
||
2851 | goto error); |
||
2852 | |||
2853 | if (dst_type == src_type && dst_pos == src_pos) |
||
2854 | return bmap; |
||
2855 | |||
2856 | isl_assert(bmap->ctx, dst_type != src_type, goto error); |
||
2857 | |||
2858 | if (pos(bmap->dim, dst_type) + dst_pos == |
||
2859 | pos(bmap->dim, src_type) + src_pos + |
||
2860 | ((src_type < dst_type) ? n : 0)) { |
||
2861 | bmap = isl_basic_map_cow(bmap); |
||
2862 | if (!bmap) |
||
2863 | return NULL; |
||
2864 | |||
2865 | bmap->dim = isl_space_move_dims(bmap->dim, dst_type, dst_pos, |
||
2866 | src_type, src_pos, n); |
||
2867 | if (!bmap->dim) |
||
2868 | goto error; |
||
2869 | |||
2870 | bmap = isl_basic_map_finalize(bmap); |
||
2871 | |||
2872 | return bmap; |
||
2873 | } |
||
2874 | |||
2875 | total = isl_basic_map_total_dim(bmap); |
||
2876 | dim_map = isl_dim_map_alloc(bmap->ctx, total); |
||
2877 | |||
2878 | off = 0; |
||
2879 | for (t = isl_dim_param; t <= isl_dim_out; ++t) { |
||
2880 | unsigned size = isl_space_dim(bmap->dim, t); |
||
2881 | if (t == dst_type) { |
||
2882 | isl_dim_map_dim_range(dim_map, bmap->dim, t, |
||
2883 | 0, dst_pos, off); |
||
2884 | off += dst_pos; |
||
2885 | isl_dim_map_dim_range(dim_map, bmap->dim, src_type, |
||
2886 | src_pos, n, off); |
||
2887 | off += n; |
||
2888 | isl_dim_map_dim_range(dim_map, bmap->dim, t, |
||
2889 | dst_pos, size - dst_pos, off); |
||
2890 | off += size - dst_pos; |
||
2891 | } else if (t == src_type) { |
||
2892 | isl_dim_map_dim_range(dim_map, bmap->dim, t, |
||
2893 | 0, src_pos, off); |
||
2894 | off += src_pos; |
||
2895 | isl_dim_map_dim_range(dim_map, bmap->dim, t, |
||
2896 | src_pos + n, size - src_pos - n, off); |
||
2897 | off += size - src_pos - n; |
||
2898 | } else { |
||
2899 | isl_dim_map_dim(dim_map, bmap->dim, t, off); |
||
2900 | off += size; |
||
2901 | } |
||
2902 | } |
||
2903 | isl_dim_map_div(dim_map, bmap, off); |
||
2904 | |||
2905 | res = isl_basic_map_alloc_space(isl_basic_map_get_space(bmap), |
||
2906 | bmap->n_div, bmap->n_eq, bmap->n_ineq); |
||
2907 | bmap = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map); |
||
2908 | |||
2909 | bmap->dim = isl_space_move_dims(bmap->dim, dst_type, dst_pos, |
||
2910 | src_type, src_pos, n); |
||
2911 | if (!bmap->dim) |
||
2912 | goto error; |
||
2913 | |||
2914 | ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED); |
||
2915 | bmap = isl_basic_map_gauss(bmap, NULL); |
||
2916 | bmap = isl_basic_map_finalize(bmap); |
||
2917 | |||
2918 | return bmap; |
||
2919 | error: |
||
2920 | isl_basic_map_free(bmap); |
||
2921 | return NULL; |
||
2922 | } |
||
2923 | |||
2924 | __isl_give isl_basic_set *isl_basic_set_move_dims(__isl_take isl_basic_set *bset, |
||
2925 | enum isl_dim_type dst_type, unsigned dst_pos, |
||
2926 | enum isl_dim_type src_type, unsigned src_pos, unsigned n) |
||
2927 | { |
||
2928 | return (isl_basic_set *)isl_basic_map_move_dims( |
||
2929 | (isl_basic_map *)bset, dst_type, dst_pos, src_type, src_pos, n); |
||
2930 | } |
||
2931 | |||
2932 | __isl_give isl_set *isl_set_move_dims(__isl_take isl_set *set, |
||
2933 | enum isl_dim_type dst_type, unsigned dst_pos, |
||
2934 | enum isl_dim_type src_type, unsigned src_pos, unsigned n) |
||
2935 | { |
||
2936 | if (!set) |
||
2937 | return NULL; |
||
2938 | isl_assert(set->ctx, dst_type != isl_dim_in, goto error); |
||
2939 | return (isl_set *)isl_map_move_dims((isl_map *)set, dst_type, dst_pos, |
||
2940 | src_type, src_pos, n); |
||
2941 | error: |
||
2942 | isl_set_free(set); |
||
2943 | return NULL; |
||
2944 | } |
||
2945 | |||
2946 | __isl_give isl_map *isl_map_move_dims(__isl_take isl_map *map, |
||
2947 | enum isl_dim_type dst_type, unsigned dst_pos, |
||
2948 | enum isl_dim_type src_type, unsigned src_pos, unsigned n) |
||
2949 | { |
||
2950 | int i; |
||
2951 | |||
2952 | if (!map) |
||
2953 | return NULL; |
||
2954 | if (n == 0) |
||
2955 | return map; |
||
2956 | |||
2957 | isl_assert(map->ctx, src_pos + n <= isl_map_dim(map, src_type), |
||
2958 | goto error); |
||
2959 | |||
2960 | if (dst_type == src_type && dst_pos == src_pos) |
||
2961 | return map; |
||
2962 | |||
2963 | isl_assert(map->ctx, dst_type != src_type, goto error); |
||
2964 | |||
2965 | map = isl_map_cow(map); |
||
2966 | if (!map) |
||
2967 | return NULL; |
||
2968 | |||
2969 | map->dim = isl_space_move_dims(map->dim, dst_type, dst_pos, src_type, src_pos, n); |
||
2970 | if (!map->dim) |
||
2971 | goto error; |
||
2972 | |||
2973 | for (i = 0; i < map->n; ++i) { |
||
2974 | map->p[i] = isl_basic_map_move_dims(map->p[i], |
||
2975 | dst_type, dst_pos, |
||
2976 | src_type, src_pos, n); |
||
2977 | if (!map->p[i]) |
||
2978 | goto error; |
||
2979 | } |
||
2980 | |||
2981 | return map; |
||
2982 | error: |
||
2983 | isl_map_free(map); |
||
2984 | return NULL; |
||
2985 | } |
||
2986 | |||
2987 | /* Move the specified dimensions to the last columns right before |
||
2988 | * the divs. Don't change the dimension specification of bmap. |
||
2989 | * That's the responsibility of the caller. |
||
2990 | */ |
||
2991 | static __isl_give isl_basic_map *move_last(__isl_take isl_basic_map *bmap, |
||
2992 | enum isl_dim_type type, unsigned first, unsigned n) |
||
2993 | { |
||
2994 | struct isl_dim_map *dim_map; |
||
2995 | struct isl_basic_map *res; |
||
2996 | enum isl_dim_type t; |
||
2997 | unsigned total, off; |
||
2998 | |||
2999 | if (!bmap) |
||
3000 | return NULL; |
||
3001 | if (pos(bmap->dim, type) + first + n == |
||
3002 | 1 + isl_space_dim(bmap->dim, isl_dim_all)) |
||
3003 | return bmap; |
||
3004 | |||
3005 | total = isl_basic_map_total_dim(bmap); |
||
3006 | dim_map = isl_dim_map_alloc(bmap->ctx, total); |
||
3007 | |||
3008 | off = 0; |
||
3009 | for (t = isl_dim_param; t <= isl_dim_out; ++t) { |
||
3010 | unsigned size = isl_space_dim(bmap->dim, t); |
||
3011 | if (t == type) { |
||
3012 | isl_dim_map_dim_range(dim_map, bmap->dim, t, |
||
3013 | 0, first, off); |
||
3014 | off += first; |
||
3015 | isl_dim_map_dim_range(dim_map, bmap->dim, t, |
||
3016 | first, n, total - bmap->n_div - n); |
||
3017 | isl_dim_map_dim_range(dim_map, bmap->dim, t, |
||
3018 | first + n, size - (first + n), off); |
||
3019 | off += size - (first + n); |
||
3020 | } else { |
||
3021 | isl_dim_map_dim(dim_map, bmap->dim, t, off); |
||
3022 | off += size; |
||
3023 | } |
||
3024 | } |
||
3025 | isl_dim_map_div(dim_map, bmap, off + n); |
||
3026 | |||
3027 | res = isl_basic_map_alloc_space(isl_basic_map_get_space(bmap), |
||
3028 | bmap->n_div, bmap->n_eq, bmap->n_ineq); |
||
3029 | res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map); |
||
3030 | return res; |
||
3031 | } |
||
3032 | |||
3033 | /* Turn the n dimensions of type type, starting at first |
||
3034 | * into existentially quantified variables. |
||
3035 | */ |
||
3036 | __isl_give isl_basic_map *isl_basic_map_project_out( |
||
3037 | __isl_take isl_basic_map *bmap, |
||
3038 | enum isl_dim_type type, unsigned first, unsigned n) |
||
3039 | { |
||
3040 | int i; |
||
3041 | size_t row_size; |
||
3042 | isl_int **new_div; |
||
3043 | isl_int *old; |
||
3044 | |||
3045 | if (n == 0) |
||
3046 | return basic_map_space_reset(bmap, type); |
||
3047 | |||
3048 | if (!bmap) |
||
3049 | return NULL; |
||
3050 | |||
3051 | if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL)) |
||
3052 | return isl_basic_map_remove_dims(bmap, type, first, n); |
||
3053 | |||
3054 | isl_assert(bmap->ctx, first + n <= isl_basic_map_dim(bmap, type), |
||
3055 | goto error); |
||
3056 | |||
3057 | bmap = move_last(bmap, type, first, n); |
||
3058 | bmap = isl_basic_map_cow(bmap); |
||
3059 | if (!bmap) |
||
3060 | return NULL; |
||
3061 | |||
3062 | row_size = 1 + isl_space_dim(bmap->dim, isl_dim_all) + bmap->extra; |
||
3063 | old = bmap->block2.data; |
||
3064 | bmap->block2 = isl_blk_extend(bmap->ctx, bmap->block2, |
||
3065 | (bmap->extra + n) * (1 + row_size)); |
||
3066 | if (!bmap->block2.data) |
||
3067 | goto error; |
||
3068 | new_div = isl_alloc_array(bmap->ctx, isl_int *, bmap->extra + n); |
||
3069 | if (!new_div) |
||
3070 | goto error; |
||
3071 | for (i = 0; i < n; ++i) { |
||
3072 | new_div[i] = bmap->block2.data + |
||
3073 | (bmap->extra + i) * (1 + row_size); |
||
3074 | isl_seq_clr(new_div[i], 1 + row_size); |
||
3075 | } |
||
3076 | for (i = 0; i < bmap->extra; ++i) |
||
3077 | new_div[n + i] = bmap->block2.data + (bmap->div[i] - old); |
||
3078 | free(bmap->div); |
||
3079 | bmap->div = new_div; |
||
3080 | bmap->n_div += n; |
||
3081 | bmap->extra += n; |
||
3082 | |||
3083 | bmap->dim = isl_space_drop_dims(bmap->dim, type, first, n); |
||
3084 | if (!bmap->dim) |
||
3085 | goto error; |
||
3086 | bmap = isl_basic_map_simplify(bmap); |
||
3087 | bmap = isl_basic_map_drop_redundant_divs(bmap); |
||
3088 | return isl_basic_map_finalize(bmap); |
||
3089 | error: |
||
3090 | isl_basic_map_free(bmap); |
||
3091 | return NULL; |
||
3092 | } |
||
3093 | |||
3094 | /* Turn the n dimensions of type type, starting at first |
||
3095 | * into existentially quantified variables. |
||
3096 | */ |
||
3097 | struct isl_basic_set *isl_basic_set_project_out(struct isl_basic_set *bset, |
||
3098 | enum isl_dim_type type, unsigned first, unsigned n) |
||
3099 | { |
||
3100 | return (isl_basic_set *)isl_basic_map_project_out( |
||
3101 | (isl_basic_map *)bset, type, first, n); |
||
3102 | } |
||
3103 | |||
3104 | /* Turn the n dimensions of type type, starting at first |
||
3105 | * into existentially quantified variables. |
||
3106 | */ |
||
3107 | __isl_give isl_map *isl_map_project_out(__isl_take isl_map *map, |
||
3108 | enum isl_dim_type type, unsigned first, unsigned n) |
||
3109 | { |
||
3110 | int i; |
||
3111 | |||
3112 | if (!map) |
||
3113 | return NULL; |
||
3114 | |||
3115 | if (n == 0) |
||
3116 | return map_space_reset(map, type); |
||
3117 | |||
3118 | isl_assert(map->ctx, first + n <= isl_map_dim(map, type), goto error); |
||
3119 | |||
3120 | map = isl_map_cow(map); |
||
3121 | if (!map) |
||
3122 | return NULL; |
||
3123 | |||
3124 | map->dim = isl_space_drop_dims(map->dim, type, first, n); |
||
3125 | if (!map->dim) |
||
3126 | goto error; |
||
3127 | |||
3128 | for (i = 0; i < map->n; ++i) { |
||
3129 | map->p[i] = isl_basic_map_project_out(map->p[i], type, first, n); |
||
3130 | if (!map->p[i]) |
||
3131 | goto error; |
||
3132 | } |
||
3133 | |||
3134 | return map; |
||
3135 | error: |
||
3136 | isl_map_free(map); |
||
3137 | return NULL; |
||
3138 | } |
||
3139 | |||
3140 | /* Turn the n dimensions of type type, starting at first |
||
3141 | * into existentially quantified variables. |
||
3142 | */ |
||
3143 | __isl_give isl_set *isl_set_project_out(__isl_take isl_set *set, |
||
3144 | enum isl_dim_type type, unsigned first, unsigned n) |
||
3145 | { |
||
3146 | return (isl_set *)isl_map_project_out((isl_map *)set, type, first, n); |
||
3147 | } |
||
3148 | |||
3149 | static struct isl_basic_map *add_divs(struct isl_basic_map *bmap, unsigned n) |
||
3150 | { |
||
3151 | int i, j; |
||
3152 | |||
3153 | for (i = 0; i < n; ++i) { |
||
3154 | j = isl_basic_map_alloc_div(bmap); |
||
3155 | if (j < 0) |
||
3156 | goto error; |
||
3157 | isl_seq_clr(bmap->div[j], 1+1+isl_basic_map_total_dim(bmap)); |
||
3158 | } |
||
3159 | return bmap; |
||
3160 | error: |
||
3161 | isl_basic_map_free(bmap); |
||
3162 | return NULL; |
||
3163 | } |
||
3164 | |||
3165 | struct isl_basic_map *isl_basic_map_apply_range( |
||
3166 | struct isl_basic_map *bmap1, struct isl_basic_map *bmap2) |
||
3167 | { |
||
3168 | isl_space *dim_result = NULL; |
||
3169 | struct isl_basic_map *bmap; |
||
3170 | unsigned n_in, n_out, n, nparam, total, pos; |
||
3171 | struct isl_dim_map *dim_map1, *dim_map2; |
||
3172 | |||
3173 | if (!bmap1 || !bmap2) |
||
3174 | goto error; |
||
3175 | |||
3176 | dim_result = isl_space_join(isl_space_copy(bmap1->dim), |
||
3177 | isl_space_copy(bmap2->dim)); |
||
3178 | |||
3179 | n_in = isl_basic_map_n_in(bmap1); |
||
3180 | n_out = isl_basic_map_n_out(bmap2); |
||
3181 | n = isl_basic_map_n_out(bmap1); |
||
3182 | nparam = isl_basic_map_n_param(bmap1); |
||
3183 | |||
3184 | total = nparam + n_in + n_out + bmap1->n_div + bmap2->n_div + n; |
||
3185 | dim_map1 = isl_dim_map_alloc(bmap1->ctx, total); |
||
3186 | dim_map2 = isl_dim_map_alloc(bmap1->ctx, total); |
||
3187 | isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0); |
||
3188 | isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0); |
||
3189 | isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam); |
||
3190 | isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += n_in); |
||
3191 | isl_dim_map_div(dim_map1, bmap1, pos += n_out); |
||
3192 | isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div); |
||
3193 | isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += bmap2->n_div); |
||
3194 | isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos); |
||
3195 | |||
3196 | bmap = isl_basic_map_alloc_space(dim_result, |
||
3197 | bmap1->n_div + bmap2->n_div + n, |
||
3198 | bmap1->n_eq + bmap2->n_eq, |
||
3199 | bmap1->n_ineq + bmap2->n_ineq); |
||
3200 | bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1); |
||
3201 | bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2); |
||
3202 | bmap = add_divs(bmap, n); |
||
3203 | bmap = isl_basic_map_simplify(bmap); |
||
3204 | bmap = isl_basic_map_drop_redundant_divs(bmap); |
||
3205 | return isl_basic_map_finalize(bmap); |
||
3206 | error: |
||
3207 | isl_basic_map_free(bmap1); |
||
3208 | isl_basic_map_free(bmap2); |
||
3209 | return NULL; |
||
3210 | } |
||
3211 | |||
3212 | struct isl_basic_set *isl_basic_set_apply( |
||
3213 | struct isl_basic_set *bset, struct isl_basic_map *bmap) |
||
3214 | { |
||
3215 | if (!bset || !bmap) |
||
3216 | goto error; |
||
3217 | |||
3218 | isl_assert(bset->ctx, isl_basic_map_compatible_domain(bmap, bset), |
||
3219 | goto error); |
||
3220 | |||
3221 | return (struct isl_basic_set *) |
||
3222 | isl_basic_map_apply_range((struct isl_basic_map *)bset, bmap); |
||
3223 | error: |
||
3224 | isl_basic_set_free(bset); |
||
3225 | isl_basic_map_free(bmap); |
||
3226 | return NULL; |
||
3227 | } |
||
3228 | |||
3229 | struct isl_basic_map *isl_basic_map_apply_domain( |
||
3230 | struct isl_basic_map *bmap1, struct isl_basic_map *bmap2) |
||
3231 | { |
||
3232 | if (!bmap1 || !bmap2) |
||
3233 | goto error; |
||
3234 | |||
3235 | isl_assert(bmap1->ctx, |
||
3236 | isl_basic_map_n_in(bmap1) == isl_basic_map_n_in(bmap2), goto error); |
||
3237 | isl_assert(bmap1->ctx, |
||
3238 | isl_basic_map_n_param(bmap1) == isl_basic_map_n_param(bmap2), |
||
3239 | goto error); |
||
3240 | |||
3241 | bmap1 = isl_basic_map_reverse(bmap1); |
||
3242 | bmap1 = isl_basic_map_apply_range(bmap1, bmap2); |
||
3243 | return isl_basic_map_reverse(bmap1); |
||
3244 | error: |
||
3245 | isl_basic_map_free(bmap1); |
||
3246 | isl_basic_map_free(bmap2); |
||
3247 | return NULL; |
||
3248 | } |
||
3249 | |||
3250 | /* Given two basic maps A -> f(A) and B -> g(B), construct a basic map |
||
3251 | * A \cap B -> f(A) + f(B) |
||
3252 | */ |
||
3253 | struct isl_basic_map *isl_basic_map_sum( |
||
3254 | struct isl_basic_map *bmap1, struct isl_basic_map *bmap2) |
||
3255 | { |
||
3256 | unsigned n_in, n_out, nparam, total, pos; |
||
3257 | struct isl_basic_map *bmap = NULL; |
||
3258 | struct isl_dim_map *dim_map1, *dim_map2; |
||
3259 | int i; |
||
3260 | |||
3261 | if (!bmap1 || !bmap2) |
||
3262 | goto error; |
||
3263 | |||
3264 | isl_assert(bmap1->ctx, isl_space_is_equal(bmap1->dim, bmap2->dim), |
||
3265 | goto error); |
||
3266 | |||
3267 | nparam = isl_basic_map_n_param(bmap1); |
||
3268 | n_in = isl_basic_map_n_in(bmap1); |
||
3269 | n_out = isl_basic_map_n_out(bmap1); |
||
3270 | |||
3271 | total = nparam + n_in + n_out + bmap1->n_div + bmap2->n_div + 2 * n_out; |
||
3272 | dim_map1 = isl_dim_map_alloc(bmap1->ctx, total); |
||
3273 | dim_map2 = isl_dim_map_alloc(bmap2->ctx, total); |
||
3274 | isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0); |
||
3275 | isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos); |
||
3276 | isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam); |
||
3277 | isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos); |
||
3278 | isl_dim_map_div(dim_map1, bmap1, pos += n_in + n_out); |
||
3279 | isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div); |
||
3280 | isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += bmap2->n_div); |
||
3281 | isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += n_out); |
||
3282 | |||
3283 | bmap = isl_basic_map_alloc_space(isl_space_copy(bmap1->dim), |
||
3284 | bmap1->n_div + bmap2->n_div + 2 * n_out, |
||
3285 | bmap1->n_eq + bmap2->n_eq + n_out, |
||
3286 | bmap1->n_ineq + bmap2->n_ineq); |
||
3287 | for (i = 0; i < n_out; ++i) { |
||
3288 | int j = isl_basic_map_alloc_equality(bmap); |
||
3289 | if (j < 0) |
||
3290 | goto error; |
||
3291 | isl_seq_clr(bmap->eq[j], 1+total); |
||
3292 | isl_int_set_si(bmap->eq[j][1+nparam+n_in+i], -1); |
||
3293 | isl_int_set_si(bmap->eq[j][1+pos+i], 1); |
||
3294 | isl_int_set_si(bmap->eq[j][1+pos-n_out+i], 1); |
||
3295 | } |
||
3296 | bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1); |
||
3297 | bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2); |
||
3298 | bmap = add_divs(bmap, 2 * n_out); |
||
3299 | |||
3300 | bmap = isl_basic_map_simplify(bmap); |
||
3301 | return isl_basic_map_finalize(bmap); |
||
3302 | error: |
||
3303 | isl_basic_map_free(bmap); |
||
3304 | isl_basic_map_free(bmap1); |
||
3305 | isl_basic_map_free(bmap2); |
||
3306 | return NULL; |
||
3307 | } |
||
3308 | |||
3309 | /* Given two maps A -> f(A) and B -> g(B), construct a map |
||
3310 | * A \cap B -> f(A) + f(B) |
||
3311 | */ |
||
3312 | struct isl_map *isl_map_sum(struct isl_map *map1, struct isl_map *map2) |
||
3313 | { |
||
3314 | struct isl_map *result; |
||
3315 | int i, j; |
||
3316 | |||
3317 | if (!map1 || !map2) |
||
3318 | goto error; |
||
3319 | |||
3320 | isl_assert(map1->ctx, isl_space_is_equal(map1->dim, map2->dim), goto error); |
||
3321 | |||
3322 | result = isl_map_alloc_space(isl_space_copy(map1->dim), |
||
3323 | map1->n * map2->n, 0); |
||
3324 | if (!result) |
||
3325 | goto error; |
||
3326 | for (i = 0; i < map1->n; ++i) |
||
3327 | for (j = 0; j < map2->n; ++j) { |
||
3328 | struct isl_basic_map *part; |
||
3329 | part = isl_basic_map_sum( |
||
3330 | isl_basic_map_copy(map1->p[i]), |
||
3331 | isl_basic_map_copy(map2->p[j])); |
||
3332 | if (isl_basic_map_is_empty(part)) |
||
3333 | isl_basic_map_free(part); |
||
3334 | else |
||
3335 | result = isl_map_add_basic_map(result, part); |
||
3336 | if (!result) |
||
3337 | goto error; |
||
3338 | } |
||
3339 | isl_map_free(map1); |
||
3340 | isl_map_free(map2); |
||
3341 | return result; |
||
3342 | error: |
||
3343 | isl_map_free(map1); |
||
3344 | isl_map_free(map2); |
||
3345 | return NULL; |
||
3346 | } |
||
3347 | |||
3348 | __isl_give isl_set *isl_set_sum(__isl_take isl_set *set1, |
||
3349 | __isl_take isl_set *set2) |
||
3350 | { |
||
3351 | return (isl_set *)isl_map_sum((isl_map *)set1, (isl_map *)set2); |
||
3352 | } |
||
3353 | |||
3354 | /* Given a basic map A -> f(A), construct A -> -f(A). |
||
3355 | */ |
||
3356 | struct isl_basic_map *isl_basic_map_neg(struct isl_basic_map *bmap) |
||
3357 | { |
||
3358 | int i, j; |
||
3359 | unsigned off, n; |
||
3360 | |||
3361 | bmap = isl_basic_map_cow(bmap); |
||
3362 | if (!bmap) |
||
3363 | return NULL; |
||
3364 | |||
3365 | n = isl_basic_map_dim(bmap, isl_dim_out); |
||
3366 | off = isl_basic_map_offset(bmap, isl_dim_out); |
||
3367 | for (i = 0; i < bmap->n_eq; ++i) |
||
3368 | for (j = 0; j < n; ++j) |
||
3369 | isl_int_neg(bmap->eq[i][off+j], bmap->eq[i][off+j]); |
||
3370 | for (i = 0; i < bmap->n_ineq; ++i) |
||
3371 | for (j = 0; j < n; ++j) |
||
3372 | isl_int_neg(bmap->ineq[i][off+j], bmap->ineq[i][off+j]); |
||
3373 | for (i = 0; i < bmap->n_div; ++i) |
||
3374 | for (j = 0; j < n; ++j) |
||
3375 | isl_int_neg(bmap->div[i][1+off+j], bmap->div[i][1+off+j]); |
||
3376 | bmap = isl_basic_map_gauss(bmap, NULL); |
||
3377 | return isl_basic_map_finalize(bmap); |
||
3378 | } |
||
3379 | |||
3380 | __isl_give isl_basic_set *isl_basic_set_neg(__isl_take isl_basic_set *bset) |
||
3381 | { |
||
3382 | return isl_basic_map_neg(bset); |
||
3383 | } |
||
3384 | |||
3385 | /* Given a map A -> f(A), construct A -> -f(A). |
||
3386 | */ |
||
3387 | struct isl_map *isl_map_neg(struct isl_map *map) |
||
3388 | { |
||
3389 | int i; |
||
3390 | |||
3391 | map = isl_map_cow(map); |
||
3392 | if (!map) |
||
3393 | return NULL; |
||
3394 | |||
3395 | for (i = 0; i < map->n; ++i) { |
||
3396 | map->p[i] = isl_basic_map_neg(map->p[i]); |
||
3397 | if (!map->p[i]) |
||
3398 | goto error; |
||
3399 | } |
||
3400 | |||
3401 | return map; |
||
3402 | error: |
||
3403 | isl_map_free(map); |
||
3404 | return NULL; |
||
3405 | } |
||
3406 | |||
3407 | __isl_give isl_set *isl_set_neg(__isl_take isl_set *set) |
||
3408 | { |
||
3409 | return (isl_set *)isl_map_neg((isl_map *)set); |
||
3410 | } |
||
3411 | |||
3412 | /* Given a basic map A -> f(A) and an integer d, construct a basic map |
||
3413 | * A -> floor(f(A)/d). |
||
3414 | */ |
||
3415 | struct isl_basic_map *isl_basic_map_floordiv(struct isl_basic_map *bmap, |
||
3416 | isl_int d) |
||
3417 | { |
||
3418 | unsigned n_in, n_out, nparam, total, pos; |
||
3419 | struct isl_basic_map *result = NULL; |
||
3420 | struct isl_dim_map *dim_map; |
||
3421 | int i; |
||
3422 | |||
3423 | if (!bmap) |
||
3424 | return NULL; |
||
3425 | |||
3426 | nparam = isl_basic_map_n_param(bmap); |
||
3427 | n_in = isl_basic_map_n_in(bmap); |
||
3428 | n_out = isl_basic_map_n_out(bmap); |
||
3429 | |||
3430 | total = nparam + n_in + n_out + bmap->n_div + n_out; |
||
3431 | dim_map = isl_dim_map_alloc(bmap->ctx, total); |
||
3432 | isl_dim_map_dim(dim_map, bmap->dim, isl_dim_param, pos = 0); |
||
3433 | isl_dim_map_dim(dim_map, bmap->dim, isl_dim_in, pos += nparam); |
||
3434 | isl_dim_map_div(dim_map, bmap, pos += n_in + n_out); |
||
3435 | isl_dim_map_dim(dim_map, bmap->dim, isl_dim_out, pos += bmap->n_div); |
||
3436 | |||
3437 | result = isl_basic_map_alloc_space(isl_space_copy(bmap->dim), |
||
3438 | bmap->n_div + n_out, |
||
3439 | bmap->n_eq, bmap->n_ineq + 2 * n_out); |
||
3440 | result = isl_basic_map_add_constraints_dim_map(result, bmap, dim_map); |
||
3441 | result = add_divs(result, n_out); |
||
3442 | for (i = 0; i < n_out; ++i) { |
||
3443 | int j; |
||
3444 | j = isl_basic_map_alloc_inequality(result); |
||
3445 | if (j < 0) |
||
3446 | goto error; |
||
3447 | isl_seq_clr(result->ineq[j], 1+total); |
||
3448 | isl_int_neg(result->ineq[j][1+nparam+n_in+i], d); |
||
3449 | isl_int_set_si(result->ineq[j][1+pos+i], 1); |
||
3450 | j = isl_basic_map_alloc_inequality(result); |
||
3451 | if (j < 0) |
||
3452 | goto error; |
||
3453 | isl_seq_clr(result->ineq[j], 1+total); |
||
3454 | isl_int_set(result->ineq[j][1+nparam+n_in+i], d); |
||
3455 | isl_int_set_si(result->ineq[j][1+pos+i], -1); |
||
3456 | isl_int_sub_ui(result->ineq[j][0], d, 1); |
||
3457 | } |
||
3458 | |||
3459 | result = isl_basic_map_simplify(result); |
||
3460 | return isl_basic_map_finalize(result); |
||
3461 | error: |
||
3462 | isl_basic_map_free(result); |
||
3463 | return NULL; |
||
3464 | } |
||
3465 | |||
3466 | /* Given a map A -> f(A) and an integer d, construct a map |
||
3467 | * A -> floor(f(A)/d). |
||
3468 | */ |
||
3469 | struct isl_map *isl_map_floordiv(struct isl_map *map, isl_int d) |
||
3470 | { |
||
3471 | int i; |
||
3472 | |||
3473 | map = isl_map_cow(map); |
||
3474 | if (!map) |
||
3475 | return NULL; |
||
3476 | |||
3477 | ISL_F_CLR(map, ISL_MAP_DISJOINT); |
||
3478 | ISL_F_CLR(map, ISL_MAP_NORMALIZED); |
||
3479 | for (i = 0; i < map->n; ++i) { |
||
3480 | map->p[i] = isl_basic_map_floordiv(map->p[i], d); |
||
3481 | if (!map->p[i]) |
||
3482 | goto error; |
||
3483 | } |
||
3484 | |||
3485 | return map; |
||
3486 | error: |
||
3487 | isl_map_free(map); |
||
3488 | return NULL; |
||
3489 | } |
||
3490 | |||
3491 | static struct isl_basic_map *var_equal(struct isl_basic_map *bmap, unsigned pos) |
||
3492 | { |
||
3493 | int i; |
||
3494 | unsigned nparam; |
||
3495 | unsigned n_in; |
||
3496 | |||
3497 | i = isl_basic_map_alloc_equality(bmap); |
||
3498 | if (i < 0) |
||
3499 | goto error; |
||
3500 | nparam = isl_basic_map_n_param(bmap); |
||
3501 | n_in = isl_basic_map_n_in(bmap); |
||
3502 | isl_seq_clr(bmap->eq[i], 1 + isl_basic_map_total_dim(bmap)); |
||
3503 | isl_int_set_si(bmap->eq[i][1+nparam+pos], -1); |
||
3504 | isl_int_set_si(bmap->eq[i][1+nparam+n_in+pos], 1); |
||
3505 | return isl_basic_map_finalize(bmap); |
||
3506 | error: |
||
3507 | isl_basic_map_free(bmap); |
||
3508 | return NULL; |
||
3509 | } |
||
3510 | |||
3511 | /* Add a constraints to "bmap" expressing i_pos < o_pos |
||
3512 | */ |
||
3513 | static struct isl_basic_map *var_less(struct isl_basic_map *bmap, unsigned pos) |
||
3514 | { |
||
3515 | int i; |
||
3516 | unsigned nparam; |
||
3517 | unsigned n_in; |
||
3518 | |||
3519 | i = isl_basic_map_alloc_inequality(bmap); |
||
3520 | if (i < 0) |
||
3521 | goto error; |
||
3522 | nparam = isl_basic_map_n_param(bmap); |
||
3523 | n_in = isl_basic_map_n_in(bmap); |
||
3524 | isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap)); |
||
3525 | isl_int_set_si(bmap->ineq[i][0], -1); |
||
3526 | isl_int_set_si(bmap->ineq[i][1+nparam+pos], -1); |
||
3527 | isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], 1); |
||
3528 | return isl_basic_map_finalize(bmap); |
||
3529 | error: |
||
3530 | isl_basic_map_free(bmap); |
||
3531 | return NULL; |
||
3532 | } |
||
3533 | |||
3534 | /* Add a constraint to "bmap" expressing i_pos <= o_pos |
||
3535 | */ |
||
3536 | static __isl_give isl_basic_map *var_less_or_equal( |
||
3537 | __isl_take isl_basic_map *bmap, unsigned pos) |
||
3538 | { |
||
3539 | int i; |
||
3540 | unsigned nparam; |
||
3541 | unsigned n_in; |
||
3542 | |||
3543 | i = isl_basic_map_alloc_inequality(bmap); |
||
3544 | if (i < 0) |
||
3545 | goto error; |
||
3546 | nparam = isl_basic_map_n_param(bmap); |
||
3547 | n_in = isl_basic_map_n_in(bmap); |
||
3548 | isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap)); |
||
3549 | isl_int_set_si(bmap->ineq[i][1+nparam+pos], -1); |
||
3550 | isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], 1); |
||
3551 | return isl_basic_map_finalize(bmap); |
||
3552 | error: |
||
3553 | isl_basic_map_free(bmap); |
||
3554 | return NULL; |
||
3555 | } |
||
3556 | |||
3557 | /* Add a constraints to "bmap" expressing i_pos > o_pos |
||
3558 | */ |
||
3559 | static struct isl_basic_map *var_more(struct isl_basic_map *bmap, unsigned pos) |
||
3560 | { |
||
3561 | int i; |
||
3562 | unsigned nparam; |
||
3563 | unsigned n_in; |
||
3564 | |||
3565 | i = isl_basic_map_alloc_inequality(bmap); |
||
3566 | if (i < 0) |
||
3567 | goto error; |
||
3568 | nparam = isl_basic_map_n_param(bmap); |
||
3569 | n_in = isl_basic_map_n_in(bmap); |
||
3570 | isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap)); |
||
3571 | isl_int_set_si(bmap->ineq[i][0], -1); |
||
3572 | isl_int_set_si(bmap->ineq[i][1+nparam+pos], 1); |
||
3573 | isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], -1); |
||
3574 | return isl_basic_map_finalize(bmap); |
||
3575 | error: |
||
3576 | isl_basic_map_free(bmap); |
||
3577 | return NULL; |
||
3578 | } |
||
3579 | |||
3580 | /* Add a constraint to "bmap" expressing i_pos >= o_pos |
||
3581 | */ |
||
3582 | static __isl_give isl_basic_map *var_more_or_equal( |
||
3583 | __isl_take isl_basic_map *bmap, unsigned pos) |
||
3584 | { |
||
3585 | int i; |
||
3586 | unsigned nparam; |
||
3587 | unsigned n_in; |
||
3588 | |||
3589 | i = isl_basic_map_alloc_inequality(bmap); |
||
3590 | if (i < 0) |
||
3591 | goto error; |
||
3592 | nparam = isl_basic_map_n_param(bmap); |
||
3593 | n_in = isl_basic_map_n_in(bmap); |
||
3594 | isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap)); |
||
3595 | isl_int_set_si(bmap->ineq[i][1+nparam+pos], 1); |
||
3596 | isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], -1); |
||
3597 | return isl_basic_map_finalize(bmap); |
||
3598 | error: |
||
3599 | isl_basic_map_free(bmap); |
||
3600 | return NULL; |
||
3601 | } |
||
3602 | |||
3603 | __isl_give isl_basic_map *isl_basic_map_equal( |
||
3604 | __isl_take isl_space *dim, unsigned n_equal) |
||
3605 | { |
||
3606 | int i; |
||
3607 | struct isl_basic_map *bmap; |
||
3608 | bmap = isl_basic_map_alloc_space(dim, 0, n_equal, 0); |
||
3609 | if (!bmap) |
||
3610 | return NULL; |
||
3611 | for (i = 0; i < n_equal && bmap; ++i) |
||
3612 | bmap = var_equal(bmap, i); |
||
3613 | return isl_basic_map_finalize(bmap); |
||
3614 | } |
||
3615 | |||
3616 | /* Return a relation on of dimension "dim" expressing i_[0..pos] << o_[0..pos] |
||
3617 | */ |
||
3618 | __isl_give isl_basic_map *isl_basic_map_less_at(__isl_take isl_space *dim, |
||
3619 | unsigned pos) |
||
3620 | { |
||
3621 | int i; |
||
3622 | struct isl_basic_map *bmap; |
||
3623 | bmap = isl_basic_map_alloc_space(dim, 0, pos, 1); |
||
3624 | if (!bmap) |
||
3625 | return NULL; |
||
3626 | for (i = 0; i < pos && bmap; ++i) |
||
3627 | bmap = var_equal(bmap, i); |
||
3628 | if (bmap) |
||
3629 | bmap = var_less(bmap, pos); |
||
3630 | return isl_basic_map_finalize(bmap); |
||
3631 | } |
||
3632 | |||
3633 | /* Return a relation on of dimension "dim" expressing i_[0..pos] <<= o_[0..pos] |
||
3634 | */ |
||
3635 | __isl_give isl_basic_map *isl_basic_map_less_or_equal_at( |
||
3636 | __isl_take isl_space *dim, unsigned pos) |
||
3637 | { |
||
3638 | int i; |
||
3639 | isl_basic_map *bmap; |
||
3640 | |||
3641 | bmap = isl_basic_map_alloc_space(dim, 0, pos, 1); |
||
3642 | for (i = 0; i < pos; ++i) |
||
3643 | bmap = var_equal(bmap, i); |
||
3644 | bmap = var_less_or_equal(bmap, pos); |
||
3645 | return isl_basic_map_finalize(bmap); |
||
3646 | } |
||
3647 | |||
3648 | /* Return a relation on pairs of sets of dimension "dim" expressing i_pos > o_pos |
||
3649 | */ |
||
3650 | __isl_give isl_basic_map *isl_basic_map_more_at(__isl_take isl_space *dim, |
||
3651 | unsigned pos) |
||
3652 | { |
||
3653 | int i; |
||
3654 | struct isl_basic_map *bmap; |
||
3655 | bmap = isl_basic_map_alloc_space(dim, 0, pos, 1); |
||
3656 | if (!bmap) |
||
3657 | return NULL; |
||
3658 | for (i = 0; i < pos && bmap; ++i) |
||
3659 | bmap = var_equal(bmap, i); |
||
3660 | if (bmap) |
||
3661 | bmap = var_more(bmap, pos); |
||
3662 | return isl_basic_map_finalize(bmap); |
||
3663 | } |
||
3664 | |||
3665 | /* Return a relation on of dimension "dim" expressing i_[0..pos] >>= o_[0..pos] |
||
3666 | */ |
||
3667 | __isl_give isl_basic_map *isl_basic_map_more_or_equal_at( |
||
3668 | __isl_take isl_space *dim, unsigned pos) |
||
3669 | { |
||
3670 | int i; |
||
3671 | isl_basic_map *bmap; |
||
3672 | |||
3673 | bmap = isl_basic_map_alloc_space(dim, 0, pos, 1); |
||
3674 | for (i = 0; i < pos; ++i) |
||
3675 | bmap = var_equal(bmap, i); |
||
3676 | bmap = var_more_or_equal(bmap, pos); |
||
3677 | return isl_basic_map_finalize(bmap); |
||
3678 | } |
||
3679 | |||
3680 | static __isl_give isl_map *map_lex_lte_first(__isl_take isl_space *dims, |
||
3681 | unsigned n, int equal) |
||
3682 | { |
||
3683 | struct isl_map *map; |
||
3684 | int i; |
||
3685 | |||
3686 | if (n == 0 && equal) |
||
3687 | return isl_map_universe(dims); |
||
3688 | |||
3689 | map = isl_map_alloc_space(isl_space_copy(dims), n, ISL_MAP_DISJOINT); |
||
3690 | |||
3691 | for (i = 0; i + 1 < n; ++i) |
||
3692 | map = isl_map_add_basic_map(map, |
||
3693 | isl_basic_map_less_at(isl_space_copy(dims), i)); |
||
3694 | if (n > 0) { |
||
3695 | if (equal) |
||
3696 | map = isl_map_add_basic_map(map, |
||
3697 | isl_basic_map_less_or_equal_at(dims, n - 1)); |
||
3698 | else |
||
3699 | map = isl_map_add_basic_map(map, |
||
3700 | isl_basic_map_less_at(dims, n - 1)); |
||
3701 | } else |
||
3702 | isl_space_free(dims); |
||
3703 | |||
3704 | return map; |
||
3705 | } |
||
3706 | |||
3707 | static __isl_give isl_map *map_lex_lte(__isl_take isl_space *dims, int equal) |
||
3708 | { |
||
3709 | if (!dims) |
||
3710 | return NULL; |
||
3711 | return map_lex_lte_first(dims, dims->n_out, equal); |
||
3712 | } |
||
3713 | |||
3714 | __isl_give isl_map *isl_map_lex_lt_first(__isl_take isl_space *dim, unsigned n) |
||
3715 | { |
||
3716 | return map_lex_lte_first(dim, n, 0); |
||
3717 | } |
||
3718 | |||
3719 | __isl_give isl_map *isl_map_lex_le_first(__isl_take isl_space *dim, unsigned n) |
||
3720 | { |
||
3721 | return map_lex_lte_first(dim, n, 1); |
||
3722 | } |
||
3723 | |||
3724 | __isl_give isl_map *isl_map_lex_lt(__isl_take isl_space *set_dim) |
||
3725 | { |
||
3726 | return map_lex_lte(isl_space_map_from_set(set_dim), 0); |
||
3727 | } |
||
3728 | |||
3729 | __isl_give isl_map *isl_map_lex_le(__isl_take isl_space *set_dim) |
||
3730 | { |
||
3731 | return map_lex_lte(isl_space_map_from_set(set_dim), 1); |
||
3732 | } |
||
3733 | |||
3734 | static __isl_give isl_map *map_lex_gte_first(__isl_take isl_space *dims, |
||
3735 | unsigned n, int equal) |
||
3736 | { |
||
3737 | struct isl_map *map; |
||
3738 | int i; |
||
3739 | |||
3740 | if (n == 0 && equal) |
||
3741 | return isl_map_universe(dims); |
||
3742 | |||
3743 | map = isl_map_alloc_space(isl_space_copy(dims), n, ISL_MAP_DISJOINT); |
||
3744 | |||
3745 | for (i = 0; i + 1 < n; ++i) |
||
3746 | map = isl_map_add_basic_map(map, |
||
3747 | isl_basic_map_more_at(isl_space_copy(dims), i)); |
||
3748 | if (n > 0) { |
||
3749 | if (equal) |
||
3750 | map = isl_map_add_basic_map(map, |
||
3751 | isl_basic_map_more_or_equal_at(dims, n - 1)); |
||
3752 | else |
||
3753 | map = isl_map_add_basic_map(map, |
||
3754 | isl_basic_map_more_at(dims, n - 1)); |
||
3755 | } else |
||
3756 | isl_space_free(dims); |
||
3757 | |||
3758 | return map; |
||
3759 | } |
||
3760 | |||
3761 | static __isl_give isl_map *map_lex_gte(__isl_take isl_space *dims, int equal) |
||
3762 | { |
||
3763 | if (!dims) |
||
3764 | return NULL; |
||
3765 | return map_lex_gte_first(dims, dims->n_out, equal); |
||
3766 | } |
||
3767 | |||
3768 | __isl_give isl_map *isl_map_lex_gt_first(__isl_take isl_space *dim, unsigned n) |
||
3769 | { |
||
3770 | return map_lex_gte_first(dim, n, 0); |
||
3771 | } |
||
3772 | |||
3773 | __isl_give isl_map *isl_map_lex_ge_first(__isl_take isl_space *dim, unsigned n) |
||
3774 | { |
||
3775 | return map_lex_gte_first(dim, n, 1); |
||
3776 | } |
||
3777 | |||
3778 | __isl_give isl_map *isl_map_lex_gt(__isl_take isl_space *set_dim) |
||
3779 | { |
||
3780 | return map_lex_gte(isl_space_map_from_set(set_dim), 0); |
||
3781 | } |
||
3782 | |||
3783 | __isl_give isl_map *isl_map_lex_ge(__isl_take isl_space *set_dim) |
||
3784 | { |
||
3785 | return map_lex_gte(isl_space_map_from_set(set_dim), 1); |
||
3786 | } |
||
3787 | |||
3788 | __isl_give isl_map *isl_set_lex_le_set(__isl_take isl_set *set1, |
||
3789 | __isl_take isl_set *set2) |
||
3790 | { |
||
3791 | isl_map *map; |
||
3792 | map = isl_map_lex_le(isl_set_get_space(set1)); |
||
3793 | map = isl_map_intersect_domain(map, set1); |
||
3794 | map = isl_map_intersect_range(map, set2); |
||
3795 | return map; |
||
3796 | } |
||
3797 | |||
3798 | __isl_give isl_map *isl_set_lex_lt_set(__isl_take isl_set *set1, |
||
3799 | __isl_take isl_set *set2) |
||
3800 | { |
||
3801 | isl_map *map; |
||
3802 | map = isl_map_lex_lt(isl_set_get_space(set1)); |
||
3803 | map = isl_map_intersect_domain(map, set1); |
||
3804 | map = isl_map_intersect_range(map, set2); |
||
3805 | return map; |
||
3806 | } |
||
3807 | |||
3808 | __isl_give isl_map *isl_set_lex_ge_set(__isl_take isl_set *set1, |
||
3809 | __isl_take isl_set *set2) |
||
3810 | { |
||
3811 | isl_map *map; |
||
3812 | map = isl_map_lex_ge(isl_set_get_space(set1)); |
||
3813 | map = isl_map_intersect_domain(map, set1); |
||
3814 | map = isl_map_intersect_range(map, set2); |
||
3815 | return map; |
||
3816 | } |
||
3817 | |||
3818 | __isl_give isl_map *isl_set_lex_gt_set(__isl_take isl_set *set1, |
||
3819 | __isl_take isl_set *set2) |
||
3820 | { |
||
3821 | isl_map *map; |
||
3822 | map = isl_map_lex_gt(isl_set_get_space(set1)); |
||
3823 | map = isl_map_intersect_domain(map, set1); |
||
3824 | map = isl_map_intersect_range(map, set2); |
||
3825 | return map; |
||
3826 | } |
||
3827 | |||
3828 | __isl_give isl_map *isl_map_lex_le_map(__isl_take isl_map *map1, |
||
3829 | __isl_take isl_map *map2) |
||
3830 | { |
||
3831 | isl_map *map; |
||
3832 | map = isl_map_lex_le(isl_space_range(isl_map_get_space(map1))); |
||
3833 | map = isl_map_apply_domain(map, isl_map_reverse(map1)); |
||
3834 | map = isl_map_apply_range(map, isl_map_reverse(map2)); |
||
3835 | return map; |
||
3836 | } |
||
3837 | |||
3838 | __isl_give isl_map *isl_map_lex_lt_map(__isl_take isl_map *map1, |
||
3839 | __isl_take isl_map *map2) |
||
3840 | { |
||
3841 | isl_map *map; |
||
3842 | map = isl_map_lex_lt(isl_space_range(isl_map_get_space(map1))); |
||
3843 | map = isl_map_apply_domain(map, isl_map_reverse(map1)); |
||
3844 | map = isl_map_apply_range(map, isl_map_reverse(map2)); |
||
3845 | return map; |
||
3846 | } |
||
3847 | |||
3848 | __isl_give isl_map *isl_map_lex_ge_map(__isl_take isl_map *map1, |
||
3849 | __isl_take isl_map *map2) |
||
3850 | { |
||
3851 | isl_map *map; |
||
3852 | map = isl_map_lex_ge(isl_space_range(isl_map_get_space(map1))); |
||
3853 | map = isl_map_apply_domain(map, isl_map_reverse(map1)); |
||
3854 | map = isl_map_apply_range(map, isl_map_reverse(map2)); |
||
3855 | return map; |
||
3856 | } |
||
3857 | |||
3858 | __isl_give isl_map *isl_map_lex_gt_map(__isl_take isl_map *map1, |
||
3859 | __isl_take isl_map *map2) |
||
3860 | { |
||
3861 | isl_map *map; |
||
3862 | map = isl_map_lex_gt(isl_space_range(isl_map_get_space(map1))); |
||
3863 | map = isl_map_apply_domain(map, isl_map_reverse(map1)); |
||
3864 | map = isl_map_apply_range(map, isl_map_reverse(map2)); |
||
3865 | return map; |
||
3866 | } |
||
3867 | |||
3868 | __isl_give isl_basic_map *isl_basic_map_from_basic_set( |
||
3869 | __isl_take isl_basic_set *bset, __isl_take isl_space *dim) |
||
3870 | { |
||
3871 | struct isl_basic_map *bmap; |
||
3872 | |||
3873 | bset = isl_basic_set_cow(bset); |
||
3874 | if (!bset || !dim) |
||
3875 | goto error; |
||
3876 | |||
3877 | isl_assert(bset->ctx, isl_space_compatible(bset->dim, dim), goto error); |
||
3878 | isl_space_free(bset->dim); |
||
3879 | bmap = (struct isl_basic_map *) bset; |
||
3880 | bmap->dim = dim; |
||
3881 | return isl_basic_map_finalize(bmap); |
||
3882 | error: |
||
3883 | isl_basic_set_free(bset); |
||
3884 | isl_space_free(dim); |
||
3885 | return NULL; |
||
3886 | } |
||
3887 | |||
3888 | struct isl_basic_set *isl_basic_set_from_basic_map(struct isl_basic_map *bmap) |
||
3889 | { |
||
3890 | if (!bmap) |
||
3891 | goto error; |
||
3892 | if (bmap->dim->n_in == 0) |
||
3893 | return (struct isl_basic_set *)bmap; |
||
3894 | bmap = isl_basic_map_cow(bmap); |
||
3895 | if (!bmap) |
||
3896 | goto error; |
||
3897 | bmap->dim = isl_space_as_set_space(bmap->dim); |
||
3898 | if (!bmap->dim) |
||
3899 | goto error; |
||
3900 | bmap = isl_basic_map_finalize(bmap); |
||
3901 | return (struct isl_basic_set *)bmap; |
||
3902 | error: |
||
3903 | isl_basic_map_free(bmap); |
||
3904 | return NULL; |
||
3905 | } |
||
3906 | |||
3907 | /* For a div d = floor(f/m), add the constraints |
||
3908 | * |
||
3909 | * f - m d >= 0 |
||
3910 | * -(f-(n-1)) + m d >= 0 |
||
3911 | * |
||
3912 | * Note that the second constraint is the negation of |
||
3913 | * |
||
3914 | * f - m d >= n |
||
3915 | */ |
||
3916 | int isl_basic_map_add_div_constraints_var(__isl_keep isl_basic_map *bmap, |
||
3917 | unsigned pos, isl_int *div) |
||
3918 | { |
||
3919 | int i, j; |
||
3920 | unsigned total = isl_basic_map_total_dim(bmap); |
||
3921 | |||
3922 | i = isl_basic_map_alloc_inequality(bmap); |
||
3923 | if (i < 0) |
||
3924 | return -1; |
||
3925 | isl_seq_cpy(bmap->ineq[i], div + 1, 1 + total); |
||
3926 | isl_int_neg(bmap->ineq[i][1 + pos], div[0]); |
||
3927 | |||
3928 | j = isl_basic_map_alloc_inequality(bmap); |
||
3929 | if (j < 0) |
||
3930 | return -1; |
||
3931 | isl_seq_neg(bmap->ineq[j], bmap->ineq[i], 1 + total); |
||
3932 | isl_int_add(bmap->ineq[j][0], bmap->ineq[j][0], bmap->ineq[j][1 + pos]); |
||
3933 | isl_int_sub_ui(bmap->ineq[j][0], bmap->ineq[j][0], 1); |
||
3934 | return j; |
||
3935 | } |
||
3936 | |||
3937 | int isl_basic_set_add_div_constraints_var(__isl_keep isl_basic_set *bset, |
||
3938 | unsigned pos, isl_int *div) |
||
3939 | { |
||
3940 | return isl_basic_map_add_div_constraints_var((isl_basic_map *)bset, |
||
3941 | pos, div); |
||
3942 | } |
||
3943 | |||
3944 | int isl_basic_map_add_div_constraints(struct isl_basic_map *bmap, unsigned div) |
||
3945 | { |
||
3946 | unsigned total = isl_basic_map_total_dim(bmap); |
||
3947 | unsigned div_pos = total - bmap->n_div + div; |
||
3948 | |||
3949 | return isl_basic_map_add_div_constraints_var(bmap, div_pos, |
||
3950 | bmap->div[div]); |
||
3951 | } |
||
3952 | |||
3953 | struct isl_basic_set *isl_basic_map_underlying_set( |
||
3954 | struct isl_basic_map *bmap) |
||
3955 | { |
||
3956 | if (!bmap) |
||
3957 | goto error; |
||
3958 | if (bmap->dim->nparam == 0 && bmap->dim->n_in == 0 && |
||
3959 | bmap->n_div == 0 && |
||
3960 | !isl_space_is_named_or_nested(bmap->dim, isl_dim_in) && |
||
3961 | !isl_space_is_named_or_nested(bmap->dim, isl_dim_out)) |
||
3962 | return (struct isl_basic_set *)bmap; |
||
3963 | bmap = isl_basic_map_cow(bmap); |
||
3964 | if (!bmap) |
||
3965 | goto error; |
||
3966 | bmap->dim = isl_space_underlying(bmap->dim, bmap->n_div); |
||
3967 | if (!bmap->dim) |
||
3968 | goto error; |
||
3969 | bmap->extra -= bmap->n_div; |
||
3970 | bmap->n_div = 0; |
||
3971 | bmap = isl_basic_map_finalize(bmap); |
||
3972 | return (struct isl_basic_set *)bmap; |
||
3973 | error: |
||
3974 | return NULL; |
||
3975 | } |
||
3976 | |||
3977 | __isl_give isl_basic_set *isl_basic_set_underlying_set( |
||
3978 | __isl_take isl_basic_set *bset) |
||
3979 | { |
||
3980 | return isl_basic_map_underlying_set((isl_basic_map *)bset); |
||
3981 | } |
||
3982 | |||
3983 | struct isl_basic_map *isl_basic_map_overlying_set( |
||
3984 | struct isl_basic_set *bset, struct isl_basic_map *like) |
||
3985 | { |
||
3986 | struct isl_basic_map *bmap; |
||
3987 | struct isl_ctx *ctx; |
||
3988 | unsigned total; |
||
3989 | int i; |
||
3990 | |||
3991 | if (!bset || !like) |
||
3992 | goto error; |
||
3993 | ctx = bset->ctx; |
||
3994 | isl_assert(ctx, bset->n_div == 0, goto error); |
||
3995 | isl_assert(ctx, isl_basic_set_n_param(bset) == 0, goto error); |
||
3996 | isl_assert(ctx, bset->dim->n_out == isl_basic_map_total_dim(like), |
||
3997 | goto error); |
||
3998 | if (isl_space_is_equal(bset->dim, like->dim) && like->n_div == 0) { |
||
3999 | isl_basic_map_free(like); |
||
4000 | return (struct isl_basic_map *)bset; |
||
4001 | } |
||
4002 | bset = isl_basic_set_cow(bset); |
||
4003 | if (!bset) |
||
4004 | goto error; |
||
4005 | total = bset->dim->n_out + bset->extra; |
||
4006 | bmap = (struct isl_basic_map *)bset; |
||
4007 | isl_space_free(bmap->dim); |
||
4008 | bmap->dim = isl_space_copy(like->dim); |
||
4009 | if (!bmap->dim) |
||
4010 | goto error; |
||
4011 | bmap->n_div = like->n_div; |
||
4012 | bmap->extra += like->n_div; |
||
4013 | if (bmap->extra) { |
||
4014 | unsigned ltotal; |
||
4015 | isl_int **div; |
||
4016 | ltotal = total - bmap->extra + like->extra; |
||
4017 | if (ltotal > total) |
||
4018 | ltotal = total; |
||
4019 | bmap->block2 = isl_blk_extend(ctx, bmap->block2, |
||
4020 | bmap->extra * (1 + 1 + total)); |
||
4021 | if (isl_blk_is_error(bmap->block2)) |
||
4022 | goto error; |
||
4023 | div = isl_realloc_array(ctx, bmap->div, isl_int *, bmap->extra); |
||
4024 | if (!div) |
||
4025 | goto error; |
||
4026 | bmap->div = div; |
||
4027 | for (i = 0; i < bmap->extra; ++i) |
||
4028 | bmap->div[i] = bmap->block2.data + i * (1 + 1 + total); |
||
4029 | for (i = 0; i < like->n_div; ++i) { |
||
4030 | isl_seq_cpy(bmap->div[i], like->div[i], 1 + 1 + ltotal); |
||
4031 | isl_seq_clr(bmap->div[i]+1+1+ltotal, total - ltotal); |
||
4032 | } |
||
4033 | bmap = isl_basic_map_extend_constraints(bmap, |
||
4034 | 0, 2 * like->n_div); |
||
4035 | for (i = 0; i < like->n_div; ++i) { |
||
4036 | if (isl_int_is_zero(bmap->div[i][0])) |
||
4037 | continue; |
||
4038 | if (isl_basic_map_add_div_constraints(bmap, i) < 0) |
||
4039 | goto error; |
||
4040 | } |
||
4041 | } |
||
4042 | isl_basic_map_free(like); |
||
4043 | bmap = isl_basic_map_simplify(bmap); |
||
4044 | bmap = isl_basic_map_finalize(bmap); |
||
4045 | return bmap; |
||
4046 | error: |
||
4047 | isl_basic_map_free(like); |
||
4048 | isl_basic_set_free(bset); |
||
4049 | return NULL; |
||
4050 | } |
||
4051 | |||
4052 | struct isl_basic_set *isl_basic_set_from_underlying_set( |
||
4053 | struct isl_basic_set *bset, struct isl_basic_set *like) |
||
4054 | { |
||
4055 | return (struct isl_basic_set *) |
||
4056 | isl_basic_map_overlying_set(bset, (struct isl_basic_map *)like); |
||
4057 | } |
||
4058 | |||
4059 | struct isl_set *isl_set_from_underlying_set( |
||
4060 | struct isl_set *set, struct isl_basic_set *like) |
||
4061 | { |
||
4062 | int i; |
||
4063 | |||
4064 | if (!set || !like) |
||
4065 | goto error; |
||
4066 | isl_assert(set->ctx, set->dim->n_out == isl_basic_set_total_dim(like), |
||
4067 | goto error); |
||
4068 | if (isl_space_is_equal(set->dim, like->dim) && like->n_div == 0) { |
||
4069 | isl_basic_set_free(like); |
||
4070 | return set; |
||
4071 | } |
||
4072 | set = isl_set_cow(set); |
||
4073 | if (!set) |
||
4074 | goto error; |
||
4075 | for (i = 0; i < set->n; ++i) { |
||
4076 | set->p[i] = isl_basic_set_from_underlying_set(set->p[i], |
||
4077 | isl_basic_set_copy(like)); |
||
4078 | if (!set->p[i]) |
||
4079 | goto error; |
||
4080 | } |
||
4081 | isl_space_free(set->dim); |
||
4082 | set->dim = isl_space_copy(like->dim); |
||
4083 | if (!set->dim) |
||
4084 | goto error; |
||
4085 | isl_basic_set_free(like); |
||
4086 | return set; |
||
4087 | error: |
||
4088 | isl_basic_set_free(like); |
||
4089 | isl_set_free(set); |
||
4090 | return NULL; |
||
4091 | } |
||
4092 | |||
4093 | struct isl_set *isl_map_underlying_set(struct isl_map *map) |
||
4094 | { |
||
4095 | int i; |
||
4096 | |||
4097 | map = isl_map_cow(map); |
||
4098 | if (!map) |
||
4099 | return NULL; |
||
4100 | map->dim = isl_space_cow(map->dim); |
||
4101 | if (!map->dim) |
||
4102 | goto error; |
||
4103 | |||
4104 | for (i = 1; i < map->n; ++i) |
||
4105 | isl_assert(map->ctx, map->p[0]->n_div == map->p[i]->n_div, |
||
4106 | goto error); |
||
4107 | for (i = 0; i < map->n; ++i) { |
||
4108 | map->p[i] = (struct isl_basic_map *) |
||
4109 | isl_basic_map_underlying_set(map->p[i]); |
||
4110 | if (!map->p[i]) |
||
4111 | goto error; |
||
4112 | } |
||
4113 | if (map->n == 0) |
||
4114 | map->dim = isl_space_underlying(map->dim, 0); |
||
4115 | else { |
||
4116 | isl_space_free(map->dim); |
||
4117 | map->dim = isl_space_copy(map->p[0]->dim); |
||
4118 | } |
||
4119 | if (!map->dim) |
||
4120 | goto error; |
||
4121 | return (struct isl_set *)map; |
||
4122 | error: |
||
4123 | isl_map_free(map); |
||
4124 | return NULL; |
||
4125 | } |
||
4126 | |||
4127 | struct isl_set *isl_set_to_underlying_set(struct isl_set *set) |
||
4128 | { |
||
4129 | return (struct isl_set *)isl_map_underlying_set((struct isl_map *)set); |
||
4130 | } |
||
4131 | |||
4132 | __isl_give isl_basic_map *isl_basic_map_reset_space( |
||
4133 | __isl_take isl_basic_map *bmap, __isl_take isl_space *dim) |
||
4134 | { |
||
4135 | bmap = isl_basic_map_cow(bmap); |
||
4136 | if (!bmap || !dim) |
||
4137 | goto error; |
||
4138 | |||
4139 | isl_space_free(bmap->dim); |
||
4140 | bmap->dim = dim; |
||
4141 | |||
4142 | bmap = isl_basic_map_finalize(bmap); |
||
4143 | |||
4144 | return bmap; |
||
4145 | error: |
||
4146 | isl_basic_map_free(bmap); |
||
4147 | isl_space_free(dim); |
||
4148 | return NULL; |
||
4149 | } |
||
4150 | |||
4151 | __isl_give isl_basic_set *isl_basic_set_reset_space( |
||
4152 | __isl_take isl_basic_set *bset, __isl_take isl_space *dim) |
||
4153 | { |
||
4154 | return (isl_basic_set *)isl_basic_map_reset_space((isl_basic_map *)bset, |
||
4155 | dim); |
||
4156 | } |
||
4157 | |||
4158 | __isl_give isl_map *isl_map_reset_space(__isl_take isl_map *map, |
||
4159 | __isl_take isl_space *dim) |
||
4160 | { |
||
4161 | int i; |
||
4162 | |||
4163 | map = isl_map_cow(map); |
||
4164 | if (!map || !dim) |
||
4165 | goto error; |
||
4166 | |||
4167 | for (i = 0; i < map->n; ++i) { |
||
4168 | map->p[i] = isl_basic_map_reset_space(map->p[i], |
||
4169 | isl_space_copy(dim)); |
||
4170 | if (!map->p[i]) |
||
4171 | goto error; |
||
4172 | } |
||
4173 | isl_space_free(map->dim); |
||
4174 | map->dim = dim; |
||
4175 | |||
4176 | return map; |
||
4177 | error: |
||
4178 | isl_map_free(map); |
||
4179 | isl_space_free(dim); |
||
4180 | return NULL; |
||
4181 | } |
||
4182 | |||
4183 | __isl_give isl_set *isl_set_reset_space(__isl_take isl_set *set, |
||
4184 | __isl_take isl_space *dim) |
||
4185 | { |
||
4186 | return (struct isl_set *) isl_map_reset_space((struct isl_map *)set, dim); |
||
4187 | } |
||
4188 | |||
4189 | /* Compute the parameter domain of the given basic set. |
||
4190 | */ |
||
4191 | __isl_give isl_basic_set *isl_basic_set_params(__isl_take isl_basic_set *bset) |
||
4192 | { |
||
4193 | isl_space *space; |
||
4194 | unsigned n; |
||
4195 | |||
4196 | if (isl_basic_set_is_params(bset)) |
||
4197 | return bset; |
||
4198 | |||
4199 | n = isl_basic_set_dim(bset, isl_dim_set); |
||
4200 | bset = isl_basic_set_project_out(bset, isl_dim_set, 0, n); |
||
4201 | space = isl_basic_set_get_space(bset); |
||
4202 | space = isl_space_params(space); |
||
4203 | bset = isl_basic_set_reset_space(bset, space); |
||
4204 | return bset; |
||
4205 | } |
||
4206 | |||
4207 | /* Compute the parameter domain of the given set. |
||
4208 | */ |
||
4209 | __isl_give isl_set *isl_set_params(__isl_take isl_set *set) |
||
4210 | { |
||
4211 | isl_space *space; |
||
4212 | unsigned n; |
||
4213 | |||
4214 | if (isl_set_is_params(set)) |
||
4215 | return set; |
||
4216 | |||
4217 | n = isl_set_dim(set, isl_dim_set); |
||
4218 | set = isl_set_project_out(set, isl_dim_set, 0, n); |
||
4219 | space = isl_set_get_space(set); |
||
4220 | space = isl_space_params(space); |
||
4221 | set = isl_set_reset_space(set, space); |
||
4222 | return set; |
||
4223 | } |
||
4224 | |||
4225 | /* Construct a zero-dimensional set with the given parameter domain. |
||
4226 | */ |
||
4227 | __isl_give isl_set *isl_set_from_params(__isl_take isl_set *set) |
||
4228 | { |
||
4229 | isl_space *space; |
||
4230 | space = isl_set_get_space(set); |
||
4231 | space = isl_space_set_from_params(space); |
||
4232 | set = isl_set_reset_space(set, space); |
||
4233 | return set; |
||
4234 | } |
||
4235 | |||
4236 | /* Compute the parameter domain of the given map. |
||
4237 | */ |
||
4238 | __isl_give isl_set *isl_map_params(__isl_take isl_map *map) |
||
4239 | { |
||
4240 | isl_space *space; |
||
4241 | unsigned n; |
||
4242 | |||
4243 | n = isl_map_dim(map, isl_dim_in); |
||
4244 | map = isl_map_project_out(map, isl_dim_in, 0, n); |
||
4245 | n = isl_map_dim(map, isl_dim_out); |
||
4246 | map = isl_map_project_out(map, isl_dim_out, 0, n); |
||
4247 | space = isl_map_get_space(map); |
||
4248 | space = isl_space_params(space); |
||
4249 | map = isl_map_reset_space(map, space); |
||
4250 | return map; |
||
4251 | } |
||
4252 | |||
4253 | struct isl_basic_set *isl_basic_map_domain(struct isl_basic_map *bmap) |
||
4254 | { |
||
4255 | isl_space *dim; |
||
4256 | struct isl_basic_set *domain; |
||
4257 | unsigned n_in; |
||
4258 | unsigned n_out; |
||
4259 | |||
4260 | if (!bmap) |
||
4261 | return NULL; |
||
4262 | dim = isl_space_domain(isl_basic_map_get_space(bmap)); |
||
4263 | |||
4264 | n_in = isl_basic_map_n_in(bmap); |
||
4265 | n_out = isl_basic_map_n_out(bmap); |
||
4266 | domain = isl_basic_set_from_basic_map(bmap); |
||
4267 | domain = isl_basic_set_project_out(domain, isl_dim_set, n_in, n_out); |
||
4268 | |||
4269 | domain = isl_basic_set_reset_space(domain, dim); |
||
4270 | |||
4271 | return domain; |
||
4272 | } |
||
4273 | |||
4274 | int isl_basic_map_may_be_set(__isl_keep isl_basic_map *bmap) |
||
4275 | { |
||
4276 | if (!bmap) |
||
4277 | return -1; |
||
4278 | return isl_space_may_be_set(bmap->dim); |
||
4279 | } |
||
4280 | |||
4281 | /* Is this basic map actually a set? |
||
4282 | * Users should never call this function. Outside of isl, |
||
4283 | * the type should indicate whether something is a set or a map. |
||
4284 | */ |
||
4285 | int isl_basic_map_is_set(__isl_keep isl_basic_map *bmap) |
||
4286 | { |
||
4287 | if (!bmap) |
||
4288 | return -1; |
||
4289 | return isl_space_is_set(bmap->dim); |
||
4290 | } |
||
4291 | |||
4292 | struct isl_basic_set *isl_basic_map_range(struct isl_basic_map *bmap) |
||
4293 | { |
||
4294 | if (!bmap) |
||
4295 | return NULL; |
||
4296 | if (isl_basic_map_is_set(bmap)) |
||
4297 | return bmap; |
||
4298 | return isl_basic_map_domain(isl_basic_map_reverse(bmap)); |
||
4299 | } |
||
4300 | |||
4301 | __isl_give isl_basic_map *isl_basic_map_domain_map( |
||
4302 | __isl_take isl_basic_map *bmap) |
||
4303 | { |
||
4304 | int i, k; |
||
4305 | isl_space *dim; |
||
4306 | isl_basic_map *domain; |
||
4307 | int nparam, n_in, n_out; |
||
4308 | unsigned total; |
||
4309 | |||
4310 | nparam = isl_basic_map_dim(bmap, isl_dim_param); |
||
4311 | n_in = isl_basic_map_dim(bmap, isl_dim_in); |
||
4312 | n_out = isl_basic_map_dim(bmap, isl_dim_out); |
||
4313 | |||
4314 | dim = isl_space_from_range(isl_space_domain(isl_basic_map_get_space(bmap))); |
||
4315 | domain = isl_basic_map_universe(dim); |
||
4316 | |||
4317 | bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap)); |
||
4318 | bmap = isl_basic_map_apply_range(bmap, domain); |
||
4319 | bmap = isl_basic_map_extend_constraints(bmap, n_in, 0); |
||
4320 | |||
4321 | total = isl_basic_map_total_dim(bmap); |
||
4322 | |||
4323 | for (i = 0; i < n_in; ++i) { |
||
4324 | k = isl_basic_map_alloc_equality(bmap); |
||
4325 | if (k < 0) |
||
4326 | goto error; |
||
4327 | isl_seq_clr(bmap->eq[k], 1 + total); |
||
4328 | isl_int_set_si(bmap->eq[k][1 + nparam + i], -1); |
||
4329 | isl_int_set_si(bmap->eq[k][1 + nparam + n_in + n_out + i], 1); |
||
4330 | } |
||
4331 | |||
4332 | bmap = isl_basic_map_gauss(bmap, NULL); |
||
4333 | return isl_basic_map_finalize(bmap); |
||
4334 | error: |
||
4335 | isl_basic_map_free(bmap); |
||
4336 | return NULL; |
||
4337 | } |
||
4338 | |||
4339 | __isl_give isl_basic_map *isl_basic_map_range_map( |
||
4340 | __isl_take isl_basic_map *bmap) |
||
4341 | { |
||
4342 | int i, k; |
||
4343 | isl_space *dim; |
||
4344 | isl_basic_map *range; |
||
4345 | int nparam, n_in, n_out; |
||
4346 | unsigned total; |
||
4347 | |||
4348 | nparam = isl_basic_map_dim(bmap, isl_dim_param); |
||
4349 | n_in = isl_basic_map_dim(bmap, isl_dim_in); |
||
4350 | n_out = isl_basic_map_dim(bmap, isl_dim_out); |
||
4351 | |||
4352 | dim = isl_space_from_range(isl_space_range(isl_basic_map_get_space(bmap))); |
||
4353 | range = isl_basic_map_universe(dim); |
||
4354 | |||
4355 | bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap)); |
||
4356 | bmap = isl_basic_map_apply_range(bmap, range); |
||
4357 | bmap = isl_basic_map_extend_constraints(bmap, n_out, 0); |
||
4358 | |||
4359 | total = isl_basic_map_total_dim(bmap); |
||
4360 | |||
4361 | for (i = 0; i < n_out; ++i) { |
||
4362 | k = isl_basic_map_alloc_equality(bmap); |
||
4363 | if (k < 0) |
||
4364 | goto error; |
||
4365 | isl_seq_clr(bmap->eq[k], 1 + total); |
||
4366 | isl_int_set_si(bmap->eq[k][1 + nparam + n_in + i], -1); |
||
4367 | isl_int_set_si(bmap->eq[k][1 + nparam + n_in + n_out + i], 1); |
||
4368 | } |
||
4369 | |||
4370 | bmap = isl_basic_map_gauss(bmap, NULL); |
||
4371 | return isl_basic_map_finalize(bmap); |
||
4372 | error: |
||
4373 | isl_basic_map_free(bmap); |
||
4374 | return NULL; |
||
4375 | } |
||
4376 | |||
4377 | int isl_map_may_be_set(__isl_keep isl_map *map) |
||
4378 | { |
||
4379 | if (!map) |
||
4380 | return -1; |
||
4381 | return isl_space_may_be_set(map->dim); |
||
4382 | } |
||
4383 | |||
4384 | /* Is this map actually a set? |
||
4385 | * Users should never call this function. Outside of isl, |
||
4386 | * the type should indicate whether something is a set or a map. |
||
4387 | */ |
||
4388 | int isl_map_is_set(__isl_keep isl_map *map) |
||
4389 | { |
||
4390 | if (!map) |
||
4391 | return -1; |
||
4392 | return isl_space_is_set(map->dim); |
||
4393 | } |
||
4394 | |||
4395 | struct isl_set *isl_map_range(struct isl_map *map) |
||
4396 | { |
||
4397 | int i; |
||
4398 | struct isl_set *set; |
||
4399 | |||
4400 | if (!map) |
||
4401 | goto error; |
||
4402 | if (isl_map_is_set(map)) |
||
4403 | return (isl_set *)map; |
||
4404 | |||
4405 | map = isl_map_cow(map); |
||
4406 | if (!map) |
||
4407 | goto error; |
||
4408 | |||
4409 | set = (struct isl_set *) map; |
||
4410 | set->dim = isl_space_range(set->dim); |
||
4411 | if (!set->dim) |
||
4412 | goto error; |
||
4413 | for (i = 0; i < map->n; ++i) { |
||
4414 | set->p[i] = isl_basic_map_range(map->p[i]); |
||
4415 | if (!set->p[i]) |
||
4416 | goto error; |
||
4417 | } |
||
4418 | ISL_F_CLR(set, ISL_MAP_DISJOINT); |
||
4419 | ISL_F_CLR(set, ISL_SET_NORMALIZED); |
||
4420 | return set; |
||
4421 | error: |
||
4422 | isl_map_free(map); |
||
4423 | return NULL; |
||
4424 | } |
||
4425 | |||
4426 | __isl_give isl_map *isl_map_domain_map(__isl_take isl_map *map) |
||
4427 | { |
||
4428 | int i; |
||
4429 | isl_space *domain_dim; |
||
4430 | |||
4431 | map = isl_map_cow(map); |
||
4432 | if (!map) |
||
4433 | return NULL; |
||
4434 | |||
4435 | domain_dim = isl_space_from_range(isl_space_domain(isl_map_get_space(map))); |
||
4436 | map->dim = isl_space_from_domain(isl_space_wrap(map->dim)); |
||
4437 | map->dim = isl_space_join(map->dim, domain_dim); |
||
4438 | if (!map->dim) |
||
4439 | goto error; |
||
4440 | for (i = 0; i < map->n; ++i) { |
||
4441 | map->p[i] = isl_basic_map_domain_map(map->p[i]); |
||
4442 | if (!map->p[i]) |
||
4443 | goto error; |
||
4444 | } |
||
4445 | ISL_F_CLR(map, ISL_MAP_DISJOINT); |
||
4446 | ISL_F_CLR(map, ISL_MAP_NORMALIZED); |
||
4447 | return map; |
||
4448 | error: |
||
4449 | isl_map_free(map); |
||
4450 | return NULL; |
||
4451 | } |
||
4452 | |||
4453 | __isl_give isl_map *isl_map_range_map(__isl_take isl_map *map) |
||
4454 | { |
||
4455 | int i; |
||
4456 | isl_space *range_dim; |
||
4457 | |||
4458 | map = isl_map_cow(map); |
||
4459 | if (!map) |
||
4460 | return NULL; |
||
4461 | |||
4462 | range_dim = isl_space_range(isl_map_get_space(map)); |
||
4463 | range_dim = isl_space_from_range(range_dim); |
||
4464 | map->dim = isl_space_from_domain(isl_space_wrap(map->dim)); |
||
4465 | map->dim = isl_space_join(map->dim, range_dim); |
||
4466 | if (!map->dim) |
||
4467 | goto error; |
||
4468 | for (i = 0; i < map->n; ++i) { |
||
4469 | map->p[i] = isl_basic_map_range_map(map->p[i]); |
||
4470 | if (!map->p[i]) |
||
4471 | goto error; |
||
4472 | } |
||
4473 | ISL_F_CLR(map, ISL_MAP_DISJOINT); |
||
4474 | ISL_F_CLR(map, ISL_MAP_NORMALIZED); |
||
4475 | return map; |
||
4476 | error: |
||
4477 | isl_map_free(map); |
||
4478 | return NULL; |
||
4479 | } |
||
4480 | |||
4481 | __isl_give isl_map *isl_map_from_set(__isl_take isl_set *set, |
||
4482 | __isl_take isl_space *dim) |
||
4483 | { |
||
4484 | int i; |
||
4485 | struct isl_map *map = NULL; |
||
4486 | |||
4487 | set = isl_set_cow(set); |
||
4488 | if (!set || !dim) |
||
4489 | goto error; |
||
4490 | isl_assert(set->ctx, isl_space_compatible(set->dim, dim), goto error); |
||
4491 | map = (struct isl_map *)set; |
||
4492 | for (i = 0; i < set->n; ++i) { |
||
4493 | map->p[i] = isl_basic_map_from_basic_set( |
||
4494 | set->p[i], isl_space_copy(dim)); |
||
4495 | if (!map->p[i]) |
||
4496 | goto error; |
||
4497 | } |
||
4498 | isl_space_free(map->dim); |
||
4499 | map->dim = dim; |
||
4500 | return map; |
||
4501 | error: |
||
4502 | isl_space_free(dim); |
||
4503 | isl_set_free(set); |
||
4504 | return NULL; |
||
4505 | } |
||
4506 | |||
4507 | __isl_give isl_basic_map *isl_basic_map_from_domain( |
||
4508 | __isl_take isl_basic_set *bset) |
||
4509 | { |
||
4510 | return isl_basic_map_reverse(isl_basic_map_from_range(bset)); |
||
4511 | } |
||
4512 | |||
4513 | __isl_give isl_basic_map *isl_basic_map_from_range( |
||
4514 | __isl_take isl_basic_set *bset) |
||
4515 | { |
||
4516 | isl_space *space; |
||
4517 | space = isl_basic_set_get_space(bset); |
||
4518 | space = isl_space_from_range(space); |
||
4519 | bset = isl_basic_set_reset_space(bset, space); |
||
4520 | return (isl_basic_map *)bset; |
||
4521 | } |
||
4522 | |||
4523 | struct isl_map *isl_map_from_range(struct isl_set *set) |
||
4524 | { |
||
4525 | isl_space *space; |
||
4526 | space = isl_set_get_space(set); |
||
4527 | space = isl_space_from_range(space); |
||
4528 | set = isl_set_reset_space(set, space); |
||
4529 | return (struct isl_map *)set; |
||
4530 | } |
||
4531 | |||
4532 | __isl_give isl_map *isl_map_from_domain(__isl_take isl_set *set) |
||
4533 | { |
||
4534 | return isl_map_reverse(isl_map_from_range(set)); |
||
4535 | } |
||
4536 | |||
4537 | __isl_give isl_basic_map *isl_basic_map_from_domain_and_range( |
||
4538 | __isl_take isl_basic_set *domain, __isl_take isl_basic_set *range) |
||
4539 | { |
||
4540 | return isl_basic_map_apply_range(isl_basic_map_reverse(domain), range); |
||
4541 | } |
||
4542 | |||
4543 | __isl_give isl_map *isl_map_from_domain_and_range(__isl_take isl_set *domain, |
||
4544 | __isl_take isl_set *range) |
||
4545 | { |
||
4546 | return isl_map_apply_range(isl_map_reverse(domain), range); |
||
4547 | } |
||
4548 | |||
4549 | struct isl_set *isl_set_from_map(struct isl_map *map) |
||
4550 | { |
||
4551 | int i; |
||
4552 | struct isl_set *set = NULL; |
||
4553 | |||
4554 | if (!map) |
||
4555 | return NULL; |
||
4556 | map = isl_map_cow(map); |
||
4557 | if (!map) |
||
4558 | return NULL; |
||
4559 | map->dim = isl_space_as_set_space(map->dim); |
||
4560 | if (!map->dim) |
||
4561 | goto error; |
||
4562 | set = (struct isl_set *)map; |
||
4563 | for (i = 0; i < map->n; ++i) { |
||
4564 | set->p[i] = isl_basic_set_from_basic_map(map->p[i]); |
||
4565 | if (!set->p[i]) |
||
4566 | goto error; |
||
4567 | } |
||
4568 | return set; |
||
4569 | error: |
||
4570 | isl_map_free(map); |
||
4571 | return NULL; |
||
4572 | } |
||
4573 | |||
4574 | __isl_give isl_map *isl_map_alloc_space(__isl_take isl_space *dim, int n, |
||
4575 | unsigned flags) |
||
4576 | { |
||
4577 | struct isl_map *map; |
||
4578 | |||
4579 | if (!dim) |
||
4580 | return NULL; |
||
4581 | if (n < 0) |
||
4582 | isl_die(dim->ctx, isl_error_internal, |
||
4583 | "negative number of basic maps", goto error); |
||
4584 | map = isl_alloc(dim->ctx, struct isl_map, |
||
4585 | sizeof(struct isl_map) + |
||
4586 | (n - 1) * sizeof(struct isl_basic_map *)); |
||
4587 | if (!map) |
||
4588 | goto error; |
||
4589 | |||
4590 | map->ctx = dim->ctx; |
||
4591 | isl_ctx_ref(map->ctx); |
||
4592 | map->ref = 1; |
||
4593 | map->size = n; |
||
4594 | map->n = 0; |
||
4595 | map->dim = dim; |
||
4596 | map->flags = flags; |
||
4597 | return map; |
||
4598 | error: |
||
4599 | isl_space_free(dim); |
||
4600 | return NULL; |
||
4601 | } |
||
4602 | |||
4603 | struct isl_map *isl_map_alloc(struct isl_ctx *ctx, |
||
4604 | unsigned nparam, unsigned in, unsigned out, int n, |
||
4605 | unsigned flags) |
||
4606 | { |
||
4607 | struct isl_map *map; |
||
4608 | isl_space *dims; |
||
4609 | |||
4610 | dims = isl_space_alloc(ctx, nparam, in, out); |
||
4611 | if (!dims) |
||
4612 | return NULL; |
||
4613 | |||
4614 | map = isl_map_alloc_space(dims, n, flags); |
||
4615 | return map; |
||
4616 | } |
||
4617 | |||
4618 | __isl_give isl_basic_map *isl_basic_map_empty(__isl_take isl_space *dim) |
||
4619 | { |
||
4620 | struct isl_basic_map *bmap; |
||
4621 | bmap = isl_basic_map_alloc_space(dim, 0, 1, 0); |
||
4622 | bmap = isl_basic_map_set_to_empty(bmap); |
||
4623 | return bmap; |
||
4624 | } |
||
4625 | |||
4626 | __isl_give isl_basic_set *isl_basic_set_empty(__isl_take isl_space *dim) |
||
4627 | { |
||
4628 | struct isl_basic_set *bset; |
||
4629 | bset = isl_basic_set_alloc_space(dim, 0, 1, 0); |
||
4630 | bset = isl_basic_set_set_to_empty(bset); |
||
4631 | return bset; |
||
4632 | } |
||
4633 | |||
4634 | struct isl_basic_map *isl_basic_map_empty_like(struct isl_basic_map *model) |
||
4635 | { |
||
4636 | struct isl_basic_map *bmap; |
||
4637 | if (!model) |
||
4638 | return NULL; |
||
4639 | bmap = isl_basic_map_alloc_space(isl_space_copy(model->dim), 0, 1, 0); |
||
4640 | bmap = isl_basic_map_set_to_empty(bmap); |
||
4641 | return bmap; |
||
4642 | } |
||
4643 | |||
4644 | struct isl_basic_map *isl_basic_map_empty_like_map(struct isl_map *model) |
||
4645 | { |
||
4646 | struct isl_basic_map *bmap; |
||
4647 | if (!model) |
||
4648 | return NULL; |
||
4649 | bmap = isl_basic_map_alloc_space(isl_space_copy(model->dim), 0, 1, 0); |
||
4650 | bmap = isl_basic_map_set_to_empty(bmap); |
||
4651 | return bmap; |
||
4652 | } |
||
4653 | |||
4654 | struct isl_basic_set *isl_basic_set_empty_like(struct isl_basic_set *model) |
||
4655 | { |
||
4656 | struct isl_basic_set *bset; |
||
4657 | if (!model) |
||
4658 | return NULL; |
||
4659 | bset = isl_basic_set_alloc_space(isl_space_copy(model->dim), 0, 1, 0); |
||
4660 | bset = isl_basic_set_set_to_empty(bset); |
||
4661 | return bset; |
||
4662 | } |
||
4663 | |||
4664 | __isl_give isl_basic_map *isl_basic_map_universe(__isl_take isl_space *dim) |
||
4665 | { |
||
4666 | struct isl_basic_map *bmap; |
||
4667 | bmap = isl_basic_map_alloc_space(dim, 0, 0, 0); |
||
4668 | bmap = isl_basic_map_finalize(bmap); |
||
4669 | return bmap; |
||
4670 | } |
||
4671 | |||
4672 | __isl_give isl_basic_set *isl_basic_set_universe(__isl_take isl_space *dim) |
||
4673 | { |
||
4674 | struct isl_basic_set *bset; |
||
4675 | bset = isl_basic_set_alloc_space(dim, 0, 0, 0); |
||
4676 | bset = isl_basic_set_finalize(bset); |
||
4677 | return bset; |
||
4678 | } |
||
4679 | |||
4680 | __isl_give isl_basic_map *isl_basic_map_nat_universe(__isl_take isl_space *dim) |
||
4681 | { |
||
4682 | int i; |
||
4683 | unsigned total = isl_space_dim(dim, isl_dim_all); |
||
4684 | isl_basic_map *bmap; |
||
4685 | |||
4686 | bmap= isl_basic_map_alloc_space(dim, 0, 0, total); |
||
4687 | for (i = 0; i < total; ++i) { |
||
4688 | int k = isl_basic_map_alloc_inequality(bmap); |
||
4689 | if (k < 0) |
||
4690 | goto error; |
||
4691 | isl_seq_clr(bmap->ineq[k], 1 + total); |
||
4692 | isl_int_set_si(bmap->ineq[k][1 + i], 1); |
||
4693 | } |
||
4694 | return bmap; |
||
4695 | error: |
||
4696 | isl_basic_map_free(bmap); |
||
4697 | return NULL; |
||
4698 | } |
||
4699 | |||
4700 | __isl_give isl_basic_set *isl_basic_set_nat_universe(__isl_take isl_space *dim) |
||
4701 | { |
||
4702 | return isl_basic_map_nat_universe(dim); |
||
4703 | } |
||
4704 | |||
4705 | __isl_give isl_map *isl_map_nat_universe(__isl_take isl_space *dim) |
||
4706 | { |
||
4707 | return isl_map_from_basic_map(isl_basic_map_nat_universe(dim)); |
||
4708 | } |
||
4709 | |||
4710 | __isl_give isl_set *isl_set_nat_universe(__isl_take isl_space *dim) |
||
4711 | { |
||
4712 | return isl_map_nat_universe(dim); |
||
4713 | } |
||
4714 | |||
4715 | __isl_give isl_basic_map *isl_basic_map_universe_like( |
||
4716 | __isl_keep isl_basic_map *model) |
||
4717 | { |
||
4718 | if (!model) |
||
4719 | return NULL; |
||
4720 | return isl_basic_map_alloc_space(isl_space_copy(model->dim), 0, 0, 0); |
||
4721 | } |
||
4722 | |||
4723 | struct isl_basic_set *isl_basic_set_universe_like(struct isl_basic_set *model) |
||
4724 | { |
||
4725 | if (!model) |
||
4726 | return NULL; |
||
4727 | return isl_basic_set_alloc_space(isl_space_copy(model->dim), 0, 0, 0); |
||
4728 | } |
||
4729 | |||
4730 | __isl_give isl_basic_set *isl_basic_set_universe_like_set( |
||
4731 | __isl_keep isl_set *model) |
||
4732 | { |
||
4733 | if (!model) |
||
4734 | return NULL; |
||
4735 | return isl_basic_set_alloc_space(isl_space_copy(model->dim), 0, 0, 0); |
||
4736 | } |
||
4737 | |||
4738 | __isl_give isl_map *isl_map_empty(__isl_take isl_space *dim) |
||
4739 | { |
||
4740 | return isl_map_alloc_space(dim, 0, ISL_MAP_DISJOINT); |
||
4741 | } |
||
4742 | |||
4743 | struct isl_map *isl_map_empty_like(struct isl_map *model) |
||
4744 | { |
||
4745 | if (!model) |
||
4746 | return NULL; |
||
4747 | return isl_map_alloc_space(isl_space_copy(model->dim), 0, ISL_MAP_DISJOINT); |
||
4748 | } |
||
4749 | |||
4750 | struct isl_map *isl_map_empty_like_basic_map(struct isl_basic_map *model) |
||
4751 | { |
||
4752 | if (!model) |
||
4753 | return NULL; |
||
4754 | return isl_map_alloc_space(isl_space_copy(model->dim), 0, ISL_MAP_DISJOINT); |
||
4755 | } |
||
4756 | |||
4757 | __isl_give isl_set *isl_set_empty(__isl_take isl_space *dim) |
||
4758 | { |
||
4759 | return isl_set_alloc_space(dim, 0, ISL_MAP_DISJOINT); |
||
4760 | } |
||
4761 | |||
4762 | struct isl_set *isl_set_empty_like(struct isl_set *model) |
||
4763 | { |
||
4764 | if (!model) |
||
4765 | return NULL; |
||
4766 | return isl_set_empty(isl_space_copy(model->dim)); |
||
4767 | } |
||
4768 | |||
4769 | __isl_give isl_map *isl_map_universe(__isl_take isl_space *dim) |
||
4770 | { |
||
4771 | struct isl_map *map; |
||
4772 | if (!dim) |
||
4773 | return NULL; |
||
4774 | map = isl_map_alloc_space(isl_space_copy(dim), 1, ISL_MAP_DISJOINT); |
||
4775 | map = isl_map_add_basic_map(map, isl_basic_map_universe(dim)); |
||
4776 | return map; |
||
4777 | } |
||
4778 | |||
4779 | __isl_give isl_set *isl_set_universe(__isl_take isl_space *dim) |
||
4780 | { |
||
4781 | struct isl_set *set; |
||
4782 | if (!dim) |
||
4783 | return NULL; |
||
4784 | set = isl_set_alloc_space(isl_space_copy(dim), 1, ISL_MAP_DISJOINT); |
||
4785 | set = isl_set_add_basic_set(set, isl_basic_set_universe(dim)); |
||
4786 | return set; |
||
4787 | } |
||
4788 | |||
4789 | __isl_give isl_set *isl_set_universe_like(__isl_keep isl_set *model) |
||
4790 | { |
||
4791 | if (!model) |
||
4792 | return NULL; |
||
4793 | return isl_set_universe(isl_space_copy(model->dim)); |
||
4794 | } |
||
4795 | |||
4796 | struct isl_map *isl_map_dup(struct isl_map *map) |
||
4797 | { |
||
4798 | int i; |
||
4799 | struct isl_map *dup; |
||
4800 | |||
4801 | if (!map) |
||
4802 | return NULL; |
||
4803 | dup = isl_map_alloc_space(isl_space_copy(map->dim), map->n, map->flags); |
||
4804 | for (i = 0; i < map->n; ++i) |
||
4805 | dup = isl_map_add_basic_map(dup, isl_basic_map_copy(map->p[i])); |
||
4806 | return dup; |
||
4807 | } |
||
4808 | |||
4809 | __isl_give isl_map *isl_map_add_basic_map(__isl_take isl_map *map, |
||
4810 | __isl_take isl_basic_map *bmap) |
||
4811 | { |
||
4812 | if (!bmap || !map) |
||
4813 | goto error; |
||
4814 | if (isl_basic_map_plain_is_empty(bmap)) { |
||
4815 | isl_basic_map_free(bmap); |
||
4816 | return map; |
||
4817 | } |
||
4818 | isl_assert(map->ctx, isl_space_is_equal(map->dim, bmap->dim), goto error); |
||
4819 | isl_assert(map->ctx, map->n < map->size, goto error); |
||
4820 | map->p[map->n] = bmap; |
||
4821 | map->n++; |
||
4822 | ISL_F_CLR(map, ISL_MAP_NORMALIZED); |
||
4823 | return map; |
||
4824 | error: |
||
4825 | if (map) |
||
4826 | isl_map_free(map); |
||
4827 | if (bmap) |
||
4828 | isl_basic_map_free(bmap); |
||
4829 | return NULL; |
||
4830 | } |
||
4831 | |||
4832 | void isl_map_free(struct isl_map *map) |
||
4833 | { |
||
4834 | int i; |
||
4835 | |||
4836 | if (!map) |
||
4837 | return; |
||
4838 | |||
4839 | if (--map->ref > 0) |
||
4840 | return; |
||
4841 | |||
4842 | isl_ctx_deref(map->ctx); |
||
4843 | for (i = 0; i < map->n; ++i) |
||
4844 | isl_basic_map_free(map->p[i]); |
||
4845 | isl_space_free(map->dim); |
||
4846 | free(map); |
||
4847 | } |
||
4848 | |||
4849 | struct isl_map *isl_map_extend(struct isl_map *base, |
||
4850 | unsigned nparam, unsigned n_in, unsigned n_out) |
||
4851 | { |
||
4852 | int i; |
||
4853 | |||
4854 | base = isl_map_cow(base); |
||
4855 | if (!base) |
||
4856 | return NULL; |
||
4857 | |||
4858 | base->dim = isl_space_extend(base->dim, nparam, n_in, n_out); |
||
4859 | if (!base->dim) |
||
4860 | goto error; |
||
4861 | for (i = 0; i < base->n; ++i) { |
||
4862 | base->p[i] = isl_basic_map_extend_space(base->p[i], |
||
4863 | isl_space_copy(base->dim), 0, 0, 0); |
||
4864 | if (!base->p[i]) |
||
4865 | goto error; |
||
4866 | } |
||
4867 | return base; |
||
4868 | error: |
||
4869 | isl_map_free(base); |
||
4870 | return NULL; |
||
4871 | } |
||
4872 | |||
4873 | struct isl_set *isl_set_extend(struct isl_set *base, |
||
4874 | unsigned nparam, unsigned dim) |
||
4875 | { |
||
4876 | return (struct isl_set *)isl_map_extend((struct isl_map *)base, |
||
4877 | nparam, 0, dim); |
||
4878 | } |
||
4879 | |||
4880 | static struct isl_basic_map *isl_basic_map_fix_pos_si( |
||
4881 | struct isl_basic_map *bmap, unsigned pos, int value) |
||
4882 | { |
||
4883 | int j; |
||
4884 | |||
4885 | bmap = isl_basic_map_cow(bmap); |
||
4886 | bmap = isl_basic_map_extend_constraints(bmap, 1, 0); |
||
4887 | j = isl_basic_map_alloc_equality(bmap); |
||
4888 | if (j < 0) |
||
4889 | goto error; |
||
4890 | isl_seq_clr(bmap->eq[j] + 1, isl_basic_map_total_dim(bmap)); |
||
4891 | isl_int_set_si(bmap->eq[j][pos], -1); |
||
4892 | isl_int_set_si(bmap->eq[j][0], value); |
||
4893 | bmap = isl_basic_map_simplify(bmap); |
||
4894 | return isl_basic_map_finalize(bmap); |
||
4895 | error: |
||
4896 | isl_basic_map_free(bmap); |
||
4897 | return NULL; |
||
4898 | } |
||
4899 | |||
4900 | static __isl_give isl_basic_map *isl_basic_map_fix_pos( |
||
4901 | __isl_take isl_basic_map *bmap, unsigned pos, isl_int value) |
||
4902 | { |
||
4903 | int j; |
||
4904 | |||
4905 | bmap = isl_basic_map_cow(bmap); |
||
4906 | bmap = isl_basic_map_extend_constraints(bmap, 1, 0); |
||
4907 | j = isl_basic_map_alloc_equality(bmap); |
||
4908 | if (j < 0) |
||
4909 | goto error; |
||
4910 | isl_seq_clr(bmap->eq[j] + 1, isl_basic_map_total_dim(bmap)); |
||
4911 | isl_int_set_si(bmap->eq[j][pos], -1); |
||
4912 | isl_int_set(bmap->eq[j][0], value); |
||
4913 | bmap = isl_basic_map_simplify(bmap); |
||
4914 | return isl_basic_map_finalize(bmap); |
||
4915 | error: |
||
4916 | isl_basic_map_free(bmap); |
||
4917 | return NULL; |
||
4918 | } |
||
4919 | |||
4920 | struct isl_basic_map *isl_basic_map_fix_si(struct isl_basic_map *bmap, |
||
4921 | enum isl_dim_type type, unsigned pos, int value) |
||
4922 | { |
||
4923 | if (!bmap) |
||
4924 | return NULL; |
||
4925 | isl_assert(bmap->ctx, pos < isl_basic_map_dim(bmap, type), goto error); |
||
4926 | return isl_basic_map_fix_pos_si(bmap, |
||
4927 | isl_basic_map_offset(bmap, type) + pos, value); |
||
4928 | error: |
||
4929 | isl_basic_map_free(bmap); |
||
4930 | return NULL; |
||
4931 | } |
||
4932 | |||
4933 | __isl_give isl_basic_map *isl_basic_map_fix(__isl_take isl_basic_map *bmap, |
||
4934 | enum isl_dim_type type, unsigned pos, isl_int value) |
||
4935 | { |
||
4936 | if (!bmap) |
||
4937 | return NULL; |
||
4938 | isl_assert(bmap->ctx, pos < isl_basic_map_dim(bmap, type), goto error); |
||
4939 | return isl_basic_map_fix_pos(bmap, |
||
4940 | isl_basic_map_offset(bmap, type) + pos, value); |
||
4941 | error: |
||
4942 | isl_basic_map_free(bmap); |
||
4943 | return NULL; |
||
4944 | } |
||
4945 | |||
4946 | struct isl_basic_set *isl_basic_set_fix_si(struct isl_basic_set *bset, |
||
4947 | enum isl_dim_type type, unsigned pos, int value) |
||
4948 | { |
||
4949 | return (struct isl_basic_set *) |
||
4950 | isl_basic_map_fix_si((struct isl_basic_map *)bset, |
||
4951 | type, pos, value); |
||
4952 | } |
||
4953 | |||
4954 | __isl_give isl_basic_set *isl_basic_set_fix(__isl_take isl_basic_set *bset, |
||
4955 | enum isl_dim_type type, unsigned pos, isl_int value) |
||
4956 | { |
||
4957 | return (struct isl_basic_set *) |
||
4958 | isl_basic_map_fix((struct isl_basic_map *)bset, |
||
4959 | type, pos, value); |
||
4960 | } |
||
4961 | |||
4962 | struct isl_basic_map *isl_basic_map_fix_input_si(struct isl_basic_map *bmap, |
||
4963 | unsigned input, int value) |
||
4964 | { |
||
4965 | return isl_basic_map_fix_si(bmap, isl_dim_in, input, value); |
||
4966 | } |
||
4967 | |||
4968 | struct isl_basic_set *isl_basic_set_fix_dim_si(struct isl_basic_set *bset, |
||
4969 | unsigned dim, int value) |
||
4970 | { |
||
4971 | return (struct isl_basic_set *) |
||
4972 | isl_basic_map_fix_si((struct isl_basic_map *)bset, |
||
4973 | isl_dim_set, dim, value); |
||
4974 | } |
||
4975 | |||
4976 | static int remove_if_empty(__isl_keep isl_map *map, int i) |
||
4977 | { |
||
4978 | int empty = isl_basic_map_plain_is_empty(map->p[i]); |
||
4979 | |||
4980 | if (empty < 0) |
||
4981 | return -1; |
||
4982 | if (!empty) |
||
4983 | return 0; |
||
4984 | |||
4985 | isl_basic_map_free(map->p[i]); |
||
4986 | if (i != map->n - 1) { |
||
4987 | ISL_F_CLR(map, ISL_MAP_NORMALIZED); |
||
4988 | map->p[i] = map->p[map->n - 1]; |
||
4989 | } |
||
4990 | map->n--; |
||
4991 | |||
4992 | return 0; |
||
4993 | } |
||
4994 | |||
4995 | struct isl_map *isl_map_fix_si(struct isl_map *map, |
||
4996 | enum isl_dim_type type, unsigned pos, int value) |
||
4997 | { |
||
4998 | int i; |
||
4999 | |||
5000 | map = isl_map_cow(map); |
||
5001 | if (!map) |
||
5002 | return NULL; |
||
5003 | |||
5004 | isl_assert(map->ctx, pos < isl_map_dim(map, type), goto error); |
||
5005 | for (i = map->n - 1; i >= 0; --i) { |
||
5006 | map->p[i] = isl_basic_map_fix_si(map->p[i], type, pos, value); |
||
5007 | if (remove_if_empty(map, i) < 0) |
||
5008 | goto error; |
||
5009 | } |
||
5010 | ISL_F_CLR(map, ISL_MAP_NORMALIZED); |
||
5011 | return map; |
||
5012 | error: |
||
5013 | isl_map_free(map); |
||
5014 | return NULL; |
||
5015 | } |
||
5016 | |||
5017 | __isl_give isl_set *isl_set_fix_si(__isl_take isl_set *set, |
||
5018 | enum isl_dim_type type, unsigned pos, int value) |
||
5019 | { |
||
5020 | return (struct isl_set *) |
||
5021 | isl_map_fix_si((struct isl_map *)set, type, pos, value); |
||
5022 | } |
||
5023 | |||
5024 | __isl_give isl_map *isl_map_fix(__isl_take isl_map *map, |
||
5025 | enum isl_dim_type type, unsigned pos, isl_int value) |
||
5026 | { |
||
5027 | int i; |
||
5028 | |||
5029 | map = isl_map_cow(map); |
||
5030 | if (!map) |
||
5031 | return NULL; |
||
5032 | |||
5033 | isl_assert(map->ctx, pos < isl_map_dim(map, type), goto error); |
||
5034 | for (i = 0; i < map->n; ++i) { |
||
5035 | map->p[i] = isl_basic_map_fix(map->p[i], type, pos, value); |
||
5036 | if (!map->p[i]) |
||
5037 | goto error; |
||
5038 | } |
||
5039 | ISL_F_CLR(map, ISL_MAP_NORMALIZED); |
||
5040 | return map; |
||
5041 | error: |
||
5042 | isl_map_free(map); |
||
5043 | return NULL; |
||
5044 | } |
||
5045 | |||
5046 | __isl_give isl_set *isl_set_fix(__isl_take isl_set *set, |
||
5047 | enum isl_dim_type type, unsigned pos, isl_int value) |
||
5048 | { |
||
5049 | return (struct isl_set *)isl_map_fix((isl_map *)set, type, pos, value); |
||
5050 | } |
||
5051 | |||
5052 | struct isl_map *isl_map_fix_input_si(struct isl_map *map, |
||
5053 | unsigned input, int value) |
||
5054 | { |
||
5055 | return isl_map_fix_si(map, isl_dim_in, input, value); |
||
5056 | } |
||
5057 | |||
5058 | struct isl_set *isl_set_fix_dim_si(struct isl_set *set, unsigned dim, int value) |
||
5059 | { |
||
5060 | return (struct isl_set *) |
||
5061 | isl_map_fix_si((struct isl_map *)set, isl_dim_set, dim, value); |
||
5062 | } |
||
5063 | |||
5064 | static __isl_give isl_basic_map *basic_map_bound_si( |
||
5065 | __isl_take isl_basic_map *bmap, |
||
5066 | enum isl_dim_type type, unsigned pos, int value, int upper) |
||
5067 | { |
||
5068 | int j; |
||
5069 | |||
5070 | if (!bmap) |
||
5071 | return NULL; |
||
5072 | isl_assert(bmap->ctx, pos < isl_basic_map_dim(bmap, type), goto error); |
||
5073 | pos += isl_basic_map_offset(bmap, type); |
||
5074 | bmap = isl_basic_map_cow(bmap); |
||
5075 | bmap = isl_basic_map_extend_constraints(bmap, 0, 1); |
||
5076 | j = isl_basic_map_alloc_inequality(bmap); |
||
5077 | if (j < 0) |
||
5078 | goto error; |
||
5079 | isl_seq_clr(bmap->ineq[j], 1 + isl_basic_map_total_dim(bmap)); |
||
5080 | if (upper) { |
||
5081 | isl_int_set_si(bmap->ineq[j][pos], -1); |
||
5082 | isl_int_set_si(bmap->ineq[j][0], value); |
||
5083 | } else { |
||
5084 | isl_int_set_si(bmap->ineq[j][pos], 1); |
||
5085 | isl_int_set_si(bmap->ineq[j][0], -value); |
||
5086 | } |
||
5087 | bmap = isl_basic_map_simplify(bmap); |
||
5088 | return isl_basic_map_finalize(bmap); |
||
5089 | error: |
||
5090 | isl_basic_map_free(bmap); |
||
5091 | return NULL; |
||
5092 | } |
||
5093 | |||
5094 | __isl_give isl_basic_map *isl_basic_map_lower_bound_si( |
||
5095 | __isl_take isl_basic_map *bmap, |
||
5096 | enum isl_dim_type type, unsigned pos, int value) |
||
5097 | { |
||
5098 | return basic_map_bound_si(bmap, type, pos, value, 0); |
||
5099 | } |
||
5100 | |||
5101 | struct isl_basic_set *isl_basic_set_lower_bound_dim(struct isl_basic_set *bset, |
||
5102 | unsigned dim, isl_int value) |
||
5103 | { |
||
5104 | int j; |
||
5105 | |||
5106 | bset = isl_basic_set_cow(bset); |
||
5107 | bset = isl_basic_set_extend_constraints(bset, 0, 1); |
||
5108 | j = isl_basic_set_alloc_inequality(bset); |
||
5109 | if (j < 0) |
||
5110 | goto error; |
||
5111 | isl_seq_clr(bset->ineq[j], 1 + isl_basic_set_total_dim(bset)); |
||
5112 | isl_int_set_si(bset->ineq[j][1 + isl_basic_set_n_param(bset) + dim], 1); |
||
5113 | isl_int_neg(bset->ineq[j][0], value); |
||
5114 | bset = isl_basic_set_simplify(bset); |
||
5115 | return isl_basic_set_finalize(bset); |
||
5116 | error: |
||
5117 | isl_basic_set_free(bset); |
||
5118 | return NULL; |
||
5119 | } |
||
5120 | |||
5121 | static __isl_give isl_map *map_bound_si(__isl_take isl_map *map, |
||
5122 | enum isl_dim_type type, unsigned pos, int value, int upper) |
||
5123 | { |
||
5124 | int i; |
||
5125 | |||
5126 | map = isl_map_cow(map); |
||
5127 | if (!map) |
||
5128 | return NULL; |
||
5129 | |||
5130 | isl_assert(map->ctx, pos < isl_map_dim(map, type), goto error); |
||
5131 | for (i = 0; i < map->n; ++i) { |
||
5132 | map->p[i] = basic_map_bound_si(map->p[i], |
||
5133 | type, pos, value, upper); |
||
5134 | if (!map->p[i]) |
||
5135 | goto error; |
||
5136 | } |
||
5137 | ISL_F_CLR(map, ISL_MAP_NORMALIZED); |
||
5138 | return map; |
||
5139 | error: |
||
5140 | isl_map_free(map); |
||
5141 | return NULL; |
||
5142 | } |
||
5143 | |||
5144 | __isl_give isl_map *isl_map_lower_bound_si(__isl_take isl_map *map, |
||
5145 | enum isl_dim_type type, unsigned pos, int value) |
||
5146 | { |
||
5147 | return map_bound_si(map, type, pos, value, 0); |
||
5148 | } |
||
5149 | |||
5150 | __isl_give isl_map *isl_map_upper_bound_si(__isl_take isl_map *map, |
||
5151 | enum isl_dim_type type, unsigned pos, int value) |
||
5152 | { |
||
5153 | return map_bound_si(map, type, pos, value, 1); |
||
5154 | } |
||
5155 | |||
5156 | __isl_give isl_set *isl_set_lower_bound_si(__isl_take isl_set *set, |
||
5157 | enum isl_dim_type type, unsigned pos, int value) |
||
5158 | { |
||
5159 | return (struct isl_set *) |
||
5160 | isl_map_lower_bound_si((struct isl_map *)set, type, pos, value); |
||
5161 | } |
||
5162 | |||
5163 | __isl_give isl_set *isl_set_upper_bound_si(__isl_take isl_set *set, |
||
5164 | enum isl_dim_type type, unsigned pos, int value) |
||
5165 | { |
||
5166 | return isl_map_upper_bound_si(set, type, pos, value); |
||
5167 | } |
||
5168 | |||
5169 | /* Bound the given variable of "bmap" from below (or above is "upper" |
||
5170 | * is set) to "value". |
||
5171 | */ |
||
5172 | static __isl_give isl_basic_map *basic_map_bound( |
||
5173 | __isl_take isl_basic_map *bmap, |
||
5174 | enum isl_dim_type type, unsigned pos, isl_int value, int upper) |
||
5175 | { |
||
5176 | int j; |
||
5177 | |||
5178 | if (!bmap) |
||
5179 | return NULL; |
||
5180 | if (pos >= isl_basic_map_dim(bmap, type)) |
||
5181 | isl_die(bmap->ctx, isl_error_invalid, |
||
5182 | "index out of bounds", goto error); |
||
5183 | pos += isl_basic_map_offset(bmap, type); |
||
5184 | bmap = isl_basic_map_cow(bmap); |
||
5185 | bmap = isl_basic_map_extend_constraints(bmap, 0, 1); |
||
5186 | j = isl_basic_map_alloc_inequality(bmap); |
||
5187 | if (j < 0) |
||
5188 | goto error; |
||
5189 | isl_seq_clr(bmap->ineq[j], 1 + isl_basic_map_total_dim(bmap)); |
||
5190 | if (upper) { |
||
5191 | isl_int_set_si(bmap->ineq[j][pos], -1); |
||
5192 | isl_int_set(bmap->ineq[j][0], value); |
||
5193 | } else { |
||
5194 | isl_int_set_si(bmap->ineq[j][pos], 1); |
||
5195 | isl_int_neg(bmap->ineq[j][0], value); |
||
5196 | } |
||
5197 | bmap = isl_basic_map_simplify(bmap); |
||
5198 | return isl_basic_map_finalize(bmap); |
||
5199 | error: |
||
5200 | isl_basic_map_free(bmap); |
||
5201 | return NULL; |
||
5202 | } |
||
5203 | |||
5204 | /* Bound the given variable of "map" from below (or above is "upper" |
||
5205 | * is set) to "value". |
||
5206 | */ |
||
5207 | static __isl_give isl_map *map_bound(__isl_take isl_map *map, |
||
5208 | enum isl_dim_type type, unsigned pos, isl_int value, int upper) |
||
5209 | { |
||
5210 | int i; |
||
5211 | |||
5212 | map = isl_map_cow(map); |
||
5213 | if (!map) |
||
5214 | return NULL; |
||
5215 | |||
5216 | if (pos >= isl_map_dim(map, type)) |
||
5217 | isl_die(map->ctx, isl_error_invalid, |
||
5218 | "index out of bounds", goto error); |
||
5219 | for (i = map->n - 1; i >= 0; --i) { |
||
5220 | map->p[i] = basic_map_bound(map->p[i], type, pos, value, upper); |
||
5221 | if (remove_if_empty(map, i) < 0) |
||
5222 | goto error; |
||
5223 | } |
||
5224 | ISL_F_CLR(map, ISL_MAP_NORMALIZED); |
||
5225 | return map; |
||
5226 | error: |
||
5227 | isl_map_free(map); |
||
5228 | return NULL; |
||
5229 | } |
||
5230 | |||
5231 | __isl_give isl_map *isl_map_lower_bound(__isl_take isl_map *map, |
||
5232 | enum isl_dim_type type, unsigned pos, isl_int value) |
||
5233 | { |
||
5234 | return map_bound(map, type, pos, value, 0); |
||
5235 | } |
||
5236 | |||
5237 | __isl_give isl_map *isl_map_upper_bound(__isl_take isl_map *map, |
||
5238 | enum isl_dim_type type, unsigned pos, isl_int value) |
||
5239 | { |
||
5240 | return map_bound(map, type, pos, value, 1); |
||
5241 | } |
||
5242 | |||
5243 | __isl_give isl_set *isl_set_lower_bound(__isl_take isl_set *set, |
||
5244 | enum isl_dim_type type, unsigned pos, isl_int value) |
||
5245 | { |
||
5246 | return isl_map_lower_bound(set, type, pos, value); |
||
5247 | } |
||
5248 | |||
5249 | __isl_give isl_set *isl_set_upper_bound(__isl_take isl_set *set, |
||
5250 | enum isl_dim_type type, unsigned pos, isl_int value) |
||
5251 | { |
||
5252 | return isl_map_upper_bound(set, type, pos, value); |
||
5253 | } |
||
5254 | |||
5255 | struct isl_set *isl_set_lower_bound_dim(struct isl_set *set, unsigned dim, |
||
5256 | isl_int value) |
||
5257 | { |
||
5258 | int i; |
||
5259 | |||
5260 | set = isl_set_cow(set); |
||
5261 | if (!set) |
||
5262 | return NULL; |
||
5263 | |||
5264 | isl_assert(set->ctx, dim < isl_set_n_dim(set), goto error); |
||
5265 | for (i = 0; i < set->n; ++i) { |
||
5266 | set->p[i] = isl_basic_set_lower_bound_dim(set->p[i], dim, value); |
||
5267 | if (!set->p[i]) |
||
5268 | goto error; |
||
5269 | } |
||
5270 | return set; |
||
5271 | error: |
||
5272 | isl_set_free(set); |
||
5273 | return NULL; |
||
5274 | } |
||
5275 | |||
5276 | struct isl_map *isl_map_reverse(struct isl_map *map) |
||
5277 | { |
||
5278 | int i; |
||
5279 | |||
5280 | map = isl_map_cow(map); |
||
5281 | if (!map) |
||
5282 | return NULL; |
||
5283 | |||
5284 | map->dim = isl_space_reverse(map->dim); |
||
5285 | if (!map->dim) |
||
5286 | goto error; |
||
5287 | for (i = 0; i < map->n; ++i) { |
||
5288 | map->p[i] = isl_basic_map_reverse(map->p[i]); |
||
5289 | if (!map->p[i]) |
||
5290 | goto error; |
||
5291 | } |
||
5292 | ISL_F_CLR(map, ISL_MAP_NORMALIZED); |
||
5293 | return map; |
||
5294 | error: |
||
5295 | isl_map_free(map); |
||
5296 | return NULL; |
||
5297 | } |
||
5298 | |||
5299 | static struct isl_map *isl_basic_map_partial_lexopt( |
||
5300 | struct isl_basic_map *bmap, struct isl_basic_set *dom, |
||
5301 | struct isl_set **empty, int max) |
||
5302 | { |
||
5303 | if (!bmap) |
||
5304 | goto error; |
||
5305 | if (bmap->ctx->opt->pip == ISL_PIP_PIP) |
||
5306 | return isl_pip_basic_map_lexopt(bmap, dom, empty, max); |
||
5307 | else |
||
5308 | return isl_tab_basic_map_partial_lexopt(bmap, dom, empty, max); |
||
5309 | error: |
||
5310 | isl_basic_map_free(bmap); |
||
5311 | isl_basic_set_free(dom); |
||
5312 | if (empty) |
||
5313 | *empty = NULL; |
||
5314 | return NULL; |
||
5315 | } |
||
5316 | |||
5317 | struct isl_map *isl_basic_map_partial_lexmax( |
||
5318 | struct isl_basic_map *bmap, struct isl_basic_set *dom, |
||
5319 | struct isl_set **empty) |
||
5320 | { |
||
5321 | return isl_basic_map_partial_lexopt(bmap, dom, empty, 1); |
||
5322 | } |
||
5323 | |||
5324 | struct isl_map *isl_basic_map_partial_lexmin( |
||
5325 | struct isl_basic_map *bmap, struct isl_basic_set *dom, |
||
5326 | struct isl_set **empty) |
||
5327 | { |
||
5328 | return isl_basic_map_partial_lexopt(bmap, dom, empty, 0); |
||
5329 | } |
||
5330 | |||
5331 | struct isl_set *isl_basic_set_partial_lexmin( |
||
5332 | struct isl_basic_set *bset, struct isl_basic_set *dom, |
||
5333 | struct isl_set **empty) |
||
5334 | { |
||
5335 | return (struct isl_set *) |
||
5336 | isl_basic_map_partial_lexmin((struct isl_basic_map *)bset, |
||
5337 | dom, empty); |
||
5338 | } |
||
5339 | |||
5340 | struct isl_set *isl_basic_set_partial_lexmax( |
||
5341 | struct isl_basic_set *bset, struct isl_basic_set *dom, |
||
5342 | struct isl_set **empty) |
||
5343 | { |
||
5344 | return (struct isl_set *) |
||
5345 | isl_basic_map_partial_lexmax((struct isl_basic_map *)bset, |
||
5346 | dom, empty); |
||
5347 | } |
||
5348 | |||
5349 | __isl_give isl_pw_multi_aff *isl_basic_map_partial_lexmin_pw_multi_aff( |
||
5350 | __isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom, |
||
5351 | __isl_give isl_set **empty) |
||
5352 | { |
||
5353 | return isl_basic_map_partial_lexopt_pw_multi_aff(bmap, dom, empty, 0); |
||
5354 | } |
||
5355 | |||
5356 | __isl_give isl_pw_multi_aff *isl_basic_map_partial_lexmax_pw_multi_aff( |
||
5357 | __isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom, |
||
5358 | __isl_give isl_set **empty) |
||
5359 | { |
||
5360 | return isl_basic_map_partial_lexopt_pw_multi_aff(bmap, dom, empty, 1); |
||
5361 | } |
||
5362 | |||
5363 | __isl_give isl_pw_multi_aff *isl_basic_set_partial_lexmin_pw_multi_aff( |
||
5364 | __isl_take isl_basic_set *bset, __isl_take isl_basic_set *dom, |
||
5365 | __isl_give isl_set **empty) |
||
5366 | { |
||
5367 | return isl_basic_map_partial_lexmin_pw_multi_aff(bset, dom, empty); |
||
5368 | } |
||
5369 | |||
5370 | __isl_give isl_pw_multi_aff *isl_basic_set_partial_lexmax_pw_multi_aff( |
||
5371 | __isl_take isl_basic_set *bset, __isl_take isl_basic_set *dom, |
||
5372 | __isl_give isl_set **empty) |
||
5373 | { |
||
5374 | return isl_basic_map_partial_lexmax_pw_multi_aff(bset, dom, empty); |
||
5375 | } |
||
5376 | |||
5377 | __isl_give isl_pw_multi_aff *isl_basic_map_lexopt_pw_multi_aff( |
||
5378 | __isl_take isl_basic_map *bmap, int max) |
||
5379 | { |
||
5380 | isl_basic_set *dom = NULL; |
||
5381 | isl_space *dom_space; |
||
5382 | |||
5383 | if (!bmap) |
||
5384 | goto error; |
||
5385 | dom_space = isl_space_domain(isl_space_copy(bmap->dim)); |
||
5386 | dom = isl_basic_set_universe(dom_space); |
||
5387 | return isl_basic_map_partial_lexopt_pw_multi_aff(bmap, dom, NULL, max); |
||
5388 | error: |
||
5389 | isl_basic_map_free(bmap); |
||
5390 | return NULL; |
||
5391 | } |
||
5392 | |||
5393 | __isl_give isl_pw_multi_aff *isl_basic_map_lexmin_pw_multi_aff( |
||
5394 | __isl_take isl_basic_map *bmap) |
||
5395 | { |
||
5396 | return isl_basic_map_lexopt_pw_multi_aff(bmap, 0); |
||
5397 | } |
||
5398 | |||
5399 | /* Given a basic map "bmap", compute the lexicographically minimal |
||
5400 | * (or maximal) image element for each domain element in dom. |
||
5401 | * Set *empty to those elements in dom that do not have an image element. |
||
5402 | * |
||
5403 | * We first make sure the basic sets in dom are disjoint and then |
||
5404 | * simply collect the results over each of the basic sets separately. |
||
5405 | * We could probably improve the efficiency a bit by moving the union |
||
5406 | * domain down into the parametric integer programming. |
||
5407 | */ |
||
5408 | static __isl_give isl_map *basic_map_partial_lexopt( |
||
5409 | __isl_take isl_basic_map *bmap, __isl_take isl_set *dom, |
||
5410 | __isl_give isl_set **empty, int max) |
||
5411 | { |
||
5412 | int i; |
||
5413 | struct isl_map *res; |
||
5414 | |||
5415 | dom = isl_set_make_disjoint(dom); |
||
5416 | if (!dom) |
||
5417 | goto error; |
||
5418 | |||
5419 | if (isl_set_plain_is_empty(dom)) { |
||
5420 | res = isl_map_empty_like_basic_map(bmap); |
||
5421 | *empty = isl_set_empty_like(dom); |
||
5422 | isl_set_free(dom); |
||
5423 | isl_basic_map_free(bmap); |
||
5424 | return res; |
||
5425 | } |
||
5426 | |||
5427 | res = isl_basic_map_partial_lexopt(isl_basic_map_copy(bmap), |
||
5428 | isl_basic_set_copy(dom->p[0]), empty, max); |
||
5429 | |||
5430 | for (i = 1; i < dom->n; ++i) { |
||
5431 | struct isl_map *res_i; |
||
5432 | struct isl_set *empty_i; |
||
5433 | |||
5434 | res_i = isl_basic_map_partial_lexopt(isl_basic_map_copy(bmap), |
||
5435 | isl_basic_set_copy(dom->p[i]), &empty_i, max); |
||
5436 | |||
5437 | res = isl_map_union_disjoint(res, res_i); |
||
5438 | *empty = isl_set_union_disjoint(*empty, empty_i); |
||
5439 | } |
||
5440 | |||
5441 | isl_set_free(dom); |
||
5442 | isl_basic_map_free(bmap); |
||
5443 | return res; |
||
5444 | error: |
||
5445 | *empty = NULL; |
||
5446 | isl_set_free(dom); |
||
5447 | isl_basic_map_free(bmap); |
||
5448 | return NULL; |
||
5449 | } |
||
5450 | |||
5451 | /* Given a map "map", compute the lexicographically minimal |
||
5452 | * (or maximal) image element for each domain element in dom. |
||
5453 | * Set *empty to those elements in dom that do not have an image element. |
||
5454 | * |
||
5455 | * We first compute the lexicographically minimal or maximal element |
||
5456 | * in the first basic map. This results in a partial solution "res" |
||
5457 | * and a subset "todo" of dom that still need to be handled. |
||
5458 | * We then consider each of the remaining maps in "map" and successively |
||
5459 | * improve both "res" and "todo". |
||
5460 | * |
||
5461 | * Let res^k and todo^k be the results after k steps and let i = k + 1. |
||
5462 | * Assume we are computing the lexicographical maximum. |
||
5463 | * We first compute the lexicographically maximal element in basic map i. |
||
5464 | * This results in a partial solution res_i and a subset todo_i. |
||
5465 | * Then we combine these results with those obtain for the first k basic maps |
||
5466 | * to obtain a result that is valid for the first k+1 basic maps. |
||
5467 | * In particular, the set where there is no solution is the set where |
||
5468 | * there is no solution for the first k basic maps and also no solution |
||
5469 | * for the ith basic map, i.e., |
||
5470 | * |
||
5471 | * todo^i = todo^k * todo_i |
||
5472 | * |
||
5473 | * On dom(res^k) * dom(res_i), we need to pick the larger of the two |
||
5474 | * solutions, arbitrarily breaking ties in favor of res^k. |
||
5475 | * That is, when res^k(a) >= res_i(a), we pick res^k and |
||
5476 | * when res^k(a) < res_i(a), we pick res_i. (Here, ">=" and "<" denote |
||
5477 | * the lexicographic order.) |
||
5478 | * In practice, we compute |
||
5479 | * |
||
5480 | * res^k * (res_i . "<=") |
||
5481 | * |
||
5482 | * and |
||
5483 | * |
||
5484 | * res_i * (res^k . "<") |
||
5485 | * |
||
5486 | * Finally, we consider the symmetric difference of dom(res^k) and dom(res_i), |
||
5487 | * where only one of res^k and res_i provides a solution and we simply pick |
||
5488 | * that one, i.e., |
||
5489 | * |
||
5490 | * res^k * todo_i |
||
5491 | * and |
||
5492 | * res_i * todo^k |
||
5493 | * |
||
5494 | * Note that we only compute these intersections when dom(res^k) intersects |
||
5495 | * dom(res_i). Otherwise, the only effect of these intersections is to |
||
5496 | * potentially break up res^k and res_i into smaller pieces. |
||
5497 | * We want to avoid such splintering as much as possible. |
||
5498 | * In fact, an earlier implementation of this function would look for |
||
5499 | * better results in the domain of res^k and for extra results in todo^k, |
||
5500 | * but this would always result in a splintering according to todo^k, |
||
5501 | * even when the domain of basic map i is disjoint from the domains of |
||
5502 | * the previous basic maps. |
||
5503 | */ |
||
5504 | static __isl_give isl_map *isl_map_partial_lexopt_aligned( |
||
5505 | __isl_take isl_map *map, __isl_take isl_set *dom, |
||
5506 | __isl_give isl_set **empty, int max) |
||
5507 | { |
||
5508 | int i; |
||
5509 | struct isl_map *res; |
||
5510 | struct isl_set *todo; |
||
5511 | |||
5512 | if (!map || !dom) |
||
5513 | goto error; |
||
5514 | |||
5515 | if (isl_map_plain_is_empty(map)) { |
||
5516 | if (empty) |
||
5517 | *empty = dom; |
||
5518 | else |
||
5519 | isl_set_free(dom); |
||
5520 | return map; |
||
5521 | } |
||
5522 | |||
5523 | res = basic_map_partial_lexopt(isl_basic_map_copy(map->p[0]), |
||
5524 | isl_set_copy(dom), &todo, max); |
||
5525 | |||
5526 | for (i = 1; i < map->n; ++i) { |
||
5527 | isl_map *lt, *le; |
||
5528 | isl_map *res_i; |
||
5529 | isl_set *todo_i; |
||
5530 | isl_space *dim = isl_space_range(isl_map_get_space(res)); |
||
5531 | |||
5532 | res_i = basic_map_partial_lexopt(isl_basic_map_copy(map->p[i]), |
||
5533 | isl_set_copy(dom), &todo_i, max); |
||
5534 | |||
5535 | if (max) { |
||
5536 | lt = isl_map_lex_lt(isl_space_copy(dim)); |
||
5537 | le = isl_map_lex_le(dim); |
||
5538 | } else { |
||
5539 | lt = isl_map_lex_gt(isl_space_copy(dim)); |
||
5540 | le = isl_map_lex_ge(dim); |
||
5541 | } |
||
5542 | lt = isl_map_apply_range(isl_map_copy(res), lt); |
||
5543 | lt = isl_map_intersect(lt, isl_map_copy(res_i)); |
||
5544 | le = isl_map_apply_range(isl_map_copy(res_i), le); |
||
5545 | le = isl_map_intersect(le, isl_map_copy(res)); |
||
5546 | |||
5547 | if (!isl_map_is_empty(lt) || !isl_map_is_empty(le)) { |
||
5548 | res = isl_map_intersect_domain(res, |
||
5549 | isl_set_copy(todo_i)); |
||
5550 | res_i = isl_map_intersect_domain(res_i, |
||
5551 | isl_set_copy(todo)); |
||
5552 | } |
||
5553 | |||
5554 | res = isl_map_union_disjoint(res, res_i); |
||
5555 | res = isl_map_union_disjoint(res, lt); |
||
5556 | res = isl_map_union_disjoint(res, le); |
||
5557 | |||
5558 | todo = isl_set_intersect(todo, todo_i); |
||
5559 | } |
||
5560 | |||
5561 | isl_set_free(dom); |
||
5562 | isl_map_free(map); |
||
5563 | |||
5564 | if (empty) |
||
5565 | *empty = todo; |
||
5566 | else |
||
5567 | isl_set_free(todo); |
||
5568 | |||
5569 | return res; |
||
5570 | error: |
||
5571 | if (empty) |
||
5572 | *empty = NULL; |
||
5573 | isl_set_free(dom); |
||
5574 | isl_map_free(map); |
||
5575 | return NULL; |
||
5576 | } |
||
5577 | |||
5578 | /* Given a map "map", compute the lexicographically minimal |
||
5579 | * (or maximal) image element for each domain element in dom. |
||
5580 | * Set *empty to those elements in dom that do not have an image element. |
||
5581 | * |
||
5582 | * Align parameters if needed and then call isl_map_partial_lexopt_aligned. |
||
5583 | */ |
||
5584 | static __isl_give isl_map *isl_map_partial_lexopt( |
||
5585 | __isl_take isl_map *map, __isl_take isl_set *dom, |
||
5586 | __isl_give isl_set **empty, int max) |
||
5587 | { |
||
5588 | if (!map || !dom) |
||
5589 | goto error; |
||
5590 | if (isl_space_match(map->dim, isl_dim_param, dom->dim, isl_dim_param)) |
||
5591 | return isl_map_partial_lexopt_aligned(map, dom, empty, max); |
||
5592 | if (!isl_space_has_named_params(map->dim) || |
||
5593 | !isl_space_has_named_params(dom->dim)) |
||
5594 | isl_die(map->ctx, isl_error_invalid, |
||
5595 | "unaligned unnamed parameters", goto error); |
||
5596 | map = isl_map_align_params(map, isl_map_get_space(dom)); |
||
5597 | dom = isl_map_align_params(dom, isl_map_get_space(map)); |
||
5598 | return isl_map_partial_lexopt_aligned(map, dom, empty, max); |
||
5599 | error: |
||
5600 | if (empty) |
||
5601 | *empty = NULL; |
||
5602 | isl_set_free(dom); |
||
5603 | isl_map_free(map); |
||
5604 | return NULL; |
||
5605 | } |
||
5606 | |||
5607 | __isl_give isl_map *isl_map_partial_lexmax( |
||
5608 | __isl_take isl_map *map, __isl_take isl_set *dom, |
||
5609 | __isl_give isl_set **empty) |
||
5610 | { |
||
5611 | return isl_map_partial_lexopt(map, dom, empty, 1); |
||
5612 | } |
||
5613 | |||
5614 | __isl_give isl_map *isl_map_partial_lexmin( |
||
5615 | __isl_take isl_map *map, __isl_take isl_set *dom, |
||
5616 | __isl_give isl_set **empty) |
||
5617 | { |
||
5618 | return isl_map_partial_lexopt(map, dom, empty, 0); |
||
5619 | } |
||
5620 | |||
5621 | __isl_give isl_set *isl_set_partial_lexmin( |
||
5622 | __isl_take isl_set *set, __isl_take isl_set *dom, |
||
5623 | __isl_give isl_set **empty) |
||
5624 | { |
||
5625 | return (struct isl_set *) |
||
5626 | isl_map_partial_lexmin((struct isl_map *)set, |
||
5627 | dom, empty); |
||
5628 | } |
||
5629 | |||
5630 | __isl_give isl_set *isl_set_partial_lexmax( |
||
5631 | __isl_take isl_set *set, __isl_take isl_set *dom, |
||
5632 | __isl_give isl_set **empty) |
||
5633 | { |
||
5634 | return (struct isl_set *) |
||
5635 | isl_map_partial_lexmax((struct isl_map *)set, |
||
5636 | dom, empty); |
||
5637 | } |
||
5638 | |||
5639 | __isl_give isl_map *isl_basic_map_lexopt(__isl_take isl_basic_map *bmap, int max) |
||
5640 | { |
||
5641 | struct isl_basic_set *dom = NULL; |
||
5642 | isl_space *dom_dim; |
||
5643 | |||
5644 | if (!bmap) |
||
5645 | goto error; |
||
5646 | dom_dim = isl_space_domain(isl_space_copy(bmap->dim)); |
||
5647 | dom = isl_basic_set_universe(dom_dim); |
||
5648 | return isl_basic_map_partial_lexopt(bmap, dom, NULL, max); |
||
5649 | error: |
||
5650 | isl_basic_map_free(bmap); |
||
5651 | return NULL; |
||
5652 | } |
||
5653 | |||
5654 | __isl_give isl_map *isl_basic_map_lexmin(__isl_take isl_basic_map *bmap) |
||
5655 | { |
||
5656 | return isl_basic_map_lexopt(bmap, 0); |
||
5657 | } |
||
5658 | |||
5659 | __isl_give isl_map *isl_basic_map_lexmax(__isl_take isl_basic_map *bmap) |
||
5660 | { |
||
5661 | return isl_basic_map_lexopt(bmap, 1); |
||
5662 | } |
||
5663 | |||
5664 | __isl_give isl_set *isl_basic_set_lexmin(__isl_take isl_basic_set *bset) |
||
5665 | { |
||
5666 | return (isl_set *)isl_basic_map_lexmin((isl_basic_map *)bset); |
||
5667 | } |
||
5668 | |||
5669 | __isl_give isl_set *isl_basic_set_lexmax(__isl_take isl_basic_set *bset) |
||
5670 | { |
||
5671 | return (isl_set *)isl_basic_map_lexmax((isl_basic_map *)bset); |
||
5672 | } |
||
5673 | |||
5674 | __isl_give isl_map *isl_map_lexopt(__isl_take isl_map *map, int max) |
||
5675 | { |
||
5676 | struct isl_set *dom = NULL; |
||
5677 | isl_space *dom_dim; |
||
5678 | |||
5679 | if (!map) |
||
5680 | goto error; |
||
5681 | dom_dim = isl_space_domain(isl_space_copy(map->dim)); |
||
5682 | dom = isl_set_universe(dom_dim); |
||
5683 | return isl_map_partial_lexopt(map, dom, NULL, max); |
||
5684 | error: |
||
5685 | isl_map_free(map); |
||
5686 | return NULL; |
||
5687 | } |
||
5688 | |||
5689 | __isl_give isl_map *isl_map_lexmin(__isl_take isl_map *map) |
||
5690 | { |
||
5691 | return isl_map_lexopt(map, 0); |
||
5692 | } |
||
5693 | |||
5694 | __isl_give isl_map *isl_map_lexmax(__isl_take isl_map *map) |
||
5695 | { |
||
5696 | return isl_map_lexopt(map, 1); |
||
5697 | } |
||
5698 | |||
5699 | __isl_give isl_set *isl_set_lexmin(__isl_take isl_set *set) |
||
5700 | { |
||
5701 | return (isl_set *)isl_map_lexmin((isl_map *)set); |
||
5702 | } |
||
5703 | |||
5704 | __isl_give isl_set *isl_set_lexmax(__isl_take isl_set *set) |
||
5705 | { |
||
5706 | return (isl_set *)isl_map_lexmax((isl_map *)set); |
||
5707 | } |
||
5708 | |||
5709 | /* Extract the first and only affine expression from list |
||
5710 | * and then add it to *pwaff with the given dom. |
||
5711 | * This domain is known to be disjoint from other domains |
||
5712 | * because of the way isl_basic_map_foreach_lexmax works. |
||
5713 | */ |
||
5714 | static int update_dim_opt(__isl_take isl_basic_set *dom, |
||
5715 | __isl_take isl_aff_list *list, void *user) |
||
5716 | { |
||
5717 | isl_ctx *ctx = isl_basic_set_get_ctx(dom); |
||
5718 | isl_aff *aff; |
||
5719 | isl_pw_aff **pwaff = user; |
||
5720 | isl_pw_aff *pwaff_i; |
||
5721 | |||
5722 | if (isl_aff_list_n_aff(list) != 1) |
||
5723 | isl_die(ctx, isl_error_internal, |
||
5724 | "expecting single element list", goto error); |
||
5725 | |||
5726 | aff = isl_aff_list_get_aff(list, 0); |
||
5727 | pwaff_i = isl_pw_aff_alloc(isl_set_from_basic_set(dom), aff); |
||
5728 | |||
5729 | *pwaff = isl_pw_aff_add_disjoint(*pwaff, pwaff_i); |
||
5730 | |||
5731 | isl_aff_list_free(list); |
||
5732 | |||
5733 | return 0; |
||
5734 | error: |
||
5735 | isl_basic_set_free(dom); |
||
5736 | isl_aff_list_free(list); |
||
5737 | return -1; |
||
5738 | } |
||
5739 | |||
5740 | /* Given a basic map with one output dimension, compute the minimum or |
||
5741 | * maximum of that dimension as an isl_pw_aff. |
||
5742 | * |
||
5743 | * The isl_pw_aff is constructed by having isl_basic_map_foreach_lexopt |
||
5744 | * call update_dim_opt on each leaf of the result. |
||
5745 | */ |
||
5746 | static __isl_give isl_pw_aff *basic_map_dim_opt(__isl_keep isl_basic_map *bmap, |
||
5747 | int max) |
||
5748 | { |
||
5749 | isl_space *dim = isl_basic_map_get_space(bmap); |
||
5750 | isl_pw_aff *pwaff; |
||
5751 | int r; |
||
5752 | |||
5753 | dim = isl_space_from_domain(isl_space_domain(dim)); |
||
5754 | dim = isl_space_add_dims(dim, isl_dim_out, 1); |
||
5755 | pwaff = isl_pw_aff_empty(dim); |
||
5756 | |||
5757 | r = isl_basic_map_foreach_lexopt(bmap, max, &update_dim_opt, &pwaff); |
||
5758 | if (r < 0) |
||
5759 | return isl_pw_aff_free(pwaff); |
||
5760 | |||
5761 | return pwaff; |
||
5762 | } |
||
5763 | |||
5764 | /* Compute the minimum or maximum of the given output dimension |
||
5765 | * as a function of the parameters and the input dimensions, |
||
5766 | * but independently of the other output dimensions. |
||
5767 | * |
||
5768 | * We first project out the other output dimension and then compute |
||
5769 | * the "lexicographic" maximum in each basic map, combining the results |
||
5770 | * using isl_pw_aff_union_max. |
||
5771 | */ |
||
5772 | static __isl_give isl_pw_aff *map_dim_opt(__isl_take isl_map *map, int pos, |
||
5773 | int max) |
||
5774 | { |
||
5775 | int i; |
||
5776 | isl_pw_aff *pwaff; |
||
5777 | unsigned n_out; |
||
5778 | |||
5779 | n_out = isl_map_dim(map, isl_dim_out); |
||
5780 | map = isl_map_project_out(map, isl_dim_out, pos + 1, n_out - (pos + 1)); |
||
5781 | map = isl_map_project_out(map, isl_dim_out, 0, pos); |
||
5782 | if (!map) |
||
5783 | return NULL; |
||
5784 | |||
5785 | if (map->n == 0) { |
||
5786 | isl_space *dim = isl_map_get_space(map); |
||
5787 | dim = isl_space_domain(isl_space_from_range(dim)); |
||
5788 | isl_map_free(map); |
||
5789 | return isl_pw_aff_empty(dim); |
||
5790 | } |
||
5791 | |||
5792 | pwaff = basic_map_dim_opt(map->p[0], max); |
||
5793 | for (i = 1; i < map->n; ++i) { |
||
5794 | isl_pw_aff *pwaff_i; |
||
5795 | |||
5796 | pwaff_i = basic_map_dim_opt(map->p[i], max); |
||
5797 | pwaff = isl_pw_aff_union_opt(pwaff, pwaff_i, max); |
||
5798 | } |
||
5799 | |||
5800 | isl_map_free(map); |
||
5801 | |||
5802 | return pwaff; |
||
5803 | } |
||
5804 | |||
5805 | /* Compute the maximum of the given output dimension as a function of the |
||
5806 | * parameters and input dimensions, but independently of |
||
5807 | * the other output dimensions. |
||
5808 | */ |
||
5809 | __isl_give isl_pw_aff *isl_map_dim_max(__isl_take isl_map *map, int pos) |
||
5810 | { |
||
5811 | return map_dim_opt(map, pos, 1); |
||
5812 | } |
||
5813 | |||
5814 | /* Compute the minimum or maximum of the given set dimension |
||
5815 | * as a function of the parameters, |
||
5816 | * but independently of the other set dimensions. |
||
5817 | */ |
||
5818 | static __isl_give isl_pw_aff *set_dim_opt(__isl_take isl_set *set, int pos, |
||
5819 | int max) |
||
5820 | { |
||
5821 | return map_dim_opt(set, pos, max); |
||
5822 | } |
||
5823 | |||
5824 | /* Compute the maximum of the given set dimension as a function of the |
||
5825 | * parameters, but independently of the other set dimensions. |
||
5826 | */ |
||
5827 | __isl_give isl_pw_aff *isl_set_dim_max(__isl_take isl_set *set, int pos) |
||
5828 | { |
||
5829 | return set_dim_opt(set, pos, 1); |
||
5830 | } |
||
5831 | |||
5832 | /* Compute the minimum of the given set dimension as a function of the |
||
5833 | * parameters, but independently of the other set dimensions. |
||
5834 | */ |
||
5835 | __isl_give isl_pw_aff *isl_set_dim_min(__isl_take isl_set *set, int pos) |
||
5836 | { |
||
5837 | return set_dim_opt(set, pos, 0); |
||
5838 | } |
||
5839 | |||
5840 | /* Apply a preimage specified by "mat" on the parameters of "bset". |
||
5841 | * bset is assumed to have only parameters and divs. |
||
5842 | */ |
||
5843 | static struct isl_basic_set *basic_set_parameter_preimage( |
||
5844 | struct isl_basic_set *bset, struct isl_mat *mat) |
||
5845 | { |
||
5846 | unsigned nparam; |
||
5847 | |||
5848 | if (!bset || !mat) |
||
5849 | goto error; |
||
5850 | |||
5851 | bset->dim = isl_space_cow(bset->dim); |
||
5852 | if (!bset->dim) |
||
5853 | goto error; |
||
5854 | |||
5855 | nparam = isl_basic_set_dim(bset, isl_dim_param); |
||
5856 | |||
5857 | isl_assert(bset->ctx, mat->n_row == 1 + nparam, goto error); |
||
5858 | |||
5859 | bset->dim->nparam = 0; |
||
5860 | bset->dim->n_out = nparam; |
||
5861 | bset = isl_basic_set_preimage(bset, mat); |
||
5862 | if (bset) { |
||
5863 | bset->dim->nparam = bset->dim->n_out; |
||
5864 | bset->dim->n_out = 0; |
||
5865 | } |
||
5866 | return bset; |
||
5867 | error: |
||
5868 | isl_mat_free(mat); |
||
5869 | isl_basic_set_free(bset); |
||
5870 | return NULL; |
||
5871 | } |
||
5872 | |||
5873 | /* Apply a preimage specified by "mat" on the parameters of "set". |
||
5874 | * set is assumed to have only parameters and divs. |
||
5875 | */ |
||
5876 | static struct isl_set *set_parameter_preimage( |
||
5877 | struct isl_set *set, struct isl_mat *mat) |
||
5878 | { |
||
5879 | isl_space *dim = NULL; |
||
5880 | unsigned nparam; |
||
5881 | |||
5882 | if (!set || !mat) |
||
5883 | goto error; |
||
5884 | |||
5885 | dim = isl_space_copy(set->dim); |
||
5886 | dim = isl_space_cow(dim); |
||
5887 | if (!dim) |
||
5888 | goto error; |
||
5889 | |||
5890 | nparam = isl_set_dim(set, isl_dim_param); |
||
5891 | |||
5892 | isl_assert(set->ctx, mat->n_row == 1 + nparam, goto error); |
||
5893 | |||
5894 | dim->nparam = 0; |
||
5895 | dim->n_out = nparam; |
||
5896 | isl_set_reset_space(set, dim); |
||
5897 | set = isl_set_preimage(set, mat); |
||
5898 | if (!set) |
||
5899 | goto error2; |
||
5900 | dim = isl_space_copy(set->dim); |
||
5901 | dim = isl_space_cow(dim); |
||
5902 | if (!dim) |
||
5903 | goto error2; |
||
5904 | dim->nparam = dim->n_out; |
||
5905 | dim->n_out = 0; |
||
5906 | isl_set_reset_space(set, dim); |
||
5907 | return set; |
||
5908 | error: |
||
5909 | isl_space_free(dim); |
||
5910 | isl_mat_free(mat); |
||
5911 | error2: |
||
5912 | isl_set_free(set); |
||
5913 | return NULL; |
||
5914 | } |
||
5915 | |||
5916 | /* Intersect the basic set "bset" with the affine space specified by the |
||
5917 | * equalities in "eq". |
||
5918 | */ |
||
5919 | static struct isl_basic_set *basic_set_append_equalities( |
||
5920 | struct isl_basic_set *bset, struct isl_mat *eq) |
||
5921 | { |
||
5922 | int i, k; |
||
5923 | unsigned len; |
||
5924 | |||
5925 | if (!bset || !eq) |
||
5926 | goto error; |
||
5927 | |||
5928 | bset = isl_basic_set_extend_space(bset, isl_space_copy(bset->dim), 0, |
||
5929 | eq->n_row, 0); |
||
5930 | if (!bset) |
||
5931 | goto error; |
||
5932 | |||
5933 | len = 1 + isl_space_dim(bset->dim, isl_dim_all) + bset->extra; |
||
5934 | for (i = 0; i < eq->n_row; ++i) { |
||
5935 | k = isl_basic_set_alloc_equality(bset); |
||
5936 | if (k < 0) |
||
5937 | goto error; |
||
5938 | isl_seq_cpy(bset->eq[k], eq->row[i], eq->n_col); |
||
5939 | isl_seq_clr(bset->eq[k] + eq->n_col, len - eq->n_col); |
||
5940 | } |
||
5941 | isl_mat_free(eq); |
||
5942 | |||
5943 | bset = isl_basic_set_gauss(bset, NULL); |
||
5944 | bset = isl_basic_set_finalize(bset); |
||
5945 | |||
5946 | return bset; |
||
5947 | error: |
||
5948 | isl_mat_free(eq); |
||
5949 | isl_basic_set_free(bset); |
||
5950 | return NULL; |
||
5951 | } |
||
5952 | |||
5953 | /* Intersect the set "set" with the affine space specified by the |
||
5954 | * equalities in "eq". |
||
5955 | */ |
||
5956 | static struct isl_set *set_append_equalities(struct isl_set *set, |
||
5957 | struct isl_mat *eq) |
||
5958 | { |
||
5959 | int i; |
||
5960 | |||
5961 | if (!set || !eq) |
||
5962 | goto error; |
||
5963 | |||
5964 | for (i = 0; i < set->n; ++i) { |
||
5965 | set->p[i] = basic_set_append_equalities(set->p[i], |
||
5966 | isl_mat_copy(eq)); |
||
5967 | if (!set->p[i]) |
||
5968 | goto error; |
||
5969 | } |
||
5970 | isl_mat_free(eq); |
||
5971 | return set; |
||
5972 | error: |
||
5973 | isl_mat_free(eq); |
||
5974 | isl_set_free(set); |
||
5975 | return NULL; |
||
5976 | } |
||
5977 | |||
5978 | /* Project the given basic set onto its parameter domain, possibly introducing |
||
5979 | * new, explicit, existential variables in the constraints. |
||
5980 | * The input has parameters and (possibly implicit) existential variables. |
||
5981 | * The output has the same parameters, but only |
||
5982 | * explicit existentially quantified variables. |
||
5983 | * |
||
5984 | * The actual projection is performed by pip, but pip doesn't seem |
||
5985 | * to like equalities very much, so we first remove the equalities |
||
5986 | * among the parameters by performing a variable compression on |
||
5987 | * the parameters. Afterward, an inverse transformation is performed |
||
5988 | * and the equalities among the parameters are inserted back in. |
||
5989 | */ |
||
5990 | static struct isl_set *parameter_compute_divs(struct isl_basic_set *bset) |
||
5991 | { |
||
5992 | int i, j; |
||
5993 | struct isl_mat *eq; |
||
5994 | struct isl_mat *T, *T2; |
||
5995 | struct isl_set *set; |
||
5996 | unsigned nparam, n_div; |
||
5997 | |||
5998 | bset = isl_basic_set_cow(bset); |
||
5999 | if (!bset) |
||
6000 | return NULL; |
||
6001 | |||
6002 | if (bset->n_eq == 0) |
||
6003 | return isl_basic_set_lexmin(bset); |
||
6004 | |||
6005 | isl_basic_set_gauss(bset, NULL); |
||
6006 | |||
6007 | nparam = isl_basic_set_dim(bset, isl_dim_param); |
||
6008 | n_div = isl_basic_set_dim(bset, isl_dim_div); |
||
6009 | |||
6010 | for (i = 0, j = n_div - 1; i < bset->n_eq && j >= 0; --j) { |
||
6011 | if (!isl_int_is_zero(bset->eq[i][1 + nparam + j])) |
||
6012 | ++i; |
||
6013 | } |
||
6014 | if (i == bset->n_eq) |
||
6015 | return isl_basic_set_lexmin(bset); |
||
6016 | |||
6017 | eq = isl_mat_sub_alloc6(bset->ctx, bset->eq, i, bset->n_eq - i, |
||
6018 | 0, 1 + nparam); |
||
6019 | eq = isl_mat_cow(eq); |
||
6020 | T = isl_mat_variable_compression(isl_mat_copy(eq), &T2); |
||
6021 | if (T && T->n_col == 0) { |
||
6022 | isl_mat_free(T); |
||
6023 | isl_mat_free(T2); |
||
6024 | isl_mat_free(eq); |
||
6025 | bset = isl_basic_set_set_to_empty(bset); |
||
6026 | return isl_set_from_basic_set(bset); |
||
6027 | } |
||
6028 | bset = basic_set_parameter_preimage(bset, T); |
||
6029 | |||
6030 | set = isl_basic_set_lexmin(bset); |
||
6031 | set = set_parameter_preimage(set, T2); |
||
6032 | set = set_append_equalities(set, eq); |
||
6033 | return set; |
||
6034 | } |
||
6035 | |||
6036 | /* Compute an explicit representation for all the existentially |
||
6037 | * quantified variables. |
||
6038 | * The input and output dimensions are first turned into parameters. |
||
6039 | * compute_divs then returns a map with the same parameters and |
||
6040 | * no input or output dimensions and the dimension specification |
||
6041 | * is reset to that of the input. |
||
6042 | */ |
||
6043 | static struct isl_map *compute_divs(struct isl_basic_map *bmap) |
||
6044 | { |
||
6045 | struct isl_basic_set *bset; |
||
6046 | struct isl_set *set; |
||
6047 | struct isl_map *map; |
||
6048 | isl_space *dim, *orig_dim = NULL; |
||
6049 | unsigned nparam; |
||
6050 | unsigned n_in; |
||
6051 | unsigned n_out; |
||
6052 | |||
6053 | bmap = isl_basic_map_cow(bmap); |
||
6054 | if (!bmap) |
||
6055 | return NULL; |
||
6056 | |||
6057 | nparam = isl_basic_map_dim(bmap, isl_dim_param); |
||
6058 | n_in = isl_basic_map_dim(bmap, isl_dim_in); |
||
6059 | n_out = isl_basic_map_dim(bmap, isl_dim_out); |
||
6060 | dim = isl_space_set_alloc(bmap->ctx, nparam + n_in + n_out, 0); |
||
6061 | if (!dim) |
||
6062 | goto error; |
||
6063 | |||
6064 | orig_dim = bmap->dim; |
||
6065 | bmap->dim = dim; |
||
6066 | bset = (struct isl_basic_set *)bmap; |
||
6067 | |||
6068 | set = parameter_compute_divs(bset); |
||
6069 | map = (struct isl_map *)set; |
||
6070 | map = isl_map_reset_space(map, orig_dim); |
||
6071 | |||
6072 | return map; |
||
6073 | error: |
||
6074 | isl_basic_map_free(bmap); |
||
6075 | return NULL; |
||
6076 | } |
||
6077 | |||
6078 | int isl_basic_map_divs_known(__isl_keep isl_basic_map *bmap) |
||
6079 | { |
||
6080 | int i; |
||
6081 | unsigned off; |
||
6082 | |||
6083 | if (!bmap) |
||
6084 | return -1; |
||
6085 | |||
6086 | off = isl_space_dim(bmap->dim, isl_dim_all); |
||
6087 | for (i = 0; i < bmap->n_div; ++i) { |
||
6088 | if (isl_int_is_zero(bmap->div[i][0])) |
||
6089 | return 0; |
||
6090 | isl_assert(bmap->ctx, isl_int_is_zero(bmap->div[i][1+1+off+i]), |
||
6091 | return -1); |
||
6092 | } |
||
6093 | return 1; |
||
6094 | } |
||
6095 | |||
6096 | static int map_divs_known(__isl_keep isl_map *map) |
||
6097 | { |
||
6098 | int i; |
||
6099 | |||
6100 | if (!map) |
||
6101 | return -1; |
||
6102 | |||
6103 | for (i = 0; i < map->n; ++i) { |
||
6104 | int known = isl_basic_map_divs_known(map->p[i]); |
||
6105 | if (known <= 0) |
||
6106 | return known; |
||
6107 | } |
||
6108 | |||
6109 | return 1; |
||
6110 | } |
||
6111 | |||
6112 | /* If bmap contains any unknown divs, then compute explicit |
||
6113 | * expressions for them. However, this computation may be |
||
6114 | * quite expensive, so first try to remove divs that aren't |
||
6115 | * strictly needed. |
||
6116 | */ |
||
6117 | struct isl_map *isl_basic_map_compute_divs(struct isl_basic_map *bmap) |
||
6118 | { |
||
6119 | int known; |
||
6120 | struct isl_map *map; |
||
6121 | |||
6122 | known = isl_basic_map_divs_known(bmap); |
||
6123 | if (known < 0) |
||
6124 | goto error; |
||
6125 | if (known) |
||
6126 | return isl_map_from_basic_map(bmap); |
||
6127 | |||
6128 | bmap = isl_basic_map_drop_redundant_divs(bmap); |
||
6129 | |||
6130 | known = isl_basic_map_divs_known(bmap); |
||
6131 | if (known < 0) |
||
6132 | goto error; |
||
6133 | if (known) |
||
6134 | return isl_map_from_basic_map(bmap); |
||
6135 | |||
6136 | map = compute_divs(bmap); |
||
6137 | return map; |
||
6138 | error: |
||
6139 | isl_basic_map_free(bmap); |
||
6140 | return NULL; |
||
6141 | } |
||
6142 | |||
6143 | struct isl_map *isl_map_compute_divs(struct isl_map *map) |
||
6144 | { |
||
6145 | int i; |
||
6146 | int known; |
||
6147 | struct isl_map *res; |
||
6148 | |||
6149 | if (!map) |
||
6150 | return NULL; |
||
6151 | if (map->n == 0) |
||
6152 | return map; |
||
6153 | |||
6154 | known = map_divs_known(map); |
||
6155 | if (known < 0) { |
||
6156 | isl_map_free(map); |
||
6157 | return NULL; |
||
6158 | } |
||
6159 | if (known) |
||
6160 | return map; |
||
6161 | |||
6162 | res = isl_basic_map_compute_divs(isl_basic_map_copy(map->p[0])); |
||
6163 | for (i = 1 ; i < map->n; ++i) { |
||
6164 | struct isl_map *r2; |
||
6165 | r2 = isl_basic_map_compute_divs(isl_basic_map_copy(map->p[i])); |
||
6166 | if (ISL_F_ISSET(map, ISL_MAP_DISJOINT)) |
||
6167 | res = isl_map_union_disjoint(res, r2); |
||
6168 | else |
||
6169 | res = isl_map_union(res, r2); |
||
6170 | } |
||
6171 | isl_map_free(map); |
||
6172 | |||
6173 | return res; |
||
6174 | } |
||
6175 | |||
6176 | struct isl_set *isl_basic_set_compute_divs(struct isl_basic_set *bset) |
||
6177 | { |
||
6178 | return (struct isl_set *) |
||
6179 | isl_basic_map_compute_divs((struct isl_basic_map *)bset); |
||
6180 | } |
||
6181 | |||
6182 | struct isl_set *isl_set_compute_divs(struct isl_set *set) |
||
6183 | { |
||
6184 | return (struct isl_set *) |
||
6185 | isl_map_compute_divs((struct isl_map *)set); |
||
6186 | } |
||
6187 | |||
6188 | struct isl_set *isl_map_domain(struct isl_map *map) |
||
6189 | { |
||
6190 | int i; |
||
6191 | struct isl_set *set; |
||
6192 | |||
6193 | if (!map) |
||
6194 | goto error; |
||
6195 | |||
6196 | map = isl_map_cow(map); |
||
6197 | if (!map) |
||
6198 | return NULL; |
||
6199 | |||
6200 | set = (struct isl_set *)map; |
||
6201 | set->dim = isl_space_domain(set->dim); |
||
6202 | if (!set->dim) |
||
6203 | goto error; |
||
6204 | for (i = 0; i < map->n; ++i) { |
||
6205 | set->p[i] = isl_basic_map_domain(map->p[i]); |
||
6206 | if (!set->p[i]) |
||
6207 | goto error; |
||
6208 | } |
||
6209 | ISL_F_CLR(set, ISL_MAP_DISJOINT); |
||
6210 | ISL_F_CLR(set, ISL_SET_NORMALIZED); |
||
6211 | return set; |
||
6212 | error: |
||
6213 | isl_map_free(map); |
||
6214 | return NULL; |
||
6215 | } |
||
6216 | |||
6217 | static __isl_give isl_map *map_union_disjoint(__isl_take isl_map *map1, |
||
6218 | __isl_take isl_map *map2) |
||
6219 | { |
||
6220 | int i; |
||
6221 | unsigned flags = 0; |
||
6222 | struct isl_map *map = NULL; |
||
6223 | |||
6224 | if (!map1 || !map2) |
||
6225 | goto error; |
||
6226 | |||
6227 | if (map1->n == 0) { |
||
6228 | isl_map_free(map1); |
||
6229 | return map2; |
||
6230 | } |
||
6231 | if (map2->n == 0) { |
||
6232 | isl_map_free(map2); |
||
6233 | return map1; |
||
6234 | } |
||
6235 | |||
6236 | isl_assert(map1->ctx, isl_space_is_equal(map1->dim, map2->dim), goto error); |
||
6237 | |||
6238 | if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) && |
||
6239 | ISL_F_ISSET(map2, ISL_MAP_DISJOINT)) |
||
6240 | ISL_FL_SET(flags, ISL_MAP_DISJOINT); |
||
6241 | |||
6242 | map = isl_map_alloc_space(isl_space_copy(map1->dim), |
||
6243 | map1->n + map2->n, flags); |
||
6244 | if (!map) |
||
6245 | goto error; |
||
6246 | for (i = 0; i < map1->n; ++i) { |
||
6247 | map = isl_map_add_basic_map(map, |
||
6248 | isl_basic_map_copy(map1->p[i])); |
||
6249 | if (!map) |
||
6250 | goto error; |
||
6251 | } |
||
6252 | for (i = 0; i < map2->n; ++i) { |
||
6253 | map = isl_map_add_basic_map(map, |
||
6254 | isl_basic_map_copy(map2->p[i])); |
||
6255 | if (!map) |
||
6256 | goto error; |
||
6257 | } |
||
6258 | isl_map_free(map1); |
||
6259 | isl_map_free(map2); |
||
6260 | return map; |
||
6261 | error: |
||
6262 | isl_map_free(map); |
||
6263 | isl_map_free(map1); |
||
6264 | isl_map_free(map2); |
||
6265 | return NULL; |
||
6266 | } |
||
6267 | |||
6268 | __isl_give isl_map *isl_map_union_disjoint(__isl_take isl_map *map1, |
||
6269 | __isl_take isl_map *map2) |
||
6270 | { |
||
6271 | return isl_map_align_params_map_map_and(map1, map2, &map_union_disjoint); |
||
6272 | } |
||
6273 | |||
6274 | struct isl_map *isl_map_union(struct isl_map *map1, struct isl_map *map2) |
||
6275 | { |
||
6276 | map1 = isl_map_union_disjoint(map1, map2); |
||
6277 | if (!map1) |
||
6278 | return NULL; |
||
6279 | if (map1->n > 1) |
||
6280 | ISL_F_CLR(map1, ISL_MAP_DISJOINT); |
||
6281 | return map1; |
||
6282 | } |
||
6283 | |||
6284 | struct isl_set *isl_set_union_disjoint( |
||
6285 | struct isl_set *set1, struct isl_set *set2) |
||
6286 | { |
||
6287 | return (struct isl_set *) |
||
6288 | isl_map_union_disjoint( |
||
6289 | (struct isl_map *)set1, (struct isl_map *)set2); |
||
6290 | } |
||
6291 | |||
6292 | struct isl_set *isl_set_union(struct isl_set *set1, struct isl_set *set2) |
||
6293 | { |
||
6294 | return (struct isl_set *) |
||
6295 | isl_map_union((struct isl_map *)set1, (struct isl_map *)set2); |
||
6296 | } |
||
6297 | |||
6298 | static __isl_give isl_map *map_intersect_range(__isl_take isl_map *map, |
||
6299 | __isl_take isl_set *set) |
||
6300 | { |
||
6301 | unsigned flags = 0; |
||
6302 | struct isl_map *result; |
||
6303 | int i, j; |
||
6304 | |||
6305 | if (!map || !set) |
||
6306 | goto error; |
||
6307 | |||
6308 | if (!isl_space_match(map->dim, isl_dim_param, set->dim, isl_dim_param)) |
||
6309 | isl_die(set->ctx, isl_error_invalid, |
||
6310 | "parameters don't match", goto error); |
||
6311 | |||
6312 | if (isl_space_dim(set->dim, isl_dim_set) != 0 && |
||
6313 | !isl_map_compatible_range(map, set)) |
||
6314 | isl_die(set->ctx, isl_error_invalid, |
||
6315 | "incompatible spaces", goto error); |
||
6316 | |||
6317 | if (isl_set_plain_is_universe(set)) { |
||
6318 | isl_set_free(set); |
||
6319 | return map; |
||
6320 | } |
||
6321 | |||
6322 | if (ISL_F_ISSET(map, ISL_MAP_DISJOINT) && |
||
6323 | ISL_F_ISSET(set, ISL_MAP_DISJOINT)) |
||
6324 | ISL_FL_SET(flags, ISL_MAP_DISJOINT); |
||
6325 | |||
6326 | result = isl_map_alloc_space(isl_space_copy(map->dim), |
||
6327 | map->n * set->n, flags); |
||
6328 | if (!result) |
||
6329 | goto error; |
||
6330 | for (i = 0; i < map->n; ++i) |
||
6331 | for (j = 0; j < set->n; ++j) { |
||
6332 | result = isl_map_add_basic_map(result, |
||
6333 | isl_basic_map_intersect_range( |
||
6334 | isl_basic_map_copy(map->p[i]), |
||
6335 | isl_basic_set_copy(set->p[j]))); |
||
6336 | if (!result) |
||
6337 | goto error; |
||
6338 | } |
||
6339 | isl_map_free(map); |
||
6340 | isl_set_free(set); |
||
6341 | return result; |
||
6342 | error: |
||
6343 | isl_map_free(map); |
||
6344 | isl_set_free(set); |
||
6345 | return NULL; |
||
6346 | } |
||
6347 | |||
6348 | __isl_give isl_map *isl_map_intersect_range(__isl_take isl_map *map, |
||
6349 | __isl_take isl_set *set) |
||
6350 | { |
||
6351 | return isl_map_align_params_map_map_and(map, set, &map_intersect_range); |
||
6352 | } |
||
6353 | |||
6354 | struct isl_map *isl_map_intersect_domain( |
||
6355 | struct isl_map *map, struct isl_set *set) |
||
6356 | { |
||
6357 | return isl_map_reverse( |
||
6358 | isl_map_intersect_range(isl_map_reverse(map), set)); |
||
6359 | } |
||
6360 | |||
6361 | static __isl_give isl_map *map_apply_domain(__isl_take isl_map *map1, |
||
6362 | __isl_take isl_map *map2) |
||
6363 | { |
||
6364 | if (!map1 || !map2) |
||
6365 | goto error; |
||
6366 | map1 = isl_map_reverse(map1); |
||
6367 | map1 = isl_map_apply_range(map1, map2); |
||
6368 | return isl_map_reverse(map1); |
||
6369 | error: |
||
6370 | isl_map_free(map1); |
||
6371 | isl_map_free(map2); |
||
6372 | return NULL; |
||
6373 | } |
||
6374 | |||
6375 | __isl_give isl_map *isl_map_apply_domain(__isl_take isl_map *map1, |
||
6376 | __isl_take isl_map *map2) |
||
6377 | { |
||
6378 | return isl_map_align_params_map_map_and(map1, map2, &map_apply_domain); |
||
6379 | } |
||
6380 | |||
6381 | static __isl_give isl_map *map_apply_range(__isl_take isl_map *map1, |
||
6382 | __isl_take isl_map *map2) |
||
6383 | { |
||
6384 | isl_space *dim_result; |
||
6385 | struct isl_map *result; |
||
6386 | int i, j; |
||
6387 | |||
6388 | if (!map1 || !map2) |
||
6389 | goto error; |
||
6390 | |||
6391 | dim_result = isl_space_join(isl_space_copy(map1->dim), |
||
6392 | isl_space_copy(map2->dim)); |
||
6393 | |||
6394 | result = isl_map_alloc_space(dim_result, map1->n * map2->n, 0); |
||
6395 | if (!result) |
||
6396 | goto error; |
||
6397 | for (i = 0; i < map1->n; ++i) |
||
6398 | for (j = 0; j < map2->n; ++j) { |
||
6399 | result = isl_map_add_basic_map(result, |
||
6400 | isl_basic_map_apply_range( |
||
6401 | isl_basic_map_copy(map1->p[i]), |
||
6402 | isl_basic_map_copy(map2->p[j]))); |
||
6403 | if (!result) |
||
6404 | goto error; |
||
6405 | } |
||
6406 | isl_map_free(map1); |
||
6407 | isl_map_free(map2); |
||
6408 | if (result && result->n <= 1) |
||
6409 | ISL_F_SET(result, ISL_MAP_DISJOINT); |
||
6410 | return result; |
||
6411 | error: |
||
6412 | isl_map_free(map1); |
||
6413 | isl_map_free(map2); |
||
6414 | return NULL; |
||
6415 | } |
||
6416 | |||
6417 | __isl_give isl_map *isl_map_apply_range(__isl_take isl_map *map1, |
||
6418 | __isl_take isl_map *map2) |
||
6419 | { |
||
6420 | return isl_map_align_params_map_map_and(map1, map2, &map_apply_range); |
||
6421 | } |
||
6422 | |||
6423 | /* |
||
6424 | * returns range - domain |
||
6425 | */ |
||
6426 | struct isl_basic_set *isl_basic_map_deltas(struct isl_basic_map *bmap) |
||
6427 | { |
||
6428 | isl_space *dims, *target_dim; |
||
6429 | struct isl_basic_set *bset; |
||
6430 | unsigned dim; |
||
6431 | unsigned nparam; |
||
6432 | int i; |
||
6433 | |||
6434 | if (!bmap) |
||
6435 | goto error; |
||
6436 | isl_assert(bmap->ctx, isl_space_tuple_match(bmap->dim, isl_dim_in, |
||
6437 | bmap->dim, isl_dim_out), |
||
6438 | goto error); |
||
6439 | target_dim = isl_space_domain(isl_basic_map_get_space(bmap)); |
||
6440 | dim = isl_basic_map_n_in(bmap); |
||
6441 | nparam = isl_basic_map_n_param(bmap); |
||
6442 | bset = isl_basic_set_from_basic_map(bmap); |
||
6443 | bset = isl_basic_set_cow(bset); |
||
6444 | dims = isl_basic_set_get_space(bset); |
||
6445 | dims = isl_space_add_dims(dims, isl_dim_set, dim); |
||
6446 | bset = isl_basic_set_extend_space(bset, dims, 0, dim, 0); |
||
6447 | bset = isl_basic_set_swap_vars(bset, 2*dim); |
||
6448 | for (i = 0; i < dim; ++i) { |
||
6449 | int j = isl_basic_map_alloc_equality( |
||
6450 | (struct isl_basic_map *)bset); |
||
6451 | if (j < 0) |
||
6452 | goto error; |
||
6453 | isl_seq_clr(bset->eq[j], 1 + isl_basic_set_total_dim(bset)); |
||
6454 | isl_int_set_si(bset->eq[j][1+nparam+i], 1); |
||
6455 | isl_int_set_si(bset->eq[j][1+nparam+dim+i], 1); |
||
6456 | isl_int_set_si(bset->eq[j][1+nparam+2*dim+i], -1); |
||
6457 | } |
||
6458 | bset = isl_basic_set_project_out(bset, isl_dim_set, dim, 2*dim); |
||
6459 | bset = isl_basic_set_reset_space(bset, target_dim); |
||
6460 | return bset; |
||
6461 | error: |
||
6462 | isl_basic_map_free(bmap); |
||
6463 | return NULL; |
||
6464 | } |
||
6465 | |||
6466 | /* |
||
6467 | * returns range - domain |
||
6468 | */ |
||
6469 | __isl_give isl_set *isl_map_deltas(__isl_take isl_map *map) |
||
6470 | { |
||
6471 | int i; |
||
6472 | isl_space *dim; |
||
6473 | struct isl_set *result; |
||
6474 | |||
6475 | if (!map) |
||
6476 | return NULL; |
||
6477 | |||
6478 | isl_assert(map->ctx, isl_space_tuple_match(map->dim, isl_dim_in, |
||
6479 | map->dim, isl_dim_out), |
||
6480 | goto error); |
||
6481 | dim = isl_map_get_space(map); |
||
6482 | dim = isl_space_domain(dim); |
||
6483 | result = isl_set_alloc_space(dim, map->n, 0); |
||
6484 | if (!result) |
||
6485 | goto error; |
||
6486 | for (i = 0; i < map->n; ++i) |
||
6487 | result = isl_set_add_basic_set(result, |
||
6488 | isl_basic_map_deltas(isl_basic_map_copy(map->p[i]))); |
||
6489 | isl_map_free(map); |
||
6490 | return result; |
||
6491 | error: |
||
6492 | isl_map_free(map); |
||
6493 | return NULL; |
||
6494 | } |
||
6495 | |||
6496 | /* |
||
6497 | * returns [domain -> range] -> range - domain |
||
6498 | */ |
||
6499 | __isl_give isl_basic_map *isl_basic_map_deltas_map( |
||
6500 | __isl_take isl_basic_map *bmap) |
||
6501 | { |
||
6502 | int i, k; |
||
6503 | isl_space *dim; |
||
6504 | isl_basic_map *domain; |
||
6505 | int nparam, n; |
||
6506 | unsigned total; |
||
6507 | |||
6508 | if (!isl_space_tuple_match(bmap->dim, isl_dim_in, bmap->dim, isl_dim_out)) |
||
6509 | isl_die(bmap->ctx, isl_error_invalid, |
||
6510 | "domain and range don't match", goto error); |
||
6511 | |||
6512 | nparam = isl_basic_map_dim(bmap, isl_dim_param); |
||
6513 | n = isl_basic_map_dim(bmap, isl_dim_in); |
||
6514 | |||
6515 | dim = isl_space_from_range(isl_space_domain(isl_basic_map_get_space(bmap))); |
||
6516 | domain = isl_basic_map_universe(dim); |
||
6517 | |||
6518 | bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap)); |
||
6519 | bmap = isl_basic_map_apply_range(bmap, domain); |
||
6520 | bmap = isl_basic_map_extend_constraints(bmap, n, 0); |
||
6521 | |||
6522 | total = isl_basic_map_total_dim(bmap); |
||
6523 | |||
6524 | for (i = 0; i < n; ++i) { |
||
6525 | k = isl_basic_map_alloc_equality(bmap); |
||
6526 | if (k < 0) |
||
6527 | goto error; |
||
6528 | isl_seq_clr(bmap->eq[k], 1 + total); |
||
6529 | isl_int_set_si(bmap->eq[k][1 + nparam + i], 1); |
||
6530 | isl_int_set_si(bmap->eq[k][1 + nparam + n + i], -1); |
||
6531 | isl_int_set_si(bmap->eq[k][1 + nparam + n + n + i], 1); |
||
6532 | } |
||
6533 | |||
6534 | bmap = isl_basic_map_gauss(bmap, NULL); |
||
6535 | return isl_basic_map_finalize(bmap); |
||
6536 | error: |
||
6537 | isl_basic_map_free(bmap); |
||
6538 | return NULL; |
||
6539 | } |
||
6540 | |||
6541 | /* |
||
6542 | * returns [domain -> range] -> range - domain |
||
6543 | */ |
||
6544 | __isl_give isl_map *isl_map_deltas_map(__isl_take isl_map *map) |
||
6545 | { |
||
6546 | int i; |
||
6547 | isl_space *domain_dim; |
||
6548 | |||
6549 | if (!map) |
||
6550 | return NULL; |
||
6551 | |||
6552 | if (!isl_space_tuple_match(map->dim, isl_dim_in, map->dim, isl_dim_out)) |
||
6553 | isl_die(map->ctx, isl_error_invalid, |
||
6554 | "domain and range don't match", goto error); |
||
6555 | |||
6556 | map = isl_map_cow(map); |
||
6557 | if (!map) |
||
6558 | return NULL; |
||
6559 | |||
6560 | domain_dim = isl_space_from_range(isl_space_domain(isl_map_get_space(map))); |
||
6561 | map->dim = isl_space_from_domain(isl_space_wrap(map->dim)); |
||
6562 | map->dim = isl_space_join(map->dim, domain_dim); |
||
6563 | if (!map->dim) |
||
6564 | goto error; |
||
6565 | for (i = 0; i < map->n; ++i) { |
||
6566 | map->p[i] = isl_basic_map_deltas_map(map->p[i]); |
||
6567 | if (!map->p[i]) |
||
6568 | goto error; |
||
6569 | } |
||
6570 | ISL_F_CLR(map, ISL_MAP_NORMALIZED); |
||
6571 | return map; |
||
6572 | error: |
||
6573 | isl_map_free(map); |
||
6574 | return NULL; |
||
6575 | } |
||
6576 | |||
6577 | __isl_give struct isl_basic_map *basic_map_identity(__isl_take isl_space *dims) |
||
6578 | { |
||
6579 | struct isl_basic_map *bmap; |
||
6580 | unsigned nparam; |
||
6581 | unsigned dim; |
||
6582 | int i; |
||
6583 | |||
6584 | if (!dims) |
||
6585 | return NULL; |
||
6586 | |||
6587 | nparam = dims->nparam; |
||
6588 | dim = dims->n_out; |
||
6589 | bmap = isl_basic_map_alloc_space(dims, 0, dim, 0); |
||
6590 | if (!bmap) |
||
6591 | goto error; |
||
6592 | |||
6593 | for (i = 0; i < dim; ++i) { |
||
6594 | int j = isl_basic_map_alloc_equality(bmap); |
||
6595 | if (j < 0) |
||
6596 | goto error; |
||
6597 | isl_seq_clr(bmap->eq[j], 1 + isl_basic_map_total_dim(bmap)); |
||
6598 | isl_int_set_si(bmap->eq[j][1+nparam+i], 1); |
||
6599 | isl_int_set_si(bmap->eq[j][1+nparam+dim+i], -1); |
||
6600 | } |
||
6601 | return isl_basic_map_finalize(bmap); |
||
6602 | error: |
||
6603 | isl_basic_map_free(bmap); |
||
6604 | return NULL; |
||
6605 | } |
||
6606 | |||
6607 | __isl_give isl_basic_map *isl_basic_map_identity(__isl_take isl_space *dim) |
||
6608 | { |
||
6609 | if (!dim) |
||
6610 | return NULL; |
||
6611 | if (dim->n_in != dim->n_out) |
||
6612 | isl_die(dim->ctx, isl_error_invalid, |
||
6613 | "number of input and output dimensions needs to be " |
||
6614 | "the same", goto error); |
||
6615 | return basic_map_identity(dim); |
||
6616 | error: |
||
6617 | isl_space_free(dim); |
||
6618 | return NULL; |
||
6619 | } |
||
6620 | |||
6621 | struct isl_basic_map *isl_basic_map_identity_like(struct isl_basic_map *model) |
||
6622 | { |
||
6623 | if (!model || !model->dim) |
||
6624 | return NULL; |
||
6625 | return isl_basic_map_identity(isl_space_copy(model->dim)); |
||
6626 | } |
||
6627 | |||
6628 | __isl_give isl_map *isl_map_identity(__isl_take isl_space *dim) |
||
6629 | { |
||
6630 | return isl_map_from_basic_map(isl_basic_map_identity(dim)); |
||
6631 | } |
||
6632 | |||
6633 | struct isl_map *isl_map_identity_like(struct isl_map *model) |
||
6634 | { |
||
6635 | if (!model || !model->dim) |
||
6636 | return NULL; |
||
6637 | return isl_map_identity(isl_space_copy(model->dim)); |
||
6638 | } |
||
6639 | |||
6640 | struct isl_map *isl_map_identity_like_basic_map(struct isl_basic_map *model) |
||
6641 | { |
||
6642 | if (!model || !model->dim) |
||
6643 | return NULL; |
||
6644 | return isl_map_identity(isl_space_copy(model->dim)); |
||
6645 | } |
||
6646 | |||
6647 | __isl_give isl_map *isl_set_identity(__isl_take isl_set *set) |
||
6648 | { |
||
6649 | isl_space *dim = isl_set_get_space(set); |
||
6650 | isl_map *id; |
||
6651 | id = isl_map_identity(isl_space_map_from_set(dim)); |
||
6652 | return isl_map_intersect_range(id, set); |
||
6653 | } |
||
6654 | |||
6655 | /* Construct a basic set with all set dimensions having only non-negative |
||
6656 | * values. |
||
6657 | */ |
||
6658 | __isl_give isl_basic_set *isl_basic_set_positive_orthant( |
||
6659 | __isl_take isl_space *space) |
||
6660 | { |
||
6661 | int i; |
||
6662 | unsigned nparam; |
||
6663 | unsigned dim; |
||
6664 | struct isl_basic_set *bset; |
||
6665 | |||
6666 | if (!space) |
||
6667 | return NULL; |
||
6668 | nparam = space->nparam; |
||
6669 | dim = space->n_out; |
||
6670 | bset = isl_basic_set_alloc_space(space, 0, 0, dim); |
||
6671 | if (!bset) |
||
6672 | return NULL; |
||
6673 | for (i = 0; i < dim; ++i) { |
||
6674 | int k = isl_basic_set_alloc_inequality(bset); |
||
6675 | if (k < 0) |
||
6676 | goto error; |
||
6677 | isl_seq_clr(bset->ineq[k], 1 + isl_basic_set_total_dim(bset)); |
||
6678 | isl_int_set_si(bset->ineq[k][1 + nparam + i], 1); |
||
6679 | } |
||
6680 | return bset; |
||
6681 | error: |
||
6682 | isl_basic_set_free(bset); |
||
6683 | return NULL; |
||
6684 | } |
||
6685 | |||
6686 | /* Construct the half-space x_pos >= 0. |
||
6687 | */ |
||
6688 | static __isl_give isl_basic_set *nonneg_halfspace(__isl_take isl_space *dim, |
||
6689 | int pos) |
||
6690 | { |
||
6691 | int k; |
||
6692 | isl_basic_set *nonneg; |
||
6693 | |||
6694 | nonneg = isl_basic_set_alloc_space(dim, 0, 0, 1); |
||
6695 | k = isl_basic_set_alloc_inequality(nonneg); |
||
6696 | if (k < 0) |
||
6697 | goto error; |
||
6698 | isl_seq_clr(nonneg->ineq[k], 1 + isl_basic_set_total_dim(nonneg)); |
||
6699 | isl_int_set_si(nonneg->ineq[k][pos], 1); |
||
6700 | |||
6701 | return isl_basic_set_finalize(nonneg); |
||
6702 | error: |
||
6703 | isl_basic_set_free(nonneg); |
||
6704 | return NULL; |
||
6705 | } |
||
6706 | |||
6707 | /* Construct the half-space x_pos <= -1. |
||
6708 | */ |
||
6709 | static __isl_give isl_basic_set *neg_halfspace(__isl_take isl_space *dim, int pos) |
||
6710 | { |
||
6711 | int k; |
||
6712 | isl_basic_set *neg; |
||
6713 | |||
6714 | neg = isl_basic_set_alloc_space(dim, 0, 0, 1); |
||
6715 | k = isl_basic_set_alloc_inequality(neg); |
||
6716 | if (k < 0) |
||
6717 | goto error; |
||
6718 | isl_seq_clr(neg->ineq[k], 1 + isl_basic_set_total_dim(neg)); |
||
6719 | isl_int_set_si(neg->ineq[k][0], -1); |
||
6720 | isl_int_set_si(neg->ineq[k][pos], -1); |
||
6721 | |||
6722 | return isl_basic_set_finalize(neg); |
||
6723 | error: |
||
6724 | isl_basic_set_free(neg); |
||
6725 | return NULL; |
||
6726 | } |
||
6727 | |||
6728 | __isl_give isl_set *isl_set_split_dims(__isl_take isl_set *set, |
||
6729 | enum isl_dim_type type, unsigned first, unsigned n) |
||
6730 | { |
||
6731 | int i; |
||
6732 | isl_basic_set *nonneg; |
||
6733 | isl_basic_set *neg; |
||
6734 | |||
6735 | if (!set) |
||
6736 | return NULL; |
||
6737 | if (n == 0) |
||
6738 | return set; |
||
6739 | |||
6740 | isl_assert(set->ctx, first + n <= isl_set_dim(set, type), goto error); |
||
6741 | |||
6742 | for (i = 0; i < n; ++i) { |
||
6743 | nonneg = nonneg_halfspace(isl_set_get_space(set), |
||
6744 | pos(set->dim, type) + first + i); |
||
6745 | neg = neg_halfspace(isl_set_get_space(set), |
||
6746 | pos(set->dim, type) + first + i); |
||
6747 | |||
6748 | set = isl_set_intersect(set, isl_basic_set_union(nonneg, neg)); |
||
6749 | } |
||
6750 | |||
6751 | return set; |
||
6752 | error: |
||
6753 | isl_set_free(set); |
||
6754 | return NULL; |
||
6755 | } |
||
6756 | |||
6757 | static int foreach_orthant(__isl_take isl_set *set, int *signs, int first, |
||
6758 | int len, int (*fn)(__isl_take isl_set *orthant, int *signs, void *user), |
||
6759 | void *user) |
||
6760 | { |
||
6761 | isl_set *half; |
||
6762 | |||
6763 | if (!set) |
||
6764 | return -1; |
||
6765 | if (isl_set_plain_is_empty(set)) { |
||
6766 | isl_set_free(set); |
||
6767 | return 0; |
||
6768 | } |
||
6769 | if (first == len) |
||
6770 | return fn(set, signs, user); |
||
6771 | |||
6772 | signs[first] = 1; |
||
6773 | half = isl_set_from_basic_set(nonneg_halfspace(isl_set_get_space(set), |
||
6774 | 1 + first)); |
||
6775 | half = isl_set_intersect(half, isl_set_copy(set)); |
||
6776 | if (foreach_orthant(half, signs, first + 1, len, fn, user) < 0) |
||
6777 | goto error; |
||
6778 | |||
6779 | signs[first] = -1; |
||
6780 | half = isl_set_from_basic_set(neg_halfspace(isl_set_get_space(set), |
||
6781 | 1 + first)); |
||
6782 | half = isl_set_intersect(half, set); |
||
6783 | return foreach_orthant(half, signs, first + 1, len, fn, user); |
||
6784 | error: |
||
6785 | isl_set_free(set); |
||
6786 | return -1; |
||
6787 | } |
||
6788 | |||
6789 | /* Call "fn" on the intersections of "set" with each of the orthants |
||
6790 | * (except for obviously empty intersections). The orthant is identified |
||
6791 | * by the signs array, with each entry having value 1 or -1 according |
||
6792 | * to the sign of the corresponding variable. |
||
6793 | */ |
||
6794 | int isl_set_foreach_orthant(__isl_keep isl_set *set, |
||
6795 | int (*fn)(__isl_take isl_set *orthant, int *signs, void *user), |
||
6796 | void *user) |
||
6797 | { |
||
6798 | unsigned nparam; |
||
6799 | unsigned nvar; |
||
6800 | int *signs; |
||
6801 | int r; |
||
6802 | |||
6803 | if (!set) |
||
6804 | return -1; |
||
6805 | if (isl_set_plain_is_empty(set)) |
||
6806 | return 0; |
||
6807 | |||
6808 | nparam = isl_set_dim(set, isl_dim_param); |
||
6809 | nvar = isl_set_dim(set, isl_dim_set); |
||
6810 | |||
6811 | signs = isl_alloc_array(set->ctx, int, nparam + nvar); |
||
6812 | |||
6813 | r = foreach_orthant(isl_set_copy(set), signs, 0, nparam + nvar, |
||
6814 | fn, user); |
||
6815 | |||
6816 | free(signs); |
||
6817 | |||
6818 | return r; |
||
6819 | } |
||
6820 | |||
6821 | int isl_set_is_equal(struct isl_set *set1, struct isl_set *set2) |
||
6822 | { |
||
6823 | return isl_map_is_equal((struct isl_map *)set1, (struct isl_map *)set2); |
||
6824 | } |
||
6825 | |||
6826 | int isl_basic_map_is_subset( |
||
6827 | struct isl_basic_map *bmap1, struct isl_basic_map *bmap2) |
||
6828 | { |
||
6829 | int is_subset; |
||
6830 | struct isl_map *map1; |
||
6831 | struct isl_map *map2; |
||
6832 | |||
6833 | if (!bmap1 || !bmap2) |
||
6834 | return -1; |
||
6835 | |||
6836 | map1 = isl_map_from_basic_map(isl_basic_map_copy(bmap1)); |
||
6837 | map2 = isl_map_from_basic_map(isl_basic_map_copy(bmap2)); |
||
6838 | |||
6839 | is_subset = isl_map_is_subset(map1, map2); |
||
6840 | |||
6841 | isl_map_free(map1); |
||
6842 | isl_map_free(map2); |
||
6843 | |||
6844 | return is_subset; |
||
6845 | } |
||
6846 | |||
6847 | int isl_basic_set_is_subset(__isl_keep isl_basic_set *bset1, |
||
6848 | __isl_keep isl_basic_set *bset2) |
||
6849 | { |
||
6850 | return isl_basic_map_is_subset(bset1, bset2); |
||
6851 | } |
||
6852 | |||
6853 | int isl_basic_map_is_equal( |
||
6854 | struct isl_basic_map *bmap1, struct isl_basic_map *bmap2) |
||
6855 | { |
||
6856 | int is_subset; |
||
6857 | |||
6858 | if (!bmap1 || !bmap2) |
||
6859 | return -1; |
||
6860 | is_subset = isl_basic_map_is_subset(bmap1, bmap2); |
||
6861 | if (is_subset != 1) |
||
6862 | return is_subset; |
||
6863 | is_subset = isl_basic_map_is_subset(bmap2, bmap1); |
||
6864 | return is_subset; |
||
6865 | } |
||
6866 | |||
6867 | int isl_basic_set_is_equal( |
||
6868 | struct isl_basic_set *bset1, struct isl_basic_set *bset2) |
||
6869 | { |
||
6870 | return isl_basic_map_is_equal( |
||
6871 | (struct isl_basic_map *)bset1, (struct isl_basic_map *)bset2); |
||
6872 | } |
||
6873 | |||
6874 | int isl_map_is_empty(struct isl_map *map) |
||
6875 | { |
||
6876 | int i; |
||
6877 | int is_empty; |
||
6878 | |||
6879 | if (!map) |
||
6880 | return -1; |
||
6881 | for (i = 0; i < map->n; ++i) { |
||
6882 | is_empty = isl_basic_map_is_empty(map->p[i]); |
||
6883 | if (is_empty < 0) |
||
6884 | return -1; |
||
6885 | if (!is_empty) |
||
6886 | return 0; |
||
6887 | } |
||
6888 | return 1; |
||
6889 | } |
||
6890 | |||
6891 | int isl_map_plain_is_empty(__isl_keep isl_map *map) |
||
6892 | { |
||
6893 | return map ? map->n == 0 : -1; |
||
6894 | } |
||
6895 | |||
6896 | int isl_map_fast_is_empty(__isl_keep isl_map *map) |
||
6897 | { |
||
6898 | return isl_map_plain_is_empty(map); |
||
6899 | } |
||
6900 | |||
6901 | int isl_set_plain_is_empty(struct isl_set *set) |
||
6902 | { |
||
6903 | return set ? set->n == 0 : -1; |
||
6904 | } |
||
6905 | |||
6906 | int isl_set_fast_is_empty(__isl_keep isl_set *set) |
||
6907 | { |
||
6908 | return isl_set_plain_is_empty(set); |
||
6909 | } |
||
6910 | |||
6911 | int isl_set_is_empty(struct isl_set *set) |
||
6912 | { |
||
6913 | return isl_map_is_empty((struct isl_map *)set); |
||
6914 | } |
||
6915 | |||
6916 | int isl_map_has_equal_space(__isl_keep isl_map *map1, __isl_keep isl_map *map2) |
||
6917 | { |
||
6918 | if (!map1 || !map2) |
||
6919 | return -1; |
||
6920 | |||
6921 | return isl_space_is_equal(map1->dim, map2->dim); |
||
6922 | } |
||
6923 | |||
6924 | int isl_set_has_equal_space(__isl_keep isl_set *set1, __isl_keep isl_set *set2) |
||
6925 | { |
||
6926 | if (!set1 || !set2) |
||
6927 | return -1; |
||
6928 | |||
6929 | return isl_space_is_equal(set1->dim, set2->dim); |
||
6930 | } |
||
6931 | |||
6932 | static int map_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2) |
||
6933 | { |
||
6934 | int is_subset; |
||
6935 | |||
6936 | if (!map1 || !map2) |
||
6937 | return -1; |
||
6938 | is_subset = isl_map_is_subset(map1, map2); |
||
6939 | if (is_subset != 1) |
||
6940 | return is_subset; |
||
6941 | is_subset = isl_map_is_subset(map2, map1); |
||
6942 | return is_subset; |
||
6943 | } |
||
6944 | |||
6945 | int isl_map_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2) |
||
6946 | { |
||
6947 | return isl_map_align_params_map_map_and_test(map1, map2, &map_is_equal); |
||
6948 | } |
||
6949 | |||
6950 | int isl_basic_map_is_strict_subset( |
||
6951 | struct isl_basic_map *bmap1, struct isl_basic_map *bmap2) |
||
6952 | { |
||
6953 | int is_subset; |
||
6954 | |||
6955 | if (!bmap1 || !bmap2) |
||
6956 | return -1; |
||
6957 | is_subset = isl_basic_map_is_subset(bmap1, bmap2); |
||
6958 | if (is_subset != 1) |
||
6959 | return is_subset; |
||
6960 | is_subset = isl_basic_map_is_subset(bmap2, bmap1); |
||
6961 | if (is_subset == -1) |
||
6962 | return is_subset; |
||
6963 | return !is_subset; |
||
6964 | } |
||
6965 | |||
6966 | int isl_map_is_strict_subset(struct isl_map *map1, struct isl_map *map2) |
||
6967 | { |
||
6968 | int is_subset; |
||
6969 | |||
6970 | if (!map1 || !map2) |
||
6971 | return -1; |
||
6972 | is_subset = isl_map_is_subset(map1, map2); |
||
6973 | if (is_subset != 1) |
||
6974 | return is_subset; |
||
6975 | is_subset = isl_map_is_subset(map2, map1); |
||
6976 | if (is_subset == -1) |
||
6977 | return is_subset; |
||
6978 | return !is_subset; |
||
6979 | } |
||
6980 | |||
6981 | int isl_set_is_strict_subset(__isl_keep isl_set *set1, __isl_keep isl_set *set2) |
||
6982 | { |
||
6983 | return isl_map_is_strict_subset((isl_map *)set1, (isl_map *)set2); |
||
6984 | } |
||
6985 | |||
6986 | int isl_basic_map_is_universe(struct isl_basic_map *bmap) |
||
6987 | { |
||
6988 | if (!bmap) |
||
6989 | return -1; |
||
6990 | return bmap->n_eq == 0 && bmap->n_ineq == 0; |
||
6991 | } |
||
6992 | |||
6993 | int isl_basic_set_is_universe(struct isl_basic_set *bset) |
||
6994 | { |
||
6995 | if (!bset) |
||
6996 | return -1; |
||
6997 | return bset->n_eq == 0 && bset->n_ineq == 0; |
||
6998 | } |
||
6999 | |||
7000 | int isl_map_plain_is_universe(__isl_keep isl_map *map) |
||
7001 | { |
||
7002 | int i; |
||
7003 | |||
7004 | if (!map) |
||
7005 | return -1; |
||
7006 | |||
7007 | for (i = 0; i < map->n; ++i) { |
||
7008 | int r = isl_basic_map_is_universe(map->p[i]); |
||
7009 | if (r < 0 || r) |
||
7010 | return r; |
||
7011 | } |
||
7012 | |||
7013 | return 0; |
||
7014 | } |
||
7015 | |||
7016 | int isl_set_plain_is_universe(__isl_keep isl_set *set) |
||
7017 | { |
||
7018 | return isl_map_plain_is_universe((isl_map *) set); |
||
7019 | } |
||
7020 | |||
7021 | int isl_set_fast_is_universe(__isl_keep isl_set *set) |
||
7022 | { |
||
7023 | return isl_set_plain_is_universe(set); |
||
7024 | } |
||
7025 | |||
7026 | int isl_basic_map_is_empty(struct isl_basic_map *bmap) |
||
7027 | { |
||
7028 | struct isl_basic_set *bset = NULL; |
||
7029 | struct isl_vec *sample = NULL; |
||
7030 | int empty; |
||
7031 | unsigned total; |
||
7032 | |||
7033 | if (!bmap) |
||
7034 | return -1; |
||
7035 | |||
7036 | if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY)) |
||
7037 | return 1; |
||
7038 | |||
7039 | if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL)) { |
||
7040 | struct isl_basic_map *copy = isl_basic_map_copy(bmap); |
||
7041 | copy = isl_basic_map_remove_redundancies(copy); |
||
7042 | empty = ISL_F_ISSET(copy, ISL_BASIC_MAP_EMPTY); |
||
7043 | isl_basic_map_free(copy); |
||
7044 | return empty; |
||
7045 | } |
||
7046 | |||
7047 | total = 1 + isl_basic_map_total_dim(bmap); |
||
7048 | if (bmap->sample && bmap->sample->size == total) { |
||
7049 | int contains = isl_basic_map_contains(bmap, bmap->sample); |
||
7050 | if (contains < 0) |
||
7051 | return -1; |
||
7052 | if (contains) |
||
7053 | return 0; |
||
7054 | } |
||
7055 | isl_vec_free(bmap->sample); |
||
7056 | bmap->sample = NULL; |
||
7057 | bset = isl_basic_map_underlying_set(isl_basic_map_copy(bmap)); |
||
7058 | if (!bset) |
||
7059 | return -1; |
||
7060 | sample = isl_basic_set_sample_vec(bset); |
||
7061 | if (!sample) |
||
7062 | return -1; |
||
7063 | empty = sample->size == 0; |
||
7064 | isl_vec_free(bmap->sample); |
||
7065 | bmap->sample = sample; |
||
7066 | if (empty) |
||
7067 | ISL_F_SET(bmap, ISL_BASIC_MAP_EMPTY); |
||
7068 | |||
7069 | return empty; |
||
7070 | } |
||
7071 | |||
7072 | int isl_basic_map_plain_is_empty(__isl_keep isl_basic_map *bmap) |
||
7073 | { |
||
7074 | if (!bmap) |
||
7075 | return -1; |
||
7076 | return ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY); |
||
7077 | } |
||
7078 | |||
7079 | int isl_basic_map_fast_is_empty(__isl_keep isl_basic_map *bmap) |
||
7080 | { |
||
7081 | return isl_basic_map_plain_is_empty(bmap); |
||
7082 | } |
||
7083 | |||
7084 | int isl_basic_set_plain_is_empty(__isl_keep isl_basic_set *bset) |
||
7085 | { |
||
7086 | if (!bset) |
||
7087 | return -1; |
||
7088 | return ISL_F_ISSET(bset, ISL_BASIC_SET_EMPTY); |
||
7089 | } |
||
7090 | |||
7091 | int isl_basic_set_fast_is_empty(__isl_keep isl_basic_set *bset) |
||
7092 | { |
||
7093 | return isl_basic_set_plain_is_empty(bset); |
||
7094 | } |
||
7095 | |||
7096 | int isl_basic_set_is_empty(struct isl_basic_set *bset) |
||
7097 | { |
||
7098 | return isl_basic_map_is_empty((struct isl_basic_map *)bset); |
||
7099 | } |
||
7100 | |||
7101 | struct isl_map *isl_basic_map_union( |
||
7102 | struct isl_basic_map *bmap1, struct isl_basic_map *bmap2) |
||
7103 | { |
||
7104 | struct isl_map *map; |
||
7105 | if (!bmap1 || !bmap2) |
||
7106 | goto error; |
||
7107 | |||
7108 | isl_assert(bmap1->ctx, isl_space_is_equal(bmap1->dim, bmap2->dim), goto error); |
||
7109 | |||
7110 | map = isl_map_alloc_space(isl_space_copy(bmap1->dim), 2, 0); |
||
7111 | if (!map) |
||
7112 | goto error; |
||
7113 | map = isl_map_add_basic_map(map, bmap1); |
||
7114 | map = isl_map_add_basic_map(map, bmap2); |
||
7115 | return map; |
||
7116 | error: |
||
7117 | isl_basic_map_free(bmap1); |
||
7118 | isl_basic_map_free(bmap2); |
||
7119 | return NULL; |
||
7120 | } |
||
7121 | |||
7122 | struct isl_set *isl_basic_set_union( |
||
7123 | struct isl_basic_set *bset1, struct isl_basic_set *bset2) |
||
7124 | { |
||
7125 | return (struct isl_set *)isl_basic_map_union( |
||
7126 | (struct isl_basic_map *)bset1, |
||
7127 | (struct isl_basic_map *)bset2); |
||
7128 | } |
||
7129 | |||
7130 | /* Order divs such that any div only depends on previous divs */ |
||
7131 | struct isl_basic_map *isl_basic_map_order_divs(struct isl_basic_map *bmap) |
||
7132 | { |
||
7133 | int i; |
||
7134 | unsigned off; |
||
7135 | |||
7136 | if (!bmap) |
||
7137 | return NULL; |
||
7138 | |||
7139 | off = isl_space_dim(bmap->dim, isl_dim_all); |
||
7140 | |||
7141 | for (i = 0; i < bmap->n_div; ++i) { |
||
7142 | int pos; |
||
7143 | if (isl_int_is_zero(bmap->div[i][0])) |
||
7144 | continue; |
||
7145 | pos = isl_seq_first_non_zero(bmap->div[i]+1+1+off+i, |
||
7146 | bmap->n_div-i); |
||
7147 | if (pos == -1) |
||
7148 | continue; |
||
7149 | isl_basic_map_swap_div(bmap, i, i + pos); |
||
7150 | --i; |
||
7151 | } |
||
7152 | return bmap; |
||
7153 | } |
||
7154 | |||
7155 | struct isl_basic_set *isl_basic_set_order_divs(struct isl_basic_set *bset) |
||
7156 | { |
||
7157 | return (struct isl_basic_set *) |
||
7158 | isl_basic_map_order_divs((struct isl_basic_map *)bset); |
||
7159 | } |
||
7160 | |||
7161 | __isl_give isl_map *isl_map_order_divs(__isl_take isl_map *map) |
||
7162 | { |
||
7163 | int i; |
||
7164 | |||
7165 | if (!map) |
||
7166 | return 0; |
||
7167 | |||
7168 | for (i = 0; i < map->n; ++i) { |
||
7169 | map->p[i] = isl_basic_map_order_divs(map->p[i]); |
||
7170 | if (!map->p[i]) |
||
7171 | goto error; |
||
7172 | } |
||
7173 | |||
7174 | return map; |
||
7175 | error: |
||
7176 | isl_map_free(map); |
||
7177 | return NULL; |
||
7178 | } |
||
7179 | |||
7180 | /* Apply the expansion computed by isl_merge_divs. |
||
7181 | * The expansion itself is given by "exp" while the resulting |
||
7182 | * list of divs is given by "div". |
||
7183 | */ |
||
7184 | __isl_give isl_basic_set *isl_basic_set_expand_divs( |
||
7185 | __isl_take isl_basic_set *bset, __isl_take isl_mat *div, int *exp) |
||
7186 | { |
||
7187 | int i, j; |
||
7188 | int n_div; |
||
7189 | |||
7190 | bset = isl_basic_set_cow(bset); |
||
7191 | if (!bset || !div) |
||
7192 | goto error; |
||
7193 | |||
7194 | if (div->n_row < bset->n_div) |
||
7195 | isl_die(isl_mat_get_ctx(div), isl_error_invalid, |
||
7196 | "not an expansion", goto error); |
||
7197 | |||
7198 | bset = isl_basic_map_extend_space(bset, isl_space_copy(bset->dim), |
||
7199 | div->n_row - bset->n_div, 0, |
||
7200 | 2 * (div->n_row - bset->n_div)); |
||
7201 | |||
7202 | n_div = bset->n_div; |
||
7203 | for (i = n_div; i < div->n_row; ++i) |
||
7204 | if (isl_basic_set_alloc_div(bset) < 0) |
||
7205 | goto error; |
||
7206 | |||
7207 | j = n_div - 1; |
||
7208 | for (i = div->n_row - 1; i >= 0; --i) { |
||
7209 | if (j >= 0 && exp[j] == i) { |
||
7210 | if (i != j) |
||
7211 | isl_basic_map_swap_div(bset, i, j); |
||
7212 | j--; |
||
7213 | } else { |
||
7214 | isl_seq_cpy(bset->div[i], div->row[i], div->n_col); |
||
7215 | if (isl_basic_map_add_div_constraints(bset, i) < 0) |
||
7216 | goto error; |
||
7217 | } |
||
7218 | } |
||
7219 | |||
7220 | isl_mat_free(div); |
||
7221 | return bset; |
||
7222 | error: |
||
7223 | isl_basic_set_free(bset); |
||
7224 | isl_mat_free(div); |
||
7225 | return NULL; |
||
7226 | } |
||
7227 | |||
7228 | /* Look for a div in dst that corresponds to the div "div" in src. |
||
7229 | * The divs before "div" in src and dst are assumed to be the same. |
||
7230 | * |
||
7231 | * Returns -1 if no corresponding div was found and the position |
||
7232 | * of the corresponding div in dst otherwise. |
||
7233 | */ |
||
7234 | static int find_div(struct isl_basic_map *dst, |
||
7235 | struct isl_basic_map *src, unsigned div) |
||
7236 | { |
||
7237 | int i; |
||
7238 | |||
7239 | unsigned total = isl_space_dim(src->dim, isl_dim_all); |
||
7240 | |||
7241 | isl_assert(dst->ctx, div <= dst->n_div, return -1); |
||
7242 | for (i = div; i < dst->n_div; ++i) |
||
7243 | if (isl_seq_eq(dst->div[i], src->div[div], 1+1+total+div) && |
||
7244 | isl_seq_first_non_zero(dst->div[i]+1+1+total+div, |
||
7245 | dst->n_div - div) == -1) |
||
7246 | return i; |
||
7247 | return -1; |
||
7248 | } |
||
7249 | |||
7250 | struct isl_basic_map *isl_basic_map_align_divs( |
||
7251 | struct isl_basic_map *dst, struct isl_basic_map *src) |
||
7252 | { |
||
7253 | int i; |
||
7254 | unsigned total = isl_space_dim(src->dim, isl_dim_all); |
||
7255 | |||
7256 | if (!dst || !src) |
||
7257 | goto error; |
||
7258 | |||
7259 | if (src->n_div == 0) |
||
7260 | return dst; |
||
7261 | |||
7262 | for (i = 0; i < src->n_div; ++i) |
||
7263 | isl_assert(src->ctx, !isl_int_is_zero(src->div[i][0]), goto error); |
||
7264 | |||
7265 | src = isl_basic_map_order_divs(src); |
||
7266 | dst = isl_basic_map_cow(dst); |
||
7267 | dst = isl_basic_map_extend_space(dst, isl_space_copy(dst->dim), |
||
7268 | src->n_div, 0, 2 * src->n_div); |
||
7269 | if (!dst) |
||
7270 | return NULL; |
||
7271 | for (i = 0; i < src->n_div; ++i) { |
||
7272 | int j = find_div(dst, src, i); |
||
7273 | if (j < 0) { |
||
7274 | j = isl_basic_map_alloc_div(dst); |
||
7275 | if (j < 0) |
||
7276 | goto error; |
||
7277 | isl_seq_cpy(dst->div[j], src->div[i], 1+1+total+i); |
||
7278 | isl_seq_clr(dst->div[j]+1+1+total+i, dst->n_div - i); |
||
7279 | if (isl_basic_map_add_div_constraints(dst, j) < 0) |
||
7280 | goto error; |
||
7281 | } |
||
7282 | if (j != i) |
||
7283 | isl_basic_map_swap_div(dst, i, j); |
||
7284 | } |
||
7285 | return dst; |
||
7286 | error: |
||
7287 | isl_basic_map_free(dst); |
||
7288 | return NULL; |
||
7289 | } |
||
7290 | |||
7291 | struct isl_basic_set *isl_basic_set_align_divs( |
||
7292 | struct isl_basic_set *dst, struct isl_basic_set *src) |
||
7293 | { |
||
7294 | return (struct isl_basic_set *)isl_basic_map_align_divs( |
||
7295 | (struct isl_basic_map *)dst, (struct isl_basic_map *)src); |
||
7296 | } |
||
7297 | |||
7298 | struct isl_map *isl_map_align_divs(struct isl_map *map) |
||
7299 | { |
||
7300 | int i; |
||
7301 | |||
7302 | if (!map) |
||
7303 | return NULL; |
||
7304 | if (map->n == 0) |
||
7305 | return map; |
||
7306 | map = isl_map_compute_divs(map); |
||
7307 | map = isl_map_cow(map); |
||
7308 | if (!map) |
||
7309 | return NULL; |
||
7310 | |||
7311 | for (i = 1; i < map->n; ++i) |
||
7312 | map->p[0] = isl_basic_map_align_divs(map->p[0], map->p[i]); |
||
7313 | for (i = 1; i < map->n; ++i) |
||
7314 | map->p[i] = isl_basic_map_align_divs(map->p[i], map->p[0]); |
||
7315 | |||
7316 | ISL_F_CLR(map, ISL_MAP_NORMALIZED); |
||
7317 | return map; |
||
7318 | } |
||
7319 | |||
7320 | struct isl_set *isl_set_align_divs(struct isl_set *set) |
||
7321 | { |
||
7322 | return (struct isl_set *)isl_map_align_divs((struct isl_map *)set); |
||
7323 | } |
||
7324 | |||
7325 | static __isl_give isl_set *set_apply( __isl_take isl_set *set, |
||
7326 | __isl_take isl_map *map) |
||
7327 | { |
||
7328 | if (!set || !map) |
||
7329 | goto error; |
||
7330 | isl_assert(set->ctx, isl_map_compatible_domain(map, set), goto error); |
||
7331 | map = isl_map_intersect_domain(map, set); |
||
7332 | set = isl_map_range(map); |
||
7333 | return set; |
||
7334 | error: |
||
7335 | isl_set_free(set); |
||
7336 | isl_map_free(map); |
||
7337 | return NULL; |
||
7338 | } |
||
7339 | |||
7340 | __isl_give isl_set *isl_set_apply( __isl_take isl_set *set, |
||
7341 | __isl_take isl_map *map) |
||
7342 | { |
||
7343 | return isl_map_align_params_map_map_and(set, map, &set_apply); |
||
7344 | } |
||
7345 | |||
7346 | /* There is no need to cow as removing empty parts doesn't change |
||
7347 | * the meaning of the set. |
||
7348 | */ |
||
7349 | struct isl_map *isl_map_remove_empty_parts(struct isl_map *map) |
||
7350 | { |
||
7351 | int i; |
||
7352 | |||
7353 | if (!map) |
||
7354 | return NULL; |
||
7355 | |||
7356 | for (i = map->n - 1; i >= 0; --i) |
||
7357 | remove_if_empty(map, i); |
||
7358 | |||
7359 | return map; |
||
7360 | } |
||
7361 | |||
7362 | struct isl_set *isl_set_remove_empty_parts(struct isl_set *set) |
||
7363 | { |
||
7364 | return (struct isl_set *) |
||
7365 | isl_map_remove_empty_parts((struct isl_map *)set); |
||
7366 | } |
||
7367 | |||
7368 | struct isl_basic_map *isl_map_copy_basic_map(struct isl_map *map) |
||
7369 | { |
||
7370 | struct isl_basic_map *bmap; |
||
7371 | if (!map || map->n == 0) |
||
7372 | return NULL; |
||
7373 | bmap = map->p[map->n-1]; |
||
7374 | isl_assert(map->ctx, ISL_F_ISSET(bmap, ISL_BASIC_SET_FINAL), return NULL); |
||
7375 | return isl_basic_map_copy(bmap); |
||
7376 | } |
||
7377 | |||
7378 | struct isl_basic_set *isl_set_copy_basic_set(struct isl_set *set) |
||
7379 | { |
||
7380 | return (struct isl_basic_set *) |
||
7381 | isl_map_copy_basic_map((struct isl_map *)set); |
||
7382 | } |
||
7383 | |||
7384 | __isl_give isl_map *isl_map_drop_basic_map(__isl_take isl_map *map, |
||
7385 | __isl_keep isl_basic_map *bmap) |
||
7386 | { |
||
7387 | int i; |
||
7388 | |||
7389 | if (!map || !bmap) |
||
7390 | goto error; |
||
7391 | for (i = map->n-1; i >= 0; --i) { |
||
7392 | if (map->p[i] != bmap) |
||
7393 | continue; |
||
7394 | map = isl_map_cow(map); |
||
7395 | if (!map) |
||
7396 | goto error; |
||
7397 | isl_basic_map_free(map->p[i]); |
||
7398 | if (i != map->n-1) { |
||
7399 | ISL_F_CLR(map, ISL_SET_NORMALIZED); |
||
7400 | map->p[i] = map->p[map->n-1]; |
||
7401 | } |
||
7402 | map->n--; |
||
7403 | return map; |
||
7404 | } |
||
7405 | return map; |
||
7406 | error: |
||
7407 | isl_map_free(map); |
||
7408 | return NULL; |
||
7409 | } |
||
7410 | |||
7411 | struct isl_set *isl_set_drop_basic_set(struct isl_set *set, |
||
7412 | struct isl_basic_set *bset) |
||
7413 | { |
||
7414 | return (struct isl_set *)isl_map_drop_basic_map((struct isl_map *)set, |
||
7415 | (struct isl_basic_map *)bset); |
||
7416 | } |
||
7417 | |||
7418 | /* Given two basic sets bset1 and bset2, compute the maximal difference |
||
7419 | * between the values of dimension pos in bset1 and those in bset2 |
||
7420 | * for any common value of the parameters and dimensions preceding pos. |
||
7421 | */ |
||
7422 | static enum isl_lp_result basic_set_maximal_difference_at( |
||
7423 | __isl_keep isl_basic_set *bset1, __isl_keep isl_basic_set *bset2, |
||
7424 | int pos, isl_int *opt) |
||
7425 | { |
||
7426 | isl_space *dims; |
||
7427 | struct isl_basic_map *bmap1 = NULL; |
||
7428 | struct isl_basic_map *bmap2 = NULL; |
||
7429 | struct isl_ctx *ctx; |
||
7430 | struct isl_vec *obj; |
||
7431 | unsigned total; |
||
7432 | unsigned nparam; |
||
7433 | unsigned dim1, dim2; |
||
7434 | enum isl_lp_result res; |
||
7435 | |||
7436 | if (!bset1 || !bset2) |
||
7437 | return isl_lp_error; |
||
7438 | |||
7439 | nparam = isl_basic_set_n_param(bset1); |
||
7440 | dim1 = isl_basic_set_n_dim(bset1); |
||
7441 | dim2 = isl_basic_set_n_dim(bset2); |
||
7442 | dims = isl_space_alloc(bset1->ctx, nparam, pos, dim1 - pos); |
||
7443 | bmap1 = isl_basic_map_from_basic_set(isl_basic_set_copy(bset1), dims); |
||
7444 | dims = isl_space_alloc(bset2->ctx, nparam, pos, dim2 - pos); |
||
7445 | bmap2 = isl_basic_map_from_basic_set(isl_basic_set_copy(bset2), dims); |
||
7446 | if (!bmap1 || !bmap2) |
||
7447 | goto error; |
||
7448 | bmap1 = isl_basic_map_cow(bmap1); |
||
7449 | bmap1 = isl_basic_map_extend(bmap1, nparam, |
||
7450 | pos, (dim1 - pos) + (dim2 - pos), |
||
7451 | bmap2->n_div, bmap2->n_eq, bmap2->n_ineq); |
||
7452 | bmap1 = add_constraints(bmap1, bmap2, 0, dim1 - pos); |
||
7453 | if (!bmap1) |
||
7454 | goto error; |
||
7455 | total = isl_basic_map_total_dim(bmap1); |
||
7456 | ctx = bmap1->ctx; |
||
7457 | obj = isl_vec_alloc(ctx, 1 + total); |
||
7458 | isl_seq_clr(obj->block.data, 1 + total); |
||
7459 | isl_int_set_si(obj->block.data[1+nparam+pos], 1); |
||
7460 | isl_int_set_si(obj->block.data[1+nparam+pos+(dim1-pos)], -1); |
||
7461 | if (!obj) |
||
7462 | goto error; |
||
7463 | res = isl_basic_map_solve_lp(bmap1, 1, obj->block.data, ctx->one, |
||
7464 | opt, NULL, NULL); |
||
7465 | isl_basic_map_free(bmap1); |
||
7466 | isl_vec_free(obj); |
||
7467 | return res; |
||
7468 | error: |
||
7469 | isl_basic_map_free(bmap1); |
||
7470 | isl_basic_map_free(bmap2); |
||
7471 | return isl_lp_error; |
||
7472 | } |
||
7473 | |||
7474 | /* Given two _disjoint_ basic sets bset1 and bset2, check whether |
||
7475 | * for any common value of the parameters and dimensions preceding pos |
||
7476 | * in both basic sets, the values of dimension pos in bset1 are |
||
7477 | * smaller or larger than those in bset2. |
||
7478 | * |
||
7479 | * Returns |
||
7480 | * 1 if bset1 follows bset2 |
||
7481 | * -1 if bset1 precedes bset2 |
||
7482 | * 0 if bset1 and bset2 are incomparable |
||
7483 | * -2 if some error occurred. |
||
7484 | */ |
||
7485 | int isl_basic_set_compare_at(struct isl_basic_set *bset1, |
||
7486 | struct isl_basic_set *bset2, int pos) |
||
7487 | { |
||
7488 | isl_int opt; |
||
7489 | enum isl_lp_result res; |
||
7490 | int cmp; |
||
7491 | |||
7492 | isl_int_init(opt); |
||
7493 | |||
7494 | res = basic_set_maximal_difference_at(bset1, bset2, pos, &opt); |
||
7495 | |||
7496 | if (res == isl_lp_empty) |
||
7497 | cmp = 0; |
||
7498 | else if ((res == isl_lp_ok && isl_int_is_pos(opt)) || |
||
7499 | res == isl_lp_unbounded) |
||
7500 | cmp = 1; |
||
7501 | else if (res == isl_lp_ok && isl_int_is_neg(opt)) |
||
7502 | cmp = -1; |
||
7503 | else |
||
7504 | cmp = -2; |
||
7505 | |||
7506 | isl_int_clear(opt); |
||
7507 | return cmp; |
||
7508 | } |
||
7509 | |||
7510 | /* Given two basic sets bset1 and bset2, check whether |
||
7511 | * for any common value of the parameters and dimensions preceding pos |
||
7512 | * there is a value of dimension pos in bset1 that is larger |
||
7513 | * than a value of the same dimension in bset2. |
||
7514 | * |
||
7515 | * Return |
||
7516 | * 1 if there exists such a pair |
||
7517 | * 0 if there is no such pair, but there is a pair of equal values |
||
7518 | * -1 otherwise |
||
7519 | * -2 if some error occurred. |
||
7520 | */ |
||
7521 | int isl_basic_set_follows_at(__isl_keep isl_basic_set *bset1, |
||
7522 | __isl_keep isl_basic_set *bset2, int pos) |
||
7523 | { |
||
7524 | isl_int opt; |
||
7525 | enum isl_lp_result res; |
||
7526 | int cmp; |
||
7527 | |||
7528 | isl_int_init(opt); |
||
7529 | |||
7530 | res = basic_set_maximal_difference_at(bset1, bset2, pos, &opt); |
||
7531 | |||
7532 | if (res == isl_lp_empty) |
||
7533 | cmp = -1; |
||
7534 | else if ((res == isl_lp_ok && isl_int_is_pos(opt)) || |
||
7535 | res == isl_lp_unbounded) |
||
7536 | cmp = 1; |
||
7537 | else if (res == isl_lp_ok && isl_int_is_neg(opt)) |
||
7538 | cmp = -1; |
||
7539 | else if (res == isl_lp_ok) |
||
7540 | cmp = 0; |
||
7541 | else |
||
7542 | cmp = -2; |
||
7543 | |||
7544 | isl_int_clear(opt); |
||
7545 | return cmp; |
||
7546 | } |
||
7547 | |||
7548 | /* Given two sets set1 and set2, check whether |
||
7549 | * for any common value of the parameters and dimensions preceding pos |
||
7550 | * there is a value of dimension pos in set1 that is larger |
||
7551 | * than a value of the same dimension in set2. |
||
7552 | * |
||
7553 | * Return |
||
7554 | * 1 if there exists such a pair |
||
7555 | * 0 if there is no such pair, but there is a pair of equal values |
||
7556 | * -1 otherwise |
||
7557 | * -2 if some error occurred. |
||
7558 | */ |
||
7559 | int isl_set_follows_at(__isl_keep isl_set *set1, |
||
7560 | __isl_keep isl_set *set2, int pos) |
||
7561 | { |
||
7562 | int i, j; |
||
7563 | int follows = -1; |
||
7564 | |||
7565 | if (!set1 || !set2) |
||
7566 | return -2; |
||
7567 | |||
7568 | for (i = 0; i < set1->n; ++i) |
||
7569 | for (j = 0; j < set2->n; ++j) { |
||
7570 | int f; |
||
7571 | f = isl_basic_set_follows_at(set1->p[i], set2->p[j], pos); |
||
7572 | if (f == 1 || f == -2) |
||
7573 | return f; |
||
7574 | if (f > follows) |
||
7575 | follows = f; |
||
7576 | } |
||
7577 | |||
7578 | return follows; |
||
7579 | } |
||
7580 | |||
7581 | static int isl_basic_map_plain_has_fixed_var(__isl_keep isl_basic_map *bmap, |
||
7582 | unsigned pos, isl_int *val) |
||
7583 | { |
||
7584 | int i; |
||
7585 | int d; |
||
7586 | unsigned total; |
||
7587 | |||
7588 | if (!bmap) |
||
7589 | return -1; |
||
7590 | total = isl_basic_map_total_dim(bmap); |
||
7591 | for (i = 0, d = total-1; i < bmap->n_eq && d+1 > pos; ++i) { |
||
7592 | for (; d+1 > pos; --d) |
||
7593 | if (!isl_int_is_zero(bmap->eq[i][1+d])) |
||
7594 | break; |
||
7595 | if (d != pos) |
||
7596 | continue; |
||
7597 | if (isl_seq_first_non_zero(bmap->eq[i]+1, d) != -1) |
||
7598 | return 0; |
||
7599 | if (isl_seq_first_non_zero(bmap->eq[i]+1+d+1, total-d-1) != -1) |
||
7600 | return 0; |
||
7601 | if (!isl_int_is_one(bmap->eq[i][1+d])) |
||
7602 | return 0; |
||
7603 | if (val) |
||
7604 | isl_int_neg(*val, bmap->eq[i][0]); |
||
7605 | return 1; |
||
7606 | } |
||
7607 | return 0; |
||
7608 | } |
||
7609 | |||
7610 | static int isl_map_plain_has_fixed_var(__isl_keep isl_map *map, |
||
7611 | unsigned pos, isl_int *val) |
||
7612 | { |
||
7613 | int i; |
||
7614 | isl_int v; |
||
7615 | isl_int tmp; |
||
7616 | int fixed; |
||
7617 | |||
7618 | if (!map) |
||
7619 | return -1; |
||
7620 | if (map->n == 0) |
||
7621 | return 0; |
||
7622 | if (map->n == 1) |
||
7623 | return isl_basic_map_plain_has_fixed_var(map->p[0], pos, val); |
||
7624 | isl_int_init(v); |
||
7625 | isl_int_init(tmp); |
||
7626 | fixed = isl_basic_map_plain_has_fixed_var(map->p[0], pos, &v); |
||
7627 | for (i = 1; fixed == 1 && i < map->n; ++i) { |
||
7628 | fixed = isl_basic_map_plain_has_fixed_var(map->p[i], pos, &tmp); |
||
7629 | if (fixed == 1 && isl_int_ne(tmp, v)) |
||
7630 | fixed = 0; |
||
7631 | } |
||
7632 | if (val) |
||
7633 | isl_int_set(*val, v); |
||
7634 | isl_int_clear(tmp); |
||
7635 | isl_int_clear(v); |
||
7636 | return fixed; |
||
7637 | } |
||
7638 | |||
7639 | static int isl_basic_set_plain_has_fixed_var(__isl_keep isl_basic_set *bset, |
||
7640 | unsigned pos, isl_int *val) |
||
7641 | { |
||
7642 | return isl_basic_map_plain_has_fixed_var((struct isl_basic_map *)bset, |
||
7643 | pos, val); |
||
7644 | } |
||
7645 | |||
7646 | static int isl_set_plain_has_fixed_var(__isl_keep isl_set *set, unsigned pos, |
||
7647 | isl_int *val) |
||
7648 | { |
||
7649 | return isl_map_plain_has_fixed_var((struct isl_map *)set, pos, val); |
||
7650 | } |
||
7651 | |||
7652 | int isl_basic_map_plain_is_fixed(__isl_keep isl_basic_map *bmap, |
||
7653 | enum isl_dim_type type, unsigned pos, isl_int *val) |
||
7654 | { |
||
7655 | if (pos >= isl_basic_map_dim(bmap, type)) |
||
7656 | return -1; |
||
7657 | return isl_basic_map_plain_has_fixed_var(bmap, |
||
7658 | isl_basic_map_offset(bmap, type) - 1 + pos, val); |
||
7659 | } |
||
7660 | |||
7661 | int isl_map_plain_is_fixed(__isl_keep isl_map *map, |
||
7662 | enum isl_dim_type type, unsigned pos, isl_int *val) |
||
7663 | { |
||
7664 | if (pos >= isl_map_dim(map, type)) |
||
7665 | return -1; |
||
7666 | return isl_map_plain_has_fixed_var(map, |
||
7667 | map_offset(map, type) - 1 + pos, val); |
||
7668 | } |
||
7669 | |||
7670 | int isl_set_plain_is_fixed(__isl_keep isl_set *set, |
||
7671 | enum isl_dim_type type, unsigned pos, isl_int *val) |
||
7672 | { |
||
7673 | return isl_map_plain_is_fixed(set, type, pos, val); |
||
7674 | } |
||
7675 | |||
7676 | int isl_map_fast_is_fixed(__isl_keep isl_map *map, |
||
7677 | enum isl_dim_type type, unsigned pos, isl_int *val) |
||
7678 | { |
||
7679 | return isl_map_plain_is_fixed(map, type, pos, val); |
||
7680 | } |
||
7681 | |||
7682 | /* Check if dimension dim has fixed value and if so and if val is not NULL, |
||
7683 | * then return this fixed value in *val. |
||
7684 | */ |
||
7685 | int isl_basic_set_plain_dim_is_fixed(__isl_keep isl_basic_set *bset, |
||
7686 | unsigned dim, isl_int *val) |
||
7687 | { |
||
7688 | return isl_basic_set_plain_has_fixed_var(bset, |
||
7689 | isl_basic_set_n_param(bset) + dim, val); |
||
7690 | } |
||
7691 | |||
7692 | /* Check if dimension dim has fixed value and if so and if val is not NULL, |
||
7693 | * then return this fixed value in *val. |
||
7694 | */ |
||
7695 | int isl_set_plain_dim_is_fixed(__isl_keep isl_set *set, |
||
7696 | unsigned dim, isl_int *val) |
||
7697 | { |
||
7698 | return isl_set_plain_has_fixed_var(set, isl_set_n_param(set) + dim, val); |
||
7699 | } |
||
7700 | |||
7701 | int isl_set_fast_dim_is_fixed(__isl_keep isl_set *set, |
||
7702 | unsigned dim, isl_int *val) |
||
7703 | { |
||
7704 | return isl_set_plain_dim_is_fixed(set, dim, val); |
||
7705 | } |
||
7706 | |||
7707 | /* Check if input variable in has fixed value and if so and if val is not NULL, |
||
7708 | * then return this fixed value in *val. |
||
7709 | */ |
||
7710 | int isl_map_plain_input_is_fixed(__isl_keep isl_map *map, |
||
7711 | unsigned in, isl_int *val) |
||
7712 | { |
||
7713 | return isl_map_plain_has_fixed_var(map, isl_map_n_param(map) + in, val); |
||
7714 | } |
||
7715 | |||
7716 | /* Check if dimension dim has an (obvious) fixed lower bound and if so |
||
7717 | * and if val is not NULL, then return this lower bound in *val. |
||
7718 | */ |
||
7719 | int isl_basic_set_plain_dim_has_fixed_lower_bound( |
||
7720 | __isl_keep isl_basic_set *bset, unsigned dim, isl_int *val) |
||
7721 | { |
||
7722 | int i, i_eq = -1, i_ineq = -1; |
||
7723 | isl_int *c; |
||
7724 | unsigned total; |
||
7725 | unsigned nparam; |
||
7726 | |||
7727 | if (!bset) |
||
7728 | return -1; |
||
7729 | total = isl_basic_set_total_dim(bset); |
||
7730 | nparam = isl_basic_set_n_param(bset); |
||
7731 | for (i = 0; i < bset->n_eq; ++i) { |
||
7732 | if (isl_int_is_zero(bset->eq[i][1+nparam+dim])) |
||
7733 | continue; |
||
7734 | if (i_eq != -1) |
||
7735 | return 0; |
||
7736 | i_eq = i; |
||
7737 | } |
||
7738 | for (i = 0; i < bset->n_ineq; ++i) { |
||
7739 | if (!isl_int_is_pos(bset->ineq[i][1+nparam+dim])) |
||
7740 | continue; |
||
7741 | if (i_eq != -1 || i_ineq != -1) |
||
7742 | return 0; |
||
7743 | i_ineq = i; |
||
7744 | } |
||
7745 | if (i_eq == -1 && i_ineq == -1) |
||
7746 | return 0; |
||
7747 | c = i_eq != -1 ? bset->eq[i_eq] : bset->ineq[i_ineq]; |
||
7748 | /* The coefficient should always be one due to normalization. */ |
||
7749 | if (!isl_int_is_one(c[1+nparam+dim])) |
||
7750 | return 0; |
||
7751 | if (isl_seq_first_non_zero(c+1, nparam+dim) != -1) |
||
7752 | return 0; |
||
7753 | if (isl_seq_first_non_zero(c+1+nparam+dim+1, |
||
7754 | total - nparam - dim - 1) != -1) |
||
7755 | return 0; |
||
7756 | if (val) |
||
7757 | isl_int_neg(*val, c[0]); |
||
7758 | return 1; |
||
7759 | } |
||
7760 | |||
7761 | int isl_set_plain_dim_has_fixed_lower_bound(__isl_keep isl_set *set, |
||
7762 | unsigned dim, isl_int *val) |
||
7763 | { |
||
7764 | int i; |
||
7765 | isl_int v; |
||
7766 | isl_int tmp; |
||
7767 | int fixed; |
||
7768 | |||
7769 | if (!set) |
||
7770 | return -1; |
||
7771 | if (set->n == 0) |
||
7772 | return 0; |
||
7773 | if (set->n == 1) |
||
7774 | return isl_basic_set_plain_dim_has_fixed_lower_bound(set->p[0], |
||
7775 | dim, val); |
||
7776 | isl_int_init(v); |
||
7777 | isl_int_init(tmp); |
||
7778 | fixed = isl_basic_set_plain_dim_has_fixed_lower_bound(set->p[0], |
||
7779 | dim, &v); |
||
7780 | for (i = 1; fixed == 1 && i < set->n; ++i) { |
||
7781 | fixed = isl_basic_set_plain_dim_has_fixed_lower_bound(set->p[i], |
||
7782 | dim, &tmp); |
||
7783 | if (fixed == 1 && isl_int_ne(tmp, v)) |
||
7784 | fixed = 0; |
||
7785 | } |
||
7786 | if (val) |
||
7787 | isl_int_set(*val, v); |
||
7788 | isl_int_clear(tmp); |
||
7789 | isl_int_clear(v); |
||
7790 | return fixed; |
||
7791 | } |
||
7792 | |||
7793 | struct constraint { |
||
7794 | unsigned size; |
||
7795 | isl_int *c; |
||
7796 | }; |
||
7797 | |||
7798 | /* uset_gist depends on constraints without existentially quantified |
||
7799 | * variables sorting first. |
||
7800 | */ |
||
7801 | static int qsort_constraint_cmp(const void *p1, const void *p2) |
||
7802 | { |
||
7803 | const struct constraint *c1 = (const struct constraint *)p1; |
||
7804 | const struct constraint *c2 = (const struct constraint *)p2; |
||
7805 | int l1, l2; |
||
7806 | unsigned size = isl_min(c1->size, c2->size); |
||
7807 | |||
7808 | l1 = isl_seq_last_non_zero(c1->c, size); |
||
7809 | l2 = isl_seq_last_non_zero(c2->c, size); |
||
7810 | |||
7811 | if (l1 != l2) |
||
7812 | return l1 - l2; |
||
7813 | |||
7814 | return isl_seq_cmp(c1->c, c2->c, size); |
||
7815 | } |
||
7816 | |||
7817 | static struct isl_basic_map *isl_basic_map_sort_constraints( |
||
7818 | struct isl_basic_map *bmap) |
||
7819 | { |
||
7820 | int i; |
||
7821 | struct constraint *c; |
||
7822 | unsigned total; |
||
7823 | |||
7824 | if (!bmap) |
||
7825 | return NULL; |
||
7826 | total = isl_basic_map_total_dim(bmap); |
||
7827 | c = isl_alloc_array(bmap->ctx, struct constraint, bmap->n_ineq); |
||
7828 | if (!c) |
||
7829 | goto error; |
||
7830 | for (i = 0; i < bmap->n_ineq; ++i) { |
||
7831 | c[i].size = total; |
||
7832 | c[i].c = bmap->ineq[i]; |
||
7833 | } |
||
7834 | qsort(c, bmap->n_ineq, sizeof(struct constraint), qsort_constraint_cmp); |
||
7835 | for (i = 0; i < bmap->n_ineq; ++i) |
||
7836 | bmap->ineq[i] = c[i].c; |
||
7837 | free(c); |
||
7838 | return bmap; |
||
7839 | error: |
||
7840 | isl_basic_map_free(bmap); |
||
7841 | return NULL; |
||
7842 | } |
||
7843 | |||
7844 | __isl_give isl_basic_set *isl_basic_set_sort_constraints( |
||
7845 | __isl_take isl_basic_set *bset) |
||
7846 | { |
||
7847 | return (struct isl_basic_set *)isl_basic_map_sort_constraints( |
||
7848 | (struct isl_basic_map *)bset); |
||
7849 | } |
||
7850 | |||
7851 | struct isl_basic_map *isl_basic_map_normalize(struct isl_basic_map *bmap) |
||
7852 | { |
||
7853 | if (!bmap) |
||
7854 | return NULL; |
||
7855 | if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_NORMALIZED)) |
||
7856 | return bmap; |
||
7857 | bmap = isl_basic_map_remove_redundancies(bmap); |
||
7858 | bmap = isl_basic_map_sort_constraints(bmap); |
||
7859 | ISL_F_SET(bmap, ISL_BASIC_MAP_NORMALIZED); |
||
7860 | return bmap; |
||
7861 | } |
||
7862 | |||
7863 | struct isl_basic_set *isl_basic_set_normalize(struct isl_basic_set *bset) |
||
7864 | { |
||
7865 | return (struct isl_basic_set *)isl_basic_map_normalize( |
||
7866 | (struct isl_basic_map *)bset); |
||
7867 | } |
||
7868 | |||
7869 | int isl_basic_map_plain_cmp(const __isl_keep isl_basic_map *bmap1, |
||
7870 | const __isl_keep isl_basic_map *bmap2) |
||
7871 | { |
||
7872 | int i, cmp; |
||
7873 | unsigned total; |
||
7874 | |||
7875 | if (bmap1 == bmap2) |
||
7876 | return 0; |
||
7877 | if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_RATIONAL) != |
||
7878 | ISL_F_ISSET(bmap2, ISL_BASIC_MAP_RATIONAL)) |
||
7879 | return ISL_F_ISSET(bmap1, ISL_BASIC_MAP_RATIONAL) ? -1 : 1; |
||
7880 | if (isl_basic_map_n_param(bmap1) != isl_basic_map_n_param(bmap2)) |
||
7881 | return isl_basic_map_n_param(bmap1) - isl_basic_map_n_param(bmap2); |
||
7882 | if (isl_basic_map_n_in(bmap1) != isl_basic_map_n_in(bmap2)) |
||
7883 | return isl_basic_map_n_out(bmap1) - isl_basic_map_n_out(bmap2); |
||
7884 | if (isl_basic_map_n_out(bmap1) != isl_basic_map_n_out(bmap2)) |
||
7885 | return isl_basic_map_n_out(bmap1) - isl_basic_map_n_out(bmap2); |
||
7886 | if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_EMPTY) && |
||
7887 | ISL_F_ISSET(bmap2, ISL_BASIC_MAP_EMPTY)) |
||
7888 | return 0; |
||
7889 | if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_EMPTY)) |
||
7890 | return 1; |
||
7891 | if (ISL_F_ISSET(bmap2, ISL_BASIC_MAP_EMPTY)) |
||
7892 | return -1; |
||
7893 | if (bmap1->n_eq != bmap2->n_eq) |
||
7894 | return bmap1->n_eq - bmap2->n_eq; |
||
7895 | if (bmap1->n_ineq != bmap2->n_ineq) |
||
7896 | return bmap1->n_ineq - bmap2->n_ineq; |
||
7897 | if (bmap1->n_div != bmap2->n_div) |
||
7898 | return bmap1->n_div - bmap2->n_div; |
||
7899 | total = isl_basic_map_total_dim(bmap1); |
||
7900 | for (i = 0; i < bmap1->n_eq; ++i) { |
||
7901 | cmp = isl_seq_cmp(bmap1->eq[i], bmap2->eq[i], 1+total); |
||
7902 | if (cmp) |
||
7903 | return cmp; |
||
7904 | } |
||
7905 | for (i = 0; i < bmap1->n_ineq; ++i) { |
||
7906 | cmp = isl_seq_cmp(bmap1->ineq[i], bmap2->ineq[i], 1+total); |
||
7907 | if (cmp) |
||
7908 | return cmp; |
||
7909 | } |
||
7910 | for (i = 0; i < bmap1->n_div; ++i) { |
||
7911 | cmp = isl_seq_cmp(bmap1->div[i], bmap2->div[i], 1+1+total); |
||
7912 | if (cmp) |
||
7913 | return cmp; |
||
7914 | } |
||
7915 | return 0; |
||
7916 | } |
||
7917 | |||
7918 | int isl_basic_set_plain_cmp(const __isl_keep isl_basic_set *bset1, |
||
7919 | const __isl_keep isl_basic_set *bset2) |
||
7920 | { |
||
7921 | return isl_basic_map_plain_cmp(bset1, bset2); |
||
7922 | } |
||
7923 | |||
7924 | int isl_set_plain_cmp(const __isl_keep isl_set *set1, |
||
7925 | const __isl_keep isl_set *set2) |
||
7926 | { |
||
7927 | int i, cmp; |
||
7928 | |||
7929 | if (set1 == set2) |
||
7930 | return 0; |
||
7931 | if (set1->n != set2->n) |
||
7932 | return set1->n - set2->n; |
||
7933 | |||
7934 | for (i = 0; i < set1->n; ++i) { |
||
7935 | cmp = isl_basic_set_plain_cmp(set1->p[i], set2->p[i]); |
||
7936 | if (cmp) |
||
7937 | return cmp; |
||
7938 | } |
||
7939 | |||
7940 | return 0; |
||
7941 | } |
||
7942 | |||
7943 | int isl_basic_map_plain_is_equal(__isl_keep isl_basic_map *bmap1, |
||
7944 | __isl_keep isl_basic_map *bmap2) |
||
7945 | { |
||
7946 | return isl_basic_map_plain_cmp(bmap1, bmap2) == 0; |
||
7947 | } |
||
7948 | |||
7949 | int isl_basic_set_plain_is_equal(__isl_keep isl_basic_set *bset1, |
||
7950 | __isl_keep isl_basic_set *bset2) |
||
7951 | { |
||
7952 | return isl_basic_map_plain_is_equal((isl_basic_map *)bset1, |
||
7953 | (isl_basic_map *)bset2); |
||
7954 | } |
||
7955 | |||
7956 | static int qsort_bmap_cmp(const void *p1, const void *p2) |
||
7957 | { |
||
7958 | const struct isl_basic_map *bmap1 = *(const struct isl_basic_map **)p1; |
||
7959 | const struct isl_basic_map *bmap2 = *(const struct isl_basic_map **)p2; |
||
7960 | |||
7961 | return isl_basic_map_plain_cmp(bmap1, bmap2); |
||
7962 | } |
||
7963 | |||
7964 | /* We normalize in place, but if anything goes wrong we need |
||
7965 | * to return NULL, so we need to make sure we don't change the |
||
7966 | * meaning of any possible other copies of map. |
||
7967 | */ |
||
7968 | struct isl_map *isl_map_normalize(struct isl_map *map) |
||
7969 | { |
||
7970 | int i, j; |
||
7971 | struct isl_basic_map *bmap; |
||
7972 | |||
7973 | if (!map) |
||
7974 | return NULL; |
||
7975 | if (ISL_F_ISSET(map, ISL_MAP_NORMALIZED)) |
||
7976 | return map; |
||
7977 | for (i = 0; i < map->n; ++i) { |
||
7978 | bmap = isl_basic_map_normalize(isl_basic_map_copy(map->p[i])); |
||
7979 | if (!bmap) |
||
7980 | goto error; |
||
7981 | isl_basic_map_free(map->p[i]); |
||
7982 | map->p[i] = bmap; |
||
7983 | } |
||
7984 | qsort(map->p, map->n, sizeof(struct isl_basic_map *), qsort_bmap_cmp); |
||
7985 | ISL_F_SET(map, ISL_MAP_NORMALIZED); |
||
7986 | map = isl_map_remove_empty_parts(map); |
||
7987 | if (!map) |
||
7988 | return NULL; |
||
7989 | for (i = map->n - 1; i >= 1; --i) { |
||
7990 | if (!isl_basic_map_plain_is_equal(map->p[i-1], map->p[i])) |
||
7991 | continue; |
||
7992 | isl_basic_map_free(map->p[i-1]); |
||
7993 | for (j = i; j < map->n; ++j) |
||
7994 | map->p[j-1] = map->p[j]; |
||
7995 | map->n--; |
||
7996 | } |
||
7997 | return map; |
||
7998 | error: |
||
7999 | isl_map_free(map); |
||
8000 | return NULL; |
||
8001 | |||
8002 | } |
||
8003 | |||
8004 | struct isl_set *isl_set_normalize(struct isl_set *set) |
||
8005 | { |
||
8006 | return (struct isl_set *)isl_map_normalize((struct isl_map *)set); |
||
8007 | } |
||
8008 | |||
8009 | int isl_map_plain_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2) |
||
8010 | { |
||
8011 | int i; |
||
8012 | int equal; |
||
8013 | |||
8014 | if (!map1 || !map2) |
||
8015 | return -1; |
||
8016 | |||
8017 | if (map1 == map2) |
||
8018 | return 1; |
||
8019 | if (!isl_space_is_equal(map1->dim, map2->dim)) |
||
8020 | return 0; |
||
8021 | |||
8022 | map1 = isl_map_copy(map1); |
||
8023 | map2 = isl_map_copy(map2); |
||
8024 | map1 = isl_map_normalize(map1); |
||
8025 | map2 = isl_map_normalize(map2); |
||
8026 | if (!map1 || !map2) |
||
8027 | goto error; |
||
8028 | equal = map1->n == map2->n; |
||
8029 | for (i = 0; equal && i < map1->n; ++i) { |
||
8030 | equal = isl_basic_map_plain_is_equal(map1->p[i], map2->p[i]); |
||
8031 | if (equal < 0) |
||
8032 | goto error; |
||
8033 | } |
||
8034 | isl_map_free(map1); |
||
8035 | isl_map_free(map2); |
||
8036 | return equal; |
||
8037 | error: |
||
8038 | isl_map_free(map1); |
||
8039 | isl_map_free(map2); |
||
8040 | return -1; |
||
8041 | } |
||
8042 | |||
8043 | int isl_map_fast_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2) |
||
8044 | { |
||
8045 | return isl_map_plain_is_equal(map1, map2); |
||
8046 | } |
||
8047 | |||
8048 | int isl_set_plain_is_equal(__isl_keep isl_set *set1, __isl_keep isl_set *set2) |
||
8049 | { |
||
8050 | return isl_map_plain_is_equal((struct isl_map *)set1, |
||
8051 | (struct isl_map *)set2); |
||
8052 | } |
||
8053 | |||
8054 | int isl_set_fast_is_equal(__isl_keep isl_set *set1, __isl_keep isl_set *set2) |
||
8055 | { |
||
8056 | return isl_set_plain_is_equal(set1, set2); |
||
8057 | } |
||
8058 | |||
8059 | /* Return an interval that ranges from min to max (inclusive) |
||
8060 | */ |
||
8061 | struct isl_basic_set *isl_basic_set_interval(struct isl_ctx *ctx, |
||
8062 | isl_int min, isl_int max) |
||
8063 | { |
||
8064 | int k; |
||
8065 | struct isl_basic_set *bset = NULL; |
||
8066 | |||
8067 | bset = isl_basic_set_alloc(ctx, 0, 1, 0, 0, 2); |
||
8068 | if (!bset) |
||
8069 | goto error; |
||
8070 | |||
8071 | k = isl_basic_set_alloc_inequality(bset); |
||
8072 | if (k < 0) |
||
8073 | goto error; |
||
8074 | isl_int_set_si(bset->ineq[k][1], 1); |
||
8075 | isl_int_neg(bset->ineq[k][0], min); |
||
8076 | |||
8077 | k = isl_basic_set_alloc_inequality(bset); |
||
8078 | if (k < 0) |
||
8079 | goto error; |
||
8080 | isl_int_set_si(bset->ineq[k][1], -1); |
||
8081 | isl_int_set(bset->ineq[k][0], max); |
||
8082 | |||
8083 | return bset; |
||
8084 | error: |
||
8085 | isl_basic_set_free(bset); |
||
8086 | return NULL; |
||
8087 | } |
||
8088 | |||
8089 | /* Return the Cartesian product of the basic sets in list (in the given order). |
||
8090 | */ |
||
8091 | __isl_give isl_basic_set *isl_basic_set_list_product( |
||
8092 | __isl_take struct isl_basic_set_list *list) |
||
8093 | { |
||
8094 | int i; |
||
8095 | unsigned dim; |
||
8096 | unsigned nparam; |
||
8097 | unsigned extra; |
||
8098 | unsigned n_eq; |
||
8099 | unsigned n_ineq; |
||
8100 | struct isl_basic_set *product = NULL; |
||
8101 | |||
8102 | if (!list) |
||
8103 | goto error; |
||
8104 | isl_assert(list->ctx, list->n > 0, goto error); |
||
8105 | isl_assert(list->ctx, list->p[0], goto error); |
||
8106 | nparam = isl_basic_set_n_param(list->p[0]); |
||
8107 | dim = isl_basic_set_n_dim(list->p[0]); |
||
8108 | extra = list->p[0]->n_div; |
||
8109 | n_eq = list->p[0]->n_eq; |
||
8110 | n_ineq = list->p[0]->n_ineq; |
||
8111 | for (i = 1; i < list->n; ++i) { |
||
8112 | isl_assert(list->ctx, list->p[i], goto error); |
||
8113 | isl_assert(list->ctx, |
||
8114 | nparam == isl_basic_set_n_param(list->p[i]), goto error); |
||
8115 | dim += isl_basic_set_n_dim(list->p[i]); |
||
8116 | extra += list->p[i]->n_div; |
||
8117 | n_eq += list->p[i]->n_eq; |
||
8118 | n_ineq += list->p[i]->n_ineq; |
||
8119 | } |
||
8120 | product = isl_basic_set_alloc(list->ctx, nparam, dim, extra, |
||
8121 | n_eq, n_ineq); |
||
8122 | if (!product) |
||
8123 | goto error; |
||
8124 | dim = 0; |
||
8125 | for (i = 0; i < list->n; ++i) { |
||
8126 | isl_basic_set_add_constraints(product, |
||
8127 | isl_basic_set_copy(list->p[i]), dim); |
||
8128 | dim += isl_basic_set_n_dim(list->p[i]); |
||
8129 | } |
||
8130 | isl_basic_set_list_free(list); |
||
8131 | return product; |
||
8132 | error: |
||
8133 | isl_basic_set_free(product); |
||
8134 | isl_basic_set_list_free(list); |
||
8135 | return NULL; |
||
8136 | } |
||
8137 | |||
8138 | struct isl_basic_map *isl_basic_map_product( |
||
8139 | struct isl_basic_map *bmap1, struct isl_basic_map *bmap2) |
||
8140 | { |
||
8141 | isl_space *dim_result = NULL; |
||
8142 | struct isl_basic_map *bmap; |
||
8143 | unsigned in1, in2, out1, out2, nparam, total, pos; |
||
8144 | struct isl_dim_map *dim_map1, *dim_map2; |
||
8145 | |||
8146 | if (!bmap1 || !bmap2) |
||
8147 | goto error; |
||
8148 | |||
8149 | isl_assert(bmap1->ctx, isl_space_match(bmap1->dim, isl_dim_param, |
||
8150 | bmap2->dim, isl_dim_param), goto error); |
||
8151 | dim_result = isl_space_product(isl_space_copy(bmap1->dim), |
||
8152 | isl_space_copy(bmap2->dim)); |
||
8153 | |||
8154 | in1 = isl_basic_map_n_in(bmap1); |
||
8155 | in2 = isl_basic_map_n_in(bmap2); |
||
8156 | out1 = isl_basic_map_n_out(bmap1); |
||
8157 | out2 = isl_basic_map_n_out(bmap2); |
||
8158 | nparam = isl_basic_map_n_param(bmap1); |
||
8159 | |||
8160 | total = nparam + in1 + in2 + out1 + out2 + bmap1->n_div + bmap2->n_div; |
||
8161 | dim_map1 = isl_dim_map_alloc(bmap1->ctx, total); |
||
8162 | dim_map2 = isl_dim_map_alloc(bmap1->ctx, total); |
||
8163 | isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0); |
||
8164 | isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0); |
||
8165 | isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam); |
||
8166 | isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos += in1); |
||
8167 | isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in2); |
||
8168 | isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += out1); |
||
8169 | isl_dim_map_div(dim_map1, bmap1, pos += out2); |
||
8170 | isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div); |
||
8171 | |||
8172 | bmap = isl_basic_map_alloc_space(dim_result, |
||
8173 | bmap1->n_div + bmap2->n_div, |
||
8174 | bmap1->n_eq + bmap2->n_eq, |
||
8175 | bmap1->n_ineq + bmap2->n_ineq); |
||
8176 | bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1); |
||
8177 | bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2); |
||
8178 | bmap = isl_basic_map_simplify(bmap); |
||
8179 | return isl_basic_map_finalize(bmap); |
||
8180 | error: |
||
8181 | isl_basic_map_free(bmap1); |
||
8182 | isl_basic_map_free(bmap2); |
||
8183 | return NULL; |
||
8184 | } |
||
8185 | |||
8186 | __isl_give isl_basic_map *isl_basic_map_flat_product( |
||
8187 | __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2) |
||
8188 | { |
||
8189 | isl_basic_map *prod; |
||
8190 | |||
8191 | prod = isl_basic_map_product(bmap1, bmap2); |
||
8192 | prod = isl_basic_map_flatten(prod); |
||
8193 | return prod; |
||
8194 | } |
||
8195 | |||
8196 | __isl_give isl_basic_set *isl_basic_set_flat_product( |
||
8197 | __isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2) |
||
8198 | { |
||
8199 | return isl_basic_map_flat_range_product(bset1, bset2); |
||
8200 | } |
||
8201 | |||
8202 | __isl_give isl_basic_map *isl_basic_map_domain_product( |
||
8203 | __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2) |
||
8204 | { |
||
8205 | isl_space *space_result = NULL; |
||
8206 | isl_basic_map *bmap; |
||
8207 | unsigned in1, in2, out, nparam, total, pos; |
||
8208 | struct isl_dim_map *dim_map1, *dim_map2; |
||
8209 | |||
8210 | if (!bmap1 || !bmap2) |
||
8211 | goto error; |
||
8212 | |||
8213 | space_result = isl_space_domain_product(isl_space_copy(bmap1->dim), |
||
8214 | isl_space_copy(bmap2->dim)); |
||
8215 | |||
8216 | in1 = isl_basic_map_dim(bmap1, isl_dim_in); |
||
8217 | in2 = isl_basic_map_dim(bmap2, isl_dim_in); |
||
8218 | out = isl_basic_map_dim(bmap1, isl_dim_out); |
||
8219 | nparam = isl_basic_map_dim(bmap1, isl_dim_param); |
||
8220 | |||
8221 | total = nparam + in1 + in2 + out + bmap1->n_div + bmap2->n_div; |
||
8222 | dim_map1 = isl_dim_map_alloc(bmap1->ctx, total); |
||
8223 | dim_map2 = isl_dim_map_alloc(bmap1->ctx, total); |
||
8224 | isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0); |
||
8225 | isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0); |
||
8226 | isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam); |
||
8227 | isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos += in1); |
||
8228 | isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in2); |
||
8229 | isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos); |
||
8230 | isl_dim_map_div(dim_map1, bmap1, pos += out); |
||
8231 | isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div); |
||
8232 | |||
8233 | bmap = isl_basic_map_alloc_space(space_result, |
||
8234 | bmap1->n_div + bmap2->n_div, |
||
8235 | bmap1->n_eq + bmap2->n_eq, |
||
8236 | bmap1->n_ineq + bmap2->n_ineq); |
||
8237 | bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1); |
||
8238 | bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2); |
||
8239 | bmap = isl_basic_map_simplify(bmap); |
||
8240 | return isl_basic_map_finalize(bmap); |
||
8241 | error: |
||
8242 | isl_basic_map_free(bmap1); |
||
8243 | isl_basic_map_free(bmap2); |
||
8244 | return NULL; |
||
8245 | } |
||
8246 | |||
8247 | __isl_give isl_basic_map *isl_basic_map_range_product( |
||
8248 | __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2) |
||
8249 | { |
||
8250 | isl_space *dim_result = NULL; |
||
8251 | isl_basic_map *bmap; |
||
8252 | unsigned in, out1, out2, nparam, total, pos; |
||
8253 | struct isl_dim_map *dim_map1, *dim_map2; |
||
8254 | |||
8255 | if (!bmap1 || !bmap2) |
||
8256 | goto error; |
||
8257 | |||
8258 | dim_result = isl_space_range_product(isl_space_copy(bmap1->dim), |
||
8259 | isl_space_copy(bmap2->dim)); |
||
8260 | |||
8261 | in = isl_basic_map_dim(bmap1, isl_dim_in); |
||
8262 | out1 = isl_basic_map_n_out(bmap1); |
||
8263 | out2 = isl_basic_map_n_out(bmap2); |
||
8264 | nparam = isl_basic_map_n_param(bmap1); |
||
8265 | |||
8266 | total = nparam + in + out1 + out2 + bmap1->n_div + bmap2->n_div; |
||
8267 | dim_map1 = isl_dim_map_alloc(bmap1->ctx, total); |
||
8268 | dim_map2 = isl_dim_map_alloc(bmap1->ctx, total); |
||
8269 | isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0); |
||
8270 | isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0); |
||
8271 | isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam); |
||
8272 | isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos); |
||
8273 | isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in); |
||
8274 | isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += out1); |
||
8275 | isl_dim_map_div(dim_map1, bmap1, pos += out2); |
||
8276 | isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div); |
||
8277 | |||
8278 | bmap = isl_basic_map_alloc_space(dim_result, |
||
8279 | bmap1->n_div + bmap2->n_div, |
||
8280 | bmap1->n_eq + bmap2->n_eq, |
||
8281 | bmap1->n_ineq + bmap2->n_ineq); |
||
8282 | bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1); |
||
8283 | bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2); |
||
8284 | bmap = isl_basic_map_simplify(bmap); |
||
8285 | return isl_basic_map_finalize(bmap); |
||
8286 | error: |
||
8287 | isl_basic_map_free(bmap1); |
||
8288 | isl_basic_map_free(bmap2); |
||
8289 | return NULL; |
||
8290 | } |
||
8291 | |||
8292 | __isl_give isl_basic_map *isl_basic_map_flat_range_product( |
||
8293 | __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2) |
||
8294 | { |
||
8295 | isl_basic_map *prod; |
||
8296 | |||
8297 | prod = isl_basic_map_range_product(bmap1, bmap2); |
||
8298 | prod = isl_basic_map_flatten_range(prod); |
||
8299 | return prod; |
||
8300 | } |
||
8301 | |||
8302 | static __isl_give isl_map *map_product(__isl_take isl_map *map1, |
||
8303 | __isl_take isl_map *map2, |
||
8304 | __isl_give isl_space *(*dim_product)(__isl_take isl_space *left, |
||
8305 | __isl_take isl_space *right), |
||
8306 | __isl_give isl_basic_map *(*basic_map_product)( |
||
8307 | __isl_take isl_basic_map *left, __isl_take isl_basic_map *right)) |
||
8308 | { |
||
8309 | unsigned flags = 0; |
||
8310 | struct isl_map *result; |
||
8311 | int i, j; |
||
8312 | |||
8313 | if (!map1 || !map2) |
||
8314 | goto error; |
||
8315 | |||
8316 | isl_assert(map1->ctx, isl_space_match(map1->dim, isl_dim_param, |
||
8317 | map2->dim, isl_dim_param), goto error); |
||
8318 | |||
8319 | if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) && |
||
8320 | ISL_F_ISSET(map2, ISL_MAP_DISJOINT)) |
||
8321 | ISL_FL_SET(flags, ISL_MAP_DISJOINT); |
||
8322 | |||
8323 | result = isl_map_alloc_space(dim_product(isl_space_copy(map1->dim), |
||
8324 | isl_space_copy(map2->dim)), |
||
8325 | map1->n * map2->n, flags); |
||
8326 | if (!result) |
||
8327 | goto error; |
||
8328 | for (i = 0; i < map1->n; ++i) |
||
8329 | for (j = 0; j < map2->n; ++j) { |
||
8330 | struct isl_basic_map *part; |
||
8331 | part = basic_map_product(isl_basic_map_copy(map1->p[i]), |
||
8332 | isl_basic_map_copy(map2->p[j])); |
||
8333 | if (isl_basic_map_is_empty(part)) |
||
8334 | isl_basic_map_free(part); |
||
8335 | else |
||
8336 | result = isl_map_add_basic_map(result, part); |
||
8337 | if (!result) |
||
8338 | goto error; |
||
8339 | } |
||
8340 | isl_map_free(map1); |
||
8341 | isl_map_free(map2); |
||
8342 | return result; |
||
8343 | error: |
||
8344 | isl_map_free(map1); |
||
8345 | isl_map_free(map2); |
||
8346 | return NULL; |
||
8347 | } |
||
8348 | |||
8349 | /* Given two maps A -> B and C -> D, construct a map [A -> C] -> [B -> D] |
||
8350 | */ |
||
8351 | static __isl_give isl_map *map_product_aligned(__isl_take isl_map *map1, |
||
8352 | __isl_take isl_map *map2) |
||
8353 | { |
||
8354 | return map_product(map1, map2, &isl_space_product, &isl_basic_map_product); |
||
8355 | } |
||
8356 | |||
8357 | __isl_give isl_map *isl_map_product(__isl_take isl_map *map1, |
||
8358 | __isl_take isl_map *map2) |
||
8359 | { |
||
8360 | return isl_map_align_params_map_map_and(map1, map2, &map_product_aligned); |
||
8361 | } |
||
8362 | |||
8363 | /* Given two maps A -> B and C -> D, construct a map (A, C) -> (B, D) |
||
8364 | */ |
||
8365 | __isl_give isl_map *isl_map_flat_product(__isl_take isl_map *map1, |
||
8366 | __isl_take isl_map *map2) |
||
8367 | { |
||
8368 | isl_map *prod; |
||
8369 | |||
8370 | prod = isl_map_product(map1, map2); |
||
8371 | prod = isl_map_flatten(prod); |
||
8372 | return prod; |
||
8373 | } |
||
8374 | |||
8375 | /* Given two set A and B, construct its Cartesian product A x B. |
||
8376 | */ |
||
8377 | struct isl_set *isl_set_product(struct isl_set *set1, struct isl_set *set2) |
||
8378 | { |
||
8379 | return isl_map_range_product(set1, set2); |
||
8380 | } |
||
8381 | |||
8382 | __isl_give isl_set *isl_set_flat_product(__isl_take isl_set *set1, |
||
8383 | __isl_take isl_set *set2) |
||
8384 | { |
||
8385 | return isl_map_flat_range_product(set1, set2); |
||
8386 | } |
||
8387 | |||
8388 | /* Given two maps A -> B and C -> D, construct a map [A -> C] -> (B * D) |
||
8389 | */ |
||
8390 | static __isl_give isl_map *map_domain_product_aligned(__isl_take isl_map *map1, |
||
8391 | __isl_take isl_map *map2) |
||
8392 | { |
||
8393 | return map_product(map1, map2, &isl_space_domain_product, |
||
8394 | &isl_basic_map_domain_product); |
||
8395 | } |
||
8396 | |||
8397 | /* Given two maps A -> B and C -> D, construct a map (A * C) -> [B -> D] |
||
8398 | */ |
||
8399 | static __isl_give isl_map *map_range_product_aligned(__isl_take isl_map *map1, |
||
8400 | __isl_take isl_map *map2) |
||
8401 | { |
||
8402 | return map_product(map1, map2, &isl_space_range_product, |
||
8403 | &isl_basic_map_range_product); |
||
8404 | } |
||
8405 | |||
8406 | __isl_give isl_map *isl_map_domain_product(__isl_take isl_map *map1, |
||
8407 | __isl_take isl_map *map2) |
||
8408 | { |
||
8409 | return isl_map_align_params_map_map_and(map1, map2, |
||
8410 | &map_domain_product_aligned); |
||
8411 | } |
||
8412 | |||
8413 | __isl_give isl_map *isl_map_range_product(__isl_take isl_map *map1, |
||
8414 | __isl_take isl_map *map2) |
||
8415 | { |
||
8416 | return isl_map_align_params_map_map_and(map1, map2, |
||
8417 | &map_range_product_aligned); |
||
8418 | } |
||
8419 | |||
8420 | /* Given two maps A -> B and C -> D, construct a map (A, C) -> (B * D) |
||
8421 | */ |
||
8422 | __isl_give isl_map *isl_map_flat_domain_product(__isl_take isl_map *map1, |
||
8423 | __isl_take isl_map *map2) |
||
8424 | { |
||
8425 | isl_map *prod; |
||
8426 | |||
8427 | prod = isl_map_domain_product(map1, map2); |
||
8428 | prod = isl_map_flatten_domain(prod); |
||
8429 | return prod; |
||
8430 | } |
||
8431 | |||
8432 | /* Given two maps A -> B and C -> D, construct a map (A * C) -> (B, D) |
||
8433 | */ |
||
8434 | __isl_give isl_map *isl_map_flat_range_product(__isl_take isl_map *map1, |
||
8435 | __isl_take isl_map *map2) |
||
8436 | { |
||
8437 | isl_map *prod; |
||
8438 | |||
8439 | prod = isl_map_range_product(map1, map2); |
||
8440 | prod = isl_map_flatten_range(prod); |
||
8441 | return prod; |
||
8442 | } |
||
8443 | |||
8444 | uint32_t isl_basic_map_get_hash(__isl_keep isl_basic_map *bmap) |
||
8445 | { |
||
8446 | int i; |
||
8447 | uint32_t hash = isl_hash_init(); |
||
8448 | unsigned total; |
||
8449 | |||
8450 | if (!bmap) |
||
8451 | return 0; |
||
8452 | bmap = isl_basic_map_copy(bmap); |
||
8453 | bmap = isl_basic_map_normalize(bmap); |
||
8454 | if (!bmap) |
||
8455 | return 0; |
||
8456 | total = isl_basic_map_total_dim(bmap); |
||
8457 | isl_hash_byte(hash, bmap->n_eq & 0xFF); |
||
8458 | for (i = 0; i < bmap->n_eq; ++i) { |
||
8459 | uint32_t c_hash; |
||
8460 | c_hash = isl_seq_get_hash(bmap->eq[i], 1 + total); |
||
8461 | isl_hash_hash(hash, c_hash); |
||
8462 | } |
||
8463 | isl_hash_byte(hash, bmap->n_ineq & 0xFF); |
||
8464 | for (i = 0; i < bmap->n_ineq; ++i) { |
||
8465 | uint32_t c_hash; |
||
8466 | c_hash = isl_seq_get_hash(bmap->ineq[i], 1 + total); |
||
8467 | isl_hash_hash(hash, c_hash); |
||
8468 | } |
||
8469 | isl_hash_byte(hash, bmap->n_div & 0xFF); |
||
8470 | for (i = 0; i < bmap->n_div; ++i) { |
||
8471 | uint32_t c_hash; |
||
8472 | if (isl_int_is_zero(bmap->div[i][0])) |
||
8473 | continue; |
||
8474 | isl_hash_byte(hash, i & 0xFF); |
||
8475 | c_hash = isl_seq_get_hash(bmap->div[i], 1 + 1 + total); |
||
8476 | isl_hash_hash(hash, c_hash); |
||
8477 | } |
||
8478 | isl_basic_map_free(bmap); |
||
8479 | return hash; |
||
8480 | } |
||
8481 | |||
8482 | uint32_t isl_basic_set_get_hash(__isl_keep isl_basic_set *bset) |
||
8483 | { |
||
8484 | return isl_basic_map_get_hash((isl_basic_map *)bset); |
||
8485 | } |
||
8486 | |||
8487 | uint32_t isl_map_get_hash(__isl_keep isl_map *map) |
||
8488 | { |
||
8489 | int i; |
||
8490 | uint32_t hash; |
||
8491 | |||
8492 | if (!map) |
||
8493 | return 0; |
||
8494 | map = isl_map_copy(map); |
||
8495 | map = isl_map_normalize(map); |
||
8496 | if (!map) |
||
8497 | return 0; |
||
8498 | |||
8499 | hash = isl_hash_init(); |
||
8500 | for (i = 0; i < map->n; ++i) { |
||
8501 | uint32_t bmap_hash; |
||
8502 | bmap_hash = isl_basic_map_get_hash(map->p[i]); |
||
8503 | isl_hash_hash(hash, bmap_hash); |
||
8504 | } |
||
8505 | |||
8506 | isl_map_free(map); |
||
8507 | |||
8508 | return hash; |
||
8509 | } |
||
8510 | |||
8511 | uint32_t isl_set_get_hash(__isl_keep isl_set *set) |
||
8512 | { |
||
8513 | return isl_map_get_hash((isl_map *)set); |
||
8514 | } |
||
8515 | |||
8516 | /* Check if the value for dimension dim is completely determined |
||
8517 | * by the values of the other parameters and variables. |
||
8518 | * That is, check if dimension dim is involved in an equality. |
||
8519 | */ |
||
8520 | int isl_basic_set_dim_is_unique(struct isl_basic_set *bset, unsigned dim) |
||
8521 | { |
||
8522 | int i; |
||
8523 | unsigned nparam; |
||
8524 | |||
8525 | if (!bset) |
||
8526 | return -1; |
||
8527 | nparam = isl_basic_set_n_param(bset); |
||
8528 | for (i = 0; i < bset->n_eq; ++i) |
||
8529 | if (!isl_int_is_zero(bset->eq[i][1 + nparam + dim])) |
||
8530 | return 1; |
||
8531 | return 0; |
||
8532 | } |
||
8533 | |||
8534 | /* Check if the value for dimension dim is completely determined |
||
8535 | * by the values of the other parameters and variables. |
||
8536 | * That is, check if dimension dim is involved in an equality |
||
8537 | * for each of the subsets. |
||
8538 | */ |
||
8539 | int isl_set_dim_is_unique(struct isl_set *set, unsigned dim) |
||
8540 | { |
||
8541 | int i; |
||
8542 | |||
8543 | if (!set) |
||
8544 | return -1; |
||
8545 | for (i = 0; i < set->n; ++i) { |
||
8546 | int unique; |
||
8547 | unique = isl_basic_set_dim_is_unique(set->p[i], dim); |
||
8548 | if (unique != 1) |
||
8549 | return unique; |
||
8550 | } |
||
8551 | return 1; |
||
8552 | } |
||
8553 | |||
8554 | int isl_set_n_basic_set(__isl_keep isl_set *set) |
||
8555 | { |
||
8556 | return set ? set->n : 0; |
||
8557 | } |
||
8558 | |||
8559 | int isl_map_foreach_basic_map(__isl_keep isl_map *map, |
||
8560 | int (*fn)(__isl_take isl_basic_map *bmap, void *user), void *user) |
||
8561 | { |
||
8562 | int i; |
||
8563 | |||
8564 | if (!map) |
||
8565 | return -1; |
||
8566 | |||
8567 | for (i = 0; i < map->n; ++i) |
||
8568 | if (fn(isl_basic_map_copy(map->p[i]), user) < 0) |
||
8569 | return -1; |
||
8570 | |||
8571 | return 0; |
||
8572 | } |
||
8573 | |||
8574 | int isl_set_foreach_basic_set(__isl_keep isl_set *set, |
||
8575 | int (*fn)(__isl_take isl_basic_set *bset, void *user), void *user) |
||
8576 | { |
||
8577 | int i; |
||
8578 | |||
8579 | if (!set) |
||
8580 | return -1; |
||
8581 | |||
8582 | for (i = 0; i < set->n; ++i) |
||
8583 | if (fn(isl_basic_set_copy(set->p[i]), user) < 0) |
||
8584 | return -1; |
||
8585 | |||
8586 | return 0; |
||
8587 | } |
||
8588 | |||
8589 | __isl_give isl_basic_set *isl_basic_set_lift(__isl_take isl_basic_set *bset) |
||
8590 | { |
||
8591 | isl_space *dim; |
||
8592 | |||
8593 | if (!bset) |
||
8594 | return NULL; |
||
8595 | |||
8596 | bset = isl_basic_set_cow(bset); |
||
8597 | if (!bset) |
||
8598 | return NULL; |
||
8599 | |||
8600 | dim = isl_basic_set_get_space(bset); |
||
8601 | dim = isl_space_lift(dim, bset->n_div); |
||
8602 | if (!dim) |
||
8603 | goto error; |
||
8604 | isl_space_free(bset->dim); |
||
8605 | bset->dim = dim; |
||
8606 | bset->extra -= bset->n_div; |
||
8607 | bset->n_div = 0; |
||
8608 | |||
8609 | bset = isl_basic_set_finalize(bset); |
||
8610 | |||
8611 | return bset; |
||
8612 | error: |
||
8613 | isl_basic_set_free(bset); |
||
8614 | return NULL; |
||
8615 | } |
||
8616 | |||
8617 | __isl_give isl_set *isl_set_lift(__isl_take isl_set *set) |
||
8618 | { |
||
8619 | int i; |
||
8620 | isl_space *dim; |
||
8621 | unsigned n_div; |
||
8622 | |||
8623 | set = isl_set_align_divs(set); |
||
8624 | |||
8625 | if (!set) |
||
8626 | return NULL; |
||
8627 | |||
8628 | set = isl_set_cow(set); |
||
8629 | if (!set) |
||
8630 | return NULL; |
||
8631 | |||
8632 | n_div = set->p[0]->n_div; |
||
8633 | dim = isl_set_get_space(set); |
||
8634 | dim = isl_space_lift(dim, n_div); |
||
8635 | if (!dim) |
||
8636 | goto error; |
||
8637 | isl_space_free(set->dim); |
||
8638 | set->dim = dim; |
||
8639 | |||
8640 | for (i = 0; i < set->n; ++i) { |
||
8641 | set->p[i] = isl_basic_set_lift(set->p[i]); |
||
8642 | if (!set->p[i]) |
||
8643 | goto error; |
||
8644 | } |
||
8645 | |||
8646 | return set; |
||
8647 | error: |
||
8648 | isl_set_free(set); |
||
8649 | return NULL; |
||
8650 | } |
||
8651 | |||
8652 | __isl_give isl_map *isl_set_lifting(__isl_take isl_set *set) |
||
8653 | { |
||
8654 | isl_space *dim; |
||
8655 | struct isl_basic_map *bmap; |
||
8656 | unsigned n_set; |
||
8657 | unsigned n_div; |
||
8658 | unsigned n_param; |
||
8659 | unsigned total; |
||
8660 | int i, k, l; |
||
8661 | |||
8662 | set = isl_set_align_divs(set); |
||
8663 | |||
8664 | if (!set) |
||
8665 | return NULL; |
||
8666 | |||
8667 | dim = isl_set_get_space(set); |
||
8668 | if (set->n == 0 || set->p[0]->n_div == 0) { |
||
8669 | isl_set_free(set); |
||
8670 | return isl_map_identity(isl_space_map_from_set(dim)); |
||
8671 | } |
||
8672 | |||
8673 | n_div = set->p[0]->n_div; |
||
8674 | dim = isl_space_map_from_set(dim); |
||
8675 | n_param = isl_space_dim(dim, isl_dim_param); |
||
8676 | n_set = isl_space_dim(dim, isl_dim_in); |
||
8677 | dim = isl_space_extend(dim, n_param, n_set, n_set + n_div); |
||
8678 | bmap = isl_basic_map_alloc_space(dim, 0, n_set, 2 * n_div); |
||
8679 | for (i = 0; i < n_set; ++i) |
||
8680 | bmap = var_equal(bmap, i); |
||
8681 | |||
8682 | total = n_param + n_set + n_set + n_div; |
||
8683 | for (i = 0; i < n_div; ++i) { |
||
8684 | k = isl_basic_map_alloc_inequality(bmap); |
||
8685 | if (k < 0) |
||
8686 | goto error; |
||
8687 | isl_seq_cpy(bmap->ineq[k], set->p[0]->div[i]+1, 1+n_param); |
||
8688 | isl_seq_clr(bmap->ineq[k]+1+n_param, n_set); |
||
8689 | isl_seq_cpy(bmap->ineq[k]+1+n_param+n_set, |
||
8690 | set->p[0]->div[i]+1+1+n_param, n_set + n_div); |
||
8691 | isl_int_neg(bmap->ineq[k][1+n_param+n_set+n_set+i], |
||
8692 | set->p[0]->div[i][0]); |
||
8693 | |||
8694 | l = isl_basic_map_alloc_inequality(bmap); |
||
8695 | if (l < 0) |
||
8696 | goto error; |
||
8697 | isl_seq_neg(bmap->ineq[l], bmap->ineq[k], 1 + total); |
||
8698 | isl_int_add(bmap->ineq[l][0], bmap->ineq[l][0], |
||
8699 | set->p[0]->div[i][0]); |
||
8700 | isl_int_sub_ui(bmap->ineq[l][0], bmap->ineq[l][0], 1); |
||
8701 | } |
||
8702 | |||
8703 | isl_set_free(set); |
||
8704 | bmap = isl_basic_map_simplify(bmap); |
||
8705 | bmap = isl_basic_map_finalize(bmap); |
||
8706 | return isl_map_from_basic_map(bmap); |
||
8707 | error: |
||
8708 | isl_set_free(set); |
||
8709 | isl_basic_map_free(bmap); |
||
8710 | return NULL; |
||
8711 | } |
||
8712 | |||
8713 | int isl_basic_set_size(__isl_keep isl_basic_set *bset) |
||
8714 | { |
||
8715 | unsigned dim; |
||
8716 | int size = 0; |
||
8717 | |||
8718 | if (!bset) |
||
8719 | return -1; |
||
8720 | |||
8721 | dim = isl_basic_set_total_dim(bset); |
||
8722 | size += bset->n_eq * (1 + dim); |
||
8723 | size += bset->n_ineq * (1 + dim); |
||
8724 | size += bset->n_div * (2 + dim); |
||
8725 | |||
8726 | return size; |
||
8727 | } |
||
8728 | |||
8729 | int isl_set_size(__isl_keep isl_set *set) |
||
8730 | { |
||
8731 | int i; |
||
8732 | int size = 0; |
||
8733 | |||
8734 | if (!set) |
||
8735 | return -1; |
||
8736 | |||
8737 | for (i = 0; i < set->n; ++i) |
||
8738 | size += isl_basic_set_size(set->p[i]); |
||
8739 | |||
8740 | return size; |
||
8741 | } |
||
8742 | |||
8743 | /* Check if there is any lower bound (if lower == 0) and/or upper |
||
8744 | * bound (if upper == 0) on the specified dim. |
||
8745 | */ |
||
8746 | static int basic_map_dim_is_bounded(__isl_keep isl_basic_map *bmap, |
||
8747 | enum isl_dim_type type, unsigned pos, int lower, int upper) |
||
8748 | { |
||
8749 | int i; |
||
8750 | |||
8751 | if (!bmap) |
||
8752 | return -1; |
||
8753 | |||
8754 | isl_assert(bmap->ctx, pos < isl_basic_map_dim(bmap, type), return -1); |
||
8755 | |||
8756 | pos += isl_basic_map_offset(bmap, type); |
||
8757 | |||
8758 | for (i = 0; i < bmap->n_div; ++i) { |
||
8759 | if (isl_int_is_zero(bmap->div[i][0])) |
||
8760 | continue; |
||
8761 | if (!isl_int_is_zero(bmap->div[i][1 + pos])) |
||
8762 | return 1; |
||
8763 | } |
||
8764 | |||
8765 | for (i = 0; i < bmap->n_eq; ++i) |
||
8766 | if (!isl_int_is_zero(bmap->eq[i][pos])) |
||
8767 | return 1; |
||
8768 | |||
8769 | for (i = 0; i < bmap->n_ineq; ++i) { |
||
8770 | int sgn = isl_int_sgn(bmap->ineq[i][pos]); |
||
8771 | if (sgn > 0) |
||
8772 | lower = 1; |
||
8773 | if (sgn < 0) |
||
8774 | upper = 1; |
||
8775 | } |
||
8776 | |||
8777 | return lower && upper; |
||
8778 | } |
||
8779 | |||
8780 | int isl_basic_map_dim_is_bounded(__isl_keep isl_basic_map *bmap, |
||
8781 | enum isl_dim_type type, unsigned pos) |
||
8782 | { |
||
8783 | return basic_map_dim_is_bounded(bmap, type, pos, 0, 0); |
||
8784 | } |
||
8785 | |||
8786 | int isl_basic_map_dim_has_lower_bound(__isl_keep isl_basic_map *bmap, |
||
8787 | enum isl_dim_type type, unsigned pos) |
||
8788 | { |
||
8789 | return basic_map_dim_is_bounded(bmap, type, pos, 0, 1); |
||
8790 | } |
||
8791 | |||
8792 | int isl_basic_map_dim_has_upper_bound(__isl_keep isl_basic_map *bmap, |
||
8793 | enum isl_dim_type type, unsigned pos) |
||
8794 | { |
||
8795 | return basic_map_dim_is_bounded(bmap, type, pos, 1, 0); |
||
8796 | } |
||
8797 | |||
8798 | int isl_map_dim_is_bounded(__isl_keep isl_map *map, |
||
8799 | enum isl_dim_type type, unsigned pos) |
||
8800 | { |
||
8801 | int i; |
||
8802 | |||
8803 | if (!map) |
||
8804 | return -1; |
||
8805 | |||
8806 | for (i = 0; i < map->n; ++i) { |
||
8807 | int bounded; |
||
8808 | bounded = isl_basic_map_dim_is_bounded(map->p[i], type, pos); |
||
8809 | if (bounded < 0 || !bounded) |
||
8810 | return bounded; |
||
8811 | } |
||
8812 | |||
8813 | return 1; |
||
8814 | } |
||
8815 | |||
8816 | /* Return 1 if the specified dim is involved in both an upper bound |
||
8817 | * and a lower bound. |
||
8818 | */ |
||
8819 | int isl_set_dim_is_bounded(__isl_keep isl_set *set, |
||
8820 | enum isl_dim_type type, unsigned pos) |
||
8821 | { |
||
8822 | return isl_map_dim_is_bounded((isl_map *)set, type, pos); |
||
8823 | } |
||
8824 | |||
8825 | static int has_bound(__isl_keep isl_map *map, |
||
8826 | enum isl_dim_type type, unsigned pos, |
||
8827 | int (*fn)(__isl_keep isl_basic_map *bmap, |
||
8828 | enum isl_dim_type type, unsigned pos)) |
||
8829 | { |
||
8830 | int i; |
||
8831 | |||
8832 | if (!map) |
||
8833 | return -1; |
||
8834 | |||
8835 | for (i = 0; i < map->n; ++i) { |
||
8836 | int bounded; |
||
8837 | bounded = fn(map->p[i], type, pos); |
||
8838 | if (bounded < 0 || bounded) |
||
8839 | return bounded; |
||
8840 | } |
||
8841 | |||
8842 | return 0; |
||
8843 | } |
||
8844 | |||
8845 | /* Return 1 if the specified dim is involved in any lower bound. |
||
8846 | */ |
||
8847 | int isl_set_dim_has_lower_bound(__isl_keep isl_set *set, |
||
8848 | enum isl_dim_type type, unsigned pos) |
||
8849 | { |
||
8850 | return has_bound(set, type, pos, &isl_basic_map_dim_has_lower_bound); |
||
8851 | } |
||
8852 | |||
8853 | /* Return 1 if the specified dim is involved in any upper bound. |
||
8854 | */ |
||
8855 | int isl_set_dim_has_upper_bound(__isl_keep isl_set *set, |
||
8856 | enum isl_dim_type type, unsigned pos) |
||
8857 | { |
||
8858 | return has_bound(set, type, pos, &isl_basic_map_dim_has_upper_bound); |
||
8859 | } |
||
8860 | |||
8861 | /* For each of the "n" variables starting at "first", determine |
||
8862 | * the sign of the variable and put the results in the first "n" |
||
8863 | * elements of the array "signs". |
||
8864 | * Sign |
||
8865 | * 1 means that the variable is non-negative |
||
8866 | * -1 means that the variable is non-positive |
||
8867 | * 0 means the variable attains both positive and negative values. |
||
8868 | */ |
||
8869 | int isl_basic_set_vars_get_sign(__isl_keep isl_basic_set *bset, |
||
8870 | unsigned first, unsigned n, int *signs) |
||
8871 | { |
||
8872 | isl_vec *bound = NULL; |
||
8873 | struct isl_tab *tab = NULL; |
||
8874 | struct isl_tab_undo *snap; |
||
8875 | int i; |
||
8876 | |||
8877 | if (!bset || !signs) |
||
8878 | return -1; |
||
8879 | |||
8880 | bound = isl_vec_alloc(bset->ctx, 1 + isl_basic_set_total_dim(bset)); |
||
8881 | tab = isl_tab_from_basic_set(bset, 0); |
||
8882 | if (!bound || !tab) |
||
8883 | goto error; |
||
8884 | |||
8885 | isl_seq_clr(bound->el, bound->size); |
||
8886 | isl_int_set_si(bound->el[0], -1); |
||
8887 | |||
8888 | snap = isl_tab_snap(tab); |
||
8889 | for (i = 0; i < n; ++i) { |
||
8890 | int empty; |
||
8891 | |||
8892 | isl_int_set_si(bound->el[1 + first + i], -1); |
||
8893 | if (isl_tab_add_ineq(tab, bound->el) < 0) |
||
8894 | goto error; |
||
8895 | empty = tab->empty; |
||
8896 | isl_int_set_si(bound->el[1 + first + i], 0); |
||
8897 | if (isl_tab_rollback(tab, snap) < 0) |
||
8898 | goto error; |
||
8899 | |||
8900 | if (empty) { |
||
8901 | signs[i] = 1; |
||
8902 | continue; |
||
8903 | } |
||
8904 | |||
8905 | isl_int_set_si(bound->el[1 + first + i], 1); |
||
8906 | if (isl_tab_add_ineq(tab, bound->el) < 0) |
||
8907 | goto error; |
||
8908 | empty = tab->empty; |
||
8909 | isl_int_set_si(bound->el[1 + first + i], 0); |
||
8910 | if (isl_tab_rollback(tab, snap) < 0) |
||
8911 | goto error; |
||
8912 | |||
8913 | signs[i] = empty ? -1 : 0; |
||
8914 | } |
||
8915 | |||
8916 | isl_tab_free(tab); |
||
8917 | isl_vec_free(bound); |
||
8918 | return 0; |
||
8919 | error: |
||
8920 | isl_tab_free(tab); |
||
8921 | isl_vec_free(bound); |
||
8922 | return -1; |
||
8923 | } |
||
8924 | |||
8925 | int isl_basic_set_dims_get_sign(__isl_keep isl_basic_set *bset, |
||
8926 | enum isl_dim_type type, unsigned first, unsigned n, int *signs) |
||
8927 | { |
||
8928 | if (!bset || !signs) |
||
8929 | return -1; |
||
8930 | isl_assert(bset->ctx, first + n <= isl_basic_set_dim(bset, type), |
||
8931 | return -1); |
||
8932 | |||
8933 | first += pos(bset->dim, type) - 1; |
||
8934 | return isl_basic_set_vars_get_sign(bset, first, n, signs); |
||
8935 | } |
||
8936 | |||
8937 | /* Check if the given basic map is obviously single-valued. |
||
8938 | * In particular, for each output dimension, check that there is |
||
8939 | * an equality that defines the output dimension in terms of |
||
8940 | * earlier dimensions. |
||
8941 | */ |
||
8942 | int isl_basic_map_plain_is_single_valued(__isl_keep isl_basic_map *bmap) |
||
8943 | { |
||
8944 | int i, j; |
||
8945 | unsigned total; |
||
8946 | unsigned n_out; |
||
8947 | unsigned o_out; |
||
8948 | |||
8949 | if (!bmap) |
||
8950 | return -1; |
||
8951 | |||
8952 | total = 1 + isl_basic_map_total_dim(bmap); |
||
8953 | n_out = isl_basic_map_dim(bmap, isl_dim_out); |
||
8954 | o_out = isl_basic_map_offset(bmap, isl_dim_out); |
||
8955 | |||
8956 | for (i = 0; i < n_out; ++i) { |
||
8957 | for (j = 0; j < bmap->n_eq; ++j) { |
||
8958 | if (isl_int_is_zero(bmap->eq[j][o_out + i])) |
||
8959 | continue; |
||
8960 | if (isl_seq_first_non_zero(bmap->eq[j] + o_out + i + 1, |
||
8961 | total - (o_out + i + 1)) == -1) |
||
8962 | break; |
||
8963 | } |
||
8964 | if (j >= bmap->n_eq) |
||
8965 | return 0; |
||
8966 | } |
||
8967 | |||
8968 | return 1; |
||
8969 | } |
||
8970 | |||
8971 | /* Check if the given basic map is single-valued. |
||
8972 | * We simply compute |
||
8973 | * |
||
8974 | * M \circ M^-1 |
||
8975 | * |
||
8976 | * and check if the result is a subset of the identity mapping. |
||
8977 | */ |
||
8978 | int isl_basic_map_is_single_valued(__isl_keep isl_basic_map *bmap) |
||
8979 | { |
||
8980 | isl_space *space; |
||
8981 | isl_basic_map *test; |
||
8982 | isl_basic_map *id; |
||
8983 | int sv; |
||
8984 | |||
8985 | sv = isl_basic_map_plain_is_single_valued(bmap); |
||
8986 | if (sv < 0 || sv) |
||
8987 | return sv; |
||
8988 | |||
8989 | test = isl_basic_map_reverse(isl_basic_map_copy(bmap)); |
||
8990 | test = isl_basic_map_apply_range(test, isl_basic_map_copy(bmap)); |
||
8991 | |||
8992 | space = isl_basic_map_get_space(bmap); |
||
8993 | space = isl_space_map_from_set(isl_space_range(space)); |
||
8994 | id = isl_basic_map_identity(space); |
||
8995 | |||
8996 | sv = isl_basic_map_is_subset(test, id); |
||
8997 | |||
8998 | isl_basic_map_free(test); |
||
8999 | isl_basic_map_free(id); |
||
9000 | |||
9001 | return sv; |
||
9002 | } |
||
9003 | |||
9004 | /* Check if the given map is obviously single-valued. |
||
9005 | */ |
||
9006 | int isl_map_plain_is_single_valued(__isl_keep isl_map *map) |
||
9007 | { |
||
9008 | if (!map) |
||
9009 | return -1; |
||
9010 | if (map->n == 0) |
||
9011 | return 1; |
||
9012 | if (map->n >= 2) |
||
9013 | return 0; |
||
9014 | |||
9015 | return isl_basic_map_plain_is_single_valued(map->p[0]); |
||
9016 | } |
||
9017 | |||
9018 | /* Check if the given map is single-valued. |
||
9019 | * We simply compute |
||
9020 | * |
||
9021 | * M \circ M^-1 |
||
9022 | * |
||
9023 | * and check if the result is a subset of the identity mapping. |
||
9024 | */ |
||
9025 | int isl_map_is_single_valued(__isl_keep isl_map *map) |
||
9026 | { |
||
9027 | isl_space *dim; |
||
9028 | isl_map *test; |
||
9029 | isl_map *id; |
||
9030 | int sv; |
||
9031 | |||
9032 | sv = isl_map_plain_is_single_valued(map); |
||
9033 | if (sv < 0 || sv) |
||
9034 | return sv; |
||
9035 | |||
9036 | test = isl_map_reverse(isl_map_copy(map)); |
||
9037 | test = isl_map_apply_range(test, isl_map_copy(map)); |
||
9038 | |||
9039 | dim = isl_space_map_from_set(isl_space_range(isl_map_get_space(map))); |
||
9040 | id = isl_map_identity(dim); |
||
9041 | |||
9042 | sv = isl_map_is_subset(test, id); |
||
9043 | |||
9044 | isl_map_free(test); |
||
9045 | isl_map_free(id); |
||
9046 | |||
9047 | return sv; |
||
9048 | } |
||
9049 | |||
9050 | int isl_map_is_injective(__isl_keep isl_map *map) |
||
9051 | { |
||
9052 | int in; |
||
9053 | |||
9054 | map = isl_map_copy(map); |
||
9055 | map = isl_map_reverse(map); |
||
9056 | in = isl_map_is_single_valued(map); |
||
9057 | isl_map_free(map); |
||
9058 | |||
9059 | return in; |
||
9060 | } |
||
9061 | |||
9062 | /* Check if the given map is obviously injective. |
||
9063 | */ |
||
9064 | int isl_map_plain_is_injective(__isl_keep isl_map *map) |
||
9065 | { |
||
9066 | int in; |
||
9067 | |||
9068 | map = isl_map_copy(map); |
||
9069 | map = isl_map_reverse(map); |
||
9070 | in = isl_map_plain_is_single_valued(map); |
||
9071 | isl_map_free(map); |
||
9072 | |||
9073 | return in; |
||
9074 | } |
||
9075 | |||
9076 | int isl_map_is_bijective(__isl_keep isl_map *map) |
||
9077 | { |
||
9078 | int sv; |
||
9079 | |||
9080 | sv = isl_map_is_single_valued(map); |
||
9081 | if (sv < 0 || !sv) |
||
9082 | return sv; |
||
9083 | |||
9084 | return isl_map_is_injective(map); |
||
9085 | } |
||
9086 | |||
9087 | int isl_set_is_singleton(__isl_keep isl_set *set) |
||
9088 | { |
||
9089 | return isl_map_is_single_valued((isl_map *)set); |
||
9090 | } |
||
9091 | |||
9092 | int isl_map_is_translation(__isl_keep isl_map *map) |
||
9093 | { |
||
9094 | int ok; |
||
9095 | isl_set *delta; |
||
9096 | |||
9097 | delta = isl_map_deltas(isl_map_copy(map)); |
||
9098 | ok = isl_set_is_singleton(delta); |
||
9099 | isl_set_free(delta); |
||
9100 | |||
9101 | return ok; |
||
9102 | } |
||
9103 | |||
9104 | static int unique(isl_int *p, unsigned pos, unsigned len) |
||
9105 | { |
||
9106 | if (isl_seq_first_non_zero(p, pos) != -1) |
||
9107 | return 0; |
||
9108 | if (isl_seq_first_non_zero(p + pos + 1, len - pos - 1) != -1) |
||
9109 | return 0; |
||
9110 | return 1; |
||
9111 | } |
||
9112 | |||
9113 | int isl_basic_set_is_box(__isl_keep isl_basic_set *bset) |
||
9114 | { |
||
9115 | int i, j; |
||
9116 | unsigned nvar; |
||
9117 | unsigned ovar; |
||
9118 | |||
9119 | if (!bset) |
||
9120 | return -1; |
||
9121 | |||
9122 | if (isl_basic_set_dim(bset, isl_dim_div) != 0) |
||
9123 | return 0; |
||
9124 | |||
9125 | nvar = isl_basic_set_dim(bset, isl_dim_set); |
||
9126 | ovar = isl_space_offset(bset->dim, isl_dim_set); |
||
9127 | for (j = 0; j < nvar; ++j) { |
||
9128 | int lower = 0, upper = 0; |
||
9129 | for (i = 0; i < bset->n_eq; ++i) { |
||
9130 | if (isl_int_is_zero(bset->eq[i][1 + ovar + j])) |
||
9131 | continue; |
||
9132 | if (!unique(bset->eq[i] + 1 + ovar, j, nvar)) |
||
9133 | return 0; |
||
9134 | break; |
||
9135 | } |
||
9136 | if (i < bset->n_eq) |
||
9137 | continue; |
||
9138 | for (i = 0; i < bset->n_ineq; ++i) { |
||
9139 | if (isl_int_is_zero(bset->ineq[i][1 + ovar + j])) |
||
9140 | continue; |
||
9141 | if (!unique(bset->ineq[i] + 1 + ovar, j, nvar)) |
||
9142 | return 0; |
||
9143 | if (isl_int_is_pos(bset->ineq[i][1 + ovar + j])) |
||
9144 | lower = 1; |
||
9145 | else |
||
9146 | upper = 1; |
||
9147 | } |
||
9148 | if (!lower || !upper) |
||
9149 | return 0; |
||
9150 | } |
||
9151 | |||
9152 | return 1; |
||
9153 | } |
||
9154 | |||
9155 | int isl_set_is_box(__isl_keep isl_set *set) |
||
9156 | { |
||
9157 | if (!set) |
||
9158 | return -1; |
||
9159 | if (set->n != 1) |
||
9160 | return 0; |
||
9161 | |||
9162 | return isl_basic_set_is_box(set->p[0]); |
||
9163 | } |
||
9164 | |||
9165 | int isl_basic_set_is_wrapping(__isl_keep isl_basic_set *bset) |
||
9166 | { |
||
9167 | if (!bset) |
||
9168 | return -1; |
||
9169 | |||
9170 | return isl_space_is_wrapping(bset->dim); |
||
9171 | } |
||
9172 | |||
9173 | int isl_set_is_wrapping(__isl_keep isl_set *set) |
||
9174 | { |
||
9175 | if (!set) |
||
9176 | return -1; |
||
9177 | |||
9178 | return isl_space_is_wrapping(set->dim); |
||
9179 | } |
||
9180 | |||
9181 | __isl_give isl_basic_set *isl_basic_map_wrap(__isl_take isl_basic_map *bmap) |
||
9182 | { |
||
9183 | bmap = isl_basic_map_cow(bmap); |
||
9184 | if (!bmap) |
||
9185 | return NULL; |
||
9186 | |||
9187 | bmap->dim = isl_space_wrap(bmap->dim); |
||
9188 | if (!bmap->dim) |
||
9189 | goto error; |
||
9190 | |||
9191 | bmap = isl_basic_map_finalize(bmap); |
||
9192 | |||
9193 | return (isl_basic_set *)bmap; |
||
9194 | error: |
||
9195 | isl_basic_map_free(bmap); |
||
9196 | return NULL; |
||
9197 | } |
||
9198 | |||
9199 | __isl_give isl_set *isl_map_wrap(__isl_take isl_map *map) |
||
9200 | { |
||
9201 | int i; |
||
9202 | |||
9203 | map = isl_map_cow(map); |
||
9204 | if (!map) |
||
9205 | return NULL; |
||
9206 | |||
9207 | for (i = 0; i < map->n; ++i) { |
||
9208 | map->p[i] = (isl_basic_map *)isl_basic_map_wrap(map->p[i]); |
||
9209 | if (!map->p[i]) |
||
9210 | goto error; |
||
9211 | } |
||
9212 | map->dim = isl_space_wrap(map->dim); |
||
9213 | if (!map->dim) |
||
9214 | goto error; |
||
9215 | |||
9216 | return (isl_set *)map; |
||
9217 | error: |
||
9218 | isl_map_free(map); |
||
9219 | return NULL; |
||
9220 | } |
||
9221 | |||
9222 | __isl_give isl_basic_map *isl_basic_set_unwrap(__isl_take isl_basic_set *bset) |
||
9223 | { |
||
9224 | bset = isl_basic_set_cow(bset); |
||
9225 | if (!bset) |
||
9226 | return NULL; |
||
9227 | |||
9228 | bset->dim = isl_space_unwrap(bset->dim); |
||
9229 | if (!bset->dim) |
||
9230 | goto error; |
||
9231 | |||
9232 | bset = isl_basic_set_finalize(bset); |
||
9233 | |||
9234 | return (isl_basic_map *)bset; |
||
9235 | error: |
||
9236 | isl_basic_set_free(bset); |
||
9237 | return NULL; |
||
9238 | } |
||
9239 | |||
9240 | __isl_give isl_map *isl_set_unwrap(__isl_take isl_set *set) |
||
9241 | { |
||
9242 | int i; |
||
9243 | |||
9244 | if (!set) |
||
9245 | return NULL; |
||
9246 | |||
9247 | if (!isl_set_is_wrapping(set)) |
||
9248 | isl_die(set->ctx, isl_error_invalid, "not a wrapping set", |
||
9249 | goto error); |
||
9250 | |||
9251 | set = isl_set_cow(set); |
||
9252 | if (!set) |
||
9253 | return NULL; |
||
9254 | |||
9255 | for (i = 0; i < set->n; ++i) { |
||
9256 | set->p[i] = (isl_basic_set *)isl_basic_set_unwrap(set->p[i]); |
||
9257 | if (!set->p[i]) |
||
9258 | goto error; |
||
9259 | } |
||
9260 | |||
9261 | set->dim = isl_space_unwrap(set->dim); |
||
9262 | if (!set->dim) |
||
9263 | goto error; |
||
9264 | |||
9265 | return (isl_map *)set; |
||
9266 | error: |
||
9267 | isl_set_free(set); |
||
9268 | return NULL; |
||
9269 | } |
||
9270 | |||
9271 | __isl_give isl_basic_map *isl_basic_map_reset(__isl_take isl_basic_map *bmap, |
||
9272 | enum isl_dim_type type) |
||
9273 | { |
||
9274 | if (!bmap) |
||
9275 | return NULL; |
||
9276 | |||
9277 | if (!isl_space_is_named_or_nested(bmap->dim, type)) |
||
9278 | return bmap; |
||
9279 | |||
9280 | bmap = isl_basic_map_cow(bmap); |
||
9281 | if (!bmap) |
||
9282 | return NULL; |
||
9283 | |||
9284 | bmap->dim = isl_space_reset(bmap->dim, type); |
||
9285 | if (!bmap->dim) |
||
9286 | goto error; |
||
9287 | |||
9288 | bmap = isl_basic_map_finalize(bmap); |
||
9289 | |||
9290 | return bmap; |
||
9291 | error: |
||
9292 | isl_basic_map_free(bmap); |
||
9293 | return NULL; |
||
9294 | } |
||
9295 | |||
9296 | __isl_give isl_map *isl_map_reset(__isl_take isl_map *map, |
||
9297 | enum isl_dim_type type) |
||
9298 | { |
||
9299 | int i; |
||
9300 | |||
9301 | if (!map) |
||
9302 | return NULL; |
||
9303 | |||
9304 | if (!isl_space_is_named_or_nested(map->dim, type)) |
||
9305 | return map; |
||
9306 | |||
9307 | map = isl_map_cow(map); |
||
9308 | if (!map) |
||
9309 | return NULL; |
||
9310 | |||
9311 | for (i = 0; i < map->n; ++i) { |
||
9312 | map->p[i] = isl_basic_map_reset(map->p[i], type); |
||
9313 | if (!map->p[i]) |
||
9314 | goto error; |
||
9315 | } |
||
9316 | map->dim = isl_space_reset(map->dim, type); |
||
9317 | if (!map->dim) |
||
9318 | goto error; |
||
9319 | |||
9320 | return map; |
||
9321 | error: |
||
9322 | isl_map_free(map); |
||
9323 | return NULL; |
||
9324 | } |
||
9325 | |||
9326 | __isl_give isl_basic_map *isl_basic_map_flatten(__isl_take isl_basic_map *bmap) |
||
9327 | { |
||
9328 | if (!bmap) |
||
9329 | return NULL; |
||
9330 | |||
9331 | if (!bmap->dim->nested[0] && !bmap->dim->nested[1]) |
||
9332 | return bmap; |
||
9333 | |||
9334 | bmap = isl_basic_map_cow(bmap); |
||
9335 | if (!bmap) |
||
9336 | return NULL; |
||
9337 | |||
9338 | bmap->dim = isl_space_flatten(bmap->dim); |
||
9339 | if (!bmap->dim) |
||
9340 | goto error; |
||
9341 | |||
9342 | bmap = isl_basic_map_finalize(bmap); |
||
9343 | |||
9344 | return bmap; |
||
9345 | error: |
||
9346 | isl_basic_map_free(bmap); |
||
9347 | return NULL; |
||
9348 | } |
||
9349 | |||
9350 | __isl_give isl_basic_set *isl_basic_set_flatten(__isl_take isl_basic_set *bset) |
||
9351 | { |
||
9352 | return (isl_basic_set *)isl_basic_map_flatten((isl_basic_map *)bset); |
||
9353 | } |
||
9354 | |||
9355 | __isl_give isl_basic_map *isl_basic_map_flatten_domain( |
||
9356 | __isl_take isl_basic_map *bmap) |
||
9357 | { |
||
9358 | if (!bmap) |
||
9359 | return NULL; |
||
9360 | |||
9361 | if (!bmap->dim->nested[0]) |
||
9362 | return bmap; |
||
9363 | |||
9364 | bmap = isl_basic_map_cow(bmap); |
||
9365 | if (!bmap) |
||
9366 | return NULL; |
||
9367 | |||
9368 | bmap->dim = isl_space_flatten_domain(bmap->dim); |
||
9369 | if (!bmap->dim) |
||
9370 | goto error; |
||
9371 | |||
9372 | bmap = isl_basic_map_finalize(bmap); |
||
9373 | |||
9374 | return bmap; |
||
9375 | error: |
||
9376 | isl_basic_map_free(bmap); |
||
9377 | return NULL; |
||
9378 | } |
||
9379 | |||
9380 | __isl_give isl_basic_map *isl_basic_map_flatten_range( |
||
9381 | __isl_take isl_basic_map *bmap) |
||
9382 | { |
||
9383 | if (!bmap) |
||
9384 | return NULL; |
||
9385 | |||
9386 | if (!bmap->dim->nested[1]) |
||
9387 | return bmap; |
||
9388 | |||
9389 | bmap = isl_basic_map_cow(bmap); |
||
9390 | if (!bmap) |
||
9391 | return NULL; |
||
9392 | |||
9393 | bmap->dim = isl_space_flatten_range(bmap->dim); |
||
9394 | if (!bmap->dim) |
||
9395 | goto error; |
||
9396 | |||
9397 | bmap = isl_basic_map_finalize(bmap); |
||
9398 | |||
9399 | return bmap; |
||
9400 | error: |
||
9401 | isl_basic_map_free(bmap); |
||
9402 | return NULL; |
||
9403 | } |
||
9404 | |||
9405 | __isl_give isl_map *isl_map_flatten(__isl_take isl_map *map) |
||
9406 | { |
||
9407 | int i; |
||
9408 | |||
9409 | if (!map) |
||
9410 | return NULL; |
||
9411 | |||
9412 | if (!map->dim->nested[0] && !map->dim->nested[1]) |
||
9413 | return map; |
||
9414 | |||
9415 | map = isl_map_cow(map); |
||
9416 | if (!map) |
||
9417 | return NULL; |
||
9418 | |||
9419 | for (i = 0; i < map->n; ++i) { |
||
9420 | map->p[i] = isl_basic_map_flatten(map->p[i]); |
||
9421 | if (!map->p[i]) |
||
9422 | goto error; |
||
9423 | } |
||
9424 | map->dim = isl_space_flatten(map->dim); |
||
9425 | if (!map->dim) |
||
9426 | goto error; |
||
9427 | |||
9428 | return map; |
||
9429 | error: |
||
9430 | isl_map_free(map); |
||
9431 | return NULL; |
||
9432 | } |
||
9433 | |||
9434 | __isl_give isl_set *isl_set_flatten(__isl_take isl_set *set) |
||
9435 | { |
||
9436 | return (isl_set *)isl_map_flatten((isl_map *)set); |
||
9437 | } |
||
9438 | |||
9439 | __isl_give isl_map *isl_set_flatten_map(__isl_take isl_set *set) |
||
9440 | { |
||
9441 | isl_space *dim, *flat_dim; |
||
9442 | isl_map *map; |
||
9443 | |||
9444 | dim = isl_set_get_space(set); |
||
9445 | flat_dim = isl_space_flatten(isl_space_copy(dim)); |
||
9446 | map = isl_map_identity(isl_space_join(isl_space_reverse(dim), flat_dim)); |
||
9447 | map = isl_map_intersect_domain(map, set); |
||
9448 | |||
9449 | return map; |
||
9450 | } |
||
9451 | |||
9452 | __isl_give isl_map *isl_map_flatten_domain(__isl_take isl_map *map) |
||
9453 | { |
||
9454 | int i; |
||
9455 | |||
9456 | if (!map) |
||
9457 | return NULL; |
||
9458 | |||
9459 | if (!map->dim->nested[0]) |
||
9460 | return map; |
||
9461 | |||
9462 | map = isl_map_cow(map); |
||
9463 | if (!map) |
||
9464 | return NULL; |
||
9465 | |||
9466 | for (i = 0; i < map->n; ++i) { |
||
9467 | map->p[i] = isl_basic_map_flatten_domain(map->p[i]); |
||
9468 | if (!map->p[i]) |
||
9469 | goto error; |
||
9470 | } |
||
9471 | map->dim = isl_space_flatten_domain(map->dim); |
||
9472 | if (!map->dim) |
||
9473 | goto error; |
||
9474 | |||
9475 | return map; |
||
9476 | error: |
||
9477 | isl_map_free(map); |
||
9478 | return NULL; |
||
9479 | } |
||
9480 | |||
9481 | __isl_give isl_map *isl_map_flatten_range(__isl_take isl_map *map) |
||
9482 | { |
||
9483 | int i; |
||
9484 | |||
9485 | if (!map) |
||
9486 | return NULL; |
||
9487 | |||
9488 | if (!map->dim->nested[1]) |
||
9489 | return map; |
||
9490 | |||
9491 | map = isl_map_cow(map); |
||
9492 | if (!map) |
||
9493 | return NULL; |
||
9494 | |||
9495 | for (i = 0; i < map->n; ++i) { |
||
9496 | map->p[i] = isl_basic_map_flatten_range(map->p[i]); |
||
9497 | if (!map->p[i]) |
||
9498 | goto error; |
||
9499 | } |
||
9500 | map->dim = isl_space_flatten_range(map->dim); |
||
9501 | if (!map->dim) |
||
9502 | goto error; |
||
9503 | |||
9504 | return map; |
||
9505 | error: |
||
9506 | isl_map_free(map); |
||
9507 | return NULL; |
||
9508 | } |
||
9509 | |||
9510 | /* Reorder the dimensions of "bmap" according to the given dim_map |
||
9511 | * and set the dimension specification to "dim". |
||
9512 | */ |
||
9513 | __isl_give isl_basic_map *isl_basic_map_realign(__isl_take isl_basic_map *bmap, |
||
9514 | __isl_take isl_space *dim, __isl_take struct isl_dim_map *dim_map) |
||
9515 | { |
||
9516 | isl_basic_map *res; |
||
9517 | unsigned flags; |
||
9518 | |||
9519 | bmap = isl_basic_map_cow(bmap); |
||
9520 | if (!bmap || !dim || !dim_map) |
||
9521 | goto error; |
||
9522 | |||
9523 | flags = bmap->flags; |
||
9524 | ISL_FL_CLR(flags, ISL_BASIC_MAP_FINAL); |
||
9525 | ISL_FL_CLR(flags, ISL_BASIC_MAP_NORMALIZED); |
||
9526 | ISL_FL_CLR(flags, ISL_BASIC_MAP_NORMALIZED_DIVS); |
||
9527 | res = isl_basic_map_alloc_space(dim, |
||
9528 | bmap->n_div, bmap->n_eq, bmap->n_ineq); |
||
9529 | res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map); |
||
9530 | if (res) |
||
9531 | res->flags = flags; |
||
9532 | res = isl_basic_map_finalize(res); |
||
9533 | return res; |
||
9534 | error: |
||
9535 | free(dim_map); |
||
9536 | isl_basic_map_free(bmap); |
||
9537 | isl_space_free(dim); |
||
9538 | return NULL; |
||
9539 | } |
||
9540 | |||
9541 | /* Reorder the dimensions of "map" according to given reordering. |
||
9542 | */ |
||
9543 | __isl_give isl_map *isl_map_realign(__isl_take isl_map *map, |
||
9544 | __isl_take isl_reordering *r) |
||
9545 | { |
||
9546 | int i; |
||
9547 | struct isl_dim_map *dim_map; |
||
9548 | |||
9549 | map = isl_map_cow(map); |
||
9550 | dim_map = isl_dim_map_from_reordering(r); |
||
9551 | if (!map || !r || !dim_map) |
||
9552 | goto error; |
||
9553 | |||
9554 | for (i = 0; i < map->n; ++i) { |
||
9555 | struct isl_dim_map *dim_map_i; |
||
9556 | |||
9557 | dim_map_i = isl_dim_map_extend(dim_map, map->p[i]); |
||
9558 | |||
9559 | map->p[i] = isl_basic_map_realign(map->p[i], |
||
9560 | isl_space_copy(r->dim), dim_map_i); |
||
9561 | |||
9562 | if (!map->p[i]) |
||
9563 | goto error; |
||
9564 | } |
||
9565 | |||
9566 | map = isl_map_reset_space(map, isl_space_copy(r->dim)); |
||
9567 | |||
9568 | isl_reordering_free(r); |
||
9569 | free(dim_map); |
||
9570 | return map; |
||
9571 | error: |
||
9572 | free(dim_map); |
||
9573 | isl_map_free(map); |
||
9574 | isl_reordering_free(r); |
||
9575 | return NULL; |
||
9576 | } |
||
9577 | |||
9578 | __isl_give isl_set *isl_set_realign(__isl_take isl_set *set, |
||
9579 | __isl_take isl_reordering *r) |
||
9580 | { |
||
9581 | return (isl_set *)isl_map_realign((isl_map *)set, r); |
||
9582 | } |
||
9583 | |||
9584 | __isl_give isl_map *isl_map_align_params(__isl_take isl_map *map, |
||
9585 | __isl_take isl_space *model) |
||
9586 | { |
||
9587 | isl_ctx *ctx; |
||
9588 | |||
9589 | if (!map || !model) |
||
9590 | goto error; |
||
9591 | |||
9592 | ctx = isl_space_get_ctx(model); |
||
9593 | if (!isl_space_has_named_params(model)) |
||
9594 | isl_die(ctx, isl_error_invalid, |
||
9595 | "model has unnamed parameters", goto error); |
||
9596 | if (!isl_space_has_named_params(map->dim)) |
||
9597 | isl_die(ctx, isl_error_invalid, |
||
9598 | "relation has unnamed parameters", goto error); |
||
9599 | if (!isl_space_match(map->dim, isl_dim_param, model, isl_dim_param)) { |
||
9600 | isl_reordering *exp; |
||
9601 | |||
9602 | model = isl_space_drop_dims(model, isl_dim_in, |
||
9603 | 0, isl_space_dim(model, isl_dim_in)); |
||
9604 | model = isl_space_drop_dims(model, isl_dim_out, |
||
9605 | 0, isl_space_dim(model, isl_dim_out)); |
||
9606 | exp = isl_parameter_alignment_reordering(map->dim, model); |
||
9607 | exp = isl_reordering_extend_space(exp, isl_map_get_space(map)); |
||
9608 | map = isl_map_realign(map, exp); |
||
9609 | } |
||
9610 | |||
9611 | isl_space_free(model); |
||
9612 | return map; |
||
9613 | error: |
||
9614 | isl_space_free(model); |
||
9615 | isl_map_free(map); |
||
9616 | return NULL; |
||
9617 | } |
||
9618 | |||
9619 | __isl_give isl_set *isl_set_align_params(__isl_take isl_set *set, |
||
9620 | __isl_take isl_space *model) |
||
9621 | { |
||
9622 | return isl_map_align_params(set, model); |
||
9623 | } |
||
9624 | |||
9625 | __isl_give isl_mat *isl_basic_map_equalities_matrix( |
||
9626 | __isl_keep isl_basic_map *bmap, enum isl_dim_type c1, |
||
9627 | enum isl_dim_type c2, enum isl_dim_type c3, |
||
9628 | enum isl_dim_type c4, enum isl_dim_type c5) |
||
9629 | { |
||
9630 | enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 }; |
||
9631 | struct isl_mat *mat; |
||
9632 | int i, j, k; |
||
9633 | int pos; |
||
9634 | |||
9635 | if (!bmap) |
||
9636 | return NULL; |
||
9637 | mat = isl_mat_alloc(bmap->ctx, bmap->n_eq, |
||
9638 | isl_basic_map_total_dim(bmap) + 1); |
||
9639 | if (!mat) |
||
9640 | return NULL; |
||
9641 | for (i = 0; i < bmap->n_eq; ++i) |
||
9642 | for (j = 0, pos = 0; j < 5; ++j) { |
||
9643 | int off = isl_basic_map_offset(bmap, c[j]); |
||
9644 | for (k = 0; k < isl_basic_map_dim(bmap, c[j]); ++k) { |
||
9645 | isl_int_set(mat->row[i][pos], |
||
9646 | bmap->eq[i][off + k]); |
||
9647 | ++pos; |
||
9648 | } |
||
9649 | } |
||
9650 | |||
9651 | return mat; |
||
9652 | } |
||
9653 | |||
9654 | __isl_give isl_mat *isl_basic_map_inequalities_matrix( |
||
9655 | __isl_keep isl_basic_map *bmap, enum isl_dim_type c1, |
||
9656 | enum isl_dim_type c2, enum isl_dim_type c3, |
||
9657 | enum isl_dim_type c4, enum isl_dim_type c5) |
||
9658 | { |
||
9659 | enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 }; |
||
9660 | struct isl_mat *mat; |
||
9661 | int i, j, k; |
||
9662 | int pos; |
||
9663 | |||
9664 | if (!bmap) |
||
9665 | return NULL; |
||
9666 | mat = isl_mat_alloc(bmap->ctx, bmap->n_ineq, |
||
9667 | isl_basic_map_total_dim(bmap) + 1); |
||
9668 | if (!mat) |
||
9669 | return NULL; |
||
9670 | for (i = 0; i < bmap->n_ineq; ++i) |
||
9671 | for (j = 0, pos = 0; j < 5; ++j) { |
||
9672 | int off = isl_basic_map_offset(bmap, c[j]); |
||
9673 | for (k = 0; k < isl_basic_map_dim(bmap, c[j]); ++k) { |
||
9674 | isl_int_set(mat->row[i][pos], |
||
9675 | bmap->ineq[i][off + k]); |
||
9676 | ++pos; |
||
9677 | } |
||
9678 | } |
||
9679 | |||
9680 | return mat; |
||
9681 | } |
||
9682 | |||
9683 | __isl_give isl_basic_map *isl_basic_map_from_constraint_matrices( |
||
9684 | __isl_take isl_space *dim, |
||
9685 | __isl_take isl_mat *eq, __isl_take isl_mat *ineq, enum isl_dim_type c1, |
||
9686 | enum isl_dim_type c2, enum isl_dim_type c3, |
||
9687 | enum isl_dim_type c4, enum isl_dim_type c5) |
||
9688 | { |
||
9689 | enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 }; |
||
9690 | isl_basic_map *bmap; |
||
9691 | unsigned total; |
||
9692 | unsigned extra; |
||
9693 | int i, j, k, l; |
||
9694 | int pos; |
||
9695 | |||
9696 | if (!dim || !eq || !ineq) |
||
9697 | goto error; |
||
9698 | |||
9699 | if (eq->n_col != ineq->n_col) |
||
9700 | isl_die(dim->ctx, isl_error_invalid, |
||
9701 | "equalities and inequalities matrices should have " |
||
9702 | "same number of columns", goto error); |
||
9703 | |||
9704 | total = 1 + isl_space_dim(dim, isl_dim_all); |
||
9705 | |||
9706 | if (eq->n_col < total) |
||
9707 | isl_die(dim->ctx, isl_error_invalid, |
||
9708 | "number of columns too small", goto error); |
||
9709 | |||
9710 | extra = eq->n_col - total; |
||
9711 | |||
9712 | bmap = isl_basic_map_alloc_space(isl_space_copy(dim), extra, |
||
9713 | eq->n_row, ineq->n_row); |
||
9714 | if (!bmap) |
||
9715 | goto error; |
||
9716 | for (i = 0; i < extra; ++i) { |
||
9717 | k = isl_basic_map_alloc_div(bmap); |
||
9718 | if (k < 0) |
||
9719 | goto error; |
||
9720 | isl_int_set_si(bmap->div[k][0], 0); |
||
9721 | } |
||
9722 | for (i = 0; i < eq->n_row; ++i) { |
||
9723 | l = isl_basic_map_alloc_equality(bmap); |
||
9724 | if (l < 0) |
||
9725 | goto error; |
||
9726 | for (j = 0, pos = 0; j < 5; ++j) { |
||
9727 | int off = isl_basic_map_offset(bmap, c[j]); |
||
9728 | for (k = 0; k < isl_basic_map_dim(bmap, c[j]); ++k) { |
||
9729 | isl_int_set(bmap->eq[l][off + k], |
||
9730 | eq->row[i][pos]); |
||
9731 | ++pos; |
||
9732 | } |
||
9733 | } |
||
9734 | } |
||
9735 | for (i = 0; i < ineq->n_row; ++i) { |
||
9736 | l = isl_basic_map_alloc_inequality(bmap); |
||
9737 | if (l < 0) |
||
9738 | goto error; |
||
9739 | for (j = 0, pos = 0; j < 5; ++j) { |
||
9740 | int off = isl_basic_map_offset(bmap, c[j]); |
||
9741 | for (k = 0; k < isl_basic_map_dim(bmap, c[j]); ++k) { |
||
9742 | isl_int_set(bmap->ineq[l][off + k], |
||
9743 | ineq->row[i][pos]); |
||
9744 | ++pos; |
||
9745 | } |
||
9746 | } |
||
9747 | } |
||
9748 | |||
9749 | isl_space_free(dim); |
||
9750 | isl_mat_free(eq); |
||
9751 | isl_mat_free(ineq); |
||
9752 | |||
9753 | return bmap; |
||
9754 | error: |
||
9755 | isl_space_free(dim); |
||
9756 | isl_mat_free(eq); |
||
9757 | isl_mat_free(ineq); |
||
9758 | return NULL; |
||
9759 | } |
||
9760 | |||
9761 | __isl_give isl_mat *isl_basic_set_equalities_matrix( |
||
9762 | __isl_keep isl_basic_set *bset, enum isl_dim_type c1, |
||
9763 | enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4) |
||
9764 | { |
||
9765 | return isl_basic_map_equalities_matrix((isl_basic_map *)bset, |
||
9766 | c1, c2, c3, c4, isl_dim_in); |
||
9767 | } |
||
9768 | |||
9769 | __isl_give isl_mat *isl_basic_set_inequalities_matrix( |
||
9770 | __isl_keep isl_basic_set *bset, enum isl_dim_type c1, |
||
9771 | enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4) |
||
9772 | { |
||
9773 | return isl_basic_map_inequalities_matrix((isl_basic_map *)bset, |
||
9774 | c1, c2, c3, c4, isl_dim_in); |
||
9775 | } |
||
9776 | |||
9777 | __isl_give isl_basic_set *isl_basic_set_from_constraint_matrices( |
||
9778 | __isl_take isl_space *dim, |
||
9779 | __isl_take isl_mat *eq, __isl_take isl_mat *ineq, enum isl_dim_type c1, |
||
9780 | enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4) |
||
9781 | { |
||
9782 | return (isl_basic_set*) |
||
9783 | isl_basic_map_from_constraint_matrices(dim, eq, ineq, |
||
9784 | c1, c2, c3, c4, isl_dim_in); |
||
9785 | } |
||
9786 | |||
9787 | int isl_basic_map_can_zip(__isl_keep isl_basic_map *bmap) |
||
9788 | { |
||
9789 | if (!bmap) |
||
9790 | return -1; |
||
9791 | |||
9792 | return isl_space_can_zip(bmap->dim); |
||
9793 | } |
||
9794 | |||
9795 | int isl_map_can_zip(__isl_keep isl_map *map) |
||
9796 | { |
||
9797 | if (!map) |
||
9798 | return -1; |
||
9799 | |||
9800 | return isl_space_can_zip(map->dim); |
||
9801 | } |
||
9802 | |||
9803 | /* Given a basic map (A -> B) -> (C -> D), return the corresponding basic map |
||
9804 | * (A -> C) -> (B -> D). |
||
9805 | */ |
||
9806 | __isl_give isl_basic_map *isl_basic_map_zip(__isl_take isl_basic_map *bmap) |
||
9807 | { |
||
9808 | unsigned pos; |
||
9809 | unsigned n1; |
||
9810 | unsigned n2; |
||
9811 | |||
9812 | if (!bmap) |
||
9813 | return NULL; |
||
9814 | |||
9815 | if (!isl_basic_map_can_zip(bmap)) |
||
9816 | isl_die(bmap->ctx, isl_error_invalid, |
||
9817 | "basic map cannot be zipped", goto error); |
||
9818 | pos = isl_basic_map_offset(bmap, isl_dim_in) + |
||
9819 | isl_space_dim(bmap->dim->nested[0], isl_dim_in); |
||
9820 | n1 = isl_space_dim(bmap->dim->nested[0], isl_dim_out); |
||
9821 | n2 = isl_space_dim(bmap->dim->nested[1], isl_dim_in); |
||
9822 | bmap = isl_basic_map_cow(bmap); |
||
9823 | bmap = isl_basic_map_swap_vars(bmap, pos, n1, n2); |
||
9824 | if (!bmap) |
||
9825 | return NULL; |
||
9826 | bmap->dim = isl_space_zip(bmap->dim); |
||
9827 | if (!bmap->dim) |
||
9828 | goto error; |
||
9829 | return bmap; |
||
9830 | error: |
||
9831 | isl_basic_map_free(bmap); |
||
9832 | return NULL; |
||
9833 | } |
||
9834 | |||
9835 | /* Given a map (A -> B) -> (C -> D), return the corresponding map |
||
9836 | * (A -> C) -> (B -> D). |
||
9837 | */ |
||
9838 | __isl_give isl_map *isl_map_zip(__isl_take isl_map *map) |
||
9839 | { |
||
9840 | int i; |
||
9841 | |||
9842 | if (!map) |
||
9843 | return NULL; |
||
9844 | |||
9845 | if (!isl_map_can_zip(map)) |
||
9846 | isl_die(map->ctx, isl_error_invalid, "map cannot be zipped", |
||
9847 | goto error); |
||
9848 | |||
9849 | map = isl_map_cow(map); |
||
9850 | if (!map) |
||
9851 | return NULL; |
||
9852 | |||
9853 | for (i = 0; i < map->n; ++i) { |
||
9854 | map->p[i] = isl_basic_map_zip(map->p[i]); |
||
9855 | if (!map->p[i]) |
||
9856 | goto error; |
||
9857 | } |
||
9858 | |||
9859 | map->dim = isl_space_zip(map->dim); |
||
9860 | if (!map->dim) |
||
9861 | goto error; |
||
9862 | |||
9863 | return map; |
||
9864 | error: |
||
9865 | isl_map_free(map); |
||
9866 | return NULL; |
||
9867 | } |
||
9868 | |||
9869 | /* Can we apply isl_basic_map_curry to "bmap"? |
||
9870 | * That is, does it have a nested relation in its domain? |
||
9871 | */ |
||
9872 | int isl_basic_map_can_curry(__isl_keep isl_basic_map *bmap) |
||
9873 | { |
||
9874 | if (!bmap) |
||
9875 | return -1; |
||
9876 | |||
9877 | return isl_space_can_curry(bmap->dim); |
||
9878 | } |
||
9879 | |||
9880 | /* Can we apply isl_map_curry to "map"? |
||
9881 | * That is, does it have a nested relation in its domain? |
||
9882 | */ |
||
9883 | int isl_map_can_curry(__isl_keep isl_map *map) |
||
9884 | { |
||
9885 | if (!map) |
||
9886 | return -1; |
||
9887 | |||
9888 | return isl_space_can_curry(map->dim); |
||
9889 | } |
||
9890 | |||
9891 | /* Given a basic map (A -> B) -> C, return the corresponding basic map |
||
9892 | * A -> (B -> C). |
||
9893 | */ |
||
9894 | __isl_give isl_basic_map *isl_basic_map_curry(__isl_take isl_basic_map *bmap) |
||
9895 | { |
||
9896 | |||
9897 | if (!bmap) |
||
9898 | return NULL; |
||
9899 | |||
9900 | if (!isl_basic_map_can_curry(bmap)) |
||
9901 | isl_die(bmap->ctx, isl_error_invalid, |
||
9902 | "basic map cannot be curried", goto error); |
||
9903 | bmap->dim = isl_space_curry(bmap->dim); |
||
9904 | if (!bmap->dim) |
||
9905 | goto error; |
||
9906 | return bmap; |
||
9907 | error: |
||
9908 | isl_basic_map_free(bmap); |
||
9909 | return NULL; |
||
9910 | } |
||
9911 | |||
9912 | /* Given a map (A -> B) -> C, return the corresponding map |
||
9913 | * A -> (B -> C). |
||
9914 | */ |
||
9915 | __isl_give isl_map *isl_map_curry(__isl_take isl_map *map) |
||
9916 | { |
||
9917 | int i; |
||
9918 | |||
9919 | if (!map) |
||
9920 | return NULL; |
||
9921 | |||
9922 | if (!isl_map_can_curry(map)) |
||
9923 | isl_die(map->ctx, isl_error_invalid, "map cannot be curried", |
||
9924 | goto error); |
||
9925 | |||
9926 | map = isl_map_cow(map); |
||
9927 | if (!map) |
||
9928 | return NULL; |
||
9929 | |||
9930 | for (i = 0; i < map->n; ++i) { |
||
9931 | map->p[i] = isl_basic_map_curry(map->p[i]); |
||
9932 | if (!map->p[i]) |
||
9933 | goto error; |
||
9934 | } |
||
9935 | |||
9936 | map->dim = isl_space_curry(map->dim); |
||
9937 | if (!map->dim) |
||
9938 | goto error; |
||
9939 | |||
9940 | return map; |
||
9941 | error: |
||
9942 | isl_map_free(map); |
||
9943 | return NULL; |
||
9944 | } |
||
9945 | |||
9946 | /* Construct a basic map mapping the domain of the affine expression |
||
9947 | * to a one-dimensional range prescribed by the affine expression. |
||
9948 | */ |
||
9949 | __isl_give isl_basic_map *isl_basic_map_from_aff(__isl_take isl_aff *aff) |
||
9950 | { |
||
9951 | int k; |
||
9952 | int pos; |
||
9953 | isl_local_space *ls; |
||
9954 | isl_basic_map *bmap; |
||
9955 | |||
9956 | if (!aff) |
||
9957 | return NULL; |
||
9958 | |||
9959 | ls = isl_aff_get_local_space(aff); |
||
9960 | bmap = isl_basic_map_from_local_space(ls); |
||
9961 | bmap = isl_basic_map_extend_constraints(bmap, 1, 0); |
||
9962 | k = isl_basic_map_alloc_equality(bmap); |
||
9963 | if (k < 0) |
||
9964 | goto error; |
||
9965 | |||
9966 | pos = isl_basic_map_offset(bmap, isl_dim_out); |
||
9967 | isl_seq_cpy(bmap->eq[k], aff->v->el + 1, pos); |
||
9968 | isl_int_neg(bmap->eq[k][pos], aff->v->el[0]); |
||
9969 | isl_seq_cpy(bmap->eq[k] + pos + 1, aff->v->el + 1 + pos, |
||
9970 | aff->v->size - (pos + 1)); |
||
9971 | |||
9972 | isl_aff_free(aff); |
||
9973 | bmap = isl_basic_map_finalize(bmap); |
||
9974 | return bmap; |
||
9975 | error: |
||
9976 | isl_aff_free(aff); |
||
9977 | isl_basic_map_free(bmap); |
||
9978 | return NULL; |
||
9979 | } |
||
9980 | |||
9981 | /* Construct a map mapping the domain of the affine expression |
||
9982 | * to a one-dimensional range prescribed by the affine expression. |
||
9983 | */ |
||
9984 | __isl_give isl_map *isl_map_from_aff(__isl_take isl_aff *aff) |
||
9985 | { |
||
9986 | isl_basic_map *bmap; |
||
9987 | |||
9988 | bmap = isl_basic_map_from_aff(aff); |
||
9989 | return isl_map_from_basic_map(bmap); |
||
9990 | } |
||
9991 | |||
9992 | /* Construct a basic map mapping the domain the multi-affine expression |
||
9993 | * to its range, with each dimension in the range equated to the |
||
9994 | * corresponding affine expression. |
||
9995 | */ |
||
9996 | __isl_give isl_basic_map *isl_basic_map_from_multi_aff( |
||
9997 | __isl_take isl_multi_aff *maff) |
||
9998 | { |
||
9999 | int i; |
||
10000 | isl_space *space; |
||
10001 | isl_basic_map *bmap; |
||
10002 | |||
10003 | if (!maff) |
||
10004 | return NULL; |
||
10005 | |||
10006 | if (isl_space_dim(maff->space, isl_dim_out) != maff->n) |
||
10007 | isl_die(isl_multi_aff_get_ctx(maff), isl_error_internal, |
||
10008 | "invalid space", return isl_multi_aff_free(maff)); |
||
10009 | |||
10010 | space = isl_space_domain(isl_multi_aff_get_space(maff)); |
||
10011 | bmap = isl_basic_map_universe(isl_space_from_domain(space)); |
||
10012 | |||
10013 | for (i = 0; i < maff->n; ++i) { |
||
10014 | isl_aff *aff; |
||
10015 | isl_basic_map *bmap_i; |
||
10016 | |||
10017 | aff = isl_aff_copy(maff->p[i]); |
||
10018 | bmap_i = isl_basic_map_from_aff(aff); |
||
10019 | |||
10020 | bmap = isl_basic_map_flat_range_product(bmap, bmap_i); |
||
10021 | } |
||
10022 | |||
10023 | bmap = isl_basic_map_reset_space(bmap, isl_multi_aff_get_space(maff)); |
||
10024 | |||
10025 | isl_multi_aff_free(maff); |
||
10026 | return bmap; |
||
10027 | } |
||
10028 | |||
10029 | /* Construct a map mapping the domain the multi-affine expression |
||
10030 | * to its range, with each dimension in the range equated to the |
||
10031 | * corresponding affine expression. |
||
10032 | */ |
||
10033 | __isl_give isl_map *isl_map_from_multi_aff(__isl_take isl_multi_aff *maff) |
||
10034 | { |
||
10035 | isl_basic_map *bmap; |
||
10036 | |||
10037 | bmap = isl_basic_map_from_multi_aff(maff); |
||
10038 | return isl_map_from_basic_map(bmap); |
||
10039 | } |
||
10040 | |||
10041 | /* Construct a basic map mapping a domain in the given space to |
||
10042 | * to an n-dimensional range, with n the number of elements in the list, |
||
10043 | * where each coordinate in the range is prescribed by the |
||
10044 | * corresponding affine expression. |
||
10045 | * The domains of all affine expressions in the list are assumed to match |
||
10046 | * domain_dim. |
||
10047 | */ |
||
10048 | __isl_give isl_basic_map *isl_basic_map_from_aff_list( |
||
10049 | __isl_take isl_space *domain_dim, __isl_take isl_aff_list *list) |
||
10050 | { |
||
10051 | int i; |
||
10052 | isl_space *dim; |
||
10053 | isl_basic_map *bmap; |
||
10054 | |||
10055 | if (!list) |
||
10056 | return NULL; |
||
10057 | |||
10058 | dim = isl_space_from_domain(domain_dim); |
||
10059 | bmap = isl_basic_map_universe(dim); |
||
10060 | |||
10061 | for (i = 0; i < list->n; ++i) { |
||
10062 | isl_aff *aff; |
||
10063 | isl_basic_map *bmap_i; |
||
10064 | |||
10065 | aff = isl_aff_copy(list->p[i]); |
||
10066 | bmap_i = isl_basic_map_from_aff(aff); |
||
10067 | |||
10068 | bmap = isl_basic_map_flat_range_product(bmap, bmap_i); |
||
10069 | } |
||
10070 | |||
10071 | isl_aff_list_free(list); |
||
10072 | return bmap; |
||
10073 | } |
||
10074 | |||
10075 | __isl_give isl_set *isl_set_equate(__isl_take isl_set *set, |
||
10076 | enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2) |
||
10077 | { |
||
10078 | return isl_map_equate(set, type1, pos1, type2, pos2); |
||
10079 | } |
||
10080 | |||
10081 | /* Construct a basic map where the given dimensions are equal to each other. |
||
10082 | */ |
||
10083 | static __isl_give isl_basic_map *equator(__isl_take isl_space *space, |
||
10084 | enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2) |
||
10085 | { |
||
10086 | isl_basic_map *bmap = NULL; |
||
10087 | int i; |
||
10088 | |||
10089 | if (!space) |
||
10090 | return NULL; |
||
10091 | |||
10092 | if (pos1 >= isl_space_dim(space, type1)) |
||
10093 | isl_die(isl_space_get_ctx(space), isl_error_invalid, |
||
10094 | "index out of bounds", goto error); |
||
10095 | if (pos2 >= isl_space_dim(space, type2)) |
||
10096 | isl_die(isl_space_get_ctx(space), isl_error_invalid, |
||
10097 | "index out of bounds", goto error); |
||
10098 | |||
10099 | if (type1 == type2 && pos1 == pos2) |
||
10100 | return isl_basic_map_universe(space); |
||
10101 | |||
10102 | bmap = isl_basic_map_alloc_space(isl_space_copy(space), 0, 1, 0); |
||
10103 | i = isl_basic_map_alloc_equality(bmap); |
||
10104 | if (i < 0) |
||
10105 | goto error; |
||
10106 | isl_seq_clr(bmap->eq[i], 1 + isl_basic_map_total_dim(bmap)); |
||
10107 | pos1 += isl_basic_map_offset(bmap, type1); |
||
10108 | pos2 += isl_basic_map_offset(bmap, type2); |
||
10109 | isl_int_set_si(bmap->eq[i][pos1], -1); |
||
10110 | isl_int_set_si(bmap->eq[i][pos2], 1); |
||
10111 | bmap = isl_basic_map_finalize(bmap); |
||
10112 | isl_space_free(space); |
||
10113 | return bmap; |
||
10114 | error: |
||
10115 | isl_space_free(space); |
||
10116 | isl_basic_map_free(bmap); |
||
10117 | return NULL; |
||
10118 | } |
||
10119 | |||
10120 | /* Add a constraint imposing that the given two dimensions are equal. |
||
10121 | */ |
||
10122 | __isl_give isl_basic_map *isl_basic_map_equate(__isl_take isl_basic_map *bmap, |
||
10123 | enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2) |
||
10124 | { |
||
10125 | isl_basic_map *eq; |
||
10126 | |||
10127 | eq = equator(isl_basic_map_get_space(bmap), type1, pos1, type2, pos2); |
||
10128 | |||
10129 | bmap = isl_basic_map_intersect(bmap, eq); |
||
10130 | |||
10131 | return bmap; |
||
10132 | } |
||
10133 | |||
10134 | /* Add a constraint imposing that the given two dimensions are equal. |
||
10135 | */ |
||
10136 | __isl_give isl_map *isl_map_equate(__isl_take isl_map *map, |
||
10137 | enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2) |
||
10138 | { |
||
10139 | isl_basic_map *bmap; |
||
10140 | |||
10141 | bmap = equator(isl_map_get_space(map), type1, pos1, type2, pos2); |
||
10142 | |||
10143 | map = isl_map_intersect(map, isl_map_from_basic_map(bmap)); |
||
10144 | |||
10145 | return map; |
||
10146 | } |
||
10147 | |||
10148 | /* Add a constraint imposing that the given two dimensions have opposite values. |
||
10149 | */ |
||
10150 | __isl_give isl_map *isl_map_oppose(__isl_take isl_map *map, |
||
10151 | enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2) |
||
10152 | { |
||
10153 | isl_basic_map *bmap = NULL; |
||
10154 | int i; |
||
10155 | |||
10156 | if (!map) |
||
10157 | return NULL; |
||
10158 | |||
10159 | if (pos1 >= isl_map_dim(map, type1)) |
||
10160 | isl_die(map->ctx, isl_error_invalid, |
||
10161 | "index out of bounds", goto error); |
||
10162 | if (pos2 >= isl_map_dim(map, type2)) |
||
10163 | isl_die(map->ctx, isl_error_invalid, |
||
10164 | "index out of bounds", goto error); |
||
10165 | |||
10166 | bmap = isl_basic_map_alloc_space(isl_map_get_space(map), 0, 1, 0); |
||
10167 | i = isl_basic_map_alloc_equality(bmap); |
||
10168 | if (i < 0) |
||
10169 | goto error; |
||
10170 | isl_seq_clr(bmap->eq[i], 1 + isl_basic_map_total_dim(bmap)); |
||
10171 | pos1 += isl_basic_map_offset(bmap, type1); |
||
10172 | pos2 += isl_basic_map_offset(bmap, type2); |
||
10173 | isl_int_set_si(bmap->eq[i][pos1], 1); |
||
10174 | isl_int_set_si(bmap->eq[i][pos2], 1); |
||
10175 | bmap = isl_basic_map_finalize(bmap); |
||
10176 | |||
10177 | map = isl_map_intersect(map, isl_map_from_basic_map(bmap)); |
||
10178 | |||
10179 | return map; |
||
10180 | error: |
||
10181 | isl_basic_map_free(bmap); |
||
10182 | isl_map_free(map); |
||
10183 | return NULL; |
||
10184 | } |
||
10185 | |||
10186 | /* Add a constraint imposing that the value of the first dimension is |
||
10187 | * greater than that of the second. |
||
10188 | */ |
||
10189 | __isl_give isl_map *isl_map_order_gt(__isl_take isl_map *map, |
||
10190 | enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2) |
||
10191 | { |
||
10192 | isl_basic_map *bmap = NULL; |
||
10193 | int i; |
||
10194 | |||
10195 | if (!map) |
||
10196 | return NULL; |
||
10197 | |||
10198 | if (pos1 >= isl_map_dim(map, type1)) |
||
10199 | isl_die(map->ctx, isl_error_invalid, |
||
10200 | "index out of bounds", goto error); |
||
10201 | if (pos2 >= isl_map_dim(map, type2)) |
||
10202 | isl_die(map->ctx, isl_error_invalid, |
||
10203 | "index out of bounds", goto error); |
||
10204 | |||
10205 | if (type1 == type2 && pos1 == pos2) { |
||
10206 | isl_space *space = isl_map_get_space(map); |
||
10207 | isl_map_free(map); |
||
10208 | return isl_map_empty(space); |
||
10209 | } |
||
10210 | |||
10211 | bmap = isl_basic_map_alloc_space(isl_map_get_space(map), 0, 0, 1); |
||
10212 | i = isl_basic_map_alloc_inequality(bmap); |
||
10213 | if (i < 0) |
||
10214 | goto error; |
||
10215 | isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap)); |
||
10216 | pos1 += isl_basic_map_offset(bmap, type1); |
||
10217 | pos2 += isl_basic_map_offset(bmap, type2); |
||
10218 | isl_int_set_si(bmap->ineq[i][pos1], 1); |
||
10219 | isl_int_set_si(bmap->ineq[i][pos2], -1); |
||
10220 | isl_int_set_si(bmap->ineq[i][0], -1); |
||
10221 | bmap = isl_basic_map_finalize(bmap); |
||
10222 | |||
10223 | map = isl_map_intersect(map, isl_map_from_basic_map(bmap)); |
||
10224 | |||
10225 | return map; |
||
10226 | error: |
||
10227 | isl_basic_map_free(bmap); |
||
10228 | isl_map_free(map); |
||
10229 | return NULL; |
||
10230 | } |
||
10231 | |||
10232 | /* Add a constraint imposing that the value of the first dimension is |
||
10233 | * smaller than that of the second. |
||
10234 | */ |
||
10235 | __isl_give isl_map *isl_map_order_lt(__isl_take isl_map *map, |
||
10236 | enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2) |
||
10237 | { |
||
10238 | return isl_map_order_gt(map, type2, pos2, type1, pos1); |
||
10239 | } |
||
10240 | |||
10241 | __isl_give isl_aff *isl_basic_map_get_div(__isl_keep isl_basic_map *bmap, |
||
10242 | int pos) |
||
10243 | { |
||
10244 | isl_aff *div; |
||
10245 | isl_local_space *ls; |
||
10246 | |||
10247 | if (!bmap) |
||
10248 | return NULL; |
||
10249 | |||
10250 | if (!isl_basic_map_divs_known(bmap)) |
||
10251 | isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid, |
||
10252 | "some divs are unknown", return NULL); |
||
10253 | |||
10254 | ls = isl_basic_map_get_local_space(bmap); |
||
10255 | div = isl_local_space_get_div(ls, pos); |
||
10256 | isl_local_space_free(ls); |
||
10257 | |||
10258 | return div; |
||
10259 | } |
||
10260 | |||
10261 | __isl_give isl_aff *isl_basic_set_get_div(__isl_keep isl_basic_set *bset, |
||
10262 | int pos) |
||
10263 | { |
||
10264 | return isl_basic_map_get_div(bset, pos); |
||
10265 | } |
||
10266 | |||
10267 | /* Plug in "subs" for dimension "type", "pos" of "bset". |
||
10268 | * |
||
10269 | * Let i be the dimension to replace and let "subs" be of the form |
||
10270 | * |
||
10271 | * f/d |
||
10272 | * |
||
10273 | * Any integer division with a non-zero coefficient for i, |
||
10274 | * |
||
10275 | * floor((a i + g)/m) |
||
10276 | * |
||
10277 | * is replaced by |
||
10278 | * |
||
10279 | * floor((a f + d g)/(m d)) |
||
10280 | * |
||
10281 | * Constraints of the form |
||
10282 | * |
||
10283 | * a i + g |
||
10284 | * |
||
10285 | * are replaced by |
||
10286 | * |
||
10287 | * a f + d g |
||
10288 | */ |
||
10289 | __isl_give isl_basic_set *isl_basic_set_substitute( |
||
10290 | __isl_take isl_basic_set *bset, |
||
10291 | enum isl_dim_type type, unsigned pos, __isl_keep isl_aff *subs) |
||
10292 | { |
||
10293 | int i; |
||
10294 | isl_int v; |
||
10295 | isl_ctx *ctx; |
||
10296 | |||
10297 | if (bset && isl_basic_set_plain_is_empty(bset)) |
||
10298 | return bset; |
||
10299 | |||
10300 | bset = isl_basic_set_cow(bset); |
||
10301 | if (!bset || !subs) |
||
10302 | goto error; |
||
10303 | |||
10304 | ctx = isl_basic_set_get_ctx(bset); |
||
10305 | if (!isl_space_is_equal(bset->dim, subs->ls->dim)) |
||
10306 | isl_die(ctx, isl_error_invalid, |
||
10307 | "spaces don't match", goto error); |
||
10308 | if (isl_local_space_dim(subs->ls, isl_dim_div) != 0) |
||
10309 | isl_die(ctx, isl_error_unsupported, |
||
10310 | "cannot handle divs yet", goto error); |
||
10311 | |||
10312 | pos += isl_basic_set_offset(bset, type); |
||
10313 | |||
10314 | isl_int_init(v); |
||
10315 | |||
10316 | for (i = 0; i < bset->n_eq; ++i) { |
||
10317 | if (isl_int_is_zero(bset->eq[i][pos])) |
||
10318 | continue; |
||
10319 | isl_int_set(v, bset->eq[i][pos]); |
||
10320 | isl_int_set_si(bset->eq[i][pos], 0); |
||
10321 | isl_seq_combine(bset->eq[i], subs->v->el[0], bset->eq[i], |
||
10322 | v, subs->v->el + 1, subs->v->size - 1); |
||
10323 | } |
||
10324 | |||
10325 | for (i = 0; i < bset->n_ineq; ++i) { |
||
10326 | if (isl_int_is_zero(bset->ineq[i][pos])) |
||
10327 | continue; |
||
10328 | isl_int_set(v, bset->ineq[i][pos]); |
||
10329 | isl_int_set_si(bset->ineq[i][pos], 0); |
||
10330 | isl_seq_combine(bset->ineq[i], subs->v->el[0], bset->ineq[i], |
||
10331 | v, subs->v->el + 1, subs->v->size - 1); |
||
10332 | } |
||
10333 | |||
10334 | for (i = 0; i < bset->n_div; ++i) { |
||
10335 | if (isl_int_is_zero(bset->div[i][1 + pos])) |
||
10336 | continue; |
||
10337 | isl_int_set(v, bset->div[i][1 + pos]); |
||
10338 | isl_int_set_si(bset->div[i][1 + pos], 0); |
||
10339 | isl_seq_combine(bset->div[i] + 1, |
||
10340 | subs->v->el[0], bset->div[i] + 1, |
||
10341 | v, subs->v->el + 1, subs->v->size - 1); |
||
10342 | isl_int_mul(bset->div[i][0], bset->div[i][0], subs->v->el[0]); |
||
10343 | } |
||
10344 | |||
10345 | isl_int_clear(v); |
||
10346 | |||
10347 | bset = isl_basic_set_simplify(bset); |
||
10348 | return isl_basic_set_finalize(bset); |
||
10349 | error: |
||
10350 | isl_basic_set_free(bset); |
||
10351 | return NULL; |
||
10352 | } |
||
10353 | |||
10354 | /* Plug in "subs" for dimension "type", "pos" of "set". |
||
10355 | */ |
||
10356 | __isl_give isl_set *isl_set_substitute(__isl_take isl_set *set, |
||
10357 | enum isl_dim_type type, unsigned pos, __isl_keep isl_aff *subs) |
||
10358 | { |
||
10359 | int i; |
||
10360 | |||
10361 | if (set && isl_set_plain_is_empty(set)) |
||
10362 | return set; |
||
10363 | |||
10364 | set = isl_set_cow(set); |
||
10365 | if (!set || !subs) |
||
10366 | goto error; |
||
10367 | |||
10368 | for (i = set->n - 1; i >= 0; --i) { |
||
10369 | set->p[i] = isl_basic_set_substitute(set->p[i], type, pos, subs); |
||
10370 | if (remove_if_empty(set, i) < 0) |
||
10371 | goto error; |
||
10372 | } |
||
10373 | |||
10374 | return set; |
||
10375 | error: |
||
10376 | isl_set_free(set); |
||
10377 | return NULL; |
||
10378 | } |