Home | History | Annotate | Line # | Download | only in dist
      1  1.1  mrg /*
      2  1.1  mrg  * Copyright 2010-2011 INRIA Saclay
      3  1.1  mrg  * Copyright 2012-2013 Ecole Normale Superieure
      4  1.1  mrg  *
      5  1.1  mrg  * Use of this software is governed by the MIT license
      6  1.1  mrg  *
      7  1.1  mrg  * Written by Sven Verdoolaege, INRIA Saclay - Ile-de-France,
      8  1.1  mrg  * Parc Club Orsay Universite, ZAC des vignes, 4 rue Jacques Monod,
      9  1.1  mrg  * 91893 Orsay, France
     10  1.1  mrg  * and Ecole Normale Superieure, 45 rue d'Ulm, 75230 Paris, France
     11  1.1  mrg  */
     12  1.1  mrg 
     13  1.1  mrg #include <isl/val.h>
     14  1.1  mrg #include <isl/space.h>
     15  1.1  mrg #include <isl_map_private.h>
     16  1.1  mrg #include <isl_aff_private.h>
     17  1.1  mrg #include <isl/constraint.h>
     18  1.1  mrg #include <isl/ilp.h>
     19  1.1  mrg #include <isl/fixed_box.h>
     20  1.1  mrg #include <isl/stream.h>
     21  1.1  mrg 
     22  1.1  mrg /* Representation of a box of fixed size containing the elements
     23  1.1  mrg  * [offset, offset + size).
     24  1.1  mrg  * "size" lives in the target space of "offset".
     25  1.1  mrg  *
     26  1.1  mrg  * If any of the "offsets" is NaN, then the object represents
     27  1.1  mrg  * the failure of finding a fixed-size box.
     28  1.1  mrg  */
     29  1.1  mrg struct isl_fixed_box {
     30  1.1  mrg 	isl_multi_aff *offset;
     31  1.1  mrg 	isl_multi_val *size;
     32  1.1  mrg };
     33  1.1  mrg 
     34  1.1  mrg /* Free "box" and return NULL.
     35  1.1  mrg  */
     36  1.1  mrg __isl_null isl_fixed_box *isl_fixed_box_free(__isl_take isl_fixed_box *box)
     37  1.1  mrg {
     38  1.1  mrg 	if (!box)
     39  1.1  mrg 		return NULL;
     40  1.1  mrg 	isl_multi_aff_free(box->offset);
     41  1.1  mrg 	isl_multi_val_free(box->size);
     42  1.1  mrg 	free(box);
     43  1.1  mrg 	return NULL;
     44  1.1  mrg }
     45  1.1  mrg 
     46  1.1  mrg /* Construct an isl_fixed_box with the given offset and size.
     47  1.1  mrg  */
     48  1.1  mrg static __isl_give isl_fixed_box *isl_fixed_box_alloc(
     49  1.1  mrg 	__isl_take isl_multi_aff *offset, __isl_take isl_multi_val *size)
     50  1.1  mrg {
     51  1.1  mrg 	isl_ctx *ctx;
     52  1.1  mrg 	isl_fixed_box *box;
     53  1.1  mrg 
     54  1.1  mrg 	if (!offset || !size)
     55  1.1  mrg 		goto error;
     56  1.1  mrg 	ctx = isl_multi_aff_get_ctx(offset);
     57  1.1  mrg 	box = isl_alloc_type(ctx, struct isl_fixed_box);
     58  1.1  mrg 	if (!box)
     59  1.1  mrg 		goto error;
     60  1.1  mrg 	box->offset = offset;
     61  1.1  mrg 	box->size = size;
     62  1.1  mrg 
     63  1.1  mrg 	return box;
     64  1.1  mrg error:
     65  1.1  mrg 	isl_multi_aff_free(offset);
     66  1.1  mrg 	isl_multi_val_free(size);
     67  1.1  mrg 	return NULL;
     68  1.1  mrg }
     69  1.1  mrg 
     70  1.1  mrg /* Construct an initial isl_fixed_box with zero offsets
     71  1.1  mrg  * in the given space and zero corresponding sizes.
     72  1.1  mrg  */
     73  1.1  mrg static __isl_give isl_fixed_box *isl_fixed_box_init(
     74  1.1  mrg 	__isl_take isl_space *space)
     75  1.1  mrg {
     76  1.1  mrg 	isl_multi_aff *offset;
     77  1.1  mrg 	isl_multi_val *size;
     78  1.1  mrg 
     79  1.1  mrg 	offset = isl_multi_aff_zero(isl_space_copy(space));
     80  1.1  mrg 	space = isl_space_drop_all_params(isl_space_range(space));
     81  1.1  mrg 	size = isl_multi_val_zero(space);
     82  1.1  mrg 	return isl_fixed_box_alloc(offset, size);
     83  1.1  mrg }
     84  1.1  mrg 
     85  1.1  mrg /* Return a copy of "box".
     86  1.1  mrg  */
     87  1.1  mrg __isl_give isl_fixed_box *isl_fixed_box_copy(__isl_keep isl_fixed_box *box)
     88  1.1  mrg {
     89  1.1  mrg 	isl_multi_aff *offset;
     90  1.1  mrg 	isl_multi_val *size;
     91  1.1  mrg 
     92  1.1  mrg 	offset = isl_fixed_box_get_offset(box);
     93  1.1  mrg 	size = isl_fixed_box_get_size(box);
     94  1.1  mrg 	return isl_fixed_box_alloc(offset, size);
     95  1.1  mrg }
     96  1.1  mrg 
     97  1.1  mrg /* Replace the offset and size in direction "pos" by "offset" and "size"
     98  1.1  mrg  * (without checking whether "box" is a valid box).
     99  1.1  mrg  */
    100  1.1  mrg static __isl_give isl_fixed_box *isl_fixed_box_set_extent(
    101  1.1  mrg 	__isl_take isl_fixed_box *box, int pos, __isl_keep isl_aff *offset,
    102  1.1  mrg 	__isl_keep isl_val *size)
    103  1.1  mrg {
    104  1.1  mrg 	if (!box)
    105  1.1  mrg 		return NULL;
    106  1.1  mrg 	box->offset = isl_multi_aff_set_aff(box->offset, pos,
    107  1.1  mrg 							isl_aff_copy(offset));
    108  1.1  mrg 	box->size = isl_multi_val_set_val(box->size, pos, isl_val_copy(size));
    109  1.1  mrg 	if (!box->offset || !box->size)
    110  1.1  mrg 		return isl_fixed_box_free(box);
    111  1.1  mrg 	return box;
    112  1.1  mrg }
    113  1.1  mrg 
    114  1.1  mrg /* Replace the offset and size in direction "pos" by "offset" and "size",
    115  1.1  mrg  * if "box" is a valid box.
    116  1.1  mrg  */
    117  1.1  mrg static __isl_give isl_fixed_box *isl_fixed_box_set_valid_extent(
    118  1.1  mrg 	__isl_take isl_fixed_box *box, int pos, __isl_keep isl_aff *offset,
    119  1.1  mrg 	__isl_keep isl_val *size)
    120  1.1  mrg {
    121  1.1  mrg 	isl_bool valid;
    122  1.1  mrg 
    123  1.1  mrg 	valid = isl_fixed_box_is_valid(box);
    124  1.1  mrg 	if (valid < 0 || !valid)
    125  1.1  mrg 		return box;
    126  1.1  mrg 	return isl_fixed_box_set_extent(box, pos, offset, size);
    127  1.1  mrg }
    128  1.1  mrg 
    129  1.1  mrg /* Replace "box" by an invalid box, by setting all offsets to NaN
    130  1.1  mrg  * (and all sizes to infinity).
    131  1.1  mrg  */
    132  1.1  mrg static __isl_give isl_fixed_box *isl_fixed_box_invalidate(
    133  1.1  mrg 	__isl_take isl_fixed_box *box)
    134  1.1  mrg {
    135  1.1  mrg 	int i;
    136  1.1  mrg 	isl_size n;
    137  1.1  mrg 	isl_space *space;
    138  1.1  mrg 	isl_val *infty;
    139  1.1  mrg 	isl_aff *nan;
    140  1.1  mrg 
    141  1.1  mrg 	if (!box)
    142  1.1  mrg 		return NULL;
    143  1.1  mrg 	n = isl_multi_val_dim(box->size, isl_dim_set);
    144  1.1  mrg 	if (n < 0)
    145  1.1  mrg 		return isl_fixed_box_free(box);
    146  1.1  mrg 
    147  1.1  mrg 	infty = isl_val_infty(isl_fixed_box_get_ctx(box));
    148  1.1  mrg 	space = isl_space_domain(isl_fixed_box_get_space(box));
    149  1.1  mrg 	nan = isl_aff_nan_on_domain(isl_local_space_from_space(space));
    150  1.1  mrg 	for (i = 0; i < n; ++i)
    151  1.1  mrg 		box = isl_fixed_box_set_extent(box, i, nan, infty);
    152  1.1  mrg 	isl_aff_free(nan);
    153  1.1  mrg 	isl_val_free(infty);
    154  1.1  mrg 
    155  1.1  mrg 	if (!box->offset || !box->size)
    156  1.1  mrg 		return isl_fixed_box_free(box);
    157  1.1  mrg 	return box;
    158  1.1  mrg }
    159  1.1  mrg 
    160  1.1  mrg /* Project the domain of the fixed box onto its parameter space.
    161  1.1  mrg  * In particular, project out the domain of the offset.
    162  1.1  mrg  */
    163  1.1  mrg static __isl_give isl_fixed_box *isl_fixed_box_project_domain_on_params(
    164  1.1  mrg 	__isl_take isl_fixed_box *box)
    165  1.1  mrg {
    166  1.1  mrg 	isl_bool valid;
    167  1.1  mrg 
    168  1.1  mrg 	valid = isl_fixed_box_is_valid(box);
    169  1.1  mrg 	if (valid < 0)
    170  1.1  mrg 		return isl_fixed_box_free(box);
    171  1.1  mrg 	if (!valid)
    172  1.1  mrg 		return box;
    173  1.1  mrg 
    174  1.1  mrg 	box->offset = isl_multi_aff_project_domain_on_params(box->offset);
    175  1.1  mrg 	if (!box->offset)
    176  1.1  mrg 		return isl_fixed_box_free(box);
    177  1.1  mrg 
    178  1.1  mrg 	return box;
    179  1.1  mrg }
    180  1.1  mrg 
    181  1.1  mrg /* Return the isl_ctx to which "box" belongs.
    182  1.1  mrg  */
    183  1.1  mrg isl_ctx *isl_fixed_box_get_ctx(__isl_keep isl_fixed_box *box)
    184  1.1  mrg {
    185  1.1  mrg 	if (!box)
    186  1.1  mrg 		return NULL;
    187  1.1  mrg 	return isl_multi_aff_get_ctx(box->offset);
    188  1.1  mrg }
    189  1.1  mrg 
    190  1.1  mrg /* Return the space in which "box" lives.
    191  1.1  mrg  */
    192  1.1  mrg __isl_give isl_space *isl_fixed_box_get_space(__isl_keep isl_fixed_box *box)
    193  1.1  mrg {
    194  1.1  mrg 	if (!box)
    195  1.1  mrg 		return NULL;
    196  1.1  mrg 	return isl_multi_aff_get_space(box->offset);
    197  1.1  mrg }
    198  1.1  mrg 
    199  1.1  mrg /* Does "box" contain valid information?
    200  1.1  mrg  */
    201  1.1  mrg isl_bool isl_fixed_box_is_valid(__isl_keep isl_fixed_box *box)
    202  1.1  mrg {
    203  1.1  mrg 	if (!box)
    204  1.1  mrg 		return isl_bool_error;
    205  1.1  mrg 	return isl_bool_not(isl_multi_aff_involves_nan(box->offset));
    206  1.1  mrg }
    207  1.1  mrg 
    208  1.1  mrg /* Return the offsets of the box "box".
    209  1.1  mrg  */
    210  1.1  mrg __isl_give isl_multi_aff *isl_fixed_box_get_offset(
    211  1.1  mrg 	__isl_keep isl_fixed_box *box)
    212  1.1  mrg {
    213  1.1  mrg 	if (!box)
    214  1.1  mrg 		return NULL;
    215  1.1  mrg 	return isl_multi_aff_copy(box->offset);
    216  1.1  mrg }
    217  1.1  mrg 
    218  1.1  mrg /* Return the sizes of the box "box".
    219  1.1  mrg  */
    220  1.1  mrg __isl_give isl_multi_val *isl_fixed_box_get_size(__isl_keep isl_fixed_box *box)
    221  1.1  mrg {
    222  1.1  mrg 	if (!box)
    223  1.1  mrg 		return NULL;
    224  1.1  mrg 	return isl_multi_val_copy(box->size);
    225  1.1  mrg }
    226  1.1  mrg 
    227  1.1  mrg /* Data used in set_dim_extent and compute_size_in_direction.
    228  1.1  mrg  *
    229  1.1  mrg  * "bset" is a wrapped copy of the basic map that has the selected
    230  1.1  mrg  * output dimension as range.
    231  1.1  mrg  * "pos" is the position of the variable representing the output dimension,
    232  1.1  mrg  * i.e., the variable for which the size should be computed.  This variable
    233  1.1  mrg  * is also the last variable in "bset".
    234  1.1  mrg  * "size" is the best size found so far
    235  1.1  mrg  * (infinity if no offset was found so far).
    236  1.1  mrg  * "offset" is the offset corresponding to the best size
    237  1.1  mrg  * (NULL if no offset was found so far).
    238  1.1  mrg  */
    239  1.1  mrg struct isl_size_info {
    240  1.1  mrg 	isl_basic_set *bset;
    241  1.1  mrg 	isl_size pos;
    242  1.1  mrg 	isl_val *size;
    243  1.1  mrg 	isl_aff *offset;
    244  1.1  mrg };
    245  1.1  mrg 
    246  1.1  mrg /* Is "c" a suitable bound on dimension "pos" for use as a lower bound
    247  1.1  mrg  * of a fixed-size range.
    248  1.1  mrg  * In particular, it needs to be a lower bound on "pos".
    249  1.1  mrg  * In order for the final offset not to be too complicated,
    250  1.1  mrg  * the constraint itself should also not involve any integer divisions.
    251  1.1  mrg  */
    252  1.1  mrg static isl_bool is_suitable_bound(__isl_keep isl_constraint *c, unsigned pos)
    253  1.1  mrg {
    254  1.1  mrg 	isl_size n_div;
    255  1.1  mrg 	isl_bool is_bound, any_divs;
    256  1.1  mrg 
    257  1.1  mrg 	is_bound = isl_constraint_is_lower_bound(c, isl_dim_set, pos);
    258  1.1  mrg 	if (is_bound < 0 || !is_bound)
    259  1.1  mrg 		return is_bound;
    260  1.1  mrg 
    261  1.1  mrg 	n_div = isl_constraint_dim(c, isl_dim_div);
    262  1.1  mrg 	if (n_div < 0)
    263  1.1  mrg 		return isl_bool_error;
    264  1.1  mrg 	any_divs = isl_constraint_involves_dims(c, isl_dim_div, 0, n_div);
    265  1.1  mrg 	return isl_bool_not(any_divs);
    266  1.1  mrg }
    267  1.1  mrg 
    268  1.1  mrg /* Given a constraint from the basic set describing the bounds on
    269  1.1  mrg  * an array index, check if it is a lower bound, say m i >= b(x), and,
    270  1.1  mrg  * if so, check whether the expression "i - ceil(b(x)/m) + 1" has a constant
    271  1.1  mrg  * upper bound.  If so, and if this bound is smaller than any bound
    272  1.1  mrg  * derived from earlier constraints, set the size to this bound on
    273  1.1  mrg  * the expression and the lower bound to ceil(b(x)/m).
    274  1.1  mrg  */
    275  1.1  mrg static isl_stat compute_size_in_direction(__isl_take isl_constraint *c,
    276  1.1  mrg 	void *user)
    277  1.1  mrg {
    278  1.1  mrg 	struct isl_size_info *info = user;
    279  1.1  mrg 	isl_val *v;
    280  1.1  mrg 	isl_aff *aff;
    281  1.1  mrg 	isl_aff *lb;
    282  1.1  mrg 	isl_bool is_bound, better;
    283  1.1  mrg 
    284  1.1  mrg 	is_bound = is_suitable_bound(c, info->pos);
    285  1.1  mrg 	if (is_bound < 0 || !is_bound) {
    286  1.1  mrg 		isl_constraint_free(c);
    287  1.1  mrg 		return is_bound < 0 ? isl_stat_error : isl_stat_ok;
    288  1.1  mrg 	}
    289  1.1  mrg 
    290  1.1  mrg 	aff = isl_constraint_get_bound(c, isl_dim_set, info->pos);
    291  1.1  mrg 	aff = isl_aff_ceil(aff);
    292  1.1  mrg 
    293  1.1  mrg 	lb = isl_aff_copy(aff);
    294  1.1  mrg 
    295  1.1  mrg 	aff = isl_aff_neg(aff);
    296  1.1  mrg 	aff = isl_aff_add_coefficient_si(aff, isl_dim_in, info->pos, 1);
    297  1.1  mrg 
    298  1.1  mrg 	v = isl_basic_set_max_val(info->bset, aff);
    299  1.1  mrg 	isl_aff_free(aff);
    300  1.1  mrg 
    301  1.1  mrg 	v = isl_val_add_ui(v, 1);
    302  1.1  mrg 	better = isl_val_lt(v, info->size);
    303  1.1  mrg 	if (better >= 0 && better) {
    304  1.1  mrg 		isl_val_free(info->size);
    305  1.1  mrg 		info->size = isl_val_copy(v);
    306  1.1  mrg 		lb = isl_aff_domain_factor_domain(lb);
    307  1.1  mrg 		isl_aff_free(info->offset);
    308  1.1  mrg 		info->offset = isl_aff_copy(lb);
    309  1.1  mrg 	}
    310  1.1  mrg 	isl_val_free(v);
    311  1.1  mrg 	isl_aff_free(lb);
    312  1.1  mrg 
    313  1.1  mrg 	isl_constraint_free(c);
    314  1.1  mrg 
    315  1.1  mrg 	return better < 0 ? isl_stat_error : isl_stat_ok;
    316  1.1  mrg }
    317  1.1  mrg 
    318  1.1  mrg /* Look for a fixed-size range of values for the output dimension "pos"
    319  1.1  mrg  * of "map", by looking for a lower-bound expression in the parameters
    320  1.1  mrg  * and input dimensions such that the range of the output dimension
    321  1.1  mrg  * is a constant shifted by this expression.
    322  1.1  mrg  *
    323  1.1  mrg  * In particular, look through the explicit lower bounds on the output dimension
    324  1.1  mrg  * for candidate expressions and pick the one that results in the smallest size.
    325  1.1  mrg  * Initialize the size with infinity and if no better size is found
    326  1.1  mrg  * then invalidate the box.  Otherwise, set the offset and size
    327  1.1  mrg  * in the given direction by those that correspond to the smallest size.
    328  1.1  mrg  *
    329  1.1  mrg  * Note that while evaluating the size corresponding to a lower bound,
    330  1.1  mrg  * an affine expression is constructed from the lower bound.
    331  1.1  mrg  * This lower bound may therefore not have any unknown local variables.
    332  1.1  mrg  * Eliminate any unknown local variables up front.
    333  1.1  mrg  * No such restriction needs to be imposed on the set over which
    334  1.1  mrg  * the size is computed.
    335  1.1  mrg  */
    336  1.1  mrg static __isl_give isl_fixed_box *set_dim_extent(__isl_take isl_fixed_box *box,
    337  1.1  mrg 	__isl_keep isl_map *map, int pos)
    338  1.1  mrg {
    339  1.1  mrg 	struct isl_size_info info;
    340  1.1  mrg 	isl_bool valid;
    341  1.1  mrg 	isl_ctx *ctx;
    342  1.1  mrg 	isl_basic_set *bset;
    343  1.1  mrg 
    344  1.1  mrg 	if (!box || !map)
    345  1.1  mrg 		return isl_fixed_box_free(box);
    346  1.1  mrg 
    347  1.1  mrg 	ctx = isl_map_get_ctx(map);
    348  1.1  mrg 	map = isl_map_copy(map);
    349  1.1  mrg 	map = isl_map_project_onto(map, isl_dim_out, pos, 1);
    350  1.1  mrg 	info.size = isl_val_infty(ctx);
    351  1.1  mrg 	info.offset = NULL;
    352  1.1  mrg 	info.pos = isl_map_dim(map, isl_dim_in);
    353  1.1  mrg 	info.bset = isl_basic_map_wrap(isl_map_simple_hull(map));
    354  1.1  mrg 	bset = isl_basic_set_copy(info.bset);
    355  1.1  mrg 	bset = isl_basic_set_remove_unknown_divs(bset);
    356  1.1  mrg 	if (info.pos < 0)
    357  1.1  mrg 		bset = isl_basic_set_free(bset);
    358  1.1  mrg 	if (isl_basic_set_foreach_constraint(bset,
    359  1.1  mrg 					&compute_size_in_direction, &info) < 0)
    360  1.1  mrg 		box = isl_fixed_box_free(box);
    361  1.1  mrg 	isl_basic_set_free(bset);
    362  1.1  mrg 	valid = isl_val_is_int(info.size);
    363  1.1  mrg 	if (valid < 0)
    364  1.1  mrg 		box = isl_fixed_box_free(box);
    365  1.1  mrg 	else if (valid)
    366  1.1  mrg 		box = isl_fixed_box_set_valid_extent(box, pos,
    367  1.1  mrg 						     info.offset, info.size);
    368  1.1  mrg 	else
    369  1.1  mrg 		box = isl_fixed_box_invalidate(box);
    370  1.1  mrg 	isl_val_free(info.size);
    371  1.1  mrg 	isl_aff_free(info.offset);
    372  1.1  mrg 	isl_basic_set_free(info.bset);
    373  1.1  mrg 
    374  1.1  mrg 	return box;
    375  1.1  mrg }
    376  1.1  mrg 
    377  1.1  mrg /* Try and construct a fixed-size rectangular box with an offset
    378  1.1  mrg  * in terms of the domain of "map" that contains the range of "map".
    379  1.1  mrg  * If no such box can be constructed, then return an invalidated box,
    380  1.1  mrg  * i.e., one where isl_fixed_box_is_valid returns false.
    381  1.1  mrg  *
    382  1.1  mrg  * Iterate over the dimensions in the range
    383  1.1  mrg  * setting the corresponding offset and extent.
    384  1.1  mrg  */
    385  1.1  mrg __isl_give isl_fixed_box *isl_map_get_range_simple_fixed_box_hull(
    386  1.1  mrg 	__isl_keep isl_map *map)
    387  1.1  mrg {
    388  1.1  mrg 	int i;
    389  1.1  mrg 	isl_size n;
    390  1.1  mrg 	isl_space *space;
    391  1.1  mrg 	isl_fixed_box *box;
    392  1.1  mrg 
    393  1.1  mrg 	n = isl_map_dim(map, isl_dim_out);
    394  1.1  mrg 	if (n < 0)
    395  1.1  mrg 		return NULL;
    396  1.1  mrg 	space = isl_map_get_space(map);
    397  1.1  mrg 	box = isl_fixed_box_init(space);
    398  1.1  mrg 
    399  1.1  mrg 	map = isl_map_detect_equalities(isl_map_copy(map));
    400  1.1  mrg 	for (i = 0; i < n; ++i) {
    401  1.1  mrg 		isl_bool valid;
    402  1.1  mrg 
    403  1.1  mrg 		box = set_dim_extent(box, map, i);
    404  1.1  mrg 		valid = isl_fixed_box_is_valid(box);
    405  1.1  mrg 		if (valid < 0 || !valid)
    406  1.1  mrg 			break;
    407  1.1  mrg 	}
    408  1.1  mrg 	isl_map_free(map);
    409  1.1  mrg 
    410  1.1  mrg 	return box;
    411  1.1  mrg }
    412  1.1  mrg 
    413  1.1  mrg /* Compute a fixed box from "set" using "map_box" by treating it as a map
    414  1.1  mrg  * with a zero-dimensional domain and
    415  1.1  mrg  * project out the domain again from the result.
    416  1.1  mrg  */
    417  1.1  mrg static __isl_give isl_fixed_box *fixed_box_as_map(__isl_keep isl_set *set,
    418  1.1  mrg 	__isl_give isl_fixed_box *(*map_box)(__isl_keep isl_map *map))
    419  1.1  mrg {
    420  1.1  mrg 	isl_map *map;
    421  1.1  mrg 	isl_fixed_box *box;
    422  1.1  mrg 
    423  1.1  mrg 	map = isl_map_from_range(isl_set_copy(set));
    424  1.1  mrg 	box = map_box(map);
    425  1.1  mrg 	isl_map_free(map);
    426  1.1  mrg 	box = isl_fixed_box_project_domain_on_params(box);
    427  1.1  mrg 
    428  1.1  mrg 	return box;
    429  1.1  mrg }
    430  1.1  mrg 
    431  1.1  mrg /* Try and construct a fixed-size rectangular box with an offset
    432  1.1  mrg  * in terms of the parameters of "set" that contains "set".
    433  1.1  mrg  * If no such box can be constructed, then return an invalidated box,
    434  1.1  mrg  * i.e., one where isl_fixed_box_is_valid returns false.
    435  1.1  mrg  *
    436  1.1  mrg  * Compute the box using isl_map_get_range_simple_fixed_box_hull
    437  1.1  mrg  * by constructing a map from the set and
    438  1.1  mrg  * project out the domain again from the result.
    439  1.1  mrg  */
    440  1.1  mrg __isl_give isl_fixed_box *isl_set_get_simple_fixed_box_hull(
    441  1.1  mrg 	__isl_keep isl_set *set)
    442  1.1  mrg {
    443  1.1  mrg 	return fixed_box_as_map(set, &isl_map_get_range_simple_fixed_box_hull);
    444  1.1  mrg }
    445  1.1  mrg 
    446  1.1  mrg /* Check whether the output elements lie on a rectangular lattice,
    447  1.1  mrg  * possibly depending on the parameters and the input dimensions.
    448  1.1  mrg  * Return a tile in this lattice.
    449  1.1  mrg  * If no stride information can be found, then return a tile of size 1
    450  1.1  mrg  * (and offset 0).
    451  1.1  mrg  *
    452  1.1  mrg  * Obtain stride information in each output dimension separately and
    453  1.1  mrg  * combine the results.
    454  1.1  mrg  */
    455  1.1  mrg __isl_give isl_fixed_box *isl_map_get_range_lattice_tile(
    456  1.1  mrg 	__isl_keep isl_map *map)
    457  1.1  mrg {
    458  1.1  mrg 	int i;
    459  1.1  mrg 	isl_size n;
    460  1.1  mrg 	isl_space *space;
    461  1.1  mrg 	isl_fixed_box *box;
    462  1.1  mrg 
    463  1.1  mrg 	n = isl_map_dim(map, isl_dim_out);
    464  1.1  mrg 	if (n < 0)
    465  1.1  mrg 		return NULL;
    466  1.1  mrg 	space = isl_map_get_space(map);
    467  1.1  mrg 	box = isl_fixed_box_init(space);
    468  1.1  mrg 
    469  1.1  mrg 	for (i = 0; i < n; ++i) {
    470  1.1  mrg 		isl_val *stride;
    471  1.1  mrg 		isl_aff *offset;
    472  1.1  mrg 		isl_stride_info *si;
    473  1.1  mrg 
    474  1.1  mrg 		si = isl_map_get_range_stride_info(map, i);
    475  1.1  mrg 		stride = isl_stride_info_get_stride(si);
    476  1.1  mrg 		offset = isl_stride_info_get_offset(si);
    477  1.1  mrg 		isl_stride_info_free(si);
    478  1.1  mrg 
    479  1.1  mrg 		box = isl_fixed_box_set_valid_extent(box, i, offset, stride);
    480  1.1  mrg 
    481  1.1  mrg 		isl_aff_free(offset);
    482  1.1  mrg 		isl_val_free(stride);
    483  1.1  mrg 	}
    484  1.1  mrg 
    485  1.1  mrg 	return box;
    486  1.1  mrg }
    487  1.1  mrg 
    488  1.1  mrg /* Check whether the elements lie on a rectangular lattice,
    489  1.1  mrg  * possibly depending on the parameters.
    490  1.1  mrg  * Return a tile in this lattice.
    491  1.1  mrg  * If no stride information can be found, then return a tile of size 1
    492  1.1  mrg  * (and offset 0).
    493  1.1  mrg  *
    494  1.1  mrg  * Consider the set as a map with a zero-dimensional domain and
    495  1.1  mrg  * obtain a lattice tile of that map.
    496  1.1  mrg  */
    497  1.1  mrg __isl_give isl_fixed_box *isl_set_get_lattice_tile(__isl_keep isl_set *set)
    498  1.1  mrg {
    499  1.1  mrg 	return fixed_box_as_map(set, &isl_map_get_range_lattice_tile);
    500  1.1  mrg }
    501  1.1  mrg 
    502  1.1  mrg /* An enumeration of the keys that may appear in a YAML mapping
    503  1.1  mrg  * of an isl_fixed_box object.
    504  1.1  mrg  */
    505  1.1  mrg enum isl_fb_key {
    506  1.1  mrg 	isl_fb_key_error = -1,
    507  1.1  mrg 	isl_fb_key_offset,
    508  1.1  mrg 	isl_fb_key_size,
    509  1.1  mrg 	isl_fb_key_end,
    510  1.1  mrg };
    511  1.1  mrg 
    512  1.1  mrg /* Textual representations of the YAML keys for an isl_fixed_box object.
    513  1.1  mrg  */
    514  1.1  mrg static char *key_str[] = {
    515  1.1  mrg 	[isl_fb_key_offset] = "offset",
    516  1.1  mrg 	[isl_fb_key_size] = "size",
    517  1.1  mrg };
    518  1.1  mrg 
    519  1.1  mrg #undef BASE
    520  1.1  mrg #define BASE multi_val
    521  1.1  mrg #include "print_yaml_field_templ.c"
    522  1.1  mrg 
    523  1.1  mrg #undef BASE
    524  1.1  mrg #define BASE multi_aff
    525  1.1  mrg #include "print_yaml_field_templ.c"
    526  1.1  mrg 
    527  1.1  mrg /* Print the information contained in "box" to "p".
    528  1.1  mrg  * The information is printed as a YAML document.
    529  1.1  mrg  */
    530  1.1  mrg __isl_give isl_printer *isl_printer_print_fixed_box(
    531  1.1  mrg 	__isl_take isl_printer *p, __isl_keep isl_fixed_box *box)
    532  1.1  mrg {
    533  1.1  mrg 	if (!box)
    534  1.1  mrg 		return isl_printer_free(p);
    535  1.1  mrg 
    536  1.1  mrg 	p = isl_printer_yaml_start_mapping(p);
    537  1.1  mrg 	p = print_yaml_field_multi_aff(p, key_str[isl_fb_key_offset],
    538  1.1  mrg 					box->offset);
    539  1.1  mrg 	p = print_yaml_field_multi_val(p, key_str[isl_fb_key_size], box->size);
    540  1.1  mrg 	p = isl_printer_yaml_end_mapping(p);
    541  1.1  mrg 
    542  1.1  mrg 	return p;
    543  1.1  mrg }
    544  1.1  mrg 
    545  1.1  mrg #undef BASE
    546  1.1  mrg #define BASE fixed_box
    547  1.1  mrg #include <print_templ_yaml.c>
    548  1.1  mrg 
    549  1.1  mrg #undef KEY
    550  1.1  mrg #define KEY enum isl_fb_key
    551  1.1  mrg #undef KEY_ERROR
    552  1.1  mrg #define KEY_ERROR isl_fb_key_error
    553  1.1  mrg #undef KEY_END
    554  1.1  mrg #define KEY_END isl_fb_key_end
    555  1.1  mrg #undef KEY_STR
    556  1.1  mrg #define KEY_STR key_str
    557  1.1  mrg #undef KEY_EXTRACT
    558  1.1  mrg #define KEY_EXTRACT extract_key
    559  1.1  mrg #undef KEY_GET
    560  1.1  mrg #define KEY_GET get_key
    561  1.1  mrg #include "extract_key.c"
    562  1.1  mrg 
    563  1.1  mrg #undef BASE
    564  1.1  mrg #define BASE multi_val
    565  1.1  mrg #include "read_in_string_templ.c"
    566  1.1  mrg 
    567  1.1  mrg #undef BASE
    568  1.1  mrg #define BASE multi_aff
    569  1.1  mrg #include "read_in_string_templ.c"
    570  1.1  mrg 
    571  1.1  mrg /* Read an isl_fixed_box object from "s".
    572  1.1  mrg  *
    573  1.1  mrg  * The input needs to contain both an offset and a size.
    574  1.1  mrg  * If either is specified multiple times, then the last specification
    575  1.1  mrg  * overrides all previous ones.  This is simpler than checking
    576  1.1  mrg  * that each is only specified once.
    577  1.1  mrg  */
    578  1.1  mrg static __isl_give isl_fixed_box *isl_stream_read_fixed_box(isl_stream *s)
    579  1.1  mrg {
    580  1.1  mrg 	isl_bool more;
    581  1.1  mrg 	isl_multi_aff *offset = NULL;
    582  1.1  mrg 	isl_multi_val *size = NULL;
    583  1.1  mrg 
    584  1.1  mrg 	if (isl_stream_yaml_read_start_mapping(s) < 0)
    585  1.1  mrg 		return NULL;
    586  1.1  mrg 
    587  1.1  mrg 	while ((more = isl_stream_yaml_next(s)) == isl_bool_true) {
    588  1.1  mrg 		enum isl_fb_key key;
    589  1.1  mrg 
    590  1.1  mrg 		key = get_key(s);
    591  1.1  mrg 		if (isl_stream_yaml_next(s) < 0)
    592  1.1  mrg 			goto error;
    593  1.1  mrg 		switch (key) {
    594  1.1  mrg 		case isl_fb_key_end:
    595  1.1  mrg 		case isl_fb_key_error:
    596  1.1  mrg 			goto error;
    597  1.1  mrg 		case isl_fb_key_offset:
    598  1.1  mrg 			isl_multi_aff_free(offset);
    599  1.1  mrg 			offset = read_multi_aff(s);
    600  1.1  mrg 			if (!offset)
    601  1.1  mrg 				goto error;
    602  1.1  mrg 			break;
    603  1.1  mrg 		case isl_fb_key_size:
    604  1.1  mrg 			isl_multi_val_free(size);
    605  1.1  mrg 			size = read_multi_val(s);
    606  1.1  mrg 			if (!size)
    607  1.1  mrg 				goto error;
    608  1.1  mrg 			break;
    609  1.1  mrg 		}
    610  1.1  mrg 	}
    611  1.1  mrg 	if (more < 0)
    612  1.1  mrg 		goto error;
    613  1.1  mrg 
    614  1.1  mrg 	if (isl_stream_yaml_read_end_mapping(s) < 0)
    615  1.1  mrg 		goto error;
    616  1.1  mrg 
    617  1.1  mrg 	if (!offset) {
    618  1.1  mrg 		isl_stream_error(s, NULL, "no offset specified");
    619  1.1  mrg 		goto error;
    620  1.1  mrg 	}
    621  1.1  mrg 
    622  1.1  mrg 	if (!size) {
    623  1.1  mrg 		isl_stream_error(s, NULL, "no size specified");
    624  1.1  mrg 		goto error;
    625  1.1  mrg 	}
    626  1.1  mrg 
    627  1.1  mrg 	return isl_fixed_box_alloc(offset, size);
    628  1.1  mrg error:
    629  1.1  mrg 	isl_multi_aff_free(offset);
    630  1.1  mrg 	isl_multi_val_free(size);
    631  1.1  mrg 	return NULL;
    632  1.1  mrg }
    633  1.1  mrg 
    634  1.1  mrg #undef TYPE_BASE
    635  1.1  mrg #define TYPE_BASE	fixed_box
    636  1.1  mrg #include "isl_read_from_str_templ.c"
    637