Example #1
0
int isl_set_count_upto(__isl_keep isl_set *set, isl_int max, isl_int *count)
{
	struct isl_counter cnt = { { &increment_counter } };

	if (!set)
		return -1;

	isl_int_init(cnt.count);
	isl_int_init(cnt.max);

	isl_int_set_si(cnt.count, 0);
	isl_int_set(cnt.max, max);
	if (isl_set_scan(isl_set_copy(set), &cnt.callback) < 0 &&
	    isl_int_lt(cnt.count, cnt.max))
		goto error;

	isl_int_set(*count, cnt.count);
	isl_int_clear(cnt.max);
	isl_int_clear(cnt.count);

	return 0;
error:
	isl_int_clear(cnt.count);
	return -1;
}
Example #2
0
/* Make first row entries in column col of bset1 identical to
 * those of bset2, using the fact that entry bset1->eq[row][col]=a
 * is non-zero.  Initially, these elements of bset1 are all zero.
 * For each row i < row, we set
 *		A[i] = a * A[i] + B[i][col] * A[row]
 *		B[i] = a * B[i]
 * so that
 *		A[i][col] = B[i][col] = a * old(B[i][col])
 */
static void construct_column(
	struct isl_basic_set *bset1, struct isl_basic_set *bset2,
	unsigned row, unsigned col)
{
	int r;
	isl_int a;
	isl_int b;
	unsigned total;

	isl_int_init(a);
	isl_int_init(b);
	total = 1 + isl_basic_set_n_dim(bset1);
	for (r = 0; r < row; ++r) {
		if (isl_int_is_zero(bset2->eq[r][col]))
			continue;
		isl_int_gcd(b, bset2->eq[r][col], bset1->eq[row][col]);
		isl_int_divexact(a, bset1->eq[row][col], b);
		isl_int_divexact(b, bset2->eq[r][col], b);
		isl_seq_combine(bset1->eq[r], a, bset1->eq[r],
					      b, bset1->eq[row], total);
		isl_seq_scale(bset2->eq[r], bset2->eq[r], a, total);
	}
	isl_int_clear(a);
	isl_int_clear(b);
	delete_row(bset1, row);
}
Example #3
0
/* Check if dimension dim belongs to a residue class
 *		i_dim \equiv r mod m
 * with m != 1 and if so return m in *modulo and r in *residue.
 * As a special case, when i_dim has a fixed value v, then
 * *modulo is set to 0 and *residue to v.
 *
 * If i_dim does not belong to such a residue class, then *modulo
 * is set to 1 and *residue is set to 0.
 */
int isl_set_dim_residue_class(struct isl_set *set,
	int pos, isl_int *modulo, isl_int *residue)
{
	isl_int m;
	isl_int r;
	int i;

	if (!set || !modulo || !residue)
		return -1;

	if (set->n == 0) {
		isl_int_set_si(*modulo, 0);
		isl_int_set_si(*residue, 0);
		return 0;
	}

	if (isl_basic_set_dim_residue_class(set->p[0], pos, modulo, residue)<0)
		return -1;

	if (set->n == 1)
		return 0;

	if (isl_int_is_one(*modulo))
		return 0;

	isl_int_init(m);
	isl_int_init(r);

	for (i = 1; i < set->n; ++i) {
		if (isl_basic_set_dim_residue_class(set->p[i], pos, &m, &r) < 0)
			goto error;
		isl_int_gcd(*modulo, *modulo, m);
		isl_int_sub(m, *residue, r);
		isl_int_gcd(*modulo, *modulo, m);
		if (!isl_int_is_zero(*modulo))
			isl_int_fdiv_r(*residue, *residue, *modulo);
		if (isl_int_is_one(*modulo))
			break;
	}

	isl_int_clear(m);
	isl_int_clear(r);

	return 0;
error:
	isl_int_clear(m);
	isl_int_clear(r);
	return -1;
}
Example #4
0
/* Given a stride constraint on iterator i (specified by level) of the form
 *
 *	i = f(outer iterators) + stride * f(existentials)
 *
 * extract f as an isl_aff.
 */
static isl_aff *extract_stride_offset(__isl_keep isl_constraint *c,
	int level, CloogStride *stride)
{
	int i;
	isl_space *dim = isl_constraint_get_space(c);
	isl_local_space *ls = isl_local_space_from_space(dim);
	isl_aff *offset = isl_aff_zero_on_domain(ls);
	isl_int u;
	unsigned nparam, nvar;

	isl_int_init(u);

	nparam = isl_constraint_dim(c, isl_dim_param);
	nvar = isl_constraint_dim(c, isl_dim_set);

	for (i = 0; i < nparam; ++i) {
		isl_constraint_get_coefficient(c, isl_dim_param, i, &u);
		isl_int_mul(u, u, stride->factor);
		offset = isl_aff_set_coefficient(offset, isl_dim_param, i, u);
	}
	for (i = 0; i < nvar; ++i) {
		if (i == level - 1)
			continue;
		isl_constraint_get_coefficient(c, isl_dim_set, i, &u);
		isl_int_mul(u, u, stride->factor);
		offset = isl_aff_set_coefficient(offset, isl_dim_in, i, u);
	}
	isl_constraint_get_constant(c, &u);
	isl_int_mul(u, u, stride->factor);
	offset = isl_aff_set_constant(offset, u);

	isl_int_clear(u);

	return offset;
}
Example #5
0
/**
 * cloog_constraint_equal_type function :
 * This function returns the type of the equality in the constraint (line) of
 * (constraints) for the element (level). An equality is 'constant' iff all
 * other factors are null except the constant one. It is a 'pure item' iff
 * it is equal or opposite to a single variable or parameter.
 * Otherwise it is an 'affine expression'.
 * For instance:
 *   i = -13 is constant, i = j, j = -M are pure items,
 *   j = 2*M, i = j+1, 2*j = M are affine expressions.
 *
 * - constraints is the matrix of constraints,
 * - level is the column number in equal of the element which is 'equal to',
 */
static int cloog_constraint_equal_type(CloogConstraint *cc, int level)
{ 
	int i;
	isl_int c;
	int type = EQTYPE_NONE;
	struct isl_constraint *constraint = cloog_constraint_to_isl(cc);
    
	isl_int_init(c);
	isl_constraint_get_constant(constraint, &c);
	if (!isl_int_is_zero(c))
		type = EQTYPE_CONSTANT;
	isl_constraint_get_coefficient(constraint, isl_dim_set, level - 1, &c);
	if (!isl_int_is_one(c) && !isl_int_is_negone(c))
		type = EQTYPE_EXAFFINE;
	for (i = 0; i < isl_constraint_dim(constraint, isl_dim_param); ++i) {
		isl_constraint_get_coefficient(constraint, isl_dim_param, i, &c);
		if (isl_int_is_zero(c))
			continue;
		if ((!isl_int_is_one(c) && !isl_int_is_negone(c)) ||
		    type != EQTYPE_NONE) {
			type = EQTYPE_EXAFFINE;
			break;
		}
		type = EQTYPE_PUREITEM;
	}
	for (i = 0; i < isl_constraint_dim(constraint, isl_dim_set); ++i) {
		if (i == level - 1)
			continue;
		isl_constraint_get_coefficient(constraint, isl_dim_set, i, &c);
		if (isl_int_is_zero(c))
			continue;
		if ((!isl_int_is_one(c) && !isl_int_is_negone(c)) ||
		    type != EQTYPE_NONE) {
			type = EQTYPE_EXAFFINE;
			break;
		}
		type = EQTYPE_PUREITEM;
	}
	for (i = 0; i < isl_constraint_dim(constraint, isl_dim_div); ++i) {
		isl_constraint_get_coefficient(constraint, isl_dim_div, i, &c);
		if (isl_int_is_zero(c))
			continue;
		if ((!isl_int_is_one(c) && !isl_int_is_negone(c)) ||
		    type != EQTYPE_NONE) {
			type = EQTYPE_EXAFFINE;
			break;
		}
		type = EQTYPE_PUREITEM;
	}
	isl_int_clear(c);

	if (type == EQTYPE_NONE)
		type = EQTYPE_CONSTANT;

	return type;
}
Example #6
0
/* Make eq[row][col] of both bmaps equal so we can add the row
 * add the column to the common matrix.
 * Note that because of the echelon form, the columns of row row
 * after column col are zero.
 */
