* 91893 Orsay, France
*/
+#include <isl_map_private.h>
#include <isl/map.h>
-#include "isl_map_private.h"
#include <isl/seq.h>
#include <isl_dim_private.h>
#include <isl/lp.h>
* variables are non-zero and if moreover the parametric constant
* can never attain positive values.
* Return IMPURE otherwise.
+ *
+ * If div_purity is NULL then we are dealing with a non-parametric set
+ * and so the constraint is obviously PURE_VAR.
*/
static int purity(__isl_keep isl_basic_set *bset, isl_int *c, int *div_purity,
int eq)
int i;
int p = 0, v = 0;
+ if (!div_purity)
+ return PURE_VAR;
+
n_div = isl_basic_set_dim(bset, isl_dim_div);
d = isl_basic_set_dim(bset, isl_dim_set);
nparam = isl_basic_set_dim(bset, isl_dim_param);
goto error;
isl_seq_clr(test->eq[k], 1 + isl_basic_map_total_dim(test));
isl_int_set_si(test->eq[k][pos], 1);
- id = isl_basic_map_identity(isl_dim_domain(isl_basic_map_get_dim(path)));
+ id = isl_basic_map_identity(isl_basic_map_get_dim(path));
is_id = isl_basic_map_is_equal(test, id);
isl_basic_map_free(test);
isl_basic_map_free(id);
return -1;
}
+/* If any of the constraints is found to be impure then this function
+ * sets *impurity to 1.
+ */
static __isl_give isl_basic_map *add_delta_constraints(
__isl_take isl_basic_map *path,
__isl_keep isl_basic_set *delta, unsigned off, unsigned nparam,
- unsigned d, int *div_purity, int eq)
+ unsigned d, int *div_purity, int eq, int *impurity)
{
int i, k;
int n = eq ? delta->n_eq : delta->n_ineq;
int p = purity(delta, delta_c[i], div_purity, eq);
if (p < 0)
goto error;
+ if (p != PURE_VAR && p != PURE_PARAM && !*impurity)
+ *impurity = 1;
if (p == IMPURE)
continue;
if (eq && p != MIXED) {
*
* In particular, let delta be defined as
*
- * \delta = [p] -> { [x] : A x + a >= and B p + b >= 0 and
+ * \delta = [p] -> { [x] : A x + a >= 0 and B p + b >= 0 and
* C x + C'p + c >= 0 and
* D x + D'p + d >= 0 }
*
* parameter dependent and others. Constraints containing
* any of the other existentially quantified variables are removed.
* This is safe, but leads to an additional overapproximation.
+ *
+ * If there are any impure constraints, then we also eliminate
+ * the parameters from \delta, resulting in a set
+ *
+ * \delta' = { [x] : E x + e >= 0 }
+ *
+ * and add the constraints
+ *
+ * E f + k e >= 0
+ *
+ * to the constructed relation.
*/
static __isl_give isl_map *path_along_delta(__isl_take isl_dim *dim,
__isl_take isl_basic_set *delta)
int i, k;
int is_id;
int *div_purity = NULL;
+ int impurity = 0;
if (!delta)
goto error;
if (!div_purity)
goto error;
- path = add_delta_constraints(path, delta, off, nparam, d, div_purity, 1);
- path = add_delta_constraints(path, delta, off, nparam, d, div_purity, 0);
+ path = add_delta_constraints(path, delta, off, nparam, d,
+ div_purity, 1, &impurity);
+ path = add_delta_constraints(path, delta, off, nparam, d,
+ div_purity, 0, &impurity);
+ if (impurity) {
+ isl_dim *dim = isl_basic_set_get_dim(delta);
+ delta = isl_basic_set_project_out(delta,
+ isl_dim_param, 0, nparam);
+ delta = isl_basic_set_add(delta, isl_dim_param, nparam);
+ delta = isl_basic_set_reset_dim(delta, dim);
+ if (!delta)
+ goto error;
+ path = isl_basic_map_extend_constraints(path, delta->n_eq,
+ delta->n_ineq + 1);
+ path = add_delta_constraints(path, delta, off, nparam, d,
+ NULL, 1, &impurity);
+ path = add_delta_constraints(path, delta, off, nparam, d,
+ NULL, 0, &impurity);
+ path = isl_basic_map_gauss(path, NULL);
+ }
is_id = empty_path_is_identity(path, off + d);
if (is_id < 0)
isl_dim_free(dim);
return isl_map_from_basic_map(path);
}
- return isl_basic_map_union(path,
- isl_basic_map_identity(isl_dim_domain(dim)));
+ return isl_basic_map_union(path, isl_basic_map_identity(dim));
error:
free(div_purity);
isl_dim_free(dim);
d = isl_map_dim(map, isl_dim_in);
- path = isl_map_identity(isl_dim_domain(isl_dim_copy(dim)));
+ path = isl_map_identity(isl_dim_copy(dim));
steps = isl_mat_alloc(map->ctx, map->n, d);
if (!steps)
if (!left || !right)
rtc = isl_map_union(isl_map_copy(tc),
- isl_map_identity(isl_dim_domain(isl_map_get_dim(tc))));
+ isl_map_identity(isl_map_get_dim(tc)));
if (!right)
qc = isl_map_apply_range(rtc, qc);
if (!left)
}
/* Compute the positive powers of "map", or an overapproximation.
- * The power is given by parameter "param". If the result is exact,
- * then *exact is set to 1.
+ * The result maps the exponent to a nested copy of the corresponding power.
+ * If the result is exact, then *exact is set to 1.
* map_power constructs an extended relation with the path lengths
* encoded as the difference between the final coordinates.
- * In the final step, this difference is equated to the parameter "param"
- * and made positive. The extra coordinates are subsequently projected out.
+ * In the final step, this difference is equated to an extra parameter
+ * and made positive. The extra coordinates are subsequently projected out
+ * and the parameter is turned into the domain of the result.
*/
-__isl_give isl_map *isl_map_power(__isl_take isl_map *map, unsigned param,
- int *exact)
+__isl_give isl_map *isl_map_power(__isl_take isl_map *map, int *exact)
{
isl_dim *target_dim;
isl_dim *dim;
isl_map *diff;
unsigned d;
+ unsigned param;
if (!map)
return NULL;
- isl_assert(map->ctx, param < isl_map_dim(map, isl_dim_param),
- goto error);
-
d = isl_map_dim(map, isl_dim_in);
+ param = isl_map_dim(map, isl_dim_param);
map = isl_map_compute_divs(map);
map = isl_map_coalesce(map);
- if (isl_map_fast_is_empty(map))
+ if (isl_map_fast_is_empty(map)) {
+ map = isl_map_from_range(isl_map_wrap(map));
+ map = isl_map_add_dims(map, isl_dim_in, 1);
+ map = isl_map_set_dim_name(map, isl_dim_in, 0, "k");
return map;
+ }
target_dim = isl_map_get_dim(map);
+ target_dim = isl_dim_from_range(isl_dim_wrap(target_dim));
+ target_dim = isl_dim_add(target_dim, isl_dim_in, 1);
+ target_dim = isl_dim_set_name(target_dim, isl_dim_in, 0, "k");
+
map = map_power(map, exact, 0);
+ map = isl_map_add_dims(map, isl_dim_param, 1);
dim = isl_map_get_dim(map);
diff = equate_parameter_to_length(dim, param);
map = isl_map_intersect(map, diff);
map = isl_map_project_out(map, isl_dim_in, d, 1);
map = isl_map_project_out(map, isl_dim_out, d, 1);
+ map = isl_map_from_range(isl_map_wrap(map));
+ map = isl_map_move_dims(map, isl_dim_in, 0, isl_dim_param, param, 1);
map = isl_map_reset_dim(map, target_dim);
return map;
-error:
- isl_map_free(map);
- return NULL;
}
/* Compute a relation that maps each element in the range of the input
if (!map)
goto error;
- if (map->ctx->opt->closure == ISL_CLOSURE_OMEGA)
+ if (map->ctx->opt->closure == ISL_CLOSURE_BOX)
return transitive_closure_omega(map, exact);
map = isl_map_compute_divs(map);