X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=isl_pw_templ.c;h=39939740247bbf4587ec83d5282c53c383a35511;hb=63fb8a7f484648c3caa25351c8c94ac2395ec563;hp=281c2c1f2c5940f1b9fa13eda90b05c5b00806ad;hpb=7f72677722dcde9b795085c74bdbc40b996cc6c2;p=platform%2Fupstream%2Fisl.git diff --git a/isl_pw_templ.c b/isl_pw_templ.c index 281c2c1..3993974 100644 --- a/isl_pw_templ.c +++ b/isl_pw_templ.c @@ -1,3 +1,5 @@ +#include + #define xFN(TYPE,NAME) TYPE ## _ ## NAME #define FN(TYPE,NAME) xFN(TYPE,NAME) #define xS(TYPE,NAME) struct TYPE ## _ ## NAME @@ -99,9 +101,9 @@ __isl_give PW *FN(PW,alloc)(__isl_take isl_set *set, __isl_take EL *el) goto error; #ifdef HAS_TYPE - pw = FN(PW,alloc_size)(isl_set_get_space(set), type, 1); + pw = FN(PW,alloc_size)(FN(EL,get_space)(el), type, 1); #else - pw = FN(PW,alloc_size)(isl_set_get_space(set), 1); + pw = FN(PW,alloc_size)(FN(EL,get_space)(el), 1); #endif return FN(PW,add_piece)(pw, set, el); @@ -173,6 +175,43 @@ void *FN(PW,free)(__isl_take PW *pw) return NULL; } +const char *FN(PW,get_dim_name)(__isl_keep PW *pw, enum isl_dim_type type, + unsigned pos) +{ + return pw ? isl_space_get_dim_name(pw->dim, type, pos) : NULL; +} + +int FN(PW,has_dim_id)(__isl_keep PW *pw, enum isl_dim_type type, unsigned pos) +{ + return pw ? isl_space_has_dim_id(pw->dim, type, pos) : -1; +} + +__isl_give isl_id *FN(PW,get_dim_id)(__isl_keep PW *pw, enum isl_dim_type type, + unsigned pos) +{ + return pw ? isl_space_get_dim_id(pw->dim, type, pos) : NULL; +} + +int FN(PW,has_tuple_name)(__isl_keep PW *pw, enum isl_dim_type type) +{ + return pw ? isl_space_has_tuple_name(pw->dim, type) : -1; +} + +const char *FN(PW,get_tuple_name)(__isl_keep PW *pw, enum isl_dim_type type) +{ + return pw ? isl_space_get_tuple_name(pw->dim, type) : NULL; +} + +int FN(PW,has_tuple_id)(__isl_keep PW *pw, enum isl_dim_type type) +{ + return pw ? isl_space_has_tuple_id(pw->dim, type) : -1; +} + +__isl_give isl_id *FN(PW,get_tuple_id)(__isl_keep PW *pw, enum isl_dim_type type) +{ + return pw ? isl_space_get_tuple_id(pw->dim, type) : NULL; +} + int FN(PW,IS_ZERO)(__isl_keep PW *pw) { if (!pw) @@ -182,26 +221,27 @@ int FN(PW,IS_ZERO)(__isl_keep PW *pw) } #ifndef NO_REALIGN -__isl_give PW *FN(PW,realign)(__isl_take PW *pw, __isl_take isl_reordering *exp) +__isl_give PW *FN(PW,realign_domain)(__isl_take PW *pw, + __isl_take isl_reordering *exp) { int i; pw = FN(PW,cow)(pw); if (!pw || !exp) - return NULL; + goto error; for (i = 0; i < pw->n; ++i) { pw->p[i].set = isl_set_realign(pw->p[i].set, isl_reordering_copy(exp)); if (!pw->p[i].set) goto error; - pw->p[i].FIELD = FN(EL,realign)(pw->p[i].FIELD, + pw->p[i].FIELD = FN(EL,realign_domain)(pw->p[i].FIELD, isl_reordering_copy(exp)); if (!pw->p[i].FIELD) goto error; } - pw = FN(PW,reset_space)(pw, isl_space_copy(exp->dim)); + pw = FN(PW,reset_domain_space)(pw, isl_space_copy(exp->dim)); isl_reordering_free(exp); return pw; @@ -235,8 +275,9 @@ __isl_give PW *FN(PW,align_params)(__isl_take PW *pw, __isl_take isl_space *mode model = isl_space_drop_dims(model, isl_dim_out, 0, isl_space_dim(model, isl_dim_out)); exp = isl_parameter_alignment_reordering(pw->dim, model); - exp = isl_reordering_extend_space(exp, FN(PW,get_space)(pw)); - pw = FN(PW,realign)(pw, exp); + exp = isl_reordering_extend_space(exp, + FN(PW,get_domain_space)(pw)); + pw = FN(PW,realign_domain)(pw, exp); } isl_space_free(model); @@ -247,7 +288,7 @@ error: return NULL; } -static __isl_give PW *align_params_pw_pw_and(__isl_take PW *pw1, +static __isl_give PW *FN(PW,align_params_pw_pw_and)(__isl_take PW *pw1, __isl_take PW *pw2, __isl_give PW *(*fn)(__isl_take PW *pw1, __isl_take PW *pw2)) { @@ -271,7 +312,7 @@ error: return NULL; } -static __isl_give PW *align_params_pw_set_and(__isl_take PW *pw, +static __isl_give PW *FN(PW,align_params_pw_set_and)(__isl_take PW *pw, __isl_take isl_set *set, __isl_give PW *(*fn)(__isl_take PW *pw, __isl_take isl_set *set)) { @@ -296,7 +337,8 @@ error: } #endif -static __isl_give PW *FN(PW,add_aligned)(__isl_take PW *pw1, __isl_take PW *pw2) +static __isl_give PW *FN(PW,union_add_aligned)(__isl_take PW *pw1, + __isl_take PW *pw2) { int i, j, n; struct PW *res; @@ -336,14 +378,14 @@ static __isl_give PW *FN(PW,add_aligned)(__isl_take PW *pw1, __isl_take PW *pw2) for (j = 0; j < pw2->n; ++j) { struct isl_set *common; EL *sum; - set = isl_set_subtract(set, - isl_set_copy(pw2->p[j].set)); common = isl_set_intersect(isl_set_copy(pw1->p[i].set), isl_set_copy(pw2->p[j].set)); if (isl_set_plain_is_empty(common)) { isl_set_free(common); continue; } + set = isl_set_subtract(set, + isl_set_copy(pw2->p[j].set)); sum = FN(EL,add_on_domain)(common, FN(EL,copy)(pw1->p[i].FIELD), @@ -372,9 +414,13 @@ error: return NULL; } -__isl_give PW *FN(PW,add)(__isl_take PW *pw1, __isl_take PW *pw2) +/* Private version of "union_add". For isl_pw_qpolynomial and + * isl_pw_qpolynomial_fold, we prefer to simply call it "add". + */ +static __isl_give PW *FN(PW,union_add_)(__isl_take PW *pw1, __isl_take PW *pw2) { - return align_params_pw_pw_and(pw1, pw2, &FN(PW,add_aligned)); + return FN(PW,align_params_pw_pw_and)(pw1, pw2, + &FN(PW,union_add_aligned)); } /* Make sure "pw" has room for at least "n" more pieces. @@ -466,7 +512,99 @@ error: __isl_give PW *FN(PW,add_disjoint)(__isl_take PW *pw1, __isl_take PW *pw2) { - return align_params_pw_pw_and(pw1, pw2, &FN(PW,add_disjoint_aligned)); + return FN(PW,align_params_pw_pw_and)(pw1, pw2, + &FN(PW,add_disjoint_aligned)); +} + +/* This function is currently only used from isl_aff.c + */ +static __isl_give PW *FN(PW,on_shared_domain_in)(__isl_take PW *pw1, + __isl_take PW *pw2, __isl_take isl_space *space, + __isl_give EL *(*fn)(__isl_take EL *el1, __isl_take EL *el2)) + __attribute__ ((unused)); + +/* Apply "fn" to pairs of elements from pw1 and pw2 on shared domains. + * The result of "fn" (and therefore also of this function) lives in "space". + */ +static __isl_give PW *FN(PW,on_shared_domain_in)(__isl_take PW *pw1, + __isl_take PW *pw2, __isl_take isl_space *space, + __isl_give EL *(*fn)(__isl_take EL *el1, __isl_take EL *el2)) +{ + int i, j, n; + PW *res = NULL; + + if (!pw1 || !pw2) + goto error; + + n = pw1->n * pw2->n; +#ifdef HAS_TYPE + res = FN(PW,alloc_size)(isl_space_copy(space), pw1->type, n); +#else + res = FN(PW,alloc_size)(isl_space_copy(space), n); +#endif + + for (i = 0; i < pw1->n; ++i) { + for (j = 0; j < pw2->n; ++j) { + isl_set *common; + EL *res_ij; + int empty; + + common = isl_set_intersect( + isl_set_copy(pw1->p[i].set), + isl_set_copy(pw2->p[j].set)); + empty = isl_set_plain_is_empty(common); + if (empty < 0 || empty) { + isl_set_free(common); + if (empty < 0) + goto error; + continue; + } + + res_ij = fn(FN(EL,copy)(pw1->p[i].FIELD), + FN(EL,copy)(pw2->p[j].FIELD)); + res_ij = FN(EL,gist)(res_ij, isl_set_copy(common)); + + res = FN(PW,add_piece)(res, common, res_ij); + } + } + + isl_space_free(space); + FN(PW,free)(pw1); + FN(PW,free)(pw2); + return res; +error: + isl_space_free(space); + FN(PW,free)(pw1); + FN(PW,free)(pw2); + FN(PW,free)(res); + return NULL; +} + +/* This function is currently only used from isl_aff.c + */ +static __isl_give PW *FN(PW,on_shared_domain)(__isl_take PW *pw1, + __isl_take PW *pw2, + __isl_give EL *(*fn)(__isl_take EL *el1, __isl_take EL *el2)) + __attribute__ ((unused)); + +/* Apply "fn" to pairs of elements from pw1 and pw2 on shared domains. + * The result of "fn" is assumed to live in the same space as "pw1" and "pw2". + */ +static __isl_give PW *FN(PW,on_shared_domain)(__isl_take PW *pw1, + __isl_take PW *pw2, + __isl_give EL *(*fn)(__isl_take EL *el1, __isl_take EL *el2)) +{ + isl_space *space; + + if (!pw1 || !pw2) + goto error; + + space = isl_space_copy(pw1->dim); + return FN(PW,on_shared_domain_in)(pw1, pw2, space, fn); +error: + FN(PW,free)(pw1); + FN(PW,free)(pw2); + return NULL; } #ifndef NO_NEG @@ -513,7 +651,8 @@ __isl_give isl_qpolynomial *FN(PW,eval)(__isl_take PW *pw, goto error; ctx = isl_point_get_ctx(pnt); pnt_dim = isl_point_get_space(pnt); - isl_assert(ctx, isl_space_is_equal(pnt_dim, pw->dim), goto error); + isl_assert(ctx, isl_space_is_domain_internal(pnt_dim, pw->dim), + goto error); for (i = 0; i < pw->n; ++i) { found = isl_set_contains_point(pw->p[i].set, pnt); @@ -526,7 +665,7 @@ __isl_give isl_qpolynomial *FN(PW,eval)(__isl_take PW *pw, qp = FN(EL,eval)(FN(EL,copy)(pw->p[i].FIELD), isl_point_copy(pnt)); else - qp = isl_qpolynomial_zero(isl_space_copy(pw->dim)); + qp = isl_qpolynomial_zero_on_domain(FN(PW,get_domain_space)(pw)); FN(PW,free)(pw); isl_space_free(pnt_dim); isl_point_free(pnt); @@ -547,7 +686,7 @@ __isl_give isl_set *FN(PW,domain)(__isl_take PW *pw) if (!pw) return NULL; - dom = isl_set_empty(isl_space_copy(pw->dim)); + dom = isl_set_empty(FN(PW,get_domain_space)(pw)); for (i = 0; i < pw->n; ++i) dom = isl_set_union_disjoint(dom, isl_set_copy(pw->p[i].set)); @@ -556,8 +695,14 @@ __isl_give isl_set *FN(PW,domain)(__isl_take PW *pw) return dom; } -static __isl_give PW *FN(PW,intersect_domain_aligned)(__isl_take PW *pw, - __isl_take isl_set *set) +/* Restrict the domain of "pw" by combining each cell + * with "set" through a call to "fn", where "fn" may be + * isl_set_intersect or isl_set_intersect_params. + */ +static __isl_give PW *FN(PW,intersect_aligned)(__isl_take PW *pw, + __isl_take isl_set *set, + __isl_give isl_set *(*fn)(__isl_take isl_set *set1, + __isl_take isl_set *set2)) { int i; @@ -575,12 +720,14 @@ static __isl_give PW *FN(PW,intersect_domain_aligned)(__isl_take PW *pw, for (i = pw->n - 1; i >= 0; --i) { isl_basic_set *aff; - pw->p[i].set = isl_set_intersect(pw->p[i].set, isl_set_copy(set)); + pw->p[i].set = fn(pw->p[i].set, isl_set_copy(set)); if (!pw->p[i].set) goto error; aff = isl_set_affine_hull(isl_set_copy(pw->p[i].set)); pw->p[i].FIELD = FN(EL,substitute_equalities)(pw->p[i].FIELD, aff); + if (!pw->p[i].FIELD) + goto error; if (isl_set_plain_is_empty(pw->p[i].set)) { isl_set_free(pw->p[i].set); FN(EL,free)(pw->p[i].FIELD); @@ -598,16 +745,41 @@ error: return NULL; } +static __isl_give PW *FN(PW,intersect_domain_aligned)(__isl_take PW *pw, + __isl_take isl_set *set) +{ + return FN(PW,intersect_aligned)(pw, set, &isl_set_intersect); +} + __isl_give PW *FN(PW,intersect_domain)(__isl_take PW *pw, __isl_take isl_set *context) { - return align_params_pw_set_and(pw, context, + return FN(PW,align_params_pw_set_and)(pw, context, &FN(PW,intersect_domain_aligned)); } -static __isl_give PW *FN(PW,gist_aligned)(__isl_take PW *pw, +static __isl_give PW *FN(PW,intersect_params_aligned)(__isl_take PW *pw, + __isl_take isl_set *set) +{ + return FN(PW,intersect_aligned)(pw, set, &isl_set_intersect_params); +} + +/* Intersect the domain of "pw" with the parameter domain "context". + */ +__isl_give PW *FN(PW,intersect_params)(__isl_take PW *pw, __isl_take isl_set *context) { + return FN(PW,align_params_pw_set_and)(pw, context, + &FN(PW,intersect_params_aligned)); +} + +static __isl_give PW *FN(PW,gist_aligned)(__isl_take PW *pw, + __isl_take isl_set *context, + __isl_give EL *(*fn_el)(__isl_take EL *el, + __isl_take isl_set *set), + __isl_give isl_set *(*fn_dom)(__isl_take isl_set *set, + __isl_take isl_basic_set *bset)) +{ int i; isl_basic_set *hull = NULL; @@ -633,17 +805,17 @@ static __isl_give PW *FN(PW,gist_aligned)(__isl_take PW *pw, goto error; for (i = pw->n - 1; i >= 0; --i) { - pw->p[i].set = isl_set_intersect(pw->p[i].set, + isl_set *set_i; + int empty; + + set_i = isl_set_intersect(isl_set_copy(pw->p[i].set), isl_set_copy(context)); - if (!pw->p[i].set) + empty = isl_set_plain_is_empty(set_i); + pw->p[i].FIELD = fn_el(pw->p[i].FIELD, set_i); + pw->p[i].set = fn_dom(pw->p[i].set, isl_basic_set_copy(hull)); + if (!pw->p[i].FIELD || !pw->p[i].set) goto error; - pw->p[i].FIELD = FN(EL,gist)(pw->p[i].FIELD, - isl_set_copy(pw->p[i].set)); - pw->p[i].set = isl_set_gist_basic_set(pw->p[i].set, - isl_basic_set_copy(hull)); - if (!pw->p[i].set) - goto error; - if (isl_set_plain_is_empty(pw->p[i].set)) { + if (empty) { isl_set_free(pw->p[i].set); FN(EL,free)(pw->p[i].FIELD); if (i != pw->n - 1) @@ -663,9 +835,31 @@ error: return NULL; } +static __isl_give PW *FN(PW,gist_domain_aligned)(__isl_take PW *pw, + __isl_take isl_set *set) +{ + return FN(PW,gist_aligned)(pw, set, &FN(EL,gist), + &isl_set_gist_basic_set); +} + __isl_give PW *FN(PW,gist)(__isl_take PW *pw, __isl_take isl_set *context) { - return align_params_pw_set_and(pw, context, &FN(PW,gist_aligned)); + return FN(PW,align_params_pw_set_and)(pw, context, + &FN(PW,gist_domain_aligned)); +} + +static __isl_give PW *FN(PW,gist_params_aligned)(__isl_take PW *pw, + __isl_take isl_set *set) +{ + return FN(PW,gist_aligned)(pw, set, &FN(EL,gist_params), + &isl_set_gist_params_basic_set); +} + +__isl_give PW *FN(PW,gist_params)(__isl_take PW *pw, + __isl_take isl_set *context) +{ + return FN(PW,align_params_pw_set_and)(pw, context, + &FN(PW,gist_params_aligned)); } __isl_give PW *FN(PW,coalesce)(__isl_take PW *pw) @@ -713,17 +907,22 @@ int FN(PW,involves_dims)(__isl_keep PW *pw, enum isl_dim_type type, unsigned first, unsigned n) { int i; + enum isl_dim_type set_type; if (!pw) return -1; if (pw->n == 0 || n == 0) return 0; + + set_type = type == isl_dim_in ? isl_dim_set : type; + for (i = 0; i < pw->n; ++i) { int involves = FN(EL,involves_dims)(pw->p[i].FIELD, type, first, n); if (involves < 0 || involves) return involves; - involves = isl_set_involves_dims(pw->p[i].set, type, first, n); + involves = isl_set_involves_dims(pw->p[i].set, + set_type, first, n); if (involves < 0 || involves) return involves; } @@ -735,17 +934,21 @@ __isl_give PW *FN(PW,set_dim_name)(__isl_take PW *pw, enum isl_dim_type type, unsigned pos, const char *s) { int i; + enum isl_dim_type set_type; pw = FN(PW,cow)(pw); if (!pw) return NULL; + set_type = type == isl_dim_in ? isl_dim_set : type; + pw->dim = isl_space_set_dim_name(pw->dim, type, pos, s); if (!pw->dim) goto error; for (i = 0; i < pw->n; ++i) { - pw->p[i].set = isl_set_set_dim_name(pw->p[i].set, type, pos, s); + pw->p[i].set = isl_set_set_dim_name(pw->p[i].set, + set_type, pos, s); if (!pw->p[i].set) goto error; pw->p[i].FIELD = FN(EL,set_dim_name)(pw->p[i].FIELD, type, pos, s); @@ -764,12 +967,56 @@ __isl_give PW *FN(PW,drop_dims)(__isl_take PW *pw, enum isl_dim_type type, unsigned first, unsigned n) { int i; + enum isl_dim_type set_type; + + if (!pw) + return NULL; + if (n == 0 && !isl_space_get_tuple_name(pw->dim, type)) + return pw; + + set_type = type == isl_dim_in ? isl_dim_set : type; + + pw = FN(PW,cow)(pw); + if (!pw) + return NULL; + pw->dim = isl_space_drop_dims(pw->dim, type, first, n); + if (!pw->dim) + goto error; + for (i = 0; i < pw->n; ++i) { + pw->p[i].FIELD = FN(EL,drop_dims)(pw->p[i].FIELD, type, first, n); + if (!pw->p[i].FIELD) + goto error; + if (type == isl_dim_out) + continue; + pw->p[i].set = isl_set_drop(pw->p[i].set, set_type, first, n); + if (!pw->p[i].set) + goto error; + } + + return pw; +error: + FN(PW,free)(pw); + return NULL; +} + +/* This function is very similar to drop_dims. + * The only difference is that the cells may still involve + * the specified dimensions. They are removed using + * isl_set_project_out instead of isl_set_drop. + */ +__isl_give PW *FN(PW,project_out)(__isl_take PW *pw, + enum isl_dim_type type, unsigned first, unsigned n) +{ + int i; + enum isl_dim_type set_type; if (!pw) return NULL; if (n == 0 && !isl_space_get_tuple_name(pw->dim, type)) return pw; + set_type = type == isl_dim_in ? isl_dim_set : type; + pw = FN(PW,cow)(pw); if (!pw) return NULL; @@ -777,7 +1024,8 @@ __isl_give PW *FN(PW,drop_dims)(__isl_take PW *pw, if (!pw->dim) goto error; for (i = 0; i < pw->n; ++i) { - pw->p[i].set = isl_set_drop(pw->p[i].set, type, first, n); + pw->p[i].set = isl_set_project_out(pw->p[i].set, + set_type, first, n); if (!pw->p[i].set) goto error; pw->p[i].FIELD = FN(EL,drop_dims)(pw->p[i].FIELD, type, first, n); @@ -790,6 +1038,21 @@ error: FN(PW,free)(pw); return NULL; } + +/* Project the domain of pw onto its parameter space. + */ +__isl_give PW *FN(PW,project_domain_on_params)(__isl_take PW *pw) +{ + isl_space *space; + unsigned n; + + n = FN(PW,dim)(pw, isl_dim_in); + pw = FN(PW,project_out)(pw, isl_dim_in, 0, n); + space = FN(PW,get_domain_space)(pw); + space = isl_space_params(space); + pw = FN(PW,reset_domain_space)(pw, space); + return pw; +} #endif #ifndef NO_INSERT_DIMS @@ -797,12 +1060,15 @@ __isl_give PW *FN(PW,insert_dims)(__isl_take PW *pw, enum isl_dim_type type, unsigned first, unsigned n) { int i; + enum isl_dim_type set_type; if (!pw) return NULL; if (n == 0 && !isl_space_is_named_or_nested(pw->dim, type)) return pw; + set_type = type == isl_dim_in ? isl_dim_set : type; + pw = FN(PW,cow)(pw); if (!pw) return NULL; @@ -813,7 +1079,7 @@ __isl_give PW *FN(PW,insert_dims)(__isl_take PW *pw, enum isl_dim_type type, for (i = 0; i < pw->n; ++i) { pw->p[i].set = isl_set_insert_dims(pw->p[i].set, - type, first, n); + set_type, first, n); if (!pw->p[i].set) goto error; pw->p[i].FIELD = FN(EL,insert_dims)(pw->p[i].FIELD, @@ -837,6 +1103,9 @@ __isl_give PW *FN(PW,fix_dim)(__isl_take PW *pw, if (!pw) return NULL; + if (type == isl_dim_in) + type = isl_dim_set; + pw = FN(PW,cow)(pw); if (!pw) return NULL; @@ -867,6 +1136,9 @@ __isl_give PW *FN(PW,split_dims)(__isl_take PW *pw, if (n == 0) return pw; + if (type == isl_dim_in) + type = isl_dim_set; + pw = FN(PW,cow)(pw); if (!pw) return NULL; @@ -901,7 +1173,7 @@ __isl_give isl_qpolynomial *FN(PW,opt)(__isl_take PW *pw, int max) if (pw->n == 0) { isl_space *dim = isl_space_copy(pw->dim); FN(PW,free)(pw); - return isl_qpolynomial_zero(dim); + return isl_qpolynomial_zero_on_domain(isl_space_domain(dim)); } opt = FN(EL,opt_on_domain)(FN(EL,copy)(pw->p[0].FIELD), @@ -936,34 +1208,91 @@ __isl_give isl_space *FN(PW,get_space)(__isl_keep PW *pw) return pw ? isl_space_copy(pw->dim) : NULL; } +__isl_give isl_space *FN(PW,get_domain_space)(__isl_keep PW *pw) +{ + return pw ? isl_space_domain(isl_space_copy(pw->dim)) : NULL; +} + #ifndef NO_RESET_DIM -__isl_give PW *FN(PW,reset_space)(__isl_take PW *pw, __isl_take isl_space *dim) +/* Reset the space of "pw". Since we don't know if the elements + * represent the spaces themselves or their domains, we pass along + * both when we call their reset_space_and_domain. + */ +static __isl_give PW *FN(PW,reset_space_and_domain)(__isl_take PW *pw, + __isl_take isl_space *space, __isl_take isl_space *domain) { int i; pw = FN(PW,cow)(pw); - if (!pw || !dim) + if (!pw || !space || !domain) goto error; for (i = 0; i < pw->n; ++i) { pw->p[i].set = isl_set_reset_space(pw->p[i].set, - isl_space_copy(dim)); + isl_space_copy(domain)); if (!pw->p[i].set) goto error; - pw->p[i].FIELD = FN(EL,reset_space)(pw->p[i].FIELD, - isl_space_copy(dim)); + pw->p[i].FIELD = FN(EL,reset_space_and_domain)(pw->p[i].FIELD, + isl_space_copy(space), isl_space_copy(domain)); if (!pw->p[i].FIELD) goto error; } + + isl_space_free(domain); + isl_space_free(pw->dim); - pw->dim = dim; + pw->dim = space; return pw; error: - isl_space_free(dim); + isl_space_free(domain); + isl_space_free(space); FN(PW,free)(pw); return NULL; } + +__isl_give PW *FN(PW,reset_domain_space)(__isl_take PW *pw, + __isl_take isl_space *domain) +{ + isl_space *space; + + space = isl_space_extend_domain_with_range(isl_space_copy(domain), + FN(PW,get_space)(pw)); + return FN(PW,reset_space_and_domain)(pw, space, domain); +} + +__isl_give PW *FN(PW,reset_space)(__isl_take PW *pw, __isl_take isl_space *dim) +{ + isl_space *domain; + + domain = isl_space_domain(isl_space_copy(dim)); + return FN(PW,reset_space_and_domain)(pw, dim, domain); +} + +__isl_give PW *FN(PW,set_tuple_id)(__isl_keep PW *pw, enum isl_dim_type type, + __isl_take isl_id *id) +{ + isl_space *space; + + pw = FN(PW,cow)(pw); + if (!pw) + return isl_id_free(id); + + space = FN(PW,get_space)(pw); + space = isl_space_set_tuple_id(space, type, id); + + return FN(PW,reset_space)(pw, space); +} + +__isl_give PW *FN(PW,set_dim_id)(__isl_take PW *pw, + enum isl_dim_type type, unsigned pos, __isl_take isl_id *id) +{ + pw = FN(PW,cow)(pw); + if (!pw) + return isl_id_free(id); + pw->dim = isl_space_set_dim_id(pw->dim, type, pos, id); + return FN(PW,reset_space)(pw, isl_space_copy(pw->dim)); +} #endif int FN(PW,has_equal_space)(__isl_keep PW *pw1, __isl_keep PW *pw2) @@ -975,7 +1304,8 @@ int FN(PW,has_equal_space)(__isl_keep PW *pw1, __isl_keep PW *pw2) } #ifndef NO_MORPH -__isl_give PW *FN(PW,morph)(__isl_take PW *pw, __isl_take isl_morph *morph) +__isl_give PW *FN(PW,morph_domain)(__isl_take PW *pw, + __isl_take isl_morph *morph) { int i; isl_ctx *ctx; @@ -984,14 +1314,14 @@ __isl_give PW *FN(PW,morph)(__isl_take PW *pw, __isl_take isl_morph *morph) goto error; ctx = isl_space_get_ctx(pw->dim); - isl_assert(ctx, isl_space_is_equal(pw->dim, morph->dom->dim), + isl_assert(ctx, isl_space_is_domain_internal(morph->dom->dim, pw->dim), goto error); pw = FN(PW,cow)(pw); if (!pw) goto error; - isl_space_free(pw->dim); - pw->dim = isl_space_copy(morph->ran->dim); + pw->dim = isl_space_extend_domain_with_range( + isl_space_copy(morph->ran->dim), pw->dim); if (!pw->dim) goto error; @@ -999,7 +1329,7 @@ __isl_give PW *FN(PW,morph)(__isl_take PW *pw, __isl_take isl_morph *morph) pw->p[i].set = isl_morph_set(isl_morph_copy(morph), pw->p[i].set); if (!pw->p[i].set) goto error; - pw->p[i].FIELD = FN(EL,morph)(pw->p[i].FIELD, + pw->p[i].FIELD = FN(EL,morph_domain)(pw->p[i].FIELD, isl_morph_copy(morph)); if (!pw->p[i].FIELD) goto error; @@ -1015,6 +1345,11 @@ error: } #endif +int FN(PW,n_piece)(__isl_keep PW *pw) +{ + return pw ? pw->n : 0; +} + int FN(PW,foreach_piece)(__isl_keep PW *pw, int (*fn)(__isl_take isl_set *set, __isl_take EL *el, void *user), void *user) @@ -1124,15 +1459,23 @@ __isl_give PW *FN(PW,move_dims)(__isl_take PW *pw, goto error; for (i = 0; i < pw->n; ++i) { + pw->p[i].FIELD = FN(EL,move_dims)(pw->p[i].FIELD, + dst_type, dst_pos, src_type, src_pos, n); + if (!pw->p[i].FIELD) + goto error; + } + + if (dst_type == isl_dim_in) + dst_type = isl_dim_set; + if (src_type == isl_dim_in) + src_type = isl_dim_set; + + for (i = 0; i < pw->n; ++i) { pw->p[i].set = isl_set_move_dims(pw->p[i].set, dst_type, dst_pos, src_type, src_pos, n); if (!pw->p[i].set) goto error; - pw->p[i].FIELD = FN(EL,move_dims)(pw->p[i].FIELD, - dst_type, dst_pos, src_type, src_pos, n); - if (!pw->p[i].FIELD) - goto error; } return pw; @@ -1148,7 +1491,7 @@ __isl_give PW *FN(PW,mul_isl_int)(__isl_take PW *pw, isl_int v) if (isl_int_is_one(v)) return pw; - if (pw && isl_int_is_zero(v)) { + if (pw && DEFAULT_IS_ZERO && isl_int_is_zero(v)) { PW *zero; isl_space *dim = FN(PW,get_space)(pw); #ifdef HAS_TYPE @@ -1185,3 +1528,251 @@ __isl_give PW *FN(PW,scale)(__isl_take PW *pw, isl_int v) { return FN(PW,mul_isl_int)(pw, v); } + +static int FN(PW,qsort_set_cmp)(const void *p1, const void *p2) +{ + isl_set *set1 = *(isl_set * const *)p1; + isl_set *set2 = *(isl_set * const *)p2; + + return isl_set_plain_cmp(set1, set2); +} + +/* We normalize in place, but if anything goes wrong we need + * to return NULL, so we need to make sure we don't change the + * meaning of any possible other copies of map. + */ +__isl_give PW *FN(PW,normalize)(__isl_take PW *pw) +{ + int i, j; + isl_set *set; + + if (!pw) + return NULL; + for (i = 0; i < pw->n; ++i) { + set = isl_set_normalize(isl_set_copy(pw->p[i].set)); + if (!set) + return FN(PW,free)(pw); + isl_set_free(pw->p[i].set); + pw->p[i].set = set; + } + qsort(pw->p, pw->n, sizeof(pw->p[0]), &FN(PW,qsort_set_cmp)); + for (i = pw->n - 1; i >= 1; --i) { + if (!isl_set_plain_is_equal(pw->p[i - 1].set, pw->p[i].set)) + continue; + if (!FN(EL,plain_is_equal)(pw->p[i - 1].FIELD, pw->p[i].FIELD)) + continue; + set = isl_set_union(isl_set_copy(pw->p[i - 1].set), + isl_set_copy(pw->p[i].set)); + if (!set) + return FN(PW,free)(pw); + isl_set_free(pw->p[i].set); + FN(EL,free)(pw->p[i].FIELD); + isl_set_free(pw->p[i - 1].set); + pw->p[i - 1].set = set; + for (j = i + 1; j < pw->n; ++j) + pw->p[j - 1] = pw->p[j]; + pw->n--; + } + + return pw; +} + +/* Is pw1 obviously equal to pw2? + * That is, do they have obviously identical cells and obviously identical + * elements on each cell? + */ +int FN(PW,plain_is_equal)(__isl_keep PW *pw1, __isl_keep PW *pw2) +{ + int i; + int equal; + + if (!pw1 || !pw2) + return -1; + + if (pw1 == pw2) + return 1; + if (!isl_space_is_equal(pw1->dim, pw2->dim)) + return 0; + + pw1 = FN(PW,copy)(pw1); + pw2 = FN(PW,copy)(pw2); + pw1 = FN(PW,normalize)(pw1); + pw2 = FN(PW,normalize)(pw2); + if (!pw1 || !pw2) + goto error; + + equal = pw1->n == pw2->n; + for (i = 0; equal && i < pw1->n; ++i) { + equal = isl_set_plain_is_equal(pw1->p[i].set, pw2->p[i].set); + if (equal < 0) + goto error; + if (!equal) + break; + equal = FN(EL,plain_is_equal)(pw1->p[i].FIELD, pw2->p[i].FIELD); + if (equal < 0) + goto error; + } + + FN(PW,free)(pw1); + FN(PW,free)(pw2); + return equal; +error: + FN(PW,free)(pw1); + FN(PW,free)(pw2); + return -1; +} + +#ifndef NO_PULLBACK +static __isl_give PW *FN(PW,align_params_pw_multi_aff_and)(__isl_take PW *pw, + __isl_take isl_multi_aff *ma, + __isl_give PW *(*fn)(__isl_take PW *pw, __isl_take isl_multi_aff *ma)) +{ + isl_ctx *ctx; + isl_space *ma_space; + + ma_space = isl_multi_aff_get_space(ma); + if (!pw || !ma || !ma_space) + goto error; + if (isl_space_match(pw->dim, isl_dim_param, ma_space, isl_dim_param)) { + isl_space_free(ma_space); + return fn(pw, ma); + } + ctx = FN(PW,get_ctx)(pw); + if (!isl_space_has_named_params(pw->dim) || + !isl_space_has_named_params(ma_space)) + isl_die(ctx, isl_error_invalid, + "unaligned unnamed parameters", goto error); + pw = FN(PW,align_params)(pw, ma_space); + ma = isl_multi_aff_align_params(ma, FN(PW,get_space)(pw)); + return fn(pw, ma); +error: + isl_space_free(ma_space); + FN(PW,free)(pw); + isl_multi_aff_free(ma); + return NULL; +} + +static __isl_give PW *FN(PW,align_params_pw_pw_multi_aff_and)(__isl_take PW *pw, + __isl_take isl_pw_multi_aff *pma, + __isl_give PW *(*fn)(__isl_take PW *pw, + __isl_take isl_pw_multi_aff *ma)) +{ + isl_ctx *ctx; + isl_space *pma_space; + + pma_space = isl_pw_multi_aff_get_space(pma); + if (!pw || !pma || !pma_space) + goto error; + if (isl_space_match(pw->dim, isl_dim_param, pma_space, isl_dim_param)) { + isl_space_free(pma_space); + return fn(pw, pma); + } + ctx = FN(PW,get_ctx)(pw); + if (!isl_space_has_named_params(pw->dim) || + !isl_space_has_named_params(pma_space)) + isl_die(ctx, isl_error_invalid, + "unaligned unnamed parameters", goto error); + pw = FN(PW,align_params)(pw, pma_space); + pma = isl_pw_multi_aff_align_params(pma, FN(PW,get_space)(pw)); + return fn(pw, pma); +error: + isl_space_free(pma_space); + FN(PW,free)(pw); + isl_pw_multi_aff_free(pma); + return NULL; +} + +/* Compute the pullback of "pw" by the function represented by "ma". + * In other words, plug in "ma" in "pw". + */ +static __isl_give PW *FN(PW,pullback_multi_aff_aligned)(__isl_take PW *pw, + __isl_take isl_multi_aff *ma) +{ + int i; + isl_space *space = NULL; + + ma = isl_multi_aff_align_divs(ma); + pw = FN(PW,cow)(pw); + if (!pw || !ma) + goto error; + + space = isl_space_join(isl_multi_aff_get_space(ma), + FN(PW,get_space)(pw)); + + for (i = 0; i < pw->n; ++i) { + pw->p[i].set = isl_set_preimage_multi_aff(pw->p[i].set, + isl_multi_aff_copy(ma)); + if (!pw->p[i].set) + goto error; + pw->p[i].FIELD = FN(EL,pullback_multi_aff)(pw->p[i].FIELD, + isl_multi_aff_copy(ma)); + if (!pw->p[i].FIELD) + goto error; + } + + pw = FN(PW,reset_space)(pw, space); + isl_multi_aff_free(ma); + return pw; +error: + isl_space_free(space); + isl_multi_aff_free(ma); + FN(PW,free)(pw); + return NULL; +} + +__isl_give PW *FN(PW,pullback_multi_aff)(__isl_take PW *pw, + __isl_take isl_multi_aff *ma) +{ + return FN(PW,align_params_pw_multi_aff_and)(pw, ma, + &FN(PW,pullback_multi_aff_aligned)); +} + +/* Compute the pullback of "pw" by the function represented by "pma". + * In other words, plug in "pma" in "pw". + */ +static __isl_give PW *FN(PW,pullback_pw_multi_aff_aligned)(__isl_take PW *pw, + __isl_take isl_pw_multi_aff *pma) +{ + int i; + PW *res; + + if (!pma) + goto error; + + if (pma->n == 0) { + isl_pw_multi_aff_free(pma); + res = FN(PW,empty)(FN(PW,get_space)(pw)); + FN(PW,free)(pw); + return res; + } + + res = FN(PW,pullback_multi_aff)(FN(PW,copy)(pw), + isl_multi_aff_copy(pma->p[0].maff)); + res = FN(PW,intersect_domain)(res, isl_set_copy(pma->p[0].set)); + + for (i = 1; i < pma->n; ++i) { + PW *res_i; + + res_i = FN(PW,pullback_multi_aff)(FN(PW,copy)(pw), + isl_multi_aff_copy(pma->p[i].maff)); + res_i = FN(PW,intersect_domain)(res_i, + isl_set_copy(pma->p[i].set)); + res = FN(PW,add_disjoint)(res, res_i); + } + + isl_pw_multi_aff_free(pma); + FN(PW,free)(pw); + return res; +error: + isl_pw_multi_aff_free(pma); + FN(PW,free)(pw); + return NULL; +} + +__isl_give PW *FN(PW,pullback_pw_multi_aff)(__isl_take PW *pw, + __isl_take isl_pw_multi_aff *pma) +{ + return FN(PW,align_params_pw_pw_multi_aff_and)(pw, pma, + &FN(PW,pullback_pw_multi_aff_aligned)); +} +#endif