static void set_common_multiple(
	struct isl_basic_set *bset1, struct isl_basic_set *bset2,
	unsigned row, unsigned col)
{
	isl_int m, c;

	if (isl_int_eq(bset1->eq[row][col], bset2->eq[row][col]))
		return;

	isl_int_init(c);
	isl_int_init(m);
	isl_int_lcm(m, bset1->eq[row][col], bset2->eq[row][col]);
	isl_int_divexact(c, m, bset1->eq[row][col]);
	isl_seq_scale(bset1->eq[row], bset1->eq[row], c, col+1);
	isl_int_divexact(c, m, bset2->eq[row][col]);
	isl_seq_scale(bset2->eq[row], bset2->eq[row], c, col+1);
	isl_int_clear(c);
	isl_int_clear(m);
}
Example #7
0
void isl_imath_submul_ui(mp_int rop, mp_int op1, unsigned long op2)
{
	isl_int temp;
	isl_int_init(temp);

	isl_int_set_ui(temp, op2);
	isl_int_submul(rop, op1, temp);

	isl_int_clear(temp);
}
Example #8
0
int cloog_constraint_is_upper_bound(CloogConstraint *constraint, int v)
{
	isl_int c;
	int res;

	isl_int_init(c);
	cloog_constraint_coefficient_get(constraint, v, &c);
	res = isl_int_is_neg(c);
	isl_int_clear(c);
	return res;
}
Example #9
0
/**
 * Return true if constraint c involves variable v (zero-based).
 */
int cloog_constraint_involves(CloogConstraint *constraint, int v)
{
	isl_int c;
	int res;

	isl_int_init(c);
	cloog_constraint_coefficient_get(constraint, v, &c);
	res = !isl_int_is_zero(c);
	isl_int_clear(c);
	return res;
}
Example #10
0
/* Compute a common lattice of solutions to the linear modulo
 * constraints specified by B and d.
 * See also the documentation of isl_mat_parameter_compression.
 * We put the matrix
 * 
 *		A = [ L_1^{-T} L_2^{-T} ... L_k^{-T} ]
 *
 * on a common denominator.  This denominator D is the lcm of modulos d.
 * Since L_i = U_i^{-1} diag(d_i, 1, ... 1), we have
 * L_i^{-T} = U_i^T diag(d_i, 1, ... 1)^{-T} = U_i^T diag(1/d_i, 1, ..., 1).
 * Putting this on the common denominator, we have
 * D * L_i^{-T} = U_i^T diag(D/d_i, D, ..., D).
 */
static struct isl_mat *parameter_compression_multi(
			struct isl_mat *B, struct isl_vec *d)
{
	int i, j, k;
	isl_int D;
	struct isl_mat *A = NULL, *U = NULL;
	struct isl_mat *T;
	unsigned size;

	isl_int_init(D);

	isl_vec_lcm(d, &D);

	size = B->n_col - 1;
	A = isl_mat_alloc(B->ctx, size, B->n_row * size);
	U = isl_mat_alloc(B->ctx, size, size);
	if (!U || !A)
		goto error;
	for (i = 0; i < B->n_row; ++i) {
		isl_seq_cpy(U->row[0], B->row[i] + 1, size);
		U = isl_mat_unimodular_complete(U, 1);
		if (!U)
			goto error;
		isl_int_divexact(D, D, d->block.data[i]);
		for (k = 0; k < U->n_col; ++k)
			isl_int_mul(A->row[k][i*size+0], D, U->row[0][k]);
		isl_int_mul(D, D, d->block.data[i]);
		for (j = 1; j < U->n_row; ++j)
			for (k = 0; k < U->n_col; ++k)
				isl_int_mul(A->row[k][i*size+j],
						D, U->row[j][k]);
	}
	A = isl_mat_left_hermite(A, 0, NULL, NULL);
	T = isl_mat_sub_alloc(A, 0, A->n_row, 0, A->n_row);
	T = isl_mat_lin_to_aff(T);
	if (!T)
		goto error;
	isl_int_set(T->row[0][0], D);
	T = isl_mat_right_inverse(T);
	if (!T)
		goto error;
	isl_assert(T->ctx, isl_int_is_one(T->row[0][0]), goto error);
	T = isl_mat_transpose(T);
	isl_mat_free(A);
	isl_mat_free(U);

