llvm/polly/lib/External/isl/isl_sample.c

/*
 * Copyright 2008-2009 Katholieke Universiteit Leuven
 *
 * Use of this software is governed by the MIT license
 *
 * Written by Sven Verdoolaege, K.U.Leuven, Departement
 * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
 */

#include <isl_ctx_private.h>
#include <isl_map_private.h>
#include "isl_sample.h"
#include <isl/vec.h>
#include <isl/mat.h>
#include <isl_seq.h>
#include "isl_equalities.h"
#include "isl_tab.h"
#include "isl_basis_reduction.h"
#include <isl_factorization.h>
#include <isl_point_private.h>
#include <isl_options_private.h>
#include <isl_vec_private.h>

#include <bset_from_bmap.c>
#include <set_to_map.c>

static __isl_give isl_vec *isl_basic_set_sample_bounded(
	__isl_take isl_basic_set *bset);

static __isl_give isl_vec *empty_sample(__isl_take isl_basic_set *bset)
{}

/* Construct a zero sample of the same dimension as bset.
 * As a special case, if bset is zero-dimensional, this
 * function creates a zero-dimensional sample point.
 */
static __isl_give isl_vec *zero_sample(__isl_take isl_basic_set *bset)
{}

static __isl_give isl_vec *interval_sample(__isl_take isl_basic_set *bset)
{}

/* Find a sample integer point, if any, in bset, which is known
 * to have equalities.  If bset contains no integer points, then
 * return a zero-length vector.
 * We simply remove the known equalities, compute a sample
 * in the resulting bset, using the specified recurse function,
 * and then transform the sample back to the original space.
 */
static __isl_give isl_vec *sample_eq(__isl_take isl_basic_set *bset,
	__isl_give isl_vec *(*recurse)(__isl_take isl_basic_set *))
{}

/* Return a matrix containing the equalities of the tableau
 * in constraint form.  The tableau is assumed to have
 * an associated bset that has been kept up-to-date.
 */
static struct isl_mat *tab_equalities(struct isl_tab *tab)
{}

/* Compute and return an initial basis for the bounded tableau "tab".
 *
 * If the tableau is either full-dimensional or zero-dimensional,
 * the we simply return an identity matrix.
 * Otherwise, we construct a basis whose first directions correspond
 * to equalities.
 */
static struct isl_mat *initial_basis(struct isl_tab *tab)
{}

/* Compute the minimum of the current ("level") basis row over "tab"
 * and store the result in position "level" of "min".
 *
 * This function assumes that at least one more row and at least
 * one more element in the constraint array are available in the tableau.
 */
static enum isl_lp_result compute_min(isl_ctx *ctx, struct isl_tab *tab,
	__isl_keep isl_vec *min, int level)
{}

/* Compute the maximum of the current ("level") basis row over "tab"
 * and store the result in position "level" of "max".
 *
 * This function assumes that at least one more row and at least
 * one more element in the constraint array are available in the tableau.
 */
static enum isl_lp_result compute_max(isl_ctx *ctx, struct isl_tab *tab,
	__isl_keep isl_vec *max, int level)
{}

/* Perform a greedy search for an integer point in the set represented
 * by "tab", given that the minimal rational value (rounded up to the
 * nearest integer) at "level" is smaller than the maximal rational
 * value (rounded down to the nearest integer).
 *
 * Return 1 if we have found an integer point (if tab->n_unbounded > 0
 * then we may have only found integer values for the bounded dimensions
 * and it is the responsibility of the caller to extend this solution
 * to the unbounded dimensions).
 * Return 0 if greedy search did not result in a solution.
 * Return -1 if some error occurred.
 *
 * We assign a value half-way between the minimum and the maximum
 * to the current dimension and check if the minimal value of the
 * next dimension is still smaller than (or equal) to the maximal value.
 * We continue this process until either
 * - the minimal value (rounded up) is greater than the maximal value
 *	(rounded down).  In this case, greedy search has failed.
 * - we have exhausted all bounded dimensions, meaning that we have
 *	found a solution.
 * - the sample value of the tableau is integral.
 * - some error has occurred.
 */
static int greedy_search(isl_ctx *ctx, struct isl_tab *tab,
	__isl_keep isl_vec *min, __isl_keep isl_vec *max, int level)
{}

