Home | History | Annotate | Line # | Download | only in dist
      1 /*
      2  * Copyright 2010-2011 INRIA Saclay
      3  * Copyright 2011      Sven Verdoolaege
      4  * Copyright 2012-2014 Ecole Normale Superieure
      5  *
      6  * Use of this software is governed by the MIT license
      7  *
      8  * Written by Sven Verdoolaege, INRIA Saclay - Ile-de-France,
      9  * Parc Club Orsay Universite, ZAC des vignes, 4 rue Jacques Monod,
     10  * 91893 Orsay, France
     11  * and Ecole Normale Superieure, 45 rue dUlm, 75230 Paris, France
     12  */
     13 
     14 #include <isl/id.h>
     15 #include <isl/aff.h>
     16 #include <isl_sort.h>
     17 #include <isl_val_private.h>
     18 
     19 #include <isl_pw_macro.h>
     20 
     21 #include "opt_type.h"
     22 
     23 __isl_give PW *FN(PW,alloc_size)(__isl_take isl_space *space
     24 	OPT_TYPE_PARAM, int n)
     25 {
     26 	isl_ctx *ctx;
     27 	struct PW *pw;
     28 
     29 	if (!space)
     30 		return NULL;
     31 	ctx = isl_space_get_ctx(space);
     32 	isl_assert(ctx, n >= 0, goto error);
     33 	pw = isl_alloc(ctx, struct PW,
     34 			sizeof(struct PW) + (n - 1) * sizeof(S(PW,piece)));
     35 	if (!pw)
     36 		goto error;
     37 
     38 	pw->ref = 1;
     39 	OPT_SET_TYPE(pw->, type);
     40 	pw->size = n;
     41 	pw->n = 0;
     42 	pw->dim = space;
     43 	return pw;
     44 error:
     45 	isl_space_free(space);
     46 	return NULL;
     47 }
     48 
     49 __isl_give PW *FN(PW,ZERO)(__isl_take isl_space *space OPT_TYPE_PARAM)
     50 {
     51 	return FN(PW,alloc_size)(space OPT_TYPE_ARG(NO_LOC), 0);
     52 }
     53 
     54 /* Add a piece with domain "set" and base expression "el"
     55  * to the piecewise expression "pw".
     56  *
     57  * Do this independently of the values of "set" and "el",
     58  * such that this function can be used by isl_pw_*_dup.
     59  */
     60 static __isl_give PW *FN(PW,add_dup_piece)(__isl_take PW *pw,
     61 	__isl_take isl_set *set, __isl_take EL *el)
     62 {
     63 	isl_ctx *ctx;
     64 	isl_space *el_dim = NULL;
     65 
     66 	if (!pw || !set || !el)
     67 		goto error;
     68 
     69 	ctx = isl_set_get_ctx(set);
     70 	if (!OPT_EQUAL_TYPES(pw->, el->))
     71 		isl_die(ctx, isl_error_invalid, "fold types don't match",
     72 			goto error);
     73 	el_dim = FN(EL,get_space(el));
     74 	isl_assert(ctx, isl_space_is_equal(pw->dim, el_dim), goto error);
     75 	isl_assert(ctx, pw->n < pw->size, goto error);
     76 
     77 	pw->p[pw->n].set = set;
     78 	pw->p[pw->n].FIELD = el;
     79 	pw->n++;
     80 
     81 	isl_space_free(el_dim);
     82 	return pw;
     83 error:
     84 	isl_space_free(el_dim);
     85 	FN(PW,free)(pw);
     86 	isl_set_free(set);
     87 	FN(EL,free)(el);
     88 	return NULL;
     89 }
     90 
     91 /* Add a piece with domain "set" and base expression "el"
     92  * to the piecewise expression "pw", provided the domain
     93  * is not obviously empty and the base expression
     94  * is not equal to the default value.
     95  */
     96 __isl_give PW *FN(PW,add_piece)(__isl_take PW *pw,
     97 	__isl_take isl_set *set, __isl_take EL *el)
     98 {
     99 	isl_bool skip;
    100 
    101 	skip = isl_set_plain_is_empty(set);
    102 	if (skip >= 0 && !skip)
    103 		skip = FN(EL,EL_IS_ZERO)(el);
    104 	if (skip >= 0 && !skip)
    105 		return FN(PW,add_dup_piece)(pw, set, el);
    106 
    107 	isl_set_free(set);
    108 	FN(EL,free)(el);
    109 	if (skip < 0)
    110 		return FN(PW,free)(pw);
    111 	return pw;
    112 }
    113 
    114 /* Does the space of "set" correspond to that of the domain of "el".
    115  */
    116 static isl_bool FN(PW,compatible_domain)(__isl_keep EL *el,
    117 	__isl_keep isl_set *set)
    118 {
    119 	isl_bool ok;
    120 	isl_space *el_space, *set_space;
    121 
    122 	if (!set || !el)
    123 		return isl_bool_error;
    124 	set_space = isl_set_get_space(set);
    125 	el_space = FN(EL,get_space)(el);
    126 	ok = isl_space_is_domain_internal(set_space, el_space);
    127 	isl_space_free(el_space);
    128 	isl_space_free(set_space);
    129 	return ok;
    130 }
    131 
    132 /* Check that the space of "set" corresponds to that of the domain of "el".
    133  */
    134 static isl_stat FN(PW,check_compatible_domain)(__isl_keep EL *el,
    135 	__isl_keep isl_set *set)
    136 {
    137 	isl_bool ok;
    138 
    139 	ok = FN(PW,compatible_domain)(el, set);
    140 	if (ok < 0)
    141 		return isl_stat_error;
    142 	if (!ok)
    143 		isl_die(isl_set_get_ctx(set), isl_error_invalid,
    144 			"incompatible spaces", return isl_stat_error);
    145 
    146 	return isl_stat_ok;
    147 }
    148 
    149 __isl_give PW *FN(PW,alloc)(OPT_TYPE_PARAM_FIRST
    150 	__isl_take isl_set *set, __isl_take EL *el)
    151 {
    152 	PW *pw;
    153 
    154 	if (FN(PW,check_compatible_domain)(el, set) < 0)
    155 		goto error;
    156 
    157 	pw = FN(PW,alloc_size)(FN(EL,get_space)(el) OPT_TYPE_ARG(NO_LOC), 1);
    158 
    159 	return FN(PW,add_piece)(pw, set, el);
    160 error:
    161 	isl_set_free(set);
    162 	FN(EL,free)(el);
    163 	return NULL;
    164 }
    165 
    166 __isl_give PW *FN(PW,dup)(__isl_keep PW *pw)
    167 {
    168 	int i;
    169 	PW *dup;
    170 
    171 	if (!pw)
    172 		return NULL;
    173 
    174 	dup = FN(PW,alloc_size)(isl_space_copy(pw->dim)
    175 				OPT_TYPE_ARG(pw->), pw->n);
    176 	if (!dup)
    177 		return NULL;
    178 
    179 	for (i = 0; i < pw->n; ++i)
    180 		dup = FN(PW,add_dup_piece)(dup, isl_set_copy(pw->p[i].set),
    181 					    FN(EL,copy)(pw->p[i].FIELD));
    182 
    183 	return dup;
    184 }
    185 
    186 __isl_give PW *FN(PW,cow)(__isl_take PW *pw)
    187 {
    188 	if (!pw)
    189 		return NULL;
    190 
    191 	if (pw->ref == 1)
    192 		return pw;
    193 	pw->ref--;
    194 	return FN(PW,dup)(pw);
    195 }
    196 
    197 __isl_give PW *FN(PW,copy)(__isl_keep PW *pw)
    198 {
    199 	if (!pw)
    200 		return NULL;
    201 
    202 	pw->ref++;
    203 	return pw;
    204 }
    205 
    206 __isl_null PW *FN(PW,free)(__isl_take PW *pw)
    207 {
    208 	int i;
    209 
    210 	if (!pw)
    211 		return NULL;
    212 	if (--pw->ref > 0)
    213 		return NULL;
    214 
    215 	for (i = 0; i < pw->n; ++i) {
    216 		isl_set_free(pw->p[i].set);
    217 		FN(EL,free)(pw->p[i].FIELD);
    218 	}
    219 	isl_space_free(pw->dim);
    220 	free(pw);
    221 
    222 	return NULL;
    223 }
    224 
    225 /* Return the space of "pw".
    226  */
    227 __isl_keep isl_space *FN(PW,peek_space)(__isl_keep PW *pw)
    228 {
    229 	return pw ? pw->dim : NULL;
    230 }
    231 
    232 __isl_give isl_space *FN(PW,get_space)(__isl_keep PW *pw)
    233 {
    234 	return isl_space_copy(FN(PW,peek_space)(pw));
    235 }
    236 
    237 /* Return the space of "pw".
    238  * This may be either a copy or the space itself
    239  * if there is only one reference to "pw".
    240  * This allows the space to be modified inplace
    241  * if both the piecewise expression and its space have only a single reference.
    242  * The caller is not allowed to modify "pw" between this call and
    243  * a subsequent call to isl_pw_*_restore_*.
    244  * The only exception is that isl_pw_*_free can be called instead.
    245  */
    246 static __isl_give isl_space *FN(PW,take_space)(__isl_keep PW *pw)
    247 {
    248 	isl_space *space;
    249 
    250 	if (!pw)
    251 		return NULL;
    252 	if (pw->ref != 1)
    253 		return FN(PW,get_space)(pw);
    254 	space = pw->dim;
    255 	pw->dim = NULL;
    256 	return space;
    257 }
    258 
    259 /* Set the space of "pw" to "space", where the space of "pw" may be missing
    260  * due to a preceding call to isl_pw_*_take_space.
    261  * However, in this case, "pw" only has a single reference and
    262  * then the call to isl_pw_*_cow has no effect.
    263  */
    264 static __isl_give PW *FN(PW,restore_space)(__isl_take PW *pw,
    265 	__isl_take isl_space *space)
    266 {
    267 	if (!pw || !space)
    268 		goto error;
    269 
    270 	if (pw->dim == space) {
    271 		isl_space_free(space);
    272 		return pw;
    273 	}
    274 
    275 	pw = FN(PW,cow)(pw);
    276 	if (!pw)
    277 		goto error;
    278 	isl_space_free(pw->dim);
    279 	pw->dim = space;
    280 
    281 	return pw;
    282 error:
    283 	FN(PW,free)(pw);
    284 	isl_space_free(space);
    285 	return NULL;
    286 }
    287 
    288 /* Check that "pos" is a valid position for a cell in "pw".
    289  */
    290 static isl_stat FN(PW,check_pos)(__isl_keep PW *pw, int pos)
    291 {
    292 	if (!pw)
    293 		return isl_stat_error;
    294 	if (pos < 0 || pos >= pw->n)
    295 		isl_die(FN(PW,get_ctx)(pw), isl_error_internal,
    296 			"position out of bounds", return isl_stat_error);
    297 	return isl_stat_ok;
    298 }
    299 
    300 /* Return the cell at position "pos" in "pw".
    301  */
    302 static __isl_keep isl_set *FN(PW,peek_domain_at)(__isl_keep PW *pw, int pos)
    303 {
    304 	if (FN(PW,check_pos)(pw, pos) < 0)
    305 		return NULL;
    306 	return pw->p[pos].set;
    307 }
    308 
    309 /* Return a copy of the cell at position "pos" in "pw".
    310  */
    311 static __isl_give isl_set *FN(PW,get_domain_at)(__isl_keep PW *pw, int pos)
    312 {
    313 	return isl_set_copy(FN(PW,peek_domain_at)(pw, pos));
    314 }
    315 
    316 /* Return the cell at position "pos" in "pw".
    317  * This may be either a copy or the cell itself
    318  * if there is only one reference to "pw".
    319  * This allows the cell to be modified inplace
    320  * if both the piecewise expression and this cell
    321  * have only a single reference.
    322  * The caller is not allowed to modify "pw" between this call and
    323  * the subsequent call to isl_pw_*_restore_domain_at.
    324  * The only exception is that isl_pw_*_free can be called instead.
    325  */
    326 static __isl_give isl_set *FN(PW,take_domain_at)(__isl_keep PW *pw, int pos)
    327 {
    328 	isl_set *domain;
    329 
    330 	if (!pw)
    331 		return NULL;
    332 	if (pw->ref != 1)
    333 		return FN(PW,get_domain_at)(pw, pos);
    334 	if (FN(PW,check_pos)(pw, pos) < 0)
    335 		return NULL;
    336 	domain = pw->p[pos].set;
    337 	pw->p[pos].set = NULL;
    338 	return domain;
    339 }
    340 
    341 /* Set the cell at position "pos" in "pw" to "el",
    342  * where this cell may be missing
    343  * due to a preceding call to isl_pw_*_take_domain_at.
    344  * However, in this case, "pw" only has a single reference and
    345  * then the call to isl_pw_*_cow has no effect.
    346  */
    347 static __isl_give PW *FN(PW,restore_domain_at)(__isl_take PW *pw, int pos,
    348 	__isl_take isl_set *domain)
    349 {
    350 	if (FN(PW,check_pos)(pw, pos) < 0 || !domain)
    351 		goto error;
    352 
    353 	if (pw->p[pos].set == domain) {
    354 		isl_set_free(domain);
    355 		return pw;
    356 	}
    357 
    358 	pw = FN(PW,cow)(pw);
    359 	if (!pw)
    360 		goto error;
    361 	isl_set_free(pw->p[pos].set);
    362 	pw->p[pos].set = domain;
    363 
    364 	return pw;
    365 error:
    366 	FN(PW,free)(pw);
    367 	isl_set_free(domain);
    368 	return NULL;
    369 }
    370 
    371 /* Return the base expression associated to
    372  * the cell at position "pos" in "pw".
    373  */
    374 __isl_keep EL *FN(PW,peek_base_at)(__isl_keep PW *pw, int pos)
    375 {
    376 	if (FN(PW,check_pos)(pw, pos) < 0)
    377 		return NULL;
    378 	return pw->p[pos].FIELD;
    379 }
    380 
    381 /* Return a copy of the base expression associated to
    382  * the cell at position "pos" in "pw".
    383  */
    384 static __isl_give EL *FN(PW,get_base_at)(__isl_keep PW *pw, int pos)
    385 {
    386 	return FN(EL,copy)(FN(PW,peek_base_at)(pw, pos));
    387 }
    388 
    389 /* Return the base expression associated to
    390  * the cell at position "pos" in "pw".
    391  * This may be either a copy or the base expression itself
    392  * if there is only one reference to "pw".
    393  * This allows the base expression to be modified inplace
    394  * if both the piecewise expression and this base expression
    395  * have only a single reference.
    396  * The caller is not allowed to modify "pw" between this call and
    397  * a subsequent call to isl_pw_*_restore_*.
    398  * The only exception is that isl_pw_*_free can be called instead.
    399  */
    400 static __isl_give EL *FN(PW,take_base_at)(__isl_keep PW *pw, int pos)
    401 {
    402 	EL *el;
    403 
    404 	if (!pw)
    405 		return NULL;
    406 	if (pw->ref != 1)
    407 		return FN(PW,get_base_at)(pw, pos);
    408 	if (FN(PW,check_pos)(pw, pos) < 0)
    409 		return NULL;
    410 	el = pw->p[pos].FIELD;
    411 	pw->p[pos].FIELD = NULL;
    412 	return el;
    413 }
    414 
    415 /* Set the base expression associated to
    416  * the cell at position "pos" in "pw" to "el",
    417  * where this base expression may be missing
    418  * due to a preceding call to isl_pw_*_take_base_at.
    419  * However, in this case, "pw" only has a single reference and
    420  * then the call to isl_pw_*_cow has no effect.
    421  * If "inplace" is set, then replacing the base expression by "el"
    422  * is known not to change the meaning of "pw".  It can therefore be replaced
    423  * in all references to "pw".
    424  */
    425 static __isl_give PW *FN(PW,restore_base_at_)(__isl_take PW *pw, int pos,
    426 	__isl_take EL *el, int inplace)
    427 {
    428 	if (FN(PW,check_pos)(pw, pos) < 0 || !el)
    429 		goto error;
    430 
    431 	if (pw->p[pos].FIELD == el) {
    432 		FN(EL,free)(el);
    433 		return pw;
    434 	}
    435 
    436 	if (!inplace)
    437 		pw = FN(PW,cow)(pw);
    438 	if (!pw)
    439 		goto error;
    440 	FN(EL,free)(pw->p[pos].FIELD);
    441 	pw->p[pos].FIELD = el;
    442 
    443 	return pw;
    444 error:
    445 	FN(PW,free)(pw);
    446 	FN(EL,free)(el);
    447 	return NULL;
    448 }
    449 
    450 /* Set the base expression associated to
    451  * the cell at position "pos" in "pw" to "el",
    452  * where this base expression may be missing
    453  * due to a preceding call to isl_pw_*_take_base_at.
    454  */
    455 static __isl_give PW *FN(PW,restore_base_at)(__isl_take PW *pw, int pos,
    456 	__isl_take EL *el)
    457 {
    458 	return FN(PW,restore_base_at_)(pw, pos, el, 0);
    459 }
    460 
    461 /* Set the base expression associated to
    462  * the cell at position "pos" in "pw" to "el",
    463  * where this base expression may be missing
    464  * due to a preceding call to isl_pw_*_take_base_at.
    465  * Furthermore, replacing the base expression by "el"
    466  * is known not to change the meaning of "pw".
    467  */
    468 static __isl_give PW *FN(PW,restore_base_at_inplace)(__isl_take PW *pw, int pos,
    469 	__isl_take EL *el)
    470 {
    471 	return FN(PW,restore_base_at_)(pw, pos, el, 1);
    472 }
    473 
    474 /* Create a piecewise expression with the given base expression on a universe
    475  * domain.
    476  */
    477 static __isl_give PW *FN(FN(FN(PW,from),BASE),type_base)(__isl_take EL *el
    478 	OPT_TYPE_PARAM)
    479 {
    480 	isl_set *dom = isl_set_universe(FN(EL,get_domain_space)(el));
    481 	return FN(PW,alloc)(OPT_TYPE_ARG_FIRST(NO_LOC) dom, el);
    482 }
    483 
    484 /* Create a piecewise expression with the given base expression on a universe
    485  * domain.
    486  *
    487  * If the default value of this piecewise type is zero and
    488  * if "el" is effectively zero, then create an empty piecewise expression
    489  * instead.
    490  */
    491 static __isl_give PW *FN(FN(FN(PW,from),BASE),type)(__isl_take EL *el
    492 	OPT_TYPE_PARAM)
    493 {
    494 	isl_bool is_zero;
    495 	isl_space *space;
    496 
    497 	if (!DEFAULT_IS_ZERO)
    498 		return FN(FN(FN(PW,from),BASE),type_base)(el
    499 							OPT_TYPE_ARG(NO_LOC));
    500 	is_zero = FN(EL,EL_IS_ZERO)(el);
    501 	if (is_zero < 0)
    502 		goto error;
    503 	if (!is_zero)
    504 		return FN(FN(FN(PW,from),BASE),type_base)(el
    505 							OPT_TYPE_ARG(NO_LOC));
    506 	space = FN(EL,get_space)(el);
    507 	FN(EL,free)(el);
    508 	return FN(PW,ZERO)(space OPT_TYPE_ARG(NO_LOC));
    509 error:
    510 	FN(EL,free)(el);
    511 	return NULL;
    512 }
    513 
    514 #ifdef HAS_TYPE
    515 /* Create a piecewise expression with the given base expression on a universe
    516  * domain.
    517  *
    518  * Pass along the type as an extra argument for improved uniformity
    519  * with piecewise types that do not have a fold type.
    520  */
    521 __isl_give PW *FN(FN(PW,from),BASE)(__isl_take EL *el)
    522 {
    523 	enum isl_fold type = FN(EL,get_type)(el);
    524 	return FN(FN(FN(PW,from),BASE),type)(el, type);
    525 }
    526 #else
    527 __isl_give PW *FN(FN(PW,from),BASE)(__isl_take EL *el)
    528 {
    529 	return FN(FN(FN(PW,from),BASE),type)(el);
    530 }
    531 #endif
    532 
    533 const char *FN(PW,get_dim_name)(__isl_keep PW *pw, enum isl_dim_type type,
    534 	unsigned pos)
    535 {
    536 	return pw ? isl_space_get_dim_name(pw->dim, type, pos) : NULL;
    537 }
    538 
    539 isl_bool FN(PW,has_dim_id)(__isl_keep PW *pw, enum isl_dim_type type,
    540 	unsigned pos)
    541 {
    542 	return pw ? isl_space_has_dim_id(pw->dim, type, pos) : isl_bool_error;
    543 }
    544 
    545 __isl_give isl_id *FN(PW,get_dim_id)(__isl_keep PW *pw, enum isl_dim_type type,
    546 	unsigned pos)
    547 {
    548 	return pw ? isl_space_get_dim_id(pw->dim, type, pos) : NULL;
    549 }
    550 
    551 isl_bool FN(PW,has_tuple_name)(__isl_keep PW *pw, enum isl_dim_type type)
    552 {
    553 	return pw ? isl_space_has_tuple_name(pw->dim, type) : isl_bool_error;
    554 }
    555 
    556 const char *FN(PW,get_tuple_name)(__isl_keep PW *pw, enum isl_dim_type type)
    557 {
    558 	return pw ? isl_space_get_tuple_name(pw->dim, type) : NULL;
    559 }
    560 
    561 isl_bool FN(PW,has_tuple_id)(__isl_keep PW *pw, enum isl_dim_type type)
    562 {
    563 	return pw ? isl_space_has_tuple_id(pw->dim, type) : isl_bool_error;
    564 }
    565 
    566 __isl_give isl_id *FN(PW,get_tuple_id)(__isl_keep PW *pw, enum isl_dim_type type)
    567 {
    568 	return pw ? isl_space_get_tuple_id(pw->dim, type) : NULL;
    569 }
    570 
    571 isl_bool FN(PW,IS_ZERO)(__isl_keep PW *pw)
    572 {
    573 	if (!pw)
    574 		return isl_bool_error;
    575 
    576 	return isl_bool_ok(pw->n == 0);
    577 }
    578 
    579 static __isl_give PW *FN(PW,realign_domain)(__isl_take PW *pw,
    580 	__isl_take isl_reordering *exp)
    581 {
    582 	int i;
    583 	isl_size n;
    584 
    585 	n = FN(PW,n_piece)(pw);
    586 	if (n < 0 || !exp)
    587 		goto error;
    588 
    589 	for (i = 0; i < n; ++i) {
    590 		isl_set *domain;
    591 		EL *el;
    592 
    593 		domain = FN(PW,take_domain_at)(pw, i);
    594 		domain = isl_set_realign(domain, isl_reordering_copy(exp));
    595 		pw = FN(PW,restore_domain_at)(pw, i, domain);
    596 
    597 		el = FN(PW,take_base_at)(pw, i);
    598 		el = FN(EL,realign_domain)(el, isl_reordering_copy(exp));
    599 		pw = FN(PW,restore_base_at)(pw, i, el);
    600 	}
    601 
    602 	pw = FN(PW,reset_domain_space)(pw, isl_reordering_get_space(exp));
    603 
    604 	isl_reordering_free(exp);
    605 	return pw;
    606 error:
    607 	isl_reordering_free(exp);
    608 	FN(PW,free)(pw);
    609 	return NULL;
    610 }
    611 
    612 #undef TYPE
    613 #define TYPE PW
    614 
    615 #include "isl_check_named_params_templ.c"
    616 
    617 /* Align the parameters of "pw" to those of "model".
    618  */
    619 __isl_give PW *FN(PW,align_params)(__isl_take PW *pw, __isl_take isl_space *model)
    620 {
    621 	isl_ctx *ctx;
    622 	isl_bool equal_params;
    623 
    624 	if (!pw || !model)
    625 		goto error;
    626 
    627 	ctx = isl_space_get_ctx(model);
    628 	if (!isl_space_has_named_params(model))
    629 		isl_die(ctx, isl_error_invalid,
    630 			"model has unnamed parameters", goto error);
    631 	if (FN(PW,check_named_params)(pw) < 0)
    632 		goto error;
    633 	equal_params = isl_space_has_equal_params(pw->dim, model);
    634 	if (equal_params < 0)
    635 		goto error;
    636 	if (!equal_params) {
    637 		isl_space *space;
    638 		isl_reordering *exp;
    639 
    640 		space = FN(PW,get_domain_space)(pw);
    641 		exp = isl_parameter_alignment_reordering(space, model);
    642 		isl_space_free(space);
    643 		pw = FN(PW,realign_domain)(pw, exp);
    644 	}
    645 
    646 	isl_space_free(model);
    647 	return pw;
    648 error:
    649 	isl_space_free(model);
    650 	FN(PW,free)(pw);
    651 	return NULL;
    652 }
    653 
    654 #undef TYPE
    655 #define TYPE	PW
    656 
    657 static
    658 #include "isl_align_params_bin_templ.c"
    659 
    660 #undef SUFFIX
    661 #define SUFFIX	set
    662 #undef ARG1
    663 #define ARG1	PW
    664 #undef ARG2
    665 #define ARG2	isl_set
    666 
    667 static
    668 #include "isl_align_params_templ.c"
    669 
    670 #undef TYPE
    671 #define TYPE	PW
    672 
    673 #include "isl_type_has_equal_space_bin_templ.c"
    674 #include "isl_type_check_equal_space_templ.c"
    675 
    676 /* Private version of "union_add".  For isl_pw_qpolynomial and
    677  * isl_pw_qpolynomial_fold, we prefer to simply call it "add".
    678  */
    679 static __isl_give PW *FN(PW,union_add_)(__isl_take PW *pw1, __isl_take PW *pw2)
    680 {
    681 	int i, j, n;
    682 	struct PW *res;
    683 	isl_ctx *ctx;
    684 	isl_set *set;
    685 
    686 	if (FN(PW,align_params_bin)(&pw1, &pw2) < 0)
    687 		goto error;
    688 
    689 	ctx = isl_space_get_ctx(pw1->dim);
    690 	if (!OPT_EQUAL_TYPES(pw1->, pw2->))
    691 		isl_die(ctx, isl_error_invalid,
    692 			"fold types don't match", goto error);
    693 	if (FN(PW,check_equal_space)(pw1, pw2) < 0)
    694 		goto error;
    695 
    696 	if (FN(PW,IS_ZERO)(pw1)) {
    697 		FN(PW,free)(pw1);
    698 		return pw2;
    699 	}
    700 
    701 	if (FN(PW,IS_ZERO)(pw2)) {
    702 		FN(PW,free)(pw2);
    703 		return pw1;
    704 	}
    705 
    706 	n = (pw1->n + 1) * (pw2->n + 1);
    707 	res = FN(PW,alloc_size)(isl_space_copy(pw1->dim)
    708 				OPT_TYPE_ARG(pw1->), n);
    709 
    710 	for (i = 0; i < pw1->n; ++i) {
    711 		set = isl_set_copy(pw1->p[i].set);
    712 		for (j = 0; j < pw2->n; ++j) {
    713 			struct isl_set *common;
    714 			EL *sum;
    715 			common = isl_set_intersect(isl_set_copy(pw1->p[i].set),
    716 						isl_set_copy(pw2->p[j].set));
    717 			if (isl_set_plain_is_empty(common)) {
    718 				isl_set_free(common);
    719 				continue;
    720 			}
    721 			set = isl_set_subtract(set,
    722 					isl_set_copy(pw2->p[j].set));
    723 
    724 			sum = FN(EL,add_on_domain)(common,
    725 						   FN(EL,copy)(pw1->p[i].FIELD),
    726 						   FN(EL,copy)(pw2->p[j].FIELD));
    727 
    728 			res = FN(PW,add_piece)(res, common, sum);
    729 		}
    730 		res = FN(PW,add_piece)(res, set, FN(EL,copy)(pw1->p[i].FIELD));
    731 	}
    732 
    733 	for (j = 0; j < pw2->n; ++j) {
    734 		set = isl_set_copy(pw2->p[j].set);
    735 		for (i = 0; i < pw1->n; ++i)
    736 			set = isl_set_subtract(set,
    737 					isl_set_copy(pw1->p[i].set));
    738 		res = FN(PW,add_piece)(res, set, FN(EL,copy)(pw2->p[j].FIELD));
    739 	}
    740 
    741 	FN(PW,free)(pw1);
    742 	FN(PW,free)(pw2);
    743 
    744 	return res;
    745 error:
    746 	FN(PW,free)(pw1);
    747 	FN(PW,free)(pw2);
    748 	return NULL;
    749 }
    750 
    751 #if !DEFAULT_IS_ZERO
    752 
    753 /* Compute the sum of "pw1" and "pw2 on the union of their domains,
    754  * with the actual sum on the shared domain and
    755  * the defined expression on the symmetric difference of the domains.
    756  *
    757  * This function is only defined for object types that do not have
    758  * a default zero value.  For other object types, this function
    759  * is simply called "add".
    760  */
    761 __isl_give PW *FN(PW,union_add)(__isl_take PW *pw1, __isl_take PW *pw2)
    762 {
    763 	return FN(PW,union_add_)(pw1, pw2);
    764 }
    765 
    766 #endif
    767 
    768 /* This function is currently only used from isl_aff.c
    769  */
    770 static __isl_give PW *FN(PW,on_shared_domain_in)(__isl_take PW *pw1,
    771 	__isl_take PW *pw2, __isl_take isl_space *space,
    772 	__isl_give EL *(*fn)(__isl_take EL *el1, __isl_take EL *el2))
    773 	__attribute__ ((unused));
    774 
    775 /* Apply "fn" to pairs of elements from pw1 and pw2 on shared domains.
    776  * The result of "fn" (and therefore also of this function) lives in "space".
    777  */
    778 static __isl_give PW *FN(PW,on_shared_domain_in)(__isl_take PW *pw1,
    779 	__isl_take PW *pw2, __isl_take isl_space *space,
    780 	__isl_give EL *(*fn)(__isl_take EL *el1, __isl_take EL *el2))
    781 {
    782 	int i, j, n;
    783 	PW *res = NULL;
    784 
    785 	if (!pw1 || !pw2)
    786 		goto error;
    787 
    788 	n = pw1->n * pw2->n;
    789 	res = FN(PW,alloc_size)(isl_space_copy(space) OPT_TYPE_ARG(pw1->), n);
    790 
    791 	for (i = 0; i < pw1->n; ++i) {
    792 		for (j = 0; j < pw2->n; ++j) {
    793 			isl_set *common;
    794 			EL *res_ij;
    795 			int empty;
    796 
    797 			common = isl_set_intersect(
    798 					isl_set_copy(pw1->p[i].set),
    799 					isl_set_copy(pw2->p[j].set));
    800 			empty = isl_set_plain_is_empty(common);
    801 			if (empty < 0 || empty) {
    802 				isl_set_free(common);
    803 				if (empty < 0)
    804 					goto error;
    805 				continue;
    806 			}
    807 
    808 			res_ij = fn(FN(EL,copy)(pw1->p[i].FIELD),
    809 				    FN(EL,copy)(pw2->p[j].FIELD));
    810 			res_ij = FN(EL,gist)(res_ij, isl_set_copy(common));
    811 
    812 			res = FN(PW,add_piece)(res, common, res_ij);
    813 		}
    814 	}
    815 
    816 	isl_space_free(space);
    817 	FN(PW,free)(pw1);
    818 	FN(PW,free)(pw2);
    819 	return res;
    820 error:
    821 	isl_space_free(space);
    822 	FN(PW,free)(pw1);
    823 	FN(PW,free)(pw2);
    824 	FN(PW,free)(res);
    825 	return NULL;
    826 }
    827 
    828 /* This function is currently only used from isl_aff.c
    829  */
    830 static __isl_give PW *FN(PW,on_shared_domain)(__isl_take PW *pw1,
    831 	__isl_take PW *pw2,
    832 	__isl_give EL *(*fn)(__isl_take EL *el1, __isl_take EL *el2))
    833 	__attribute__ ((unused));
    834 
    835 /* Apply "fn" to pairs of elements from pw1 and pw2 on shared domains.
    836  * The result of "fn" is assumed to live in the same space as "pw1" and "pw2".
    837  */
    838 static __isl_give PW *FN(PW,on_shared_domain)(__isl_take PW *pw1,
    839 	__isl_take PW *pw2,
    840 	__isl_give EL *(*fn)(__isl_take EL *el1, __isl_take EL *el2))
    841 {
    842 	isl_space *space;
    843 
    844 	if (FN(PW,check_equal_space)(pw1, pw2) < 0)
    845 		goto error;
    846 
    847 	space = isl_space_copy(pw1->dim);
    848 	return FN(PW,on_shared_domain_in)(pw1, pw2, space, fn);
    849 error:
    850 	FN(PW,free)(pw1);
    851 	FN(PW,free)(pw2);
    852 	return NULL;
    853 }
    854 
    855 /* Return the parameter domain of "pw".
    856  */
    857 __isl_give isl_set *FN(PW,params)(__isl_take PW *pw)
    858 {
    859 	return isl_set_params(FN(PW,domain)(pw));
    860 }
    861 
    862 __isl_give isl_set *FN(PW,domain)(__isl_take PW *pw)
    863 {
    864 	int i;
    865 	isl_set *dom;
    866 
    867 	if (!pw)
    868 		return NULL;
    869 
    870 	dom = isl_set_empty(FN(PW,get_domain_space)(pw));
    871 	for (i = 0; i < pw->n; ++i)
    872 		dom = isl_set_union_disjoint(dom, isl_set_copy(pw->p[i].set));
    873 
    874 	FN(PW,free)(pw);
    875 
    876 	return dom;
    877 }
    878 
    879 /* Exploit the equalities in the domain of piece "i" of "pw"
    880  * to simplify the associated function.
    881  * If the domain of piece "i" is empty, then remove it entirely,
    882  * replacing it with the final piece.
    883  */
    884 static __isl_give PW *FN(PW,exploit_equalities_and_remove_if_empty)(
    885 	__isl_take PW *pw, int i)
    886 {
    887 	EL *el;
    888 	isl_set *domain;
    889 	isl_basic_set *aff;
    890 	int empty;
    891 
    892 	domain = FN(PW,peek_domain_at)(pw, i);
    893 	empty = isl_set_plain_is_empty(domain);
    894 	if (empty < 0)
    895 		return FN(PW,free)(pw);
    896 	if (empty) {
    897 		isl_set_free(pw->p[i].set);
    898 		FN(EL,free)(pw->p[i].FIELD);
    899 		if (i != pw->n - 1)
    900 			pw->p[i] = pw->p[pw->n - 1];
    901 		pw->n--;
    902 
    903 		return pw;
    904 	}
    905 
    906 	aff = isl_set_affine_hull(FN(PW,get_domain_at)(pw, i));
    907 	el = FN(PW,take_base_at)(pw, i);
    908 	el = FN(EL,substitute_equalities)(el, aff);
    909 	pw = FN(PW,restore_base_at_inplace)(pw, i, el);
    910 
    911 	return pw;
    912 }
    913 
    914 /* Restrict the domain of "pw" by combining each cell
    915  * with "set" through a call to "fn", where "fn" may be
    916  * isl_set_intersect, isl_set_intersect_params, isl_set_intersect_factor_domain,
    917  * isl_set_intersect_factor_range or isl_set_subtract.
    918  */
    919 static __isl_give PW *FN(PW,restrict_domain)(__isl_take PW *pw,
    920 	__isl_take isl_set *set,
    921 	__isl_give isl_set *(*fn)(__isl_take isl_set *set1,
    922 				    __isl_take isl_set *set2))
    923 {
    924 	int i;
    925 	isl_size n;
    926 
    927 	FN(PW,align_params_set)(&pw, &set);
    928 	n = FN(PW,n_piece)(pw);
    929 	if (n < 0 || !set)
    930 		goto error;
    931 
    932 	for (i = n - 1; i >= 0; --i) {
    933 		isl_set *domain;
    934 
    935 		domain = FN(PW,take_domain_at)(pw, i);
    936 		domain = fn(domain, isl_set_copy(set));
    937 		pw = FN(PW,restore_domain_at)(pw, i, domain);
    938 		pw = FN(PW,exploit_equalities_and_remove_if_empty)(pw, i);
    939 	}
    940 
    941 	isl_set_free(set);
    942 	return pw;
    943 error:
    944 	isl_set_free(set);
    945 	FN(PW,free)(pw);
    946 	return NULL;
    947 }
    948 
    949 __isl_give PW *FN(PW,intersect_domain)(__isl_take PW *pw,
    950 	__isl_take isl_set *context)
    951 {
    952 	return FN(PW,restrict_domain)(pw, context, &isl_set_intersect);
    953 }
    954 
    955 /* Intersect the domain of "pw" with the parameter domain "context".
    956  */
    957 __isl_give PW *FN(PW,intersect_params)(__isl_take PW *pw,
    958 	__isl_take isl_set *context)
    959 {
    960 	return FN(PW,restrict_domain)(pw, context, &isl_set_intersect_params);
    961 }
    962 
    963 /* Given a piecewise expression "pw" with domain in a space [A -> B] and
    964  * a set in the space A, intersect the domain with the set.
    965  */
    966 __isl_give PW *FN(PW,intersect_domain_wrapped_domain)(__isl_take PW *pw,
    967 	__isl_take isl_set *set)
    968 {
    969 	return FN(PW,restrict_domain)(pw, set,
    970 					    &isl_set_intersect_factor_domain);
    971 }
    972 
    973 /* Given a piecewise expression "pw" with domain in a space [A -> B] and
    974  * a set in the space B, intersect the domain with the set.
    975  */
    976 __isl_give PW *FN(PW,intersect_domain_wrapped_range)(__isl_take PW *pw,
    977 	__isl_take isl_set *set)
    978 {
    979 	return FN(PW,restrict_domain)(pw, set, &isl_set_intersect_factor_range);
    980 }
    981 
    982 /* Subtract "domain' from the domain of "pw".
    983  */
    984 __isl_give PW *FN(PW,subtract_domain)(__isl_take PW *pw,
    985 	__isl_take isl_set *domain)
    986 {
    987 	return FN(PW,restrict_domain)(pw, domain, &isl_set_subtract);
    988 }
    989 
    990 /* Return -1 if the piece "p1" should be sorted before "p2"
    991  * and 1 if it should be sorted after "p2".
    992  * Return 0 if they do not need to be sorted in a specific order.
    993  *
    994  * The two pieces are compared on the basis of their function value expressions.
    995  */
    996 static int FN(PW,sort_field_cmp)(const void *p1, const void *p2, void *arg)
    997 {
    998 	struct FN(PW,piece) const *pc1 = p1;
    999 	struct FN(PW,piece) const *pc2 = p2;
   1000 
   1001 	return FN(EL,plain_cmp)(pc1->FIELD, pc2->FIELD);
   1002 }
   1003 
   1004 /* Sort the pieces of "pw" according to their function value
   1005  * expressions and then combine pairs of adjacent pieces with
   1006  * the same such expression.
   1007  *
   1008  * The sorting is performed in place because it does not
   1009  * change the meaning of "pw", but care needs to be
   1010  * taken not to change any possible other copies of "pw"
   1011  * in case anything goes wrong.
   1012  */
   1013 static __isl_give PW *FN(PW,sort_unique)(__isl_take PW *pw)
   1014 {
   1015 	int i, j;
   1016 	isl_set *set;
   1017 
   1018 	if (!pw)
   1019 		return NULL;
   1020 	if (pw->n <= 1)
   1021 		return pw;
   1022 	if (isl_sort(pw->p, pw->n, sizeof(pw->p[0]),
   1023 		    &FN(PW,sort_field_cmp), NULL) < 0)
   1024 		return FN(PW,free)(pw);
   1025 	for (i = pw->n - 1; i >= 1; --i) {
   1026 		isl_bool equal;
   1027 		EL *el, *el_prev;
   1028 		isl_set *set_prev;
   1029 
   1030 		el = FN(PW,peek_base_at)(pw, i);
   1031 		el_prev = FN(PW,peek_base_at)(pw, i - 1);
   1032 		equal = FN(EL,plain_is_equal)(el, el_prev);
   1033 		if (equal < 0)
   1034 			return FN(PW,free)(pw);
   1035 		if (!equal)
   1036 			continue;
   1037 		set = FN(PW,get_domain_at)(pw, i);
   1038 		set_prev = FN(PW,get_domain_at)(pw, i - 1);
   1039 		set = isl_set_union(set_prev, set);
   1040 		if (!set)
   1041 			return FN(PW,free)(pw);
   1042 		isl_set_free(pw->p[i].set);
   1043 		FN(EL,free)(pw->p[i].FIELD);
   1044 		isl_set_free(pw->p[i - 1].set);
   1045 		pw->p[i - 1].set = set;
   1046 		for (j = i + 1; j < pw->n; ++j)
   1047 			pw->p[j - 1] = pw->p[j];
   1048 		pw->n--;
   1049 	}
   1050 
   1051 	return pw;
   1052 }
   1053 
   1054 /* Compute the gist of "pw" with respect to the domain constraints
   1055  * of "context" for the case where the domain of the last element
   1056  * of "pw" is equal to "context".
   1057  * Compute the gist of this element, replace
   1058  * its domain by the universe and drop all other elements
   1059  * as their domains are necessarily disjoint from "context".
   1060  */
   1061 static __isl_give PW *FN(PW,gist_last)(__isl_take PW *pw,
   1062 	__isl_take isl_set *context)
   1063 {
   1064 	int i;
   1065 	isl_space *space;
   1066 	EL *el;
   1067 
   1068 	for (i = 0; i < pw->n - 1; ++i) {
   1069 		isl_set_free(pw->p[i].set);
   1070 		FN(EL,free)(pw->p[i].FIELD);
   1071 	}
   1072 	pw->p[0].FIELD = pw->p[pw->n - 1].FIELD;
   1073 	pw->p[0].set = pw->p[pw->n - 1].set;
   1074 	pw->n = 1;
   1075 
   1076 	space = isl_set_get_space(context);
   1077 	el = FN(PW,take_base_at)(pw, 0);
   1078 	el = FN(EL,gist)(el, context);
   1079 	pw = FN(PW,restore_base_at)(pw, 0, el);
   1080 	context = isl_set_universe(space);
   1081 	pw = FN(PW,restore_domain_at)(pw, 0, context);
   1082 
   1083 	return pw;
   1084 }
   1085 
   1086 /* Compute the gist of "pw" with respect to the domain constraints
   1087  * of "context".
   1088  * Call "fn_dom" to compute the gist of the domains and
   1089  * "intersect_context" to intersect the domain with the context.
   1090  *
   1091  * If the piecewise expression is empty or the context is the universe,
   1092  * then nothing can be simplified.
   1093  * If "pw" has a single domain and it is equal to "context",
   1094  * then simply replace the domain by the universe.
   1095  * Combine duplicate function value expressions first
   1096  * to increase the chance of "pw" having a single domain.
   1097  */
   1098 static __isl_give PW *FN(PW,gist_fn)(__isl_take PW *pw,
   1099 	__isl_take isl_set *context,
   1100 	__isl_give isl_set *(*fn_dom)(__isl_take isl_set *set,
   1101 				    __isl_take isl_set *context),
   1102 	__isl_give isl_set *intersect_context(__isl_take isl_set *set,
   1103 		__isl_take isl_set *context))
   1104 {
   1105 	int i;
   1106 	int is_universe;
   1107 
   1108 	pw = FN(PW,sort_unique)(pw);
   1109 	if (!pw || !context)
   1110 		goto error;
   1111 
   1112 	if (pw->n == 0) {
   1113 		isl_set_free(context);
   1114 		return pw;
   1115 	}
   1116 
   1117 	is_universe = isl_set_plain_is_universe(context);
   1118 	if (is_universe < 0)
   1119 		goto error;
   1120 	if (is_universe) {
   1121 		isl_set_free(context);
   1122 		return pw;
   1123 	}
   1124 
   1125 	FN(PW,align_params_set)(&pw, &context);
   1126 
   1127 	pw = FN(PW,cow)(pw);
   1128 	if (!pw)
   1129 		goto error;
   1130 
   1131 	if (pw->n == 1) {
   1132 		int equal;
   1133 
   1134 		equal = isl_set_plain_is_equal(pw->p[0].set, context);
   1135 		if (equal < 0)
   1136 			goto error;
   1137 		if (equal)
   1138 			return FN(PW,gist_last)(pw, context);
   1139 	}
   1140 
   1141 	context = isl_set_compute_divs(context);
   1142 
   1143 	for (i = pw->n - 1; i >= 0; --i) {
   1144 		isl_set *set_i;
   1145 		EL *el;
   1146 		int empty;
   1147 
   1148 		if (i == pw->n - 1) {
   1149 			int equal;
   1150 			equal = isl_set_plain_is_equal(pw->p[i].set, context);
   1151 			if (equal < 0)
   1152 				goto error;
   1153 			if (equal)
   1154 				return FN(PW,gist_last)(pw, context);
   1155 		}
   1156 		set_i = FN(PW,get_domain_at)(pw, i);
   1157 		set_i = intersect_context(set_i, isl_set_copy(context));
   1158 		empty = isl_set_plain_is_empty(set_i);
   1159 		el = FN(PW,take_base_at)(pw, i);
   1160 		el = FN(EL,gist)(el, set_i);
   1161 		pw = FN(PW,restore_base_at)(pw, i, el);
   1162 		set_i = FN(PW,take_domain_at)(pw, i);
   1163 		set_i = fn_dom(set_i, isl_set_copy(context));
   1164 		pw = FN(PW,restore_domain_at)(pw, i, set_i);
   1165 		if (empty < 0 || !pw)
   1166 			goto error;
   1167 		if (empty) {
   1168 			isl_set_free(pw->p[i].set);
   1169 			FN(EL,free)(pw->p[i].FIELD);
   1170 			if (i != pw->n - 1)
   1171 				pw->p[i] = pw->p[pw->n - 1];
   1172 			pw->n--;
   1173 		}
   1174 	}
   1175 
   1176 	isl_set_free(context);
   1177 
   1178 	return pw;
   1179 error:
   1180 	FN(PW,free)(pw);
   1181 	isl_set_free(context);
   1182 	return NULL;
   1183 }
   1184 
   1185 __isl_give PW *FN(PW,gist)(__isl_take PW *pw, __isl_take isl_set *context)
   1186 {
   1187 	return FN(PW,gist_fn)(pw, context, &isl_set_gist,
   1188 					&isl_set_intersect);
   1189 }
   1190 
   1191 __isl_give PW *FN(PW,gist_params)(__isl_take PW *pw,
   1192 	__isl_take isl_set *context)
   1193 {
   1194 	return FN(PW,gist_fn)(pw, context, &isl_set_gist_params,
   1195 					&isl_set_intersect_params);
   1196 }
   1197 
   1198 /* Coalesce the domains of "pw".
   1199  *
   1200  * Prior to the actual coalescing, first sort the pieces such that
   1201  * pieces with the same function value expression are combined
   1202  * into a single piece, the combined domain of which can then
   1203  * be coalesced.
   1204  */
   1205 __isl_give PW *FN(PW,coalesce)(__isl_take PW *pw)
   1206 {
   1207 	int i;
   1208 	isl_size n;
   1209 
   1210 	pw = FN(PW,sort_unique)(pw);
   1211 	n = FN(PW,n_piece)(pw);
   1212 	if (n < 0)
   1213 		return FN(PW,free)(pw);
   1214 
   1215 	for (i = 0; i < n; ++i) {
   1216 		pw->p[i].set = isl_set_coalesce(pw->p[i].set);
   1217 		if (!pw->p[i].set)
   1218 			goto error;
   1219 	}
   1220 
   1221 	return pw;
   1222 error:
   1223 	FN(PW,free)(pw);
   1224 	return NULL;
   1225 }
   1226 
   1227 isl_ctx *FN(PW,get_ctx)(__isl_keep PW *pw)
   1228 {
   1229 	return pw ? isl_space_get_ctx(pw->dim) : NULL;
   1230 }
   1231 
   1232 isl_bool FN(PW,involves_dims)(__isl_keep PW *pw, enum isl_dim_type type,
   1233 	unsigned first, unsigned n)
   1234 {
   1235 	int i;
   1236 	enum isl_dim_type set_type;
   1237 
   1238 	if (!pw)
   1239 		return isl_bool_error;
   1240 	if (pw->n == 0 || n == 0)
   1241 		return isl_bool_false;
   1242 
   1243 	set_type = type == isl_dim_in ? isl_dim_set : type;
   1244 
   1245 	for (i = 0; i < pw->n; ++i) {
   1246 		isl_bool involves = FN(EL,involves_dims)(pw->p[i].FIELD,
   1247 							type, first, n);
   1248 		if (involves < 0 || involves)
   1249 			return involves;
   1250 		involves = isl_set_involves_dims(pw->p[i].set,
   1251 							set_type, first, n);
   1252 		if (involves < 0 || involves)
   1253 			return involves;
   1254 	}
   1255 	return isl_bool_false;
   1256 }
   1257 
   1258 __isl_give PW *FN(PW,set_dim_name)(__isl_take PW *pw,
   1259 	enum isl_dim_type type, unsigned pos, const char *s)
   1260 {
   1261 	isl_space *space;
   1262 
   1263 	space = FN(PW,get_space)(pw);
   1264 	space = isl_space_set_dim_name(space, type, pos, s);
   1265 	return FN(PW,reset_space)(pw, space);
   1266 }
   1267 
   1268 __isl_give PW *FN(PW,drop_dims)(__isl_take PW *pw,
   1269 	enum isl_dim_type type, unsigned first, unsigned n)
   1270 {
   1271 	int i;
   1272 	isl_size n_piece;
   1273 	enum isl_dim_type set_type;
   1274 	isl_space *space;
   1275 
   1276 	n_piece = FN(PW,n_piece)(pw);
   1277 	if (n_piece < 0)
   1278 		return FN(PW,free)(pw);
   1279 	if (n == 0 && !isl_space_get_tuple_name(pw->dim, type))
   1280 		return pw;
   1281 
   1282 	set_type = type == isl_dim_in ? isl_dim_set : type;
   1283 
   1284 	space = FN(PW,take_space)(pw);
   1285 	space = isl_space_drop_dims(space, type, first, n);
   1286 	pw = FN(PW,restore_space)(pw, space);
   1287 	for (i = 0; i < n_piece; ++i) {
   1288 		isl_set *domain;
   1289 		EL *el;
   1290 
   1291 		el = FN(PW,take_base_at)(pw, i);
   1292 		el = FN(EL,drop_dims)(el, type, first, n);
   1293 		pw = FN(PW,restore_base_at)(pw, i, el);
   1294 		if (type == isl_dim_out)
   1295 			continue;
   1296 		domain = FN(PW,take_domain_at)(pw, i);
   1297 		domain = isl_set_drop(domain, set_type, first, n);
   1298 		pw = FN(PW,restore_domain_at)(pw, i, domain);
   1299 	}
   1300 
   1301 	return pw;
   1302 }
   1303 
   1304 /* This function is very similar to drop_dims.
   1305  * The only difference is that the cells may still involve
   1306  * the specified dimensions.  They are removed using
   1307  * isl_set_project_out instead of isl_set_drop.
   1308  */
   1309 __isl_give PW *FN(PW,project_out)(__isl_take PW *pw,
   1310 	enum isl_dim_type type, unsigned first, unsigned n)
   1311 {
   1312 	int i;
   1313 	isl_size n_piece;
   1314 	enum isl_dim_type set_type;
   1315 	isl_space *space;
   1316 
   1317 	n_piece = FN(PW,n_piece)(pw);
   1318 	if (n_piece < 0)
   1319 		return FN(PW,free)(pw);
   1320 	if (n == 0 && !isl_space_get_tuple_name(pw->dim, type))
   1321 		return pw;
   1322 
   1323 	set_type = type == isl_dim_in ? isl_dim_set : type;
   1324 
   1325 	space = FN(PW,take_space)(pw);
   1326 	space = isl_space_drop_dims(space, type, first, n);
   1327 	pw = FN(PW,restore_space)(pw, space);
   1328 	for (i = 0; i < n_piece; ++i) {
   1329 		isl_set *domain;
   1330 		EL *el;
   1331 
   1332 		domain = FN(PW,take_domain_at)(pw, i);
   1333 		domain = isl_set_project_out(domain, set_type, first, n);
   1334 		pw = FN(PW,restore_domain_at)(pw, i, domain);
   1335 		el = FN(PW,take_base_at)(pw, i);
   1336 		el = FN(EL,drop_dims)(el, type, first, n);
   1337 		pw = FN(PW,restore_base_at)(pw, i, el);
   1338 	}
   1339 
   1340 	return pw;
   1341 }
   1342 
   1343 /* Project the domain of pw onto its parameter space.
   1344  */
   1345 __isl_give PW *FN(PW,project_domain_on_params)(__isl_take PW *pw)
   1346 {
   1347 	isl_space *space;
   1348 	isl_size n;
   1349 
   1350 	n = FN(PW,dim)(pw, isl_dim_in);
   1351 	if (n < 0)
   1352 		return FN(PW,free)(pw);
   1353 	pw = FN(PW,project_out)(pw, isl_dim_in, 0, n);
   1354 	space = FN(PW,get_domain_space)(pw);
   1355 	space = isl_space_params(space);
   1356 	pw = FN(PW,reset_domain_space)(pw, space);
   1357 	return pw;
   1358 }
   1359 
   1360 #undef TYPE
   1361 #define TYPE	PW
   1362 #include "isl_drop_unused_params_templ.c"
   1363 
   1364 isl_size FN(PW,dim)(__isl_keep PW *pw, enum isl_dim_type type)
   1365 {
   1366 	return isl_space_dim(FN(PW,peek_space)(pw), type);
   1367 }
   1368 
   1369 __isl_give isl_space *FN(PW,get_domain_space)(__isl_keep PW *pw)
   1370 {
   1371 	return pw ? isl_space_domain(isl_space_copy(pw->dim)) : NULL;
   1372 }
   1373 
   1374 /* Return the position of the dimension of the given type and name
   1375  * in "pw".
   1376  * Return -1 if no such dimension can be found.
   1377  */
   1378 int FN(PW,find_dim_by_name)(__isl_keep PW *pw,
   1379 	enum isl_dim_type type, const char *name)
   1380 {
   1381 	if (!pw)
   1382 		return -1;
   1383 	return isl_space_find_dim_by_name(pw->dim, type, name);
   1384 }
   1385 
   1386 /* Return the position of the dimension of the given type and identifier
   1387  * in "pw".
   1388  * Return -1 if no such dimension can be found.
   1389  */
   1390 static int FN(PW,find_dim_by_id)(__isl_keep PW *pw,
   1391 	enum isl_dim_type type, __isl_keep isl_id *id)
   1392 {
   1393 	isl_space *space;
   1394 
   1395 	space = FN(PW,peek_space)(pw);
   1396 	return isl_space_find_dim_by_id(space, type, id);
   1397 }
   1398 
   1399 /* Does the piecewise expression "pw" depend in any way
   1400  * on the parameter with identifier "id"?
   1401  */
   1402 isl_bool FN(PW,involves_param_id)(__isl_keep PW *pw, __isl_keep isl_id *id)
   1403 {
   1404 	int pos;
   1405 
   1406 	if (!pw || !id)
   1407 		return isl_bool_error;
   1408 	if (pw->n == 0)
   1409 		return isl_bool_false;
   1410 
   1411 	pos = FN(PW,find_dim_by_id)(pw, isl_dim_param, id);
   1412 	if (pos < 0)
   1413 		return isl_bool_false;
   1414 	return FN(PW,involves_dims)(pw, isl_dim_param, pos, 1);
   1415 }
   1416 
   1417 /* Reset the space of "pw".  Since we don't know if the elements
   1418  * represent the spaces themselves or their domains, we pass along
   1419  * both when we call their reset_space_and_domain.
   1420  */
   1421 static __isl_give PW *FN(PW,reset_space_and_domain)(__isl_take PW *pw,
   1422 	__isl_take isl_space *space, __isl_take isl_space *domain)
   1423 {
   1424 	int i;
   1425 	isl_size n;
   1426 
   1427 	n = FN(PW,n_piece)(pw);
   1428 	if (n < 0 || !space || !domain)
   1429 		goto error;
   1430 
   1431 	for (i = 0; i < n; ++i) {
   1432 		isl_set *set;
   1433 		EL *el;
   1434 
   1435 		set = FN(PW,take_domain_at)(pw, i);
   1436 		set = isl_set_reset_space(set, isl_space_copy(domain));
   1437 		pw = FN(PW,restore_domain_at)(pw, i, set);
   1438 		el = FN(PW,take_base_at)(pw, i);
   1439 		el = FN(EL,reset_space_and_domain)(el,
   1440 			      isl_space_copy(space), isl_space_copy(domain));
   1441 		pw = FN(PW,restore_base_at)(pw, i, el);
   1442 	}
   1443 
   1444 	isl_space_free(domain);
   1445 
   1446 	pw = FN(PW,restore_space)(pw, space);
   1447 
   1448 	return pw;
   1449 error:
   1450 	isl_space_free(domain);
   1451 	isl_space_free(space);
   1452 	FN(PW,free)(pw);
   1453 	return NULL;
   1454 }
   1455 
   1456 __isl_give PW *FN(PW,reset_domain_space)(__isl_take PW *pw,
   1457 	__isl_take isl_space *domain)
   1458 {
   1459 	isl_space *space;
   1460 
   1461 	space = isl_space_extend_domain_with_range(isl_space_copy(domain),
   1462 						   FN(PW,get_space)(pw));
   1463 	return FN(PW,reset_space_and_domain)(pw, space, domain);
   1464 }
   1465 
   1466 __isl_give PW *FN(PW,reset_space)(__isl_take PW *pw,
   1467 	__isl_take isl_space *space)
   1468 {
   1469 	isl_space *domain;
   1470 
   1471 	domain = isl_space_domain(isl_space_copy(space));
   1472 	return FN(PW,reset_space_and_domain)(pw, space, domain);
   1473 }
   1474 
   1475 __isl_give PW *FN(PW,set_tuple_id)(__isl_take PW *pw, enum isl_dim_type type,
   1476 	__isl_take isl_id *id)
   1477 {
   1478 	isl_space *space;
   1479 
   1480 	pw = FN(PW,cow)(pw);
   1481 	if (!pw)
   1482 		goto error;
   1483 
   1484 	space = FN(PW,get_space)(pw);
   1485 	space = isl_space_set_tuple_id(space, type, id);
   1486 
   1487 	return FN(PW,reset_space)(pw, space);
   1488 error:
   1489 	isl_id_free(id);
   1490 	return FN(PW,free)(pw);
   1491 }
   1492 
   1493 /* Drop the id on the specified tuple.
   1494  */
   1495 __isl_give PW *FN(PW,reset_tuple_id)(__isl_take PW *pw, enum isl_dim_type type)
   1496 {
   1497 	isl_space *space;
   1498 
   1499 	if (!pw)
   1500 		return NULL;
   1501 	if (!FN(PW,has_tuple_id)(pw, type))
   1502 		return pw;
   1503 
   1504 	pw = FN(PW,cow)(pw);
   1505 	if (!pw)
   1506 		return NULL;
   1507 
   1508 	space = FN(PW,get_space)(pw);
   1509 	space = isl_space_reset_tuple_id(space, type);
   1510 
   1511 	return FN(PW,reset_space)(pw, space);
   1512 }
   1513 
   1514 __isl_give PW *FN(PW,set_dim_id)(__isl_take PW *pw,
   1515 	enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)
   1516 {
   1517 	isl_space *space;
   1518 
   1519 	space = FN(PW,get_space)(pw);
   1520 	space = isl_space_set_dim_id(space, type, pos, id);
   1521 	return FN(PW,reset_space)(pw, space);
   1522 }
   1523 
   1524 /* Reset the user pointer on all identifiers of parameters and tuples
   1525  * of the space of "pw".
   1526  */
   1527 __isl_give PW *FN(PW,reset_user)(__isl_take PW *pw)
   1528 {
   1529 	isl_space *space;
   1530 
   1531 	space = FN(PW,get_space)(pw);
   1532 	space = isl_space_reset_user(space);
   1533 
   1534 	return FN(PW,reset_space)(pw, space);
   1535 }
   1536 
   1537 isl_size FN(PW,n_piece)(__isl_keep PW *pw)
   1538 {
   1539 	return pw ? pw->n : isl_size_error;
   1540 }
   1541 
   1542 isl_stat FN(PW,foreach_piece)(__isl_keep PW *pw,
   1543 	isl_stat (*fn)(__isl_take isl_set *set, __isl_take EL *el, void *user),
   1544 	void *user)
   1545 {
   1546 	int i;
   1547 
   1548 	if (!pw)
   1549 		return isl_stat_error;
   1550 
   1551 	for (i = 0; i < pw->n; ++i)
   1552 		if (fn(isl_set_copy(pw->p[i].set),
   1553 				FN(EL,copy)(pw->p[i].FIELD), user) < 0)
   1554 			return isl_stat_error;
   1555 
   1556 	return isl_stat_ok;
   1557 }
   1558 
   1559 /* Does "test" succeed on every cell of "pw"?
   1560  */
   1561 isl_bool FN(PW,every_piece)(__isl_keep PW *pw,
   1562 	isl_bool (*test)(__isl_keep isl_set *set,
   1563 		__isl_keep EL *el, void *user), void *user)
   1564 {
   1565 	int i;
   1566 
   1567 	if (!pw)
   1568 		return isl_bool_error;
   1569 
   1570 	for (i = 0; i < pw->n; ++i) {
   1571 		isl_bool r;
   1572 
   1573 		r = test(pw->p[i].set, pw->p[i].FIELD, user);
   1574 		if (r < 0 || !r)
   1575 			return r;
   1576 	}
   1577 
   1578 	return isl_bool_true;
   1579 }
   1580 
   1581 /* Is "pw" defined over a single universe domain?
   1582  *
   1583  * If the default value of this piecewise type is zero,
   1584  * then a "pw" with a zero number of cells is also accepted
   1585  * as it represents the default zero value.
   1586  */
   1587 isl_bool FN(FN(PW,isa),BASE)(__isl_keep PW *pw)
   1588 {
   1589 	isl_size n;
   1590 
   1591 	n = FN(PW,n_piece)(pw);
   1592 	if (n < 0)
   1593 		return isl_bool_error;
   1594 	if (DEFAULT_IS_ZERO && n == 0)
   1595 		return isl_bool_true;
   1596 	if (n != 1)
   1597 		return isl_bool_false;
   1598 	return isl_set_plain_is_universe(FN(PW,peek_domain_at)(pw, 0));
   1599 }
   1600 
   1601 /* Return a zero base expression in the same space (and of the same type)
   1602  * as "pw".
   1603  */
   1604 static __isl_give EL *FN(EL,zero_like_type)(__isl_take PW *pw OPT_TYPE_PARAM)
   1605 {
   1606 	isl_space *space;
   1607 
   1608 	space = FN(PW,get_space)(pw);
   1609 	FN(PW,free)(pw);
   1610 	return FN(EL,zero_in_space)(space OPT_TYPE_ARG(NO_LOC));
   1611 }
   1612 
   1613 #ifndef HAS_TYPE
   1614 /* Return a zero base expression in the same space as "pw".
   1615  */
   1616 static __isl_give EL *FN(EL,zero_like)(__isl_take PW *pw)
   1617 {
   1618 	return FN(EL,zero_like_type)(pw);
   1619 }
   1620 #else
   1621 /* Return a zero base expression in the same space and of the same type
   1622  * as "pw".
   1623  *
   1624  * Pass along the type as an explicit argument for uniform handling
   1625  * in isl_*_zero_like_type.
   1626  */
   1627 static __isl_give EL *FN(EL,zero_like)(__isl_take PW *pw)
   1628 {
   1629 	enum isl_fold type;
   1630 
   1631 	type = FN(PW,get_type)(pw);
   1632 	if (type < 0)
   1633 		goto error;
   1634 	return FN(EL,zero_like_type)(pw, type);
   1635 error:
   1636 	FN(PW,free)(pw);
   1637 	return NULL;
   1638 }
   1639 #endif
   1640 
   1641 /* Given that "pw" is defined over a single universe domain,
   1642  * return the base expression associated to this domain.
   1643  *
   1644  * If the number of cells is zero, then "pw" is of a piecewise type
   1645  * with a default zero value and effectively represents zero.
   1646  * In this case, create a zero base expression in the same space
   1647  * (and with the same type).
   1648  * Otherwise, simply extract the associated base expression.
   1649  */
   1650 __isl_give EL *FN(FN(PW,as),BASE)(__isl_take PW *pw)
   1651 {
   1652 	isl_bool is_total;
   1653 	isl_size n;
   1654 	EL *el;
   1655 
   1656 	is_total = FN(FN(PW,isa),BASE)(pw);
   1657 	if (is_total < 0)
   1658 		goto error;
   1659 	if (!is_total)
   1660 		isl_die(FN(PW,get_ctx)(pw), isl_error_invalid,
   1661 			"expecting single total function", goto error);
   1662 	n = FN(PW,n_piece)(pw);
   1663 	if (n < 0)
   1664 		goto error;
   1665 	if (n == 0)
   1666 		return FN(EL,zero_like)(pw);
   1667 	el = FN(PW,take_base_at)(pw, 0);
   1668 	FN(PW,free)(pw);
   1669 	return el;
   1670 error:
   1671 	FN(PW,free)(pw);
   1672 	return NULL;
   1673 }
   1674 
   1675 #ifdef HAS_TYPE
   1676 /* Negate the type of "pw".
   1677  */
   1678 static __isl_give PW *FN(PW,negate_type)(__isl_take PW *pw)
   1679 {
   1680 	pw = FN(PW,cow)(pw);
   1681 	if (!pw)
   1682 		return NULL;
   1683 	pw->type = isl_fold_type_negate(pw->type);
   1684 	return pw;
   1685 }
   1686 #else
   1687 /* Negate the type of "pw".
   1688  * Since "pw" does not have a type, do nothing.
   1689  */
   1690 static __isl_give PW *FN(PW,negate_type)(__isl_take PW *pw)
   1691 {
   1692 	return pw;
   1693 }
   1694 #endif
   1695 
   1696 /* Multiply the pieces of "pw" by "v" and return the result.
   1697  */
   1698 __isl_give PW *FN(PW,scale_val)(__isl_take PW *pw, __isl_take isl_val *v)
   1699 {
   1700 	int i;
   1701 	isl_size n;
   1702 
   1703 	if (!pw || !v)
   1704 		goto error;
   1705 
   1706 	if (isl_val_is_one(v)) {
   1707 		isl_val_free(v);
   1708 		return pw;
   1709 	}
   1710 	if (pw && DEFAULT_IS_ZERO && isl_val_is_zero(v)) {
   1711 		PW *zero;
   1712 		isl_space *space = FN(PW,get_space)(pw);
   1713 		zero = FN(PW,ZERO)(space OPT_TYPE_ARG(pw->));
   1714 		FN(PW,free)(pw);
   1715 		isl_val_free(v);
   1716 		return zero;
   1717 	}
   1718 	if (isl_val_is_neg(v))
   1719 		pw = FN(PW,negate_type)(pw);
   1720 	n = FN(PW,n_piece)(pw);
   1721 	if (n < 0)
   1722 		goto error;
   1723 
   1724 	for (i = 0; i < n; ++i) {
   1725 		EL *el;
   1726 
   1727 		el = FN(PW,take_base_at)(pw, i);
   1728 		el = FN(EL,scale_val)(el, isl_val_copy(v));
   1729 		pw = FN(PW,restore_base_at)(pw, i, el);
   1730 	}
   1731 
   1732 	isl_val_free(v);
   1733 	return pw;
   1734 error:
   1735 	isl_val_free(v);
   1736 	FN(PW,free)(pw);
   1737 	return NULL;
   1738 }
   1739 
   1740 /* Divide the pieces of "pw" by "v" and return the result.
   1741  */
   1742 __isl_give PW *FN(PW,scale_down_val)(__isl_take PW *pw, __isl_take isl_val *v)
   1743 {
   1744 	int i;
   1745 	isl_size n;
   1746 
   1747 	if (!pw || !v)
   1748 		goto error;
   1749 
   1750 	if (isl_val_is_one(v)) {
   1751 		isl_val_free(v);
   1752 		return pw;
   1753 	}
   1754 
   1755 	if (!isl_val_is_rat(v))
   1756 		isl_die(isl_val_get_ctx(v), isl_error_invalid,
   1757 			"expecting rational factor", goto error);
   1758 	if (isl_val_is_zero(v))
   1759 		isl_die(isl_val_get_ctx(v), isl_error_invalid,
   1760 			"cannot scale down by zero", goto error);
   1761 
   1762 	if (isl_val_is_neg(v))
   1763 		pw = FN(PW,negate_type)(pw);
   1764 	n = FN(PW,n_piece)(pw);
   1765 	if (n < 0)
   1766 		goto error;
   1767 
   1768 	for (i = 0; i < n; ++i) {
   1769 		EL *el;
   1770 
   1771 		el = FN(PW,take_base_at)(pw, i);
   1772 		el = FN(EL,scale_down_val)(el, isl_val_copy(v));
   1773 		pw = FN(PW,restore_base_at)(pw, i, el);
   1774 	}
   1775 
   1776 	isl_val_free(v);
   1777 	return pw;
   1778 error:
   1779 	isl_val_free(v);
   1780 	FN(PW,free)(pw);
   1781 	return NULL;
   1782 }
   1783 
   1784 /* Apply some normalization to "pw".
   1785  * In particular, sort the pieces according to their function value
   1786  * expressions, combining pairs of adjacent pieces with
   1787  * the same such expression, and then normalize the domains of the pieces.
   1788  *
   1789  * We normalize in place, but if anything goes wrong we need
   1790  * to return NULL, so we need to make sure we don't change the
   1791  * meaning of any possible other copies of "pw".
   1792  */
   1793 static __isl_give PW *FN(PW,normalize)(__isl_take PW *pw)
   1794 {
   1795 	int i;
   1796 	isl_set *set;
   1797 
   1798 	pw = FN(PW,sort_unique)(pw);
   1799 	if (!pw)
   1800 		return NULL;
   1801 	for (i = 0; i < pw->n; ++i) {
   1802 		set = isl_set_normalize(isl_set_copy(pw->p[i].set));
   1803 		if (!set)
   1804 			return FN(PW,free)(pw);
   1805 		isl_set_free(pw->p[i].set);
   1806 		pw->p[i].set = set;
   1807 	}
   1808 
   1809 	return pw;
   1810 }
   1811 
   1812 /* Is pw1 obviously equal to pw2?
   1813  * That is, do they have obviously identical cells and obviously identical
   1814  * elements on each cell?
   1815  *
   1816  * If "pw1" or "pw2" contain any NaNs, then they are considered
   1817  * not to be the same.  A NaN is not equal to anything, not even
   1818  * to another NaN.
   1819  */
   1820 isl_bool FN(PW,plain_is_equal)(__isl_keep PW *pw1, __isl_keep PW *pw2)
   1821 {
   1822 	int i;
   1823 	isl_bool equal, has_nan;
   1824 
   1825 	if (!pw1 || !pw2)
   1826 		return isl_bool_error;
   1827 
   1828 	has_nan = FN(PW,involves_nan)(pw1);
   1829 	if (has_nan >= 0 && !has_nan)
   1830 		has_nan = FN(PW,involves_nan)(pw2);
   1831 	if (has_nan < 0 || has_nan)
   1832 		return isl_bool_not(has_nan);
   1833 
   1834 	if (pw1 == pw2)
   1835 		return isl_bool_true;
   1836 	equal = FN(PW,has_equal_space)(pw1, pw2);
   1837 	if (equal < 0 || !equal)
   1838 		return equal;
   1839 
   1840 	pw1 = FN(PW,copy)(pw1);
   1841 	pw2 = FN(PW,copy)(pw2);
   1842 	pw1 = FN(PW,normalize)(pw1);
   1843 	pw2 = FN(PW,normalize)(pw2);
   1844 	if (!pw1 || !pw2)
   1845 		goto error;
   1846 
   1847 	equal = isl_bool_ok(pw1->n == pw2->n);
   1848 	for (i = 0; equal && i < pw1->n; ++i) {
   1849 		equal = isl_set_plain_is_equal(pw1->p[i].set, pw2->p[i].set);
   1850 		if (equal < 0)
   1851 			goto error;
   1852 		if (!equal)
   1853 			break;
   1854 		equal = FN(EL,plain_is_equal)(pw1->p[i].FIELD, pw2->p[i].FIELD);
   1855 		if (equal < 0)
   1856 			goto error;
   1857 	}
   1858 
   1859 	FN(PW,free)(pw1);
   1860 	FN(PW,free)(pw2);
   1861 	return equal;
   1862 error:
   1863 	FN(PW,free)(pw1);
   1864 	FN(PW,free)(pw2);
   1865 	return isl_bool_error;
   1866 }
   1867 
   1868 /* Does "pw" involve any NaNs?
   1869  */
   1870 isl_bool FN(PW,involves_nan)(__isl_keep PW *pw)
   1871 {
   1872 	int i;
   1873 
   1874 	if (!pw)
   1875 		return isl_bool_error;
   1876 	if (pw->n == 0)
   1877 		return isl_bool_false;
   1878 
   1879 	for (i = 0; i < pw->n; ++i) {
   1880 		isl_bool has_nan = FN(EL,involves_nan)(pw->p[i].FIELD);
   1881 		if (has_nan < 0 || has_nan)
   1882 			return has_nan;
   1883 	}
   1884 
   1885 	return isl_bool_false;
   1886 }
   1887