	isl_int_clear(D);
	return T;
error:
	isl_mat_free(A);
	isl_mat_free(U);
	isl_int_clear(D);
	return NULL;
}
Example #11
0
static isl_constraint *
build_linearized_memory_access (isl_map *map, poly_dr_p pdr)
{
  isl_constraint *res;
  isl_local_space *ls = isl_local_space_from_space (isl_map_get_space (map));
  unsigned offset, nsubs;
  int i;
  isl_int size, subsize;

  res = isl_equality_alloc (ls);
  isl_int_init (size);
  isl_int_set_ui (size, 1);
  isl_int_init (subsize);
  isl_int_set_ui (subsize, 1);

  nsubs = isl_set_dim (pdr->extent, isl_dim_set);
  /* -1 for the already included L dimension.  */
  offset = isl_map_dim (map, isl_dim_out) - 1 - nsubs;
  res = isl_constraint_set_coefficient_si (res, isl_dim_out, offset + nsubs, -1);
  /* Go through all subscripts from last to first.  First dimension
     is the alias set, ignore it.  */
  for (i = nsubs - 1; i >= 1; i--)
    {
      isl_space *dc;
      isl_aff *aff;

      res = isl_constraint_set_coefficient (res, isl_dim_out, offset + i, size);

      dc = isl_set_get_space (pdr->extent);
      aff = isl_aff_zero_on_domain (isl_local_space_from_space (dc));
      aff = isl_aff_set_coefficient_si (aff, isl_dim_in, i, 1);
      isl_set_max (pdr->extent, aff, &subsize);
      isl_aff_free (aff);
      isl_int_mul (size, size, subsize);
    }

  isl_int_clear (subsize);
  isl_int_clear (size);

  return res;
}
Example #12
0
/// Add an isl constraint to an ScopLib matrix.
///
/// @param user The matrix
/// @param c The constraint
int ScopLib::accessToMatrix_constraint(isl_constraint *c, void *user) {
  scoplib_matrix_p m = (scoplib_matrix_p) user;

  int nb_params = isl_constraint_dim(c, isl_dim_param);
  int nb_in = isl_constraint_dim(c, isl_dim_in);
  int nb_div = isl_constraint_dim(c, isl_dim_div);

  assert(!nb_div && "Existentially quantified variables not yet supported");

  scoplib_vector_p vec =
    scoplib_vector_malloc(nb_params + nb_in + 2);

  isl_int v;
  isl_int_init(v);

  // The access dimension has to be one.
  isl_constraint_get_coefficient(c, isl_dim_out, 0, &v);
  assert((isl_int_is_one(v) || isl_int_is_negone(v))
         && "Access relations not supported in scoplib");
  bool inverse = isl_int_is_one(v);

  // Assign variables
  for (int i = 0; i < nb_in; ++i) {
    isl_constraint_get_coefficient(c, isl_dim_in, i, &v);

    if (inverse) isl_int_neg(v,v);

    isl_int_set(vec->p[i + 1], v);
  }

  // Assign parameters
  for (int i = 0; i < nb_params; ++i) {
    isl_constraint_get_coefficient(c, isl_dim_param, i, &v);

    if (inverse) isl_int_neg(v,v);

    isl_int_set(vec->p[nb_in + i + 1], v);
  }

  // Assign constant
  isl_constraint_get_constant(c, &v);

  if (inverse) isl_int_neg(v,v);

  isl_int_set(vec->p[nb_in + nb_params + 1], v);

  scoplib_matrix_insert_vector(m, vec, m->NbRows);

  isl_constraint_free(c);
  isl_int_clear(v);

  return 0;
}
Example #13
0
static int add_constant_term(CloogConstraint *c, void *user)
{
	isl_int *bound = (isl_int *)user;
	isl_int v;

	isl_int_init(v);

	cloog_constraint_constant_get(c, &v);
	isl_int_add(*bound, *bound, v);

	isl_int_clear(v);

	return 0;
}
int main(int argc, char **argv)
{
	struct isl_ctx *ctx = isl_ctx_alloc();
	struct isl_basic_set *bset;
	struct isl_vec *obj;
	struct isl_vec *sol;
	isl_int opt;
	unsigned dim;
	enum isl_lp_result res;
	isl_printer *p;

	isl_int_init(opt);
	bset = isl_basic_set_read_from_file(ctx, stdin);
	assert(bset);
	obj = isl_vec_read_from_file(ctx, stdin);
	assert(obj);
	dim = isl_basic_set_total_dim(bset);
	assert(obj->size >= dim && obj->size <= dim + 1);
	if (obj->size != dim + 1)
		obj = isl_vec_lin_to_aff(obj);
	else
		obj = vec_ror(obj);
	res = isl_basic_set_solve_ilp(bset, 0, obj->el, &opt, &sol);
	switch (res) {
	case isl_lp_error:
		fprintf(stderr, "error\n");
		return -1;
	case isl_lp_empty:
		fprintf(stdout, "empty\n");
		break;
	case isl_lp_unbounded:
		fprintf(stdout, "unbounded\n");
		break;
	case isl_lp_ok:
		p = isl_printer_to_file(ctx, stdout);
		p = isl_printer_print_vec(p, sol);
		p = isl_printer_end_line(p);
		p = isl_printer_print_isl_int(p, opt);
		p = isl_printer_end_line(p);
		isl_printer_free(p);
	}
	isl_basic_set_free(bset);
	isl_vec_free(obj);
	isl_vec_free(sol);
	isl_ctx_free(ctx);
	isl_int_clear(opt);

	return 0;
}
Example #15
0
static int bound_is_integer(__isl_take isl_constraint *bound, unsigned pos)
{
	isl_int c;
	int is_int;

	if (!bound)
		return 1;

	isl_int_init(c);
	isl_constraint_get_coefficient(bound, isl_dim_set, pos, &c);
	is_int = isl_int_is_one(c) || isl_int_is_negone(c);
	isl_int_clear(c);

	return is_int;
}
Example #16
0
/* Make first row entries in column col of bset1 identical to
 * those of bset2, using only these entries of the two matrices.
 * Let t be the last row with different entries.
 * For each row i < t, we set
 *	A[i] = (A[t][col]-B[t][col]) * A[i] + (B[i][col]-A[i][col) * A[t]
 *	B[i] = (A[t][col]-B[t][col]) * B[i] + (B[i][col]-A[i][col) * B[t]
 * so that
 *	A[i][col] = B[i][col] = old(A[t][col]*B[i][col]-A[i][col]*B[t][col])
 */
static int transform_column(
	struct isl_basic_set *bset1, struct isl_basic_set *bset2,
	unsigned row, unsigned col)
{
	int i, t;
	isl_int a, b, g;
	unsigned total;

	for (t = row-1; t >= 0; --t)
		if (isl_int_ne(bset1->eq[t][col], bset2->eq[t][col]))
			break;
	if (t < 0)
		return 0;

	total = 1 + isl_basic_set_n_dim(bset1);
	isl_int_init(a);
	isl_int_init(b);
	isl_int_init(g);
	isl_int_sub(b, bset1->eq[t][col], bset2->eq[t][col]);
	for (i = 0; i < t; ++i) {
		isl_int_sub(a, bset2->eq[i][col], bset1->eq[i][col]);
		isl_int_gcd(g, a, b);
		isl_int_divexact(a, a, g);
		isl_int_divexact(g, b, g);
		isl_seq_combine(bset1->eq[i], g, bset1->eq[i], a, bset1->eq[t],
				total);
		isl_seq_combine(bset2->eq[i], g, bset2->eq[i], a, bset2->eq[t],
				total);
	}
	isl_int_clear(a);
	isl_int_clear(b);
	isl_int_clear(g);
	delete_row(bset1, t);
	delete_row(bset2, t);
	return 1;
}
Example #17
0
/// Add an isl constraint to an ScopLib matrix.
///
/// @param user The matrix
/// @param c The constraint
int ScopLib::scatteringToMatrix_constraint(isl_constraint *c, void *user) {
  scoplib_matrix_p m = (scoplib_matrix_p) user;

  int nb_params = isl_constraint_dim(c, isl_dim_param);
  int nb_in = isl_constraint_dim(c, isl_dim_in);
  int nb_div = isl_constraint_dim(c, isl_dim_div);

  assert(!nb_div && "Existentially quantified variables not yet supported");

  scoplib_vector_p vec =
    scoplib_vector_malloc(nb_params + nb_in + 2);

  // Assign type
  if (isl_constraint_is_equality(c))
    scoplib_vector_tag_equality(vec);
  else
    scoplib_vector_tag_inequality(vec);

  isl_int v;
  isl_int_init(v);

  // Assign variables
  for (int i = 0; i < nb_in; ++i) {
    isl_constraint_get_coefficient(c, isl_dim_in, i, &v);
    isl_int_set(vec->p[i + 1], v);
  }

  // Assign parameters
  for (int i = 0; i < nb_params; ++i) {
    isl_constraint_get_coefficient(c, isl_dim_param, i, &v);
    isl_int_set(vec->p[nb_in + i + 1], v);
  }

  // Assign constant
  isl_constraint_get_constant(c, &v);
  isl_int_set(vec->p[nb_in + nb_params + 1], v);

  scoplib_vector_p null =
    scoplib_vector_malloc(nb_params + nb_in + 2);

  vec = scoplib_vector_sub(null, vec);
  scoplib_matrix_insert_vector(m, vec, 0);

  isl_constraint_free(c);
  isl_int_clear(v);

  return 0;
}
Example #18
0
/* Add term "term" to data->poly if it has sign data->sign.
 * The sign is determined based on the signs of the parameters
 * and variables in data->signs.  The integer divisions, if
 * any, are assumed to be non-negative.
 */