/* Given a tableau representing a set, find and return
 * an integer point in the set, if there is any.
 *
 * We perform a depth first search
 * for an integer point, by scanning all possible values in the range
 * attained by a basis vector, where an initial basis may have been set
 * by the calling function.  Otherwise an initial basis that exploits
 * the equalities in the tableau is created.
 * tab->n_zero is currently ignored and is clobbered by this function.
 *
 * The tableau is allowed to have unbounded direction, but then
 * the calling function needs to set an initial basis, with the
 * unbounded directions last and with tab->n_unbounded set
 * to the number of unbounded directions.
 * Furthermore, the calling functions needs to add shifted copies
 * of all constraints involving unbounded directions to ensure
 * that any feasible rational value in these directions can be rounded
 * up to yield a feasible integer value.
 * In particular, let B define the given basis x' = B x
 * and let T be the inverse of B, i.e., X = T x'.
 * Let a x + c >= 0 be a constraint of the set represented by the tableau,
 * or a T x' + c >= 0 in terms of the given basis.  Assume that
 * the bounded directions have an integer value, then we can safely
 * round up the values for the unbounded directions if we make sure
 * that x' not only satisfies the original constraint, but also
 * the constraint "a T x' + c + s >= 0" with s the sum of all
 * negative values in the last n_unbounded entries of "a T".
 * The calling function therefore needs to add the constraint
 * a x + c + s >= 0.  The current function then scans the first
 * directions for an integer value and once those have been found,
 * it can compute "T ceil(B x)" to yield an integer point in the set.
 * Note that during the search, the first rows of B may be changed
 * by a basis reduction, but the last n_unbounded rows of B remain
 * unaltered and are also not mixed into the first rows.
 *
 * The search is implemented iteratively.  "level" identifies the current
 * basis vector.  "init" is true if we want the first value at the current
 * level and false if we want the next value.
 *
 * At the start of each level, we first check if we can find a solution
 * using greedy search.  If not, we continue with the exhaustive search.
 *
 * The initial basis is the identity matrix.  If the range in some direction
 * contains more than one integer value, we perform basis reduction based
 * on the value of ctx->opt->gbr
 *	- ISL_GBR_NEVER:	never perform basis reduction
 *	- ISL_GBR_ONCE:		only perform basis reduction the first
 *				time such a range is encountered
 *	- ISL_GBR_ALWAYS:	always perform basis reduction when
 *				such a range is encountered
 *
 * When ctx->opt->gbr is set to ISL_GBR_ALWAYS, then we allow the basis
 * reduction computation to return early.  That is, as soon as it
 * finds a reasonable first direction.
 */ 
__isl_give isl_vec *isl_tab_sample(struct isl_tab *tab)
{}

static __isl_give isl_vec *sample_bounded(__isl_take isl_basic_set *bset);

/* Internal data for factored_sample.
 * "sample" collects the sample and may get reset to a zero-length vector
 * signaling the absence of a sample vector.
 * "pos" is the position of the contribution of the next factor.
 */
struct isl_factored_sample_data {};

/* isl_factorizer_every_factor_basic_set callback that extends
 * the sample in data->sample with the contribution
 * of the factor "bset".
 * If "bset" turns out to be empty, then the product is empty too and
 * no further factors need to be considered.
 */
static isl_bool factor_sample(__isl_keep isl_basic_set *bset, void *user)
{}

/* Compute a sample point of the given basic set, based on the given,
 * non-trivial factorization.
 */
static __isl_give isl_vec *factored_sample(__isl_take isl_basic_set *bset,
	__isl_take isl_factorizer *f)
{}

/* Given a basic set that is known to be bounded, find and return
 * an integer point in the basic set, if there is any.
 *
 * After handling some trivial cases, we construct a tableau
 * and then use isl_tab_sample to find a sample, passing it
 * the identity matrix as initial basis.
 */ 
static __isl_give isl_vec *sample_bounded(__isl_take isl_basic_set *bset)
{}

