2 * Copyright 2010 INRIA Saclay
4 * Use of this software is governed by the GNU LGPLv2.1 license
6 * Written by Sven Verdoolaege, INRIA Saclay - Ile-de-France,
7 * Parc Club Orsay Universite, ZAC des vignes, 4 rue Jacques Monod,
12 #include "isl_map_private.h"
15 * The transitive closure implementation is based on the paper
16 * "Computing the Transitive Closure of a Union of Affine Integer
17 * Tuple Relations" by Anna Beletska, Denis Barthou, Wlodzimierz Bielecki and
21 /* Given a union of translations (uniform dependences), return a matrix
22 * with as many rows as there are disjuncts in the union and as many
23 * columns as there are input dimensions (which should be equal to
24 * the number of output dimensions).
25 * Each row contains the translation performed by the corresponding disjunct.
26 * If "map" turns out not to be a union of translations, then the contents
27 * of the returned matrix are undefined and *ok is set to 0.
29 static __isl_give isl_mat
*extract_steps(__isl_keep isl_map
*map
, int *ok
)
32 struct isl_mat
*steps
;
33 unsigned dim
= isl_map_dim(map
, isl_dim_in
);
37 steps
= isl_mat_alloc(map
->ctx
, map
->n
, dim
);
41 for (i
= 0; i
< map
->n
; ++i
) {
42 struct isl_basic_set
*delta
;
44 delta
= isl_basic_map_deltas(isl_basic_map_copy(map
->p
[i
]));
46 for (j
= 0; j
< dim
; ++j
) {
49 fixed
= isl_basic_set_fast_dim_is_fixed(delta
, j
,
52 isl_basic_set_free(delta
);
59 isl_basic_set_free(delta
);
74 /* Given a set of n offsets v_i (the rows of "steps"), construct a relation
75 * of the given dimension specification that maps a element x to any
76 * element that can be reached by taking a positive number of steps
77 * along any of the offsets, where the number of steps k is equal to
78 * parameter "param". That is, construct
80 * { [x] -> [y] : exists k_i >= 0, y = x + \sum_i k_i v_i, k = \sum_i k_i > 0 }
82 * If strict is non-negative, then at least one step should be taken
83 * along the given offset v_strict, i.e., k_strict > 0.
85 static __isl_give isl_map
*path_along_steps(__isl_take isl_dim
*dim
,
86 __isl_keep isl_mat
*steps
, unsigned param
, int strict
)
89 struct isl_basic_map
*path
= NULL
;
97 d
= isl_dim_size(dim
, isl_dim_in
);
99 nparam
= isl_dim_size(dim
, isl_dim_param
);
101 path
= isl_basic_map_alloc_dim(isl_dim_copy(dim
), n
, d
+ 1, n
+ 1);
103 for (i
= 0; i
< n
; ++i
) {
104 k
= isl_basic_map_alloc_div(path
);
107 isl_assert(steps
->ctx
, i
== k
, goto error
);
108 isl_int_set_si(path
->div
[k
][0], 0);
111 for (i
= 0; i
< d
; ++i
) {
112 k
= isl_basic_map_alloc_equality(path
);
115 isl_seq_clr(path
->eq
[k
], 1 + isl_basic_map_total_dim(path
));
116 isl_int_set_si(path
->eq
[k
][1 + nparam
+ i
], 1);
117 isl_int_set_si(path
->eq
[k
][1 + nparam
+ d
+ i
], -1);
118 for (j
= 0; j
< n
; ++j
)
119 isl_int_set(path
->eq
[k
][1 + nparam
+ 2 * d
+ j
],
123 k
= isl_basic_map_alloc_equality(path
);
126 isl_seq_clr(path
->eq
[k
], 1 + isl_basic_map_total_dim(path
));
127 isl_int_set_si(path
->eq
[k
][1 + param
], -1);
128 for (j
= 0; j
< n
; ++j
)
129 isl_int_set_si(path
->eq
[k
][1 + nparam
+ 2 * d
+ j
], 1);
131 for (i
= 0; i
< n
; ++i
) {
132 k
= isl_basic_map_alloc_inequality(path
);
135 isl_seq_clr(path
->ineq
[k
], 1 + isl_basic_map_total_dim(path
));
136 isl_int_set_si(path
->ineq
[k
][1 + nparam
+ 2 * d
+ i
], 1);
138 isl_int_set_si(path
->ineq
[k
][0], -1);
141 k
= isl_basic_map_alloc_inequality(path
);
144 isl_seq_clr(path
->ineq
[k
], 1 + isl_basic_map_total_dim(path
));
145 isl_int_set_si(path
->ineq
[k
][1 + param
], 1);
146 isl_int_set_si(path
->ineq
[k
][0], -1);
150 path
= isl_basic_map_simplify(path
);
151 path
= isl_basic_map_finalize(path
);
152 return isl_map_from_basic_map(path
);
155 isl_basic_map_free(path
);
159 /* Check whether the overapproximation of the power of "map" is exactly
160 * the power of "map". In particular, for each path of a given length
161 * that starts of in domain or range and ends up in the range,
162 * check whether there is at least one path of the same length
163 * with a valid first segment, i.e., one in "map".
164 * If "project" is set, then we drop the condition that the lengths
165 * should be the same.
167 * "domain" and "range" are the domain and range of "map"
168 * "steps" represents the translations of "map"
169 * "path" is a path along "steps"
171 * "domain", "range", "steps" and "path" have been precomputed by the calling
174 static int check_path_exactness(__isl_take isl_map
*map
,
175 __isl_take isl_set
*domain
, __isl_take isl_set
*range
,
176 __isl_take isl_map
*path
, __isl_keep isl_mat
*steps
, unsigned param
,
186 test
= isl_map_empty(isl_map_get_dim(map
));
187 for (i
= 0; i
< map
->n
; ++i
) {
188 struct isl_map
*path_i
;
189 struct isl_set
*dom_i
;
190 path_i
= path_along_steps(isl_map_get_dim(map
), steps
, param
, i
);
191 dom_i
= isl_set_from_basic_set(
192 isl_basic_map_domain(isl_basic_map_copy(map
->p
[i
])));
193 path_i
= isl_map_intersect_domain(path_i
, dom_i
);
194 test
= isl_map_union(test
, path_i
);
197 test
= isl_map_intersect_range(test
, isl_set_copy(range
));
199 domain
= isl_set_union(domain
, isl_set_copy(range
));
200 path
= isl_map_intersect_domain(path
, domain
);
201 path
= isl_map_intersect_range(path
, range
);
204 path
= isl_map_project_out(path
, isl_dim_param
, param
, 1);
205 test
= isl_map_project_out(test
, isl_dim_param
, param
, 1);
208 ok
= isl_map_is_subset(path
, test
);
216 isl_set_free(domain
);
222 /* Check whether any path of length at least one along "steps" is acyclic.
223 * That is, check whether
225 * \sum_i k_i = \delta_i
229 * with \delta_i the rows of "steps", is infeasible.
231 static int is_acyclic(__isl_keep isl_mat
*steps
)
235 struct isl_basic_set
*test
;
240 test
= isl_basic_set_alloc(steps
->ctx
, 0, steps
->n_row
, 0,
241 steps
->n_col
, steps
->n_row
+ 1);
243 for (i
= 0; i
< steps
->n_col
; ++i
) {
244 k
= isl_basic_set_alloc_equality(test
);
247 isl_int_set_si(test
->eq
[k
][0], 0);
248 for (j
= 0; j
< steps
->n_row
; ++j
)
249 isl_int_set(test
->eq
[k
][1 + j
], steps
->row
[j
][i
]);
251 for (j
= 0; j
< steps
->n_row
; ++j
) {
252 k
= isl_basic_set_alloc_inequality(test
);
255 isl_seq_clr(test
->ineq
[k
], 1 + steps
->n_row
);
256 isl_int_set_si(test
->ineq
[k
][1 + j
], 1);
259 k
= isl_basic_set_alloc_inequality(test
);
262 isl_int_set_si(test
->ineq
[k
][0], -1);
263 for (j
= 0; j
< steps
->n_row
; ++j
)
264 isl_int_set_si(test
->ineq
[k
][1 + j
], 1);
266 acyclic
= isl_basic_set_is_empty(test
);
268 isl_basic_set_free(test
);
271 isl_basic_set_free(test
);
275 /* Check whether the overapproximation of the power of "map" is exactly
276 * the power of "map", possibly after projecting out the power (if "project"
279 * If "project" is not set, then we simply check for each power if there
280 * is a path of the given length with valid initial segment.
281 * If "project" is set, then we check if "steps" can only result in acyclic
282 * paths. If so, we only need to check that there is a path of _some_
283 * length >= 1. Otherwise, we perform the standard check, i.e., whether
284 * there is a path of the given length.
286 static int check_exactness(__isl_take isl_map
*map
, __isl_take isl_set
*domain
,
287 __isl_take isl_set
*range
, __isl_take isl_map
*path
,
288 __isl_keep isl_mat
*steps
, unsigned param
, int project
)
293 return check_path_exactness(map
, domain
, range
, path
, steps
,
296 acyclic
= is_acyclic(steps
);
300 return check_path_exactness(map
, domain
, range
, path
, steps
,
304 isl_set_free(domain
);
310 /* Compute the positive powers of "map", or an overapproximation.
311 * The power is given by parameter "param". If the result is exact,
312 * then *exact is set to 1.
313 * If project is set, then we are actually interested in the transitive
314 * closure, so we can use a more relaxed exactness check.
316 static __isl_give isl_map
*map_power(__isl_take isl_map
*map
, unsigned param
,
317 int *exact
, int project
)
319 struct isl_mat
*steps
= NULL
;
320 struct isl_set
*domain
= NULL
;
321 struct isl_set
*range
= NULL
;
322 struct isl_map
*app
= NULL
;
323 struct isl_map
*path
= NULL
;
329 map
= isl_map_remove_empty_parts(map
);
333 if (isl_map_fast_is_empty(map
))
336 isl_assert(map
->ctx
, param
< isl_map_dim(map
, isl_dim_param
), goto error
);
338 isl_map_dim(map
, isl_dim_in
) == isl_map_dim(map
, isl_dim_out
),
341 domain
= isl_map_domain(isl_map_copy(map
));
342 range
= isl_map_range(isl_map_copy(map
));
343 app
= isl_map_from_domain_and_range(isl_set_copy(domain
),
344 isl_set_copy(range
));
346 steps
= extract_steps(map
, &ok
);
350 path
= path_along_steps(isl_map_get_dim(map
), steps
, param
, -1);
351 app
= isl_map_intersect(app
, isl_map_copy(path
));
354 (*exact
= check_exactness(isl_map_copy(map
), isl_set_copy(domain
),
355 isl_set_copy(range
), isl_map_copy(path
),
356 steps
, param
, project
)) < 0)
364 isl_set_free(domain
);
371 isl_set_free(domain
);
380 /* Compute the positive powers of "map", or an overapproximation.
381 * The power is given by parameter "param". If the result is exact,
382 * then *exact is set to 1.
384 __isl_give isl_map
*isl_map_power(__isl_take isl_map
*map
, unsigned param
,
387 return map_power(map
, param
, exact
, 0);
390 /* Compute the transitive closure of "map", or an overapproximation.
391 * If the result is exact, then *exact is set to 1.
392 * Simply compute the powers of map and then project out the parameter
393 * describing the power.
395 __isl_give isl_map
*isl_map_transitive_closure(__isl_take isl_map
*map
,
403 param
= isl_map_dim(map
, isl_dim_param
);
404 map
= isl_map_add(map
, isl_dim_param
, 1);
405 map
= map_power(map
, param
, exact
, 1);
406 map
= isl_map_project_out(map
, isl_dim_param
, param
, 1);