static isl_stat collect_fixed_sign_terms(__isl_take isl_term *term, void *user)
{
	struct isl_fixed_sign_data *data = (struct isl_fixed_sign_data *)user;
	isl_int n;
	int i;
	int sign;
	unsigned nparam;
	unsigned nvar;

	if (!term)
		return isl_stat_error;

	nparam = isl_term_dim(term, isl_dim_param);
	nvar = isl_term_dim(term, isl_dim_set);

	isl_int_init(n);

	isl_term_get_num(term, &n);

	sign = isl_int_sgn(n);
	for (i = 0; i < nparam; ++i) {
		if (data->signs[i] > 0)
			continue;
		if (isl_term_get_exp(term, isl_dim_param, i) % 2)
			sign = -sign;
	}
	for (i = 0; i < nvar; ++i) {
		if (data->signs[nparam + i] > 0)
			continue;
		if (isl_term_get_exp(term, isl_dim_set, i) % 2)
			sign = -sign;
	}

	if (sign == data->sign) {
		isl_qpolynomial *t = isl_qpolynomial_from_term(term);

		data->poly = isl_qpolynomial_add(data->poly, t);
	} else
		isl_term_free(term);

	isl_int_clear(n);

	return isl_stat_ok;
}
Example #19
0
static void copy_solution(struct isl_vec *vec, int maximize, isl_int *opt,
	isl_int *opt_denom, PipQuast *sol)
{
	int i;
	PipList *list;
	isl_int tmp;

	if (opt) {
		if (opt_denom) {
			isl_seq_cpy_from_pip(opt,
				 &sol->list->vector->the_vector[0], 1);
			isl_seq_cpy_from_pip(opt_denom,
				 &sol->list->vector->the_deno[0], 1);
		} else if (maximize)
			mpz_fdiv_q(*opt, sol->list->vector->the_vector[0],
					 sol->list->vector->the_deno[0]);
		else
			mpz_cdiv_q(*opt, sol->list->vector->the_vector[0],
					 sol->list->vector->the_deno[0]);
	}

	if (!vec)
		return;

	isl_int_init(tmp);
	isl_int_set_si(vec->el[0], 1);
	for (i = 0, list = sol->list->next; list; ++i, list = list->next) {
		isl_seq_cpy_from_pip(&vec->el[1 + i],
			&list->vector->the_deno[0], 1);
		isl_int_lcm(vec->el[0], vec->el[0], vec->el[1 + i]);
	}
	for (i = 0, list = sol->list->next; list; ++i, list = list->next) {
		isl_seq_cpy_from_pip(&tmp, &list->vector->the_deno[0], 1);
		isl_int_divexact(tmp, vec->el[0], tmp);
		isl_seq_cpy_from_pip(&vec->el[1 + i],
			&list->vector->the_vector[0], 1);
		isl_int_mul(vec->el[1 + i], vec->el[1 + i], tmp);
	}
	isl_int_clear(tmp);
}
Example #20
0
static struct isl_blk extend(struct isl_ctx *ctx, struct isl_blk block,
				size_t new_n)
{
	int i;
	isl_int *p;

	if (block.size >= new_n)
		return block;

	p = block.data;
	block.data = isl_realloc_array(ctx, block.data, isl_int, new_n);
	if (!block.data) {
		free(p);
		return isl_blk_error();
	}

	for (i = block.size; i < new_n; ++i)
		isl_int_init(block.data[i]);
	block.size = new_n;

	return block;
}
Example #21
0
/* Add stride constraints to "bset" based on the inverse mapping
 * that was plugged in.  In particular, if morph maps x' to x,
 * the the constraints of the original input
 *
 *	A x' + b >= 0
 *
 * have been rewritten to
 *
 *	A inv x + b >= 0
 *
 * However, this substitution may loose information on the integrality of x',
 * so we need to impose that
 *
 *	inv x
 *
 * is integral.  If inv = B/d, this means that we need to impose that
 *
 *	B x = 0		mod d
 *
 * or
 *
 *	exists alpha in Z^m: B x = d alpha
 *
 */
static __isl_give isl_basic_set *add_strides(__isl_take isl_basic_set *bset,
	__isl_keep isl_morph *morph)
{
	int i, div, k;
	isl_int gcd;

	if (isl_int_is_one(morph->inv->row[0][0]))
		return bset;

	isl_int_init(gcd);

	for (i = 0; 1 + i < morph->inv->n_row; ++i) {
		isl_seq_gcd(morph->inv->row[1 + i], morph->inv->n_col, &gcd);
		if (isl_int_is_divisible_by(gcd, morph->inv->row[0][0]))
			continue;
		div = isl_basic_set_alloc_div(bset);
		if (div < 0)
			goto error;
		k = isl_basic_set_alloc_equality(bset);
		if (k < 0)
			goto error;
		isl_seq_cpy(bset->eq[k], morph->inv->row[1 + i],
			    morph->inv->n_col);
		isl_seq_clr(bset->eq[k] + morph->inv->n_col, bset->n_div);
		isl_int_set(bset->eq[k][morph->inv->n_col + div],
			    morph->inv->row[0][0]);
	}

	isl_int_clear(gcd);

	return bset;
error:
	isl_int_clear(gcd);
	isl_basic_set_free(bset);
	return NULL;
}
Example #22
0
/* Given a basic set, exploit the equalties in the a basic set to construct
 * a morphishm that maps the basic set to a lower-dimensional space.
 * Specifically, the morphism reduces the number of dimensions of type "type".
 *
 * This function is a slight generalization of isl_mat_variable_compression
 * in that it allows the input to be parametric and that it allows for the
 * compression of either parameters or set variables.
 *
 * We first select the equalities of interest, that is those that involve
 * variables of type "type" and no later variables.
 * Denote those equalities as
 *
 *		-C(p) + M x = 0
 *
 * where C(p) depends on the parameters if type == isl_dim_set and
 * is a constant if type == isl_dim_param.
 *
 * First compute the (left) Hermite normal form of M,
 *
 *		M [U1 U2] = M U = H = [H1 0]
 * or
 *		              M = H Q = [H1 0] [Q1]
 *                                             [Q2]
 *
 * with U, Q unimodular, Q = U^{-1} (and H lower triangular).
 * Define the transformed variables as
 *
 *		x = [U1 U2] [ x1' ] = [U1 U2] [Q1] x
 *		            [ x2' ]           [Q2]
 *
 * The equalities then become
 *
 *		-C(p) + H1 x1' = 0   or   x1' = H1^{-1} C(p) = C'(p)
 *
 * If the denominator of the constant term does not divide the
 * the common denominator of the parametric terms, then every
 * integer point is mapped to a non-integer point and then the original set has no
 * integer solutions (since the x' are a unimodular transformation
 * of the x).  In this case, an empty morphism is returned.
 * Otherwise, the transformation is given by
 *
 *		x = U1 H1^{-1} C(p) + U2 x2'
 *
 * The inverse transformation is simply
 *
 *		x2' = Q2 x
 *
 * Both matrices are extended to map the full original space to the full
 * compressed space.
 */