/* Given a basic set "bset" and a value "sample" for the first coordinates
 * of bset, plug in these values and drop the corresponding coordinates.
 *
 * We do this by computing the preimage of the transformation
 *
 *	     [ 1 0 ]
 *	x =  [ s 0 ] x'
 *	     [ 0 I ]
 *
 * where [1 s] is the sample value and I is the identity matrix of the
 * appropriate dimension.
 */
static __isl_give isl_basic_set *plug_in(__isl_take isl_basic_set *bset,
	__isl_take isl_vec *sample)
{}

/* Given a basic set "bset", return any (possibly non-integer) point
 * in the basic set.
 */
static __isl_give isl_vec *rational_sample(__isl_take isl_basic_set *bset)
{}

/* Given a linear cone "cone" and a rational point "vec",
 * construct a polyhedron with shifted copies of the constraints in "cone",
 * i.e., a polyhedron with "cone" as its recession cone, such that each
 * point x in this polyhedron is such that the unit box positioned at x
 * lies entirely inside the affine cone 'vec + cone'.
 * Any rational point in this polyhedron may therefore be rounded up
 * to yield an integer point that lies inside said affine cone.
 *
 * Denote the constraints of cone by "<a_i, x> >= 0" and the rational
 * point "vec" by v/d.
 * Let b_i = <a_i, v>.  Then the affine cone 'vec + cone' is given
 * by <a_i, x> - b/d >= 0.
 * The polyhedron <a_i, x> - ceil{b/d} >= 0 is a subset of this affine cone.
 * We prefer this polyhedron over the actual affine cone because it doesn't
 * require a scaling of the constraints.
 * If each of the vertices of the unit cube positioned at x lies inside
 * this polyhedron, then the whole unit cube at x lies inside the affine cone.
 * We therefore impose that x' = x + \sum e_i, for any selection of unit
 * vectors lies inside the polyhedron, i.e.,
 *
 *	<a_i, x'> - ceil{b/d} = <a_i, x> + sum a_i - ceil{b/d} >= 0
 *
 * The most stringent of these constraints is the one that selects
 * all negative a_i, so the polyhedron we are looking for has constraints
 *
 *	<a_i, x> + sum_{a_i < 0} a_i - ceil{b/d} >= 0
 *
 * Note that if cone were known to have only non-negative rays
 * (which can be accomplished by a unimodular transformation),
 * then we would only have to check the points x' = x + e_i
 * and we only have to add the smallest negative a_i (if any)
 * instead of the sum of all negative a_i.
 */
static __isl_give isl_basic_set *shift_cone(__isl_take isl_basic_set *cone,
	__isl_take isl_vec *vec)
{}

/* Given a rational point vec in a (transformed) basic set,
 * such that cone is the recession cone of the original basic set,
 * "round up" the rational point to an integer point.
 *
 * We first check if the rational point just happens to be integer.
 * If not, we transform the cone in the same way as the basic set,
 * pick a point x in this cone shifted to the rational point such that
 * the whole unit cube at x is also inside this affine cone.
 * Then we simply round up the coordinates of x and return the
 * resulting integer point.
 */
static __isl_give isl_vec *round_up_in_cone(__isl_take isl_vec *vec,
	__isl_take isl_basic_set *cone, __isl_take isl_mat *U)
{}

/* Concatenate two integer vectors, i.e., two vectors with denominator
 * (stored in element 0) equal to 1.
 */
static __isl_give isl_vec *vec_concat(__isl_take isl_vec *vec1,
	__isl_take isl_vec *vec2)
{}

/* Give a basic set "bset" with recession cone "cone", compute and
 * return an integer point in bset, if any.
 *
 * If the recession cone is full-dimensional, then we know that
 * bset contains an infinite number of integer points and it is
 * fairly easy to pick one of them.
 * If the recession cone is not full-dimensional, then we first
 * transform bset such that the bounded directions appear as
 * the first dimensions of the transformed basic set.
 * We do this by using a unimodular transformation that transforms
 * the equalities in the recession cone to equalities on the first
 * dimensions.
 *
 * The transformed set is then projected onto its bounded dimensions.
 * Note that to compute this projection, we can simply drop all constraints
 * involving any of the unbounded dimensions since these constraints
 * cannot be combined to produce a constraint on the bounded dimensions.
 * To see this, assume that there is such a combination of constraints
 * that produces a constraint on the bounded dimensions.  This means
 * that some combination of the unbounded dimensions has both an upper
 * bound and a lower bound in terms of the bounded dimensions, but then
 * this combination would be a bounded direction too and would have been
 * transformed into a bounded dimensions.
 *
 * We then compute a sample value in the bounded dimensions.
 * If no such value can be found, then the original set did not contain
 * any integer points and we are done.
 * Otherwise, we plug in the value we found in the bounded dimensions,
 * project out these bounded dimensions and end up with a set with
 * a full-dimensional recession cone.
 * A sample point in this set is computed by "rounding up" any
 * rational point in the set.
 *
 * The sample points in the bounded and unbounded dimensions are
 * then combined into a single sample point and transformed back
 * to the original space.
 */