__isl_give isl_morph *isl_basic_set_variable_compression(
	__isl_keep isl_basic_set *bset, enum isl_dim_type type)
{
	unsigned otype;
	unsigned ntype;
	unsigned orest;
	unsigned nrest;
	int f_eq, n_eq;
	isl_space *dim;
	isl_mat *H, *U, *Q, *C = NULL, *H1, *U1, *U2;
	isl_basic_set *dom, *ran;

	if (!bset)
		return NULL;

	if (isl_basic_set_plain_is_empty(bset))
		return isl_morph_empty(bset);

	isl_assert(bset->ctx, bset->n_div == 0, return NULL);

	otype = 1 + isl_space_offset(bset->dim, type);
	ntype = isl_basic_set_dim(bset, type);
	orest = otype + ntype;
	nrest = isl_basic_set_total_dim(bset) - (orest - 1);

	for (f_eq = 0; f_eq < bset->n_eq; ++f_eq)
		if (isl_seq_first_non_zero(bset->eq[f_eq] + orest, nrest) == -1)
			break;
	for (n_eq = 0; f_eq + n_eq < bset->n_eq; ++n_eq)
		if (isl_seq_first_non_zero(bset->eq[f_eq + n_eq] + otype, ntype) == -1)
			break;
	if (n_eq == 0)
		return isl_morph_identity(bset);

	H = isl_mat_sub_alloc6(bset->ctx, bset->eq, f_eq, n_eq, otype, ntype);
	H = isl_mat_left_hermite(H, 0, &U, &Q);
	if (!H || !U || !Q)
		goto error;
	Q = isl_mat_drop_rows(Q, 0, n_eq);
	Q = isl_mat_diagonal(isl_mat_identity(bset->ctx, otype), Q);
	Q = isl_mat_diagonal(Q, isl_mat_identity(bset->ctx, nrest));
	C = isl_mat_alloc(bset->ctx, 1 + n_eq, otype);
	if (!C)
		goto error;
	isl_int_set_si(C->row[0][0], 1);
	isl_seq_clr(C->row[0] + 1, otype - 1);
	isl_mat_sub_neg(C->ctx, C->row + 1, bset->eq + f_eq, n_eq, 0, 0, otype);
	H1 = isl_mat_sub_alloc(H, 0, H->n_row, 0, H->n_row);
	H1 = isl_mat_lin_to_aff(H1);
	C = isl_mat_inverse_product(H1, C);
	if (!C)
		goto error;
	isl_mat_free(H);

	if (!isl_int_is_one(C->row[0][0])) {
		int i;
		isl_int g;

		isl_int_init(g);
		for (i = 0; i < n_eq; ++i) {
			isl_seq_gcd(C->row[1 + i] + 1, otype - 1, &g);
			isl_int_gcd(g, g, C->row[0][0]);
			if (!isl_int_is_divisible_by(C->row[1 + i][0], g))
				break;
		}
		isl_int_clear(g);

		if (i < n_eq) {
			isl_mat_free(C);
			isl_mat_free(U);
			isl_mat_free(Q);
			return isl_morph_empty(bset);
		}

		C = isl_mat_normalize(C);
	}

	U1 = isl_mat_sub_alloc(U, 0, U->n_row, 0, n_eq);
	U1 = isl_mat_lin_to_aff(U1);
	U2 = isl_mat_sub_alloc(U, 0, U->n_row, n_eq, U->n_row - n_eq);
	U2 = isl_mat_lin_to_aff(U2);
	isl_mat_free(U);

	C = isl_mat_product(U1, C);
	C = isl_mat_aff_direct_sum(C, U2);
	C = insert_parameter_rows(C, otype - 1);
	C = isl_mat_diagonal(C, isl_mat_identity(bset->ctx, nrest));

	dim = isl_space_copy(bset->dim);
	dim = isl_space_drop_dims(dim, type, 0, ntype);
	dim = isl_space_add_dims(dim, type, ntype - n_eq);
	ran = isl_basic_set_universe(dim);
	dom = copy_equalities(bset, f_eq, n_eq);

	return isl_morph_alloc(dom, ran, Q, C);
error:
	isl_mat_free(C);
	isl_mat_free(H);
	isl_mat_free(U);
	isl_mat_free(Q);
	return NULL;
}
Example #23
0
__isl_give isl_basic_set *isl_basic_set_box_from_points(
	__isl_take isl_point *pnt1, __isl_take isl_point *pnt2)
{
	isl_basic_set *bset;
	unsigned total;
	int i;
	int k;
	isl_int t;

	isl_int_init(t);

	if (!pnt1 || !pnt2)
		goto error;

	isl_assert(pnt1->dim->ctx,
			isl_dim_equal(pnt1->dim, pnt2->dim), goto error);

	if (isl_point_is_void(pnt1) && isl_point_is_void(pnt2)) {
		isl_dim *dim = isl_dim_copy(pnt1->dim);
		isl_point_free(pnt1);
		isl_point_free(pnt2);
		isl_int_clear(t);
		return isl_basic_set_empty(dim);
	}
	if (isl_point_is_void(pnt1)) {
		isl_point_free(pnt1);
		isl_int_clear(t);
		return isl_basic_set_from_point(pnt2);
	}
	if (isl_point_is_void(pnt2)) {
		isl_point_free(pnt2);
		isl_int_clear(t);
		return isl_basic_set_from_point(pnt1);
	}

	total = isl_dim_total(pnt1->dim);
	bset = isl_basic_set_alloc_dim(isl_dim_copy(pnt1->dim), 0, 0, 2 * total);

	for (i = 0; i < total; ++i) {
		isl_int_mul(t, pnt1->vec->el[1 + i], pnt2->vec->el[0]);
		isl_int_submul(t, pnt2->vec->el[1 + i], pnt1->vec->el[0]);

		k = isl_basic_set_alloc_inequality(bset);
		if (k < 0)
			goto error;
		isl_seq_clr(bset->ineq[k] + 1, total);
		if (isl_int_is_pos(t)) {
			isl_int_set_si(bset->ineq[k][1 + i], -1);
			isl_int_set(bset->ineq[k][0], pnt1->vec->el[1 + i]);
		} else {
			isl_int_set_si(bset->ineq[k][1 + i], 1);
			isl_int_neg(bset->ineq[k][0], pnt1->vec->el[1 + i]);
		}
		isl_int_fdiv_q(bset->ineq[k][0], bset->ineq[k][0], pnt1->vec->el[0]);

		k = isl_basic_set_alloc_inequality(bset);
		if (k < 0)
			goto error;
		isl_seq_clr(bset->ineq[k] + 1, total);
		if (isl_int_is_pos(t)) {
			isl_int_set_si(bset->ineq[k][1 + i], 1);
			isl_int_neg(bset->ineq[k][0], pnt2->vec->el[1 + i]);
		} else {
			isl_int_set_si(bset->ineq[k][1 + i], -1);
			isl_int_set(bset->ineq[k][0], pnt2->vec->el[1 + i]);
		}
		isl_int_fdiv_q(bset->ineq[k][0], bset->ineq[k][0], pnt2->vec->el[0]);
	}

	bset = isl_basic_set_finalize(bset);

	isl_point_free(pnt1);
	isl_point_free(pnt2);

	isl_int_clear(t);

	return bset;
error:
	isl_point_free(pnt1);
	isl_point_free(pnt2);
	isl_int_clear(t);
	return NULL;
}
Example #24
0
/* Given a set of modulo constraints
 *
 *		c + A y = 0 mod d
 *
 * this function returns an affine transformation T,
 *
 *		y = T y'
 *
 * that bijectively maps the integer vectors y' to integer
 * vectors y that satisfy the modulo constraints.
 *
 * This function is inspired by Section 2.5.3
 * of B. Meister, "Stating and Manipulating Periodicity in the Polytope
 * Model.  Applications to Program Analysis and Optimization".
 * However, the implementation only follows the algorithm of that
 * section for computing a particular solution and not for computing
 * a general homogeneous solution.  The latter is incomplete and
 * may remove some valid solutions.
 * Instead, we use an adaptation of the algorithm in Section 7 of
 * B. Meister, S. Verdoolaege, "Polynomial Approximations in the Polytope
 * Model: Bringing the Power of Quasi-Polynomials to the Masses".
 *
 * The input is given as a matrix B = [ c A ] and a vector d.
 * Each element of the vector d corresponds to a row in B.
 * The output is a lower triangular matrix.
 * If no integer vector y satisfies the given constraints then
 * a matrix with zero columns is returned.
 *
 * We first compute a particular solution y_0 to the given set of
 * modulo constraints in particular_solution.  If no such solution
 * exists, then we return a zero-columned transformation matrix.
 * Otherwise, we compute the generic solution to
 *
 *		A y = 0 mod d
 *
 * That is we want to compute G such that
 *
 *		y = G y''
 *
 * with y'' integer, describes the set of solutions.
 *
 * We first remove the common factors of each row.
 * In particular if gcd(A_i,d_i) != 1, then we divide the whole
 * row i (including d_i) by this common factor.  If afterwards gcd(A_i) != 1,
 * then we divide this row of A by the common factor, unless gcd(A_i) = 0.
 * In the later case, we simply drop the row (in both A and d).
 *
 * If there are no rows left in A, then G is the identity matrix. Otherwise,
 * for each row i, we now determine the lattice of integer vectors
 * that satisfies this row.  Let U_i be the unimodular extension of the
 * row A_i.  This unimodular extension exists because gcd(A_i) = 1.
 * The first component of
 *
 *		y' = U_i y
 *
 * needs to be a multiple of d_i.  Let y' = diag(d_i, 1, ..., 1) y''.
 * Then,
 *
 *		y = U_i^{-1} diag(d_i, 1, ..., 1) y''
 *
 * for arbitrary integer vectors y''.  That is, y belongs to the lattice
 * generated by the columns of L_i = U_i^{-1} diag(d_i, 1, ..., 1).
 * If there is only one row, then G = L_1.
 *
 * If there is more than one row left, we need to compute the intersection
 * of the lattices.  That is, we need to compute an L such that
 *
 *		L = L_i L_i'	for all i
 *
 * with L_i' some integer matrices.  Let A be constructed as follows
 *
 *		A = [ L_1^{-T} L_2^{-T} ... L_k^{-T} ]
 *
 * and computed the Hermite Normal Form of A = [ H 0 ] U
 * Then,
 *
 *		L_i^{-T} = H U_{1,i}
 *
 * or
 *
 *		H^{-T} = L_i U_{1,i}^T
 *
 * In other words G = L = H^{-T}.
 * To ensure that G is lower triangular, we compute and use its Hermite
 * normal form.
 *
 * The affine transformation matrix returned is then
 *
 *		[  1   0  ]
 *		[ y_0  G  ]
 *
 * as any y = y_0 + G y' with y' integer is a solution to the original
 * modulo constraints.
 */
struct isl_mat *isl_mat_parameter_compression(
			struct isl_mat *B, struct isl_vec *d)
{
	int i;
	struct isl_mat *cst = NULL;
	struct isl_mat *T = NULL;
	isl_int D;

	if (!B || !d)
		goto error;
	isl_assert(B->ctx, B->n_row == d->size, goto error);
	cst = particular_solution(B, d);
	if (!cst)
		goto error;
	if (cst->n_col == 0) {
		T = isl_mat_alloc(B->ctx, B->n_col, 0);
		isl_mat_free(cst);
		isl_mat_free(B);
		isl_vec_free(d);
		return T;
	}
	isl_int_init(D);
	/* Replace a*g*row = 0 mod g*m by row = 0 mod m */
	for (i = 0; i < B->n_row; ++i) {
		isl_seq_gcd(B->row[i] + 1, B->n_col - 1, &D);
		if (isl_int_is_one(D))
			continue;
		if (isl_int_is_zero(D)) {
			B = isl_mat_drop_rows(B, i, 1);
			d = isl_vec_cow(d);
			if (!B || !d)
				goto error2;
			isl_seq_cpy(d->block.data+i, d->block.data+i+1,
							d->size - (i+1));
			d->size--;
			i--;
			continue;
		}
		B = isl_mat_cow(B);
		if (!B)
			goto error2;
		isl_seq_scale_down(B->row[i] + 1, B->row[i] + 1, D, B->n_col-1);
		isl_int_gcd(D, D, d->block.data[i]);
		d = isl_vec_cow(d);
		if (!d)
			goto error2;
		isl_int_divexact(d->block.data[i], d->block.data[i], D);
	}
	isl_int_clear(D);
	if (B->n_row == 0)
		T = isl_mat_identity(B->ctx, B->n_col);
	else if (B->n_row == 1)
		T = parameter_compression_1(B, d);
	else
		T = parameter_compression_multi(B, d);
	T = isl_mat_left_hermite(T, 0, NULL, NULL);
	if (!T)
		goto error;
	isl_mat_sub_copy(T->ctx, T->row + 1, cst->row, cst->n_row, 0, 0, 1);
	isl_mat_free(cst);
	isl_mat_free(B);
	isl_vec_free(d);
	return T;
error2:
	isl_int_clear(D);
error:
	isl_mat_free(cst);
	isl_mat_free(B);
	isl_vec_free(d);
	return NULL;
}
/* Compute a reduced basis for the set represented by the tableau "tab".
 * tab->basis, which must be initialized by the calling function to an affine
 * unimodular basis, is updated to reflect the reduced basis.
 * The first tab->n_zero rows of the basis (ignoring the constant row)
 * are assumed to correspond to equalities and are left untouched.
 * tab->n_zero is updated to reflect any additional equalities that
 * have been detected in the first rows of the new basis.
 * The final tab->n_unbounded rows of the basis are assumed to correspond
 * to unbounded directions and are also left untouched.
 * In particular this means that the remaining rows are assumed to
 * correspond to bounded directions.
 *
 * This function implements the algorithm described in
 * "An Implementation of the Generalized Basis Reduction Algorithm
 *  for Integer Programming" of Cook el al. to compute a reduced basis.
 * We use \epsilon = 1/4.
 *
 * If ctx->opt->gbr_only_first is set, the user is only interested
 * in the first direction.  In this case we stop the basis reduction when
 * the width in the first direction becomes smaller than 2.
 */