__isl_give isl_vec *isl_basic_set_sample_with_cone(
	__isl_take isl_basic_set *bset, __isl_take isl_basic_set *cone)
{}

static void vec_sum_of_neg(__isl_keep isl_vec *v, isl_int *s)
{}

/* Given a tableau "tab", a tableau "tab_cone" that corresponds
 * to the recession cone and the inverse of a new basis U = inv(B),
 * with the unbounded directions in B last,
 * add constraints to "tab" that ensure any rational value
 * in the unbounded directions can be rounded up to an integer value.
 *
 * The new basis is given by x' = B x, i.e., x = U x'.
 * For any rational value of the last tab->n_unbounded coordinates
 * in the update tableau, the value that is obtained by rounding
 * up this value should be contained in the original tableau.
 * For any constraint "a x + c >= 0", we therefore need to add
 * a constraint "a x + c + s >= 0", with s the sum of all negative
 * entries in the last elements of "a U".
 *
 * Since we are not interested in the first entries of any of the "a U",
 * we first drop the columns of U that correpond to bounded directions.
 */
static int tab_shift_cone(struct isl_tab *tab,
	struct isl_tab *tab_cone, struct isl_mat *U)
{}

/* Compute and return an initial basis for the possibly
 * unbounded tableau "tab".  "tab_cone" is a tableau
 * for the corresponding recession cone.
 * Additionally, add constraints to "tab" that ensure
 * that any rational value for the unbounded directions
 * can be rounded up to an integer value.
 *
 * If the tableau is bounded, i.e., if the recession cone
 * is zero-dimensional, then we just use inital_basis.
 * Otherwise, we construct a basis whose first directions
 * correspond to equalities, followed by bounded directions,
 * i.e., equalities in the recession cone.
 * The remaining directions are then unbounded.
 */
int isl_tab_set_initial_basis_with_cone(struct isl_tab *tab,
	struct isl_tab *tab_cone)
{}

/* Compute and return a sample point in bset using generalized basis
 * reduction.  We first check if the input set has a non-trivial
 * recession cone.  If so, we perform some extra preprocessing in
 * sample_with_cone.  Otherwise, we directly perform generalized basis
 * reduction.
 */
static __isl_give isl_vec *gbr_sample(__isl_take isl_basic_set *bset)
{}

static __isl_give isl_vec *basic_set_sample(__isl_take isl_basic_set *bset,
	int bounded)
{}

__isl_give isl_vec *isl_basic_set_sample_vec(__isl_take isl_basic_set *bset)
{}

/* Compute an integer sample in "bset", where the caller guarantees
 * that "bset" is bounded.
 */
__isl_give isl_vec *isl_basic_set_sample_bounded(__isl_take isl_basic_set *bset)
{}

__isl_give isl_basic_set *isl_basic_set_from_vec(__isl_take isl_vec *vec)
{}

__isl_give isl_basic_map *isl_basic_map_sample(__isl_take isl_basic_map *bmap)
{}

__isl_give isl_basic_set *isl_basic_set_sample(__isl_take isl_basic_set *bset)
{}

__isl_give isl_basic_map *isl_map_sample(__isl_take isl_map *map)
{}

__isl_give isl_basic_set *isl_set_sample(__isl_take isl_set *set)
{}

__isl_give isl_point *isl_basic_set_sample_point(__isl_take isl_basic_set *bset)
{}

__isl_give isl_point *isl_set_sample_point(__isl_take isl_set *set)
{}