struct isl_tab *isl_tab_compute_reduced_basis(struct isl_tab *tab)
{
    unsigned dim;
    struct isl_ctx *ctx;
    struct isl_mat *B;
    int unbounded;
    int i;
    GBR_LP *lp = NULL;
    GBR_type F_old, alpha, F_new;
    int row;
    isl_int tmp;
    struct isl_vec *b_tmp;
    GBR_type *F = NULL;
    GBR_type *alpha_buffer[2] = { NULL, NULL };
    GBR_type *alpha_saved;
    GBR_type F_saved;
    int use_saved = 0;
    isl_int mu[2];
    GBR_type mu_F[2];
    GBR_type two;
    GBR_type one;
    int empty = 0;
    int fixed = 0;
    int fixed_saved = 0;
    int mu_fixed[2];
    int n_bounded;
    int gbr_only_first;

    if (!tab)
        return NULL;

    if (tab->empty)
        return tab;

    ctx = tab->mat->ctx;
    gbr_only_first = ctx->opt->gbr_only_first;
    dim = tab->n_var;
    B = tab->basis;
    if (!B)
        return tab;

    n_bounded = dim - tab->n_unbounded;
    if (n_bounded <= tab->n_zero + 1)
        return tab;

    isl_int_init(tmp);
    isl_int_init(mu[0]);
    isl_int_init(mu[1]);

    GBR_init(alpha);
    GBR_init(F_old);
    GBR_init(F_new);
    GBR_init(F_saved);
    GBR_init(mu_F[0]);
    GBR_init(mu_F[1]);
    GBR_init(two);
    GBR_init(one);

    b_tmp = isl_vec_alloc(ctx, dim);
    if (!b_tmp)
        goto error;

    F = isl_alloc_array(ctx, GBR_type, n_bounded);
    alpha_buffer[0] = isl_alloc_array(ctx, GBR_type, n_bounded);
    alpha_buffer[1] = isl_alloc_array(ctx, GBR_type, n_bounded);
    alpha_saved = alpha_buffer[0];

    if (!F || !alpha_buffer[0] || !alpha_buffer[1])
        goto error;

    for (i = 0; i < n_bounded; ++i) {
        GBR_init(F[i]);
        GBR_init(alpha_buffer[0][i]);
        GBR_init(alpha_buffer[1][i]);
    }

    GBR_set_ui(two, 2);
    GBR_set_ui(one, 1);

    lp = GBR_lp_init(tab);
    if (!lp)
        goto error;

    i = tab->n_zero;

    GBR_lp_set_obj(lp, B->row[1+i]+1, dim);
    ctx->stats->gbr_solved_lps++;
    unbounded = GBR_lp_solve(lp);
    isl_assert(ctx, !unbounded, goto error);
    GBR_lp_get_obj_val(lp, &F[i]);

    if (GBR_lt(F[i], one)) {
        if (!GBR_is_zero(F[i])) {
            empty = GBR_lp_cut(lp, B->row[1+i]+1);
            if (empty)
                goto done;
            GBR_set_ui(F[i], 0);
        }
        tab->n_zero++;
    }

    do {
        if (i+1 == tab->n_zero) {
            GBR_lp_set_obj(lp, B->row[1+i+1]+1, dim);
            ctx->stats->gbr_solved_lps++;
            unbounded = GBR_lp_solve(lp);
            isl_assert(ctx, !unbounded, goto error);
            GBR_lp_get_obj_val(lp, &F_new);
            fixed = GBR_lp_is_fixed(lp);
            GBR_set_ui(alpha, 0);
        } else if (use_saved) {
            row = GBR_lp_next_row(lp);
            GBR_set(F_new, F_saved);
            fixed = fixed_saved;
            GBR_set(alpha, alpha_saved[i]);
        } else {
            row = GBR_lp_add_row(lp, B->row[1+i]+1, dim);
            GBR_lp_set_obj(lp, B->row[1+i+1]+1, dim);
            ctx->stats->gbr_solved_lps++;
            unbounded = GBR_lp_solve(lp);
            isl_assert(ctx, !unbounded, goto error);
            GBR_lp_get_obj_val(lp, &F_new);
            fixed = GBR_lp_is_fixed(lp);

            GBR_lp_get_alpha(lp, row, &alpha);

            if (i > 0)
                save_alpha(lp, row-i, i, alpha_saved);

            if (GBR_lp_del_row(lp) < 0)
                goto error;
        }
        GBR_set(F[i+1], F_new);

        GBR_floor(mu[0], alpha);
        GBR_ceil(mu[1], alpha);

        if (isl_int_eq(mu[0], mu[1]))
            isl_int_set(tmp, mu[0]);
        else {
            int j;

            for (j = 0; j <= 1; ++j) {
                isl_int_set(tmp, mu[j]);
                isl_seq_combine(b_tmp->el,
                                ctx->one, B->row[1+i+1]+1,
                                tmp, B->row[1+i]+1, dim);
                GBR_lp_set_obj(lp, b_tmp->el, dim);
                ctx->stats->gbr_solved_lps++;
                unbounded = GBR_lp_solve(lp);
                isl_assert(ctx, !unbounded, goto error);
                GBR_lp_get_obj_val(lp, &mu_F[j]);
                mu_fixed[j] = GBR_lp_is_fixed(lp);
                if (i > 0)
                    save_alpha(lp, row-i, i, alpha_buffer[j]);
            }

            if (GBR_lt(mu_F[0], mu_F[1]))
                j = 0;
            else
                j = 1;

            isl_int_set(tmp, mu[j]);
            GBR_set(F_new, mu_F[j]);
            fixed = mu_fixed[j];
            alpha_saved = alpha_buffer[j];
        }
        isl_seq_combine(B->row[1+i+1]+1, ctx->one, B->row[1+i+1]+1,
                        tmp, B->row[1+i]+1, dim);

        if (i+1 == tab->n_zero && fixed) {
            if (!GBR_is_zero(F[i+1])) {
                empty = GBR_lp_cut(lp, B->row[1+i+1]+1);
                if (empty)
                    goto done;
                GBR_set_ui(F[i+1], 0);
            }
            tab->n_zero++;
        }

        GBR_set(F_old, F[i]);

        use_saved = 0;
        /* mu_F[0] = 4 * F_new; mu_F[1] = 3 * F_old */
        GBR_set_ui(mu_F[0], 4);
        GBR_mul(mu_F[0], mu_F[0], F_new);
        GBR_set_ui(mu_F[1], 3);
        GBR_mul(mu_F[1], mu_F[1], F_old);
        if (GBR_lt(mu_F[0], mu_F[1])) {
            B = isl_mat_swap_rows(B, 1 + i, 1 + i + 1);
            if (i > tab->n_zero) {
                use_saved = 1;
                GBR_set(F_saved, F_new);
                fixed_saved = fixed;
                if (GBR_lp_del_row(lp) < 0)
                    goto error;
                --i;
            } else {
                GBR_set(F[tab->n_zero], F_new);
                if (gbr_only_first && GBR_lt(F[tab->n_zero], two))
                    break;

                if (fixed) {
                    if (!GBR_is_zero(F[tab->n_zero])) {
                        empty = GBR_lp_cut(lp, B->row[1+tab->n_zero]+1);
                        if (empty)
                            goto done;
                        GBR_set_ui(F[tab->n_zero], 0);
                    }
                    tab->n_zero++;
                }
            }
        } else {
            GBR_lp_add_row(lp, B->row[1+i]+1, dim);
            ++i;
        }
    } while (i < n_bounded - 1);
Example #26
0
static void
pdr_stride_in_loop (mpz_t stride, graphite_dim_t depth, poly_dr_p pdr)
{
  poly_bb_p pbb = PDR_PBB (pdr);
  isl_map *map;
  isl_set *set;
  isl_aff *aff;
  isl_space *dc;
  isl_constraint *lma, *c;
  isl_int islstride;
  graphite_dim_t time_depth;
  unsigned offset, nt;
  unsigned i;
  /* XXX isl rewrite following comments.  */
  /* Builds a partial difference equations and inserts them
     into pointset powerset polyhedron P.  Polyhedron is assumed
     to have the format: T|I|T'|I'|G|S|S'|l1|l2.

     TIME_DEPTH is the time dimension w.r.t. which we are
     differentiating.
     OFFSET represents the number of dimensions between
     columns t_{time_depth} and t'_{time_depth}.
     DIM_SCTR is the number of scattering dimensions.  It is
     essentially the dimensionality of the T vector.

     The following equations are inserted into the polyhedron P:
     | t_1 = t_1'
     | ...
     | t_{time_depth-1} = t'_{time_depth-1}
     | t_{time_depth} = t'_{time_depth} + 1
     | t_{time_depth+1} = t'_{time_depth + 1}
     | ...
     | t_{dim_sctr} = t'_{dim_sctr}.  */

  /* Add the equality: t_{time_depth} = t'_{time_depth} + 1.
     This is the core part of this alogrithm, since this
     constraint asks for the memory access stride (difference)
     between two consecutive points in time dimensions.  */

  /* Add equalities:
     | t1 = t1'
     | ...
     | t_{time_depth-1} = t'_{time_depth-1}
     | t_{time_depth+1} = t'_{time_depth+1}
     | ...
     | t_{dim_sctr} = t'_{dim_sctr}

     This means that all the time dimensions are equal except for
     time_depth, where the constraint is t_{depth} = t'_{depth} + 1
     step.  More to this: we should be careful not to add equalities
     to the 'coupled' dimensions, which happens when the one dimension
     is stripmined dimension, and the other dimension corresponds
     to the point loop inside stripmined dimension.  */

  /* pdr->accesses:    [P1..nb_param,I1..nb_domain]->[a,S1..nb_subscript]
          ??? [P] not used for PDRs?
     pdr->extent:      [a,S1..nb_subscript]
     pbb->domain:      [P1..nb_param,I1..nb_domain]
     pbb->transformed: [P1..nb_param,I1..nb_domain]->[T1..Tnb_sctr]
          [T] includes local vars (currently unused)
     
     First we create [P,I] -> [T,a,S].  */
  
  map = isl_map_flat_range_product (isl_map_copy (pbb->transformed),
				    isl_map_copy (pdr->accesses));
  /* Add a dimension for L: [P,I] -> [T,a,S,L].*/
  map = isl_map_add_dims (map, isl_dim_out, 1);
  /* Build a constraint for "lma[S] - L == 0", effectively calculating
     L in terms of subscripts.  */
  lma = build_linearized_memory_access (map, pdr);
  /* And add it to the map, so we now have:
     [P,I] -> [T,a,S,L] : lma([S]) == L.  */
  map = isl_map_add_constraint (map, lma);

  /* Then we create  [P,I,P',I'] -> [T,a,S,L,T',a',S',L'].  */
  map = isl_map_flat_product (map, isl_map_copy (map));

  /* Now add the equality T[time_depth] == T'[time_depth]+1.  This will
     force L' to be the linear address at T[time_depth] + 1. */
  time_depth = psct_dynamic_dim (pbb, depth);
  /* Length of [a,S] plus [L] ...  */
  offset = 1 + isl_map_dim (pdr->accesses, isl_dim_out);
  /* ... plus [T].  */
  offset += isl_map_dim (pbb->transformed, isl_dim_out);

  c = isl_equality_alloc (isl_local_space_from_space (isl_map_get_space (map)));
  c = isl_constraint_set_coefficient_si (c, isl_dim_out, time_depth, 1);
  c = isl_constraint_set_coefficient_si (c, isl_dim_out,
					 offset + time_depth, -1);
  c = isl_constraint_set_constant_si (c, 1);
  map = isl_map_add_constraint (map, c);

  /* Now we equate most of the T/T' elements (making PITaSL nearly
     the same is (PITaSL)', except for one dimension, namely for 'depth'
     (an index into [I]), after translating to index into [T].  Take care
     to not produce an empty map, which indicates we wanted to equate
     two dimensions that are already coupled via the above time_depth
     dimension.  Happens with strip mining where several scatter dimension
     are interdependend.  */
  /* Length of [T].  */
  nt = pbb_nb_scattering_transform (pbb) + pbb_nb_local_vars (pbb);
  for (i = 0; i < nt; i++)
    if (i != time_depth)
      {
	isl_map *temp = isl_map_equate (isl_map_copy (map),
					isl_dim_out, i,
					isl_dim_out, offset + i);
	if (isl_map_is_empty (temp))
	  isl_map_free (temp);
	else
	  {
	    isl_map_free (map);
	    map = temp;
	  }
      }

  /* Now maximize the expression L' - L.  */
  set = isl_map_range (map);
  dc = isl_set_get_space (set);
  aff = isl_aff_zero_on_domain (isl_local_space_from_space (dc));
  aff = isl_aff_set_coefficient_si (aff, isl_dim_in, offset - 1, -1);
  aff = isl_aff_set_coefficient_si (aff, isl_dim_in, offset + offset - 1, 1);
  isl_int_init (islstride);
  isl_set_max (set, aff, &islstride);
  isl_int_get_gmp (islstride, stride);
  isl_int_clear (islstride);
  isl_aff_free (aff);
  isl_set_free (set);

  if (dump_file && (dump_flags & TDF_DETAILS))
    {
      char *str;
      void (*gmp_free) (void *, size_t);

      fprintf (dump_file, "\nStride in BB_%d, DR_%d, depth %d:",
	       pbb_index (pbb), PDR_ID (pdr), (int) depth);
      str = mpz_get_str (0, 10, stride);
      fprintf (dump_file, "  %s ", str);
      mp_get_memory_functions (NULL, NULL, &gmp_free);
      (*gmp_free) (str, strlen (str) + 1);
    }
}