X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=isl_input.c;h=c36dfef497b4a4751e9347f8bbfa5c1451ba66e0;hb=30af80d912554eeef1ffecf5b71a5537b65f5f32;hp=4b97aea6547c14b250a31ba9e52d69932181330a;hpb=892fb27ee14523cdd277639f82a7842e993b486d;p=platform%2Fupstream%2Fisl.git diff --git a/isl_input.c b/isl_input.c index 4b97aea..c36dfef 100644 --- a/isl_input.c +++ b/isl_input.c @@ -13,15 +13,18 @@ #include #include #include -#include -#include -#include -#include -#include "isl_stream.h" -#include "isl_map_private.h" -#include "isl_obj.h" +#include +#include +#include +#include +#include +#include +#include #include "isl_polynomial_private.h" -#include +#include +#include +#include +#include struct variable { char *name; @@ -88,7 +91,7 @@ static struct variable *variable_new(struct vars *v, const char *name, int len, int pos) { struct variable *var; - var = isl_alloc_type(v->ctx, struct variable); + var = isl_calloc_type(v->ctx, struct variable); if (!var) goto error; var->name = strdup(name); @@ -124,29 +127,63 @@ static int vars_pos(struct vars *v, const char *s, int len) return pos; } -static __isl_give isl_basic_map *set_name(__isl_take isl_basic_map *bmap, +static int vars_add_anon(struct vars *v) +{ + v->v = variable_new(v, "", 0, v->n); + + if (!v->v) + return -1; + v->n++; + + return 0; +} + +static __isl_give isl_map *set_name(__isl_take isl_map *map, enum isl_dim_type type, unsigned pos, char *name) { char *prime; - if (!bmap) + if (!map) return NULL; if (!name) - return bmap; + return map; prime = strchr(name, '\''); if (prime) *prime = '\0'; - bmap->dim = isl_dim_set_name(bmap->dim, type, pos, name); + map = isl_map_set_dim_name(map, type, pos, name); if (prime) *prime = '\''; - if (!bmap->dim) + return map; +} + +/* Obtain next token, with some preprocessing. + * In particular, evaluate expressions of the form x^y, + * with x and y values. + */ +static struct isl_token *next_token(struct isl_stream *s) +{ + struct isl_token *tok, *tok2; + + tok = isl_stream_next_token(s); + if (!tok || tok->type != ISL_TOKEN_VALUE) + return tok; + if (!isl_stream_eat_if_available(s, '^')) + return tok; + tok2 = isl_stream_next_token(s); + if (!tok2 || tok2->type != ISL_TOKEN_VALUE) { + isl_stream_error(s, tok2, "expecting constant value"); goto error; + } - return bmap; + isl_int_pow_ui(tok->u.v, tok->u.v, isl_int_get_ui(tok2->u.v)); + + isl_token_free(tok2); + return tok; error: - isl_basic_map_free(bmap); + isl_token_free(tok); + isl_token_free(tok2); return NULL; } @@ -154,7 +191,7 @@ static int accept_cst_factor(struct isl_stream *s, isl_int *f) { struct isl_token *tok; - tok = isl_stream_next_token(s); + tok = next_token(s); if (!tok || tok->type != ISL_TOKEN_VALUE) { isl_stream_error(s, tok, "expecting constant value"); goto error; @@ -173,22 +210,163 @@ error: return -1; } -static struct isl_vec *accept_affine(struct isl_stream *s, struct vars *v); +/* Given an affine expression aff, return an affine expression + * for aff % d, with d the next token on the stream, which is + * assumed to be a constant. + * + * We introduce an integer division q = [aff/d] and the result + * is set to aff - d q. + */ +static __isl_give isl_pw_aff *affine_mod(struct isl_stream *s, + struct vars *v, __isl_take isl_pw_aff *aff) +{ + struct isl_token *tok; + isl_pw_aff *q; + + tok = next_token(s); + if (!tok || tok->type != ISL_TOKEN_VALUE) { + isl_stream_error(s, tok, "expecting constant value"); + goto error; + } + + q = isl_pw_aff_copy(aff); + q = isl_pw_aff_scale_down(q, tok->u.v); + q = isl_pw_aff_floor(q); + q = isl_pw_aff_scale(q, tok->u.v); + + aff = isl_pw_aff_sub(aff, q); -static __isl_give isl_vec *accept_affine_factor(struct isl_stream *s, - struct vars *v) + isl_token_free(tok); + return aff; +error: + isl_pw_aff_free(aff); + isl_token_free(tok); + return NULL; +} + +static __isl_give isl_pw_aff *accept_affine(struct isl_stream *s, + __isl_take isl_space *dim, struct vars *v); +static __isl_give isl_pw_aff_list *accept_affine_list(struct isl_stream *s, + __isl_take isl_space *dim, struct vars *v); + +static __isl_give isl_pw_aff *accept_minmax(struct isl_stream *s, + __isl_take isl_space *dim, struct vars *v) { - struct isl_token *tok = NULL; - isl_vec *aff = NULL; + struct isl_token *tok; + isl_pw_aff_list *list = NULL; + int min; tok = isl_stream_next_token(s); + if (!tok) + goto error; + min = tok->type == ISL_TOKEN_MIN; + isl_token_free(tok); + + if (isl_stream_eat(s, '(')) + goto error; + + list = accept_affine_list(s, isl_space_copy(dim), v); + if (!list) + goto error; + + if (isl_stream_eat(s, ')')) + goto error; + + isl_space_free(dim); + return min ? isl_pw_aff_list_min(list) : isl_pw_aff_list_max(list); +error: + isl_space_free(dim); + isl_pw_aff_list_free(list); + return NULL; +} + +static __isl_give isl_pw_aff *accept_div(struct isl_stream *s, + __isl_take isl_space *dim, struct vars *v) +{ + struct isl_token *tok; + int seen_paren = 0; + int f = 0; + int c = 0; + isl_pw_aff *pwaff = NULL; + + if (isl_stream_eat_if_available(s, ISL_TOKEN_FLOORD)) + f = 1; + else if (isl_stream_eat_if_available(s, ISL_TOKEN_CEILD)) + c = 1; + if (f || c) { + if (isl_stream_eat(s, '(')) + goto error; + } else { + if (isl_stream_eat(s, '[')) + goto error; + if (isl_stream_eat_if_available(s, '(')) + seen_paren = 1; + } + + pwaff = accept_affine(s, isl_space_copy(dim), v); + + if (f || c) { + if (isl_stream_eat(s, ',')) + goto error; + } else { + if (seen_paren && isl_stream_eat(s, ')')) + goto error; + if (isl_stream_eat(s, '/')) + goto error; + } + + tok = next_token(s); + if (!tok) + goto error; + if (tok->type != ISL_TOKEN_VALUE) { + isl_stream_error(s, tok, "expected denominator"); + isl_stream_push_token(s, tok); + goto error; + } + isl_pw_aff_scale_down(pwaff, tok->u.v); + isl_token_free(tok); + + if (c) + pwaff = isl_pw_aff_ceil(pwaff); + else + pwaff = isl_pw_aff_floor(pwaff); + + if (f || c) { + if (isl_stream_eat(s, ')')) + goto error; + } else { + if (isl_stream_eat(s, ']')) + goto error; + } + + isl_space_free(dim); + return pwaff; +error: + isl_space_free(dim); + isl_pw_aff_free(pwaff); + return NULL; +} + +static __isl_give isl_pw_aff *accept_affine_factor(struct isl_stream *s, + __isl_take isl_space *dim, struct vars *v) +{ + struct isl_token *tok = NULL; + isl_pw_aff *res = NULL; + + tok = next_token(s); if (!tok) { isl_stream_error(s, NULL, "unexpected EOF"); goto error; } - if (tok->type == ISL_TOKEN_IDENT) { + + if (tok->type == ISL_TOKEN_AFF) { + res = isl_pw_aff_copy(tok->u.pwaff); + isl_token_free(tok); + } else if (tok->type == ISL_TOKEN_IDENT) { int n = v->n; int pos = vars_pos(v, tok->u.s, -1); + isl_aff *aff; + if (pos < 0) goto error; if (pos >= n) { @@ -196,68 +374,99 @@ static __isl_give isl_vec *accept_affine_factor(struct isl_stream *s, goto error; } - aff = isl_vec_alloc(v->ctx, 1 + v->n); + aff = isl_aff_zero(isl_local_space_from_space(isl_space_copy(dim))); if (!aff) goto error; - isl_seq_clr(aff->el, aff->size); - isl_int_set_si(aff->el[1 + pos], 1); + isl_int_set_si(aff->v->el[2 + pos], 1); + res = isl_pw_aff_from_aff(aff); isl_token_free(tok); } else if (tok->type == ISL_TOKEN_VALUE) { if (isl_stream_eat_if_available(s, '*')) { - aff = accept_affine_factor(s, v); - aff = isl_vec_scale(aff, tok->u.v); + res = accept_affine_factor(s, isl_space_copy(dim), v); + res = isl_pw_aff_scale(res, tok->u.v); } else { - aff = isl_vec_alloc(v->ctx, 1 + v->n); - if (!aff) - goto error; - isl_seq_clr(aff->el, aff->size); - isl_int_set(aff->el[0], tok->u.v); + isl_local_space *ls; + isl_aff *aff; + ls = isl_local_space_from_space(isl_space_copy(dim)); + aff = isl_aff_zero(ls); + aff = isl_aff_add_constant(aff, tok->u.v); + res = isl_pw_aff_from_aff(aff); } isl_token_free(tok); } else if (tok->type == '(') { isl_token_free(tok); tok = NULL; - aff = accept_affine(s, v); - if (!aff) + res = accept_affine(s, isl_space_copy(dim), v); + if (!res) goto error; if (isl_stream_eat(s, ')')) goto error; + } else if (tok->type == '[' || + tok->type == ISL_TOKEN_FLOORD || + tok->type == ISL_TOKEN_CEILD) { + isl_stream_push_token(s, tok); + tok = NULL; + res = accept_div(s, isl_space_copy(dim), v); + } else if (tok->type == ISL_TOKEN_MIN || tok->type == ISL_TOKEN_MAX) { + isl_stream_push_token(s, tok); + tok = NULL; + res = accept_minmax(s, isl_space_copy(dim), v); } else { isl_stream_error(s, tok, "expecting factor"); goto error; } + if (isl_stream_eat_if_available(s, '%') || + isl_stream_eat_if_available(s, ISL_TOKEN_MOD)) { + isl_space_free(dim); + return affine_mod(s, v, res); + } if (isl_stream_eat_if_available(s, '*')) { isl_int f; isl_int_init(f); isl_int_set_si(f, 1); if (accept_cst_factor(s, &f) < 0) { isl_int_clear(f); - goto error; + goto error2; } - aff = isl_vec_scale(aff, f); + res = isl_pw_aff_scale(res, f); isl_int_clear(f); } - return aff; + isl_space_free(dim); + return res; error: isl_token_free(tok); - isl_vec_free(aff); +error2: + isl_pw_aff_free(res); + isl_space_free(dim); return NULL; } -static struct isl_vec *accept_affine(struct isl_stream *s, struct vars *v) +static __isl_give isl_pw_aff *add_cst(__isl_take isl_pw_aff *pwaff, isl_int v) +{ + isl_aff *aff; + + aff = isl_aff_zero(isl_local_space_from_space(isl_pw_aff_get_space(pwaff))); + aff = isl_aff_add_constant(aff, v); + + return isl_pw_aff_add(pwaff, isl_pw_aff_from_aff(aff)); +} + +static __isl_give isl_pw_aff *accept_affine(struct isl_stream *s, + __isl_take isl_space *dim, struct vars *v) { struct isl_token *tok = NULL; - struct isl_vec *aff; + isl_local_space *ls; + isl_pw_aff *res; int sign = 1; - aff = isl_vec_alloc(v->ctx, 1 + v->n); - if (!aff) - return NULL; - isl_seq_clr(aff->el, aff->size); + ls = isl_local_space_from_space(isl_space_copy(dim)); + res = isl_pw_aff_from_aff(isl_aff_zero(ls)); + if (!res) + goto error; for (;;) { - tok = isl_stream_next_token(s); + tok = next_token(s); if (!tok) { isl_stream_error(s, NULL, "unexpected EOF"); goto error; @@ -267,15 +476,21 @@ static struct isl_vec *accept_affine(struct isl_stream *s, struct vars *v) isl_token_free(tok); continue; } - if (tok->type == '(' || tok->type == ISL_TOKEN_IDENT) { - isl_vec *aff2; + if (tok->type == '(' || tok->type == '[' || + tok->type == ISL_TOKEN_MIN || tok->type == ISL_TOKEN_MAX || + tok->type == ISL_TOKEN_FLOORD || + tok->type == ISL_TOKEN_CEILD || + tok->type == ISL_TOKEN_IDENT || + tok->type == ISL_TOKEN_AFF) { + isl_pw_aff *term; isl_stream_push_token(s, tok); tok = NULL; - aff2 = accept_affine_factor(s, v); + term = accept_affine_factor(s, isl_space_copy(dim), v); if (sign < 0) - aff2 = isl_vec_scale(aff2, s->ctx->negone); - aff = isl_vec_add(aff, aff2); - if (!aff) + res = isl_pw_aff_sub(res, term); + else + res = isl_pw_aff_add(res, term); + if (!res) goto error; sign = 1; } else if (tok->type == ISL_TOKEN_VALUE) { @@ -283,20 +498,27 @@ static struct isl_vec *accept_affine(struct isl_stream *s, struct vars *v) isl_int_neg(tok->u.v, tok->u.v); if (isl_stream_eat_if_available(s, '*') || isl_stream_next_token_is(s, ISL_TOKEN_IDENT)) { - isl_vec *aff2; - aff2 = accept_affine_factor(s, v); - aff2 = isl_vec_scale(aff2, tok->u.v); - aff = isl_vec_add(aff, aff2); - if (!aff) + isl_pw_aff *term; + term = accept_affine_factor(s, + isl_space_copy(dim), v); + term = isl_pw_aff_scale(term, tok->u.v); + res = isl_pw_aff_add(res, term); + if (!res) goto error; } else { - isl_int_add(aff->el[0], aff->el[0], tok->u.v); + res = add_cst(res, tok->u.v); } sign = 1; + } else { + isl_stream_error(s, tok, "unexpected isl_token"); + isl_stream_push_token(s, tok); + isl_pw_aff_free(res); + isl_space_free(dim); + return NULL; } isl_token_free(tok); - tok = isl_stream_next_token(s); + tok = next_token(s); if (tok && tok->type == '-') { sign = -sign; isl_token_free(tok); @@ -313,49 +535,159 @@ static struct isl_vec *accept_affine(struct isl_stream *s, struct vars *v) } } - return aff; + isl_space_free(dim); + return res; error: + isl_space_free(dim); isl_token_free(tok); - isl_vec_free(aff); + isl_pw_aff_free(res); return NULL; } -static __isl_give isl_basic_map *read_var_def(struct isl_stream *s, - __isl_take isl_basic_map *bmap, enum isl_dim_type type, struct vars *v) +static int is_comparator(struct isl_token *tok) { - struct isl_vec *vec; - int k; + if (!tok) + return 0; - vec = accept_affine(s, v); - if (!vec) + switch (tok->type) { + case ISL_TOKEN_LT: + case ISL_TOKEN_GT: + case ISL_TOKEN_LE: + case ISL_TOKEN_GE: + case ISL_TOKEN_NE: + case '=': + return 1; + default: + return 0; + } +} + +static struct isl_map *read_disjuncts(struct isl_stream *s, + struct vars *v, __isl_take isl_map *map); +static __isl_give isl_pw_aff *accept_extended_affine(struct isl_stream *s, + __isl_take isl_space *dim, struct vars *v); + +/* Accept a ternary operator, given the first argument. + */ +static __isl_give isl_pw_aff *accept_ternary(struct isl_stream *s, + __isl_take isl_map *cond, struct vars *v) +{ + isl_space *dim; + isl_pw_aff *pwaff1 = NULL, *pwaff2 = NULL; + + if (!cond) + return NULL; + + if (isl_stream_eat(s, '?')) goto error; - v->v = variable_new(v, "", 0, v->n); - if (!v->v) + + dim = isl_space_wrap(isl_map_get_space(cond)); + pwaff1 = accept_extended_affine(s, dim, v); + if (!pwaff1) goto error; - v->n++; - bmap = isl_basic_map_extend_constraints(bmap, 1, 0); - k = isl_basic_map_alloc_equality(bmap); - if (k >= 0) { - isl_seq_cpy(bmap->eq[k], vec->el, vec->size); - isl_int_set_si(bmap->eq[k][vec->size], -1); - } - isl_vec_free(vec); - if (k < 0) + + if (isl_stream_eat(s, ':')) goto error; - return bmap; + pwaff2 = accept_extended_affine(s, isl_pw_aff_get_space(pwaff1), v); + if (!pwaff1) + goto error; + + return isl_pw_aff_cond(isl_map_wrap(cond), pwaff1, pwaff2); error: - isl_basic_map_free(bmap); + isl_map_free(cond); + isl_pw_aff_free(pwaff1); + isl_pw_aff_free(pwaff2); return NULL; } -static __isl_give isl_basic_map *read_var_list(struct isl_stream *s, - __isl_take isl_basic_map *bmap, enum isl_dim_type type, struct vars *v) +/* Accept an affine expression that may involve ternary operators. + * We first read an affine expression. + * If it is not followed by a comparison operator, we simply return it. + * Otherwise, we assume the affine epxression is part of the first + * argument of a ternary operator and try to parse that. + */ +static __isl_give isl_pw_aff *accept_extended_affine(struct isl_stream *s, + __isl_take isl_space *dim, struct vars *v) +{ + isl_map *cond; + isl_pw_aff *pwaff; + struct isl_token *tok; + int line = -1, col = -1; + int is_comp; + + tok = isl_stream_next_token(s); + if (tok) { + line = tok->line; + col = tok->col; + isl_stream_push_token(s, tok); + } + + pwaff = accept_affine(s, dim, v); + if (!pwaff) + return NULL; + + tok = isl_stream_next_token(s); + if (!tok) + return isl_pw_aff_free(pwaff); + + is_comp = is_comparator(tok); + isl_stream_push_token(s, tok); + if (!is_comp) + return pwaff; + + tok = isl_token_new(s->ctx, line, col, 0); + if (!tok) + return isl_pw_aff_free(pwaff); + tok->type = ISL_TOKEN_AFF; + tok->u.pwaff = pwaff; + + cond = isl_map_universe(isl_space_unwrap(isl_pw_aff_get_space(pwaff))); + + isl_stream_push_token(s, tok); + + cond = read_disjuncts(s, v, cond); + + return accept_ternary(s, cond, v); +} + +static __isl_give isl_map *read_var_def(struct isl_stream *s, + __isl_take isl_map *map, enum isl_dim_type type, struct vars *v) +{ + isl_pw_aff *def; + int pos; + isl_map *def_map; + + if (type == isl_dim_param) + pos = isl_map_dim(map, isl_dim_param); + else { + pos = isl_map_dim(map, isl_dim_in); + if (type == isl_dim_out) + pos += isl_map_dim(map, isl_dim_out); + type = isl_dim_in; + } + --pos; + + def = accept_extended_affine(s, isl_space_wrap(isl_map_get_space(map)), v); + def_map = isl_map_from_pw_aff(def); + def_map = isl_map_equate(def_map, type, pos, isl_dim_out, 0); + def_map = isl_set_unwrap(isl_map_domain(def_map)); + + map = isl_map_intersect(map, def_map); + + return map; +} + +static __isl_give isl_map *read_var_list(struct isl_stream *s, + __isl_take isl_map *map, enum isl_dim_type type, struct vars *v) { int i = 0; struct isl_token *tok; - while ((tok = isl_stream_next_token(s)) != NULL) { + if (isl_stream_next_token_is(s, ']')) + return map; + + while ((tok = next_token(s)) != NULL) { int new_name = 0; if (tok->type == ISL_TOKEN_IDENT) { @@ -367,11 +699,12 @@ static __isl_give isl_basic_map *read_var_list(struct isl_stream *s, } if (new_name) { - bmap = isl_basic_map_add(bmap, type, 1); - bmap = set_name(bmap, type, i, v->v->name); + map = isl_map_add_dims(map, type, 1); + map = set_name(map, type, i, v->v->name); isl_token_free(tok); - } else if (tok->type == ISL_TOKEN_IDENT || - tok->type == ISL_TOKEN_VALUE) { + if (isl_stream_eat_if_available(s, '=')) + map = read_var_def(s, map, type, v); + } else { if (type == isl_dim_param) { isl_stream_error(s, tok, "expecting unique identifier"); @@ -379,13 +712,18 @@ static __isl_give isl_basic_map *read_var_list(struct isl_stream *s, } isl_stream_push_token(s, tok); tok = NULL; - bmap = isl_basic_map_add(bmap, type, 1); - bmap = read_var_def(s, bmap, type, v); - } else - break; + if (vars_add_anon(v) < 0) + goto error; + map = isl_map_add_dims(map, type, 1); + map = read_var_def(s, map, type, v); + } tok = isl_stream_next_token(s); - if (!tok || tok->type != ',') + if (tok && tok->type == ']' && + isl_stream_next_token_is(s, '[')) { + isl_token_free(tok); + tok = isl_stream_next_token(s); + } else if (!tok || tok->type != ',') break; isl_token_free(tok); @@ -394,24 +732,24 @@ static __isl_give isl_basic_map *read_var_list(struct isl_stream *s, if (tok) isl_stream_push_token(s, tok); - return bmap; + return map; error: isl_token_free(tok); - isl_basic_map_free(bmap); + isl_map_free(map); return NULL; } -static __isl_give isl_mat *accept_affine_list(struct isl_stream *s, - struct vars *v) +static __isl_give isl_pw_aff_list *accept_affine_list(struct isl_stream *s, + __isl_take isl_space *dim, struct vars *v) { - struct isl_vec *vec; - struct isl_mat *mat; + isl_pw_aff *pwaff; + isl_pw_aff_list *list; struct isl_token *tok = NULL; - vec = accept_affine(s, v); - mat = isl_mat_from_row_vec(vec); - if (!mat) - return NULL; + pwaff = accept_affine(s, isl_space_copy(dim), v); + list = isl_pw_aff_list_from_pw_aff(pwaff); + if (!list) + goto error; for (;;) { tok = isl_stream_next_token(s); @@ -425,83 +763,29 @@ static __isl_give isl_mat *accept_affine_list(struct isl_stream *s, } isl_token_free(tok); - vec = accept_affine(s, v); - mat = isl_mat_vec_concat(mat, vec); - if (!mat) + pwaff = accept_affine(s, isl_space_copy(dim), v); + list = isl_pw_aff_list_concat(list, + isl_pw_aff_list_from_pw_aff(pwaff)); + if (!list) return NULL; } - return mat; + isl_space_free(dim); + return list; error: - isl_mat_free(mat); + isl_space_free(dim); + isl_pw_aff_list_free(list); return NULL; } -static struct isl_basic_map *add_div_definition(struct isl_stream *s, - struct vars *v, struct isl_basic_map *bmap, int k) -{ - struct isl_token *tok; - int seen_paren = 0; - struct isl_vec *aff; - - if (isl_stream_eat(s, '[')) - goto error; - - tok = isl_stream_next_token(s); - if (!tok) - goto error; - if (tok->type == '(') { - seen_paren = 1; - isl_token_free(tok); - } else - isl_stream_push_token(s, tok); - - aff = accept_affine(s, v); - if (!aff) - goto error; - - isl_seq_cpy(bmap->div[k] + 1, aff->el, aff->size); - - isl_vec_free(aff); - - if (seen_paren && isl_stream_eat(s, ')')) - goto error; - if (isl_stream_eat(s, '/')) - goto error; - - tok = isl_stream_next_token(s); - if (!tok) - goto error; - if (tok->type != ISL_TOKEN_VALUE) { - isl_stream_error(s, tok, "expected denominator"); - isl_stream_push_token(s, tok); - goto error; - } - isl_int_set(bmap->div[k][0], tok->u.v); - isl_token_free(tok); - - if (isl_stream_eat(s, ']')) - goto error; - - if (isl_basic_map_add_div_constraints(bmap, k) < 0) - goto error; - - return bmap; -error: - isl_basic_map_free(bmap); - return NULL; -} - -static struct isl_basic_map *read_defined_var_list(struct isl_stream *s, - struct vars *v, struct isl_basic_map *bmap) +static __isl_give isl_map *read_defined_var_list(struct isl_stream *s, + struct vars *v, __isl_take isl_map *map) { struct isl_token *tok; while ((tok = isl_stream_next_token(s)) != NULL) { - int k; int p; int n = v->n; - unsigned total = isl_basic_map_total_dim(bmap); if (tok->type != ISL_TOKEN_IDENT) break; @@ -514,19 +798,13 @@ static struct isl_basic_map *read_defined_var_list(struct isl_stream *s, goto error; } - bmap = isl_basic_map_cow(bmap); - bmap = isl_basic_map_extend_dim(bmap, isl_dim_copy(bmap->dim), - 1, 0, 2); - - if ((k = isl_basic_map_alloc_div(bmap)) < 0) - goto error; - isl_seq_clr(bmap->div[k], 1 + 1 + total); + map = isl_map_add_dims(map, isl_dim_out, 1); isl_token_free(tok); tok = isl_stream_next_token(s); if (tok && tok->type == '=') { isl_token_free(tok); - bmap = add_div_definition(s, v, bmap, k); + map = read_var_def(s, map, isl_dim_out, v); tok = isl_stream_next_token(s); } @@ -538,21 +816,61 @@ static struct isl_basic_map *read_defined_var_list(struct isl_stream *s, if (tok) isl_stream_push_token(s, tok); - return bmap; + return map; error: isl_token_free(tok); - isl_basic_map_free(bmap); + isl_map_free(map); return NULL; } -static __isl_give isl_basic_map *read_tuple(struct isl_stream *s, - __isl_take isl_basic_map *bmap, enum isl_dim_type type, struct vars *v) +static int next_is_tuple(struct isl_stream *s) +{ + struct isl_token *tok; + int is_tuple; + + tok = isl_stream_next_token(s); + if (!tok) + return 0; + if (tok->type == '[') { + isl_stream_push_token(s, tok); + return 1; + } + if (tok->type != ISL_TOKEN_IDENT && !tok->is_keyword) { + isl_stream_push_token(s, tok); + return 0; + } + + is_tuple = isl_stream_next_token_is(s, '['); + + isl_stream_push_token(s, tok); + + return is_tuple; +} + +static __isl_give isl_map *read_tuple(struct isl_stream *s, + __isl_take isl_map *map, enum isl_dim_type type, struct vars *v); + +static __isl_give isl_set *read_nested_tuple(struct isl_stream *s, + __isl_take isl_map *map, struct vars *v) +{ + map = read_tuple(s, map, isl_dim_in, v); + if (isl_stream_eat(s, ISL_TOKEN_TO)) + goto error; + map = read_tuple(s, map, isl_dim_out, v); + return isl_map_wrap(map); +error: + isl_map_free(map); + return NULL; +} + +static __isl_give isl_map *read_tuple(struct isl_stream *s, + __isl_take isl_map *map, enum isl_dim_type type, struct vars *v) { struct isl_token *tok; char *name = NULL; tok = isl_stream_next_token(s); - if (tok && tok->type == ISL_TOKEN_IDENT) { + if (tok && (tok->type == ISL_TOKEN_IDENT || tok->is_keyword)) { name = strdup(tok->u.s); if (!name) goto error; @@ -564,7 +882,31 @@ static __isl_give isl_basic_map *read_tuple(struct isl_stream *s, goto error; } isl_token_free(tok); - bmap = read_var_list(s, bmap, type, v); + if (type != isl_dim_param && next_is_tuple(s)) { + isl_space *dim = isl_map_get_space(map); + int nparam = isl_space_dim(dim, isl_dim_param); + int n_in = isl_space_dim(dim, isl_dim_in); + isl_set *nested; + if (type == isl_dim_out) { + dim = isl_space_move_dims(dim, isl_dim_param, nparam, + isl_dim_in, 0, n_in); + dim = isl_space_params(dim); + } + nested = read_nested_tuple(s, isl_map_universe(dim), v); + if (type == isl_dim_in) { + nested = isl_map_reverse(nested); + map = isl_map_intersect(nested, map); + } else { + isl_set *set; + dim = isl_set_get_space(nested); + dim = isl_space_drop_dims(dim, isl_dim_param, nparam, n_in); + dim = isl_space_join(isl_map_get_space(map), dim); + set = isl_map_domain(map); + nested = isl_map_reset_space(nested, dim); + map = isl_map_intersect_domain(nested, set); + } + } else + map = read_var_list(s, map, type, v); tok = isl_stream_next_token(s); if (!tok || tok->type != ']') { isl_stream_error(s, tok, "expecting ']'"); @@ -573,141 +915,56 @@ static __isl_give isl_basic_map *read_tuple(struct isl_stream *s, isl_token_free(tok); if (name) { - bmap = isl_basic_map_set_tuple_name(bmap, type, name); + map = isl_map_set_tuple_name(map, type, name); free(name); } - return bmap; + return map; error: if (tok) isl_token_free(tok); - isl_basic_map_free(bmap); - return NULL; -} - -static struct isl_basic_map *add_constraints(struct isl_stream *s, - struct vars *v, struct isl_basic_map *bmap); - -static struct isl_basic_map *add_exists(struct isl_stream *s, - struct vars *v, struct isl_basic_map *bmap) -{ - struct isl_token *tok; - int n = v->n; - int extra; - int seen_paren = 0; - int i; - unsigned total; - - tok = isl_stream_next_token(s); - if (!tok) - goto error; - if (tok->type == '(') { - seen_paren = 1; - isl_token_free(tok); - } else - isl_stream_push_token(s, tok); - - bmap = read_defined_var_list(s, v, bmap); - if (!bmap) - goto error; - - if (isl_stream_eat(s, ':')) - goto error; - bmap = add_constraints(s, v, bmap); - if (seen_paren && isl_stream_eat(s, ')')) - goto error; - return bmap; -error: - isl_basic_map_free(bmap); + isl_map_free(map); return NULL; } -static __isl_give isl_basic_map *construct_constraint( - __isl_take isl_basic_map *bmap, enum isl_token_type type, - isl_int *left, isl_int *right) +static __isl_give isl_set *construct_constraints( + __isl_take isl_set *set, enum isl_token_type type, + __isl_keep isl_pw_aff_list *left, __isl_keep isl_pw_aff_list *right) { - int k; - unsigned len; - struct isl_ctx *ctx; + isl_set *cond; - if (!bmap) - return NULL; - len = 1 + isl_basic_map_total_dim(bmap); - ctx = bmap->ctx; - - k = isl_basic_map_alloc_inequality(bmap); - if (k < 0) - goto error; if (type == ISL_TOKEN_LE) - isl_seq_combine(bmap->ineq[k], ctx->negone, left, - ctx->one, right, - len); + cond = isl_pw_aff_list_le_set(isl_pw_aff_list_copy(left), + isl_pw_aff_list_copy(right)); else if (type == ISL_TOKEN_GE) - isl_seq_combine(bmap->ineq[k], ctx->one, left, - ctx->negone, right, - len); - else if (type == ISL_TOKEN_LT) { - isl_seq_combine(bmap->ineq[k], ctx->negone, left, - ctx->one, right, - len); - isl_int_sub_ui(bmap->ineq[k][0], bmap->ineq[k][0], 1); - } else if (type == ISL_TOKEN_GT) { - isl_seq_combine(bmap->ineq[k], ctx->one, left, - ctx->negone, right, - len); - isl_int_sub_ui(bmap->ineq[k][0], bmap->ineq[k][0], 1); - } else { - isl_seq_combine(bmap->ineq[k], ctx->one, left, - ctx->negone, right, - len); - isl_basic_map_inequality_to_equality(bmap, k); - } - - return bmap; -error: - isl_basic_map_free(bmap); - return NULL; -} - -static int is_comparator(struct isl_token *tok) -{ - if (!tok) - return 0; + cond = isl_pw_aff_list_ge_set(isl_pw_aff_list_copy(left), + isl_pw_aff_list_copy(right)); + else if (type == ISL_TOKEN_LT) + cond = isl_pw_aff_list_lt_set(isl_pw_aff_list_copy(left), + isl_pw_aff_list_copy(right)); + else if (type == ISL_TOKEN_GT) + cond = isl_pw_aff_list_gt_set(isl_pw_aff_list_copy(left), + isl_pw_aff_list_copy(right)); + else if (type == ISL_TOKEN_NE) + cond = isl_pw_aff_list_ne_set(isl_pw_aff_list_copy(left), + isl_pw_aff_list_copy(right)); + else + cond = isl_pw_aff_list_eq_set(isl_pw_aff_list_copy(left), + isl_pw_aff_list_copy(right)); - switch (tok->type) { - case ISL_TOKEN_LT: - case ISL_TOKEN_GT: - case ISL_TOKEN_LE: - case ISL_TOKEN_GE: - case '=': - return 1; - default: - return 0; - } + return isl_set_intersect(set, cond); } -static struct isl_basic_map *add_constraint(struct isl_stream *s, - struct vars *v, struct isl_basic_map *bmap) +static __isl_give isl_map *add_constraint(struct isl_stream *s, + struct vars *v, __isl_take isl_map *map) { - int i, j; - unsigned total = isl_basic_map_total_dim(bmap); struct isl_token *tok = NULL; - struct isl_mat *aff1 = NULL, *aff2 = NULL; - - tok = isl_stream_next_token(s); - if (!tok) - goto error; - if (tok->type == ISL_TOKEN_EXISTS) { - isl_token_free(tok); - return add_exists(s, v, bmap); - } - isl_stream_push_token(s, tok); - tok = NULL; - - bmap = isl_basic_map_cow(bmap); + isl_pw_aff_list *list1 = NULL, *list2 = NULL; + isl_set *set; - aff1 = accept_affine_list(s, v); - if (!aff1) + set = isl_map_wrap(map); + list1 = accept_affine_list(s, isl_set_get_space(set), v); + if (!list1) goto error; tok = isl_stream_next_token(s); if (!is_comparator(tok)) { @@ -717,22 +974,15 @@ static struct isl_basic_map *add_constraint(struct isl_stream *s, tok = NULL; goto error; } - isl_assert(aff1->ctx, aff1->n_col == 1 + total, goto error); for (;;) { - aff2 = accept_affine_list(s, v); - if (!aff2) + list2 = accept_affine_list(s, isl_set_get_space(set), v); + if (!list2) goto error; - isl_assert(aff2->ctx, aff2->n_col == 1 + total, goto error); - - bmap = isl_basic_map_extend_constraints(bmap, 0, - aff1->n_row * aff2->n_row); - for (i = 0; i < aff1->n_row; ++i) - for (j = 0; j < aff2->n_row; ++j) - bmap = construct_constraint(bmap, tok->type, - aff1->row[i], aff2->row[j]); + + set = construct_constraints(set, tok->type, list1, list2); isl_token_free(tok); - isl_mat_free(aff1); - aff1 = aff2; + isl_pw_aff_list_free(list1); + list1 = list2; tok = isl_stream_next_token(s); if (!is_comparator(tok)) { @@ -741,119 +991,207 @@ static struct isl_basic_map *add_constraint(struct isl_stream *s, break; } } - isl_mat_free(aff1); + isl_pw_aff_list_free(list1); - return bmap; + return isl_set_unwrap(set); error: if (tok) isl_token_free(tok); - isl_mat_free(aff1); - isl_mat_free(aff2); - isl_basic_map_free(bmap); + isl_pw_aff_list_free(list1); + isl_pw_aff_list_free(list2); + isl_set_free(set); return NULL; } -static struct isl_basic_map *add_constraints(struct isl_stream *s, - struct vars *v, struct isl_basic_map *bmap) +static __isl_give isl_map *read_exists(struct isl_stream *s, + struct vars *v, __isl_take isl_map *map) { - struct isl_token *tok; + int n = v->n; + int seen_paren = isl_stream_eat_if_available(s, '('); - for (;;) { - bmap = add_constraint(s, v, bmap); - if (!bmap) - return NULL; - tok = isl_stream_next_token(s); - if (!tok) { - isl_stream_error(s, NULL, "unexpected EOF"); + map = isl_map_from_domain(isl_map_wrap(map)); + map = read_defined_var_list(s, v, map); + + if (isl_stream_eat(s, ':')) + goto error; + + map = read_disjuncts(s, v, map); + map = isl_set_unwrap(isl_map_domain(map)); + + vars_drop(v, v->n - n); + if (seen_paren && isl_stream_eat(s, ')')) + goto error; + + return map; +error: + isl_map_free(map); + return NULL; +} + +/* Parse an expression between parentheses and push the result + * back on the stream. + * + * The parsed expression may be either an affine expression + * or a condition. The first type is pushed onto the stream + * as an isl_pw_aff, while the second is pushed as an isl_map. + * + * If the initial token indicates the start of a condition, + * we parse it as such. + * Otherwise, we first parse an affine expression and push + * that onto the stream. If the affine expression covers the + * entire expression between parentheses, we return. + * Otherwise, we assume that the affine expression is the + * start of a condition and continue parsing. + */ +static int resolve_paren_expr(struct isl_stream *s, + struct vars *v, __isl_take isl_map *map) +{ + struct isl_token *tok, *tok2; + int line, col; + isl_pw_aff *pwaff; + + tok = isl_stream_next_token(s); + if (!tok || tok->type != '(') + goto error; + + if (isl_stream_next_token_is(s, ISL_TOKEN_EXISTS) || + isl_stream_next_token_is(s, ISL_TOKEN_TRUE) || + isl_stream_next_token_is(s, ISL_TOKEN_FALSE)) { + map = read_disjuncts(s, v, map); + if (isl_stream_eat(s, ')')) goto error; - } - if (tok->type != ISL_TOKEN_AND) - break; + tok->type = ISL_TOKEN_MAP; + tok->u.map = map; + isl_stream_push_token(s, tok); + return 0; + } + + tok2 = isl_stream_next_token(s); + if (!tok2) + goto error; + line = tok2->line; + col = tok2->col; + isl_stream_push_token(s, tok2); + + pwaff = accept_affine(s, isl_space_wrap(isl_map_get_space(map)), v); + if (!pwaff) + goto error; + + tok2 = isl_token_new(s->ctx, line, col, 0); + if (!tok2) + goto error2; + tok2->type = ISL_TOKEN_AFF; + tok2->u.pwaff = pwaff; + + if (isl_stream_eat_if_available(s, ')')) { + isl_stream_push_token(s, tok2); isl_token_free(tok); + isl_map_free(map); + return 0; } + + isl_stream_push_token(s, tok2); + + map = read_disjuncts(s, v, map); + if (isl_stream_eat(s, ')')) + goto error; + + tok->type = ISL_TOKEN_MAP; + tok->u.map = map; isl_stream_push_token(s, tok); - return bmap; + return 0; +error2: + isl_pw_aff_free(pwaff); error: - if (tok) - isl_token_free(tok); - isl_basic_map_free(bmap); - return NULL; + isl_token_free(tok); + isl_map_free(map); + return -1; } -static struct isl_basic_map *read_disjunct(struct isl_stream *s, - struct vars *v, __isl_take isl_dim *dim) +static __isl_give isl_map *read_conjunct(struct isl_stream *s, + struct vars *v, __isl_take isl_map *map) { - int seen_paren = 0; - struct isl_token *tok; - struct isl_basic_map *bmap; - - bmap = isl_basic_map_alloc_dim(dim, 0, 0, 0); - if (!bmap) - return NULL; + if (isl_stream_next_token_is(s, '(')) + if (resolve_paren_expr(s, v, isl_map_copy(map))) + goto error; - tok = isl_stream_next_token(s); - if (!tok) - goto error; - if (tok->type == '(') { - seen_paren = 1; + if (isl_stream_next_token_is(s, ISL_TOKEN_MAP)) { + struct isl_token *tok; + tok = isl_stream_next_token(s); + if (!tok) + goto error; + isl_map_free(map); + map = isl_map_copy(tok->u.map); isl_token_free(tok); - } else - isl_stream_push_token(s, tok); + return map; + } - bmap = add_constraints(s, v, bmap); - bmap = isl_basic_map_simplify(bmap); - bmap = isl_basic_map_finalize(bmap); + if (isl_stream_eat_if_available(s, ISL_TOKEN_EXISTS)) + return read_exists(s, v, map); - if (seen_paren && isl_stream_eat(s, ')')) - goto error; + if (isl_stream_eat_if_available(s, ISL_TOKEN_TRUE)) + return map; - return bmap; + if (isl_stream_eat_if_available(s, ISL_TOKEN_FALSE)) { + isl_space *dim = isl_map_get_space(map); + isl_map_free(map); + return isl_map_empty(dim); + } + + return add_constraint(s, v, map); error: - isl_basic_map_free(bmap); + isl_map_free(map); return NULL; } +static __isl_give isl_map *read_conjuncts(struct isl_stream *s, + struct vars *v, __isl_take isl_map *map) +{ + isl_map *res; + int negate; + + negate = isl_stream_eat_if_available(s, ISL_TOKEN_NOT); + res = read_conjunct(s, v, isl_map_copy(map)); + if (negate) + res = isl_map_subtract(isl_map_copy(map), res); + + while (isl_stream_eat_if_available(s, ISL_TOKEN_AND)) { + isl_map *res_i; + + negate = isl_stream_eat_if_available(s, ISL_TOKEN_NOT); + res_i = read_conjunct(s, v, isl_map_copy(map)); + if (negate) + res = isl_map_subtract(res, res_i); + else + res = isl_map_intersect(res, res_i); + } + + isl_map_free(map); + return res; +} + static struct isl_map *read_disjuncts(struct isl_stream *s, - struct vars *v, __isl_take isl_dim *dim) + struct vars *v, __isl_take isl_map *map) { - struct isl_token *tok; - struct isl_map *map; + isl_map *res; - tok = isl_stream_next_token(s); - if (!tok) { - isl_stream_error(s, NULL, "unexpected EOF"); - goto error; - } - if (tok->type == '}') { - isl_stream_push_token(s, tok); + if (isl_stream_next_token_is(s, '}')) { + isl_space *dim = isl_map_get_space(map); + isl_map_free(map); return isl_map_universe(dim); } - isl_stream_push_token(s, tok); - - map = isl_map_empty(isl_dim_copy(dim)); - for (;;) { - struct isl_basic_map *bmap; - int n = v->n; - bmap = read_disjunct(s, v, isl_dim_copy(dim)); - map = isl_map_union(map, isl_map_from_basic_map(bmap)); + res = read_conjuncts(s, v, isl_map_copy(map)); + while (isl_stream_eat_if_available(s, ISL_TOKEN_OR)) { + isl_map *res_i; - vars_drop(v, v->n - n); - - tok = isl_stream_next_token(s); - if (!tok || tok->type != ISL_TOKEN_OR) - break; - isl_token_free(tok); + res_i = read_conjuncts(s, v, isl_map_copy(map)); + res = isl_map_union(res, res_i); } - if (tok) - isl_stream_push_token(s, tok); - isl_dim_free(dim); - return map; -error: - isl_dim_free(dim); - return NULL; + isl_map_free(map); + return res; } static int polylib_pos_to_isl_pos(__isl_keep isl_basic_map *bmap, int pos) @@ -974,6 +1312,13 @@ static __isl_give isl_basic_map *basic_map_read_polylib(struct isl_stream *s, isl_stream_error(s, NULL, "unexpected EOF"); return NULL; } + if (tok->type != ISL_TOKEN_VALUE || tok2->type != ISL_TOKEN_VALUE) { + isl_stream_push_token(s, tok2); + isl_stream_push_token(s, tok); + isl_stream_error(s, NULL, + "expecting constraint matrix dimensions"); + return NULL; + } n_row = isl_int_get_si(tok->u.v); n_col = isl_int_get_si(tok2->u.v); on_new_line = tok2->on_new_line; @@ -1040,6 +1385,7 @@ static __isl_give isl_basic_map *basic_map_read_polylib(struct isl_stream *s, int k = isl_basic_map_alloc_div(bmap); if (k < 0) goto error; + isl_seq_clr(bmap->div[k], 1 + 1 + nparam + in + out + local); } for (i = 0; i < n_row; ++i) @@ -1073,11 +1419,17 @@ static struct isl_map *map_read_polylib(struct isl_stream *s, int nparam) return NULL; } tok2 = isl_stream_next_token_on_same_line(s); - if (tok2) { + if (tok2 && tok2->type == ISL_TOKEN_VALUE) { isl_stream_push_token(s, tok2); isl_stream_push_token(s, tok); return isl_map_from_basic_map(basic_map_read_polylib(s, nparam)); } + if (tok2) { + isl_stream_error(s, tok2, "unexpected token"); + isl_stream_push_token(s, tok2); + isl_stream_push_token(s, tok); + return NULL; + } n = isl_int_get_si(tok->u.v); isl_token_free(tok); @@ -1085,7 +1437,7 @@ static struct isl_map *map_read_polylib(struct isl_stream *s, int nparam) map = isl_map_from_basic_map(basic_map_read_polylib(s, nparam)); - for (i = 1; i < n; ++i) + for (i = 1; map && i < n; ++i) map = isl_map_union(map, isl_map_from_basic_map(basic_map_read_polylib(s, nparam))); @@ -1117,105 +1469,96 @@ static int optional_power(struct isl_stream *s) return pow; } -static __isl_give isl_div *read_div(struct isl_stream *s, - __isl_keep isl_basic_map *bmap, struct vars *v) -{ - unsigned total = isl_basic_map_total_dim(bmap); - int k; - - bmap = isl_basic_map_copy(bmap); - bmap = isl_basic_map_cow(bmap); - bmap = isl_basic_map_extend_dim(bmap, isl_dim_copy(bmap->dim), - 1, 0, 2); - - if ((k = isl_basic_map_alloc_div(bmap)) < 0) - goto error; - isl_seq_clr(bmap->div[k], 1 + 1 + total); - bmap = add_div_definition(s, v, bmap, k); - - return isl_basic_map_div(bmap, k); -error: - isl_basic_map_free(bmap); - return NULL; -} +static __isl_give isl_pw_qpolynomial *read_term(struct isl_stream *s, + __isl_keep isl_map *map, struct vars *v); -static __isl_give isl_qpolynomial *read_term(struct isl_stream *s, - __isl_keep isl_basic_map *bmap, struct vars *v); - -static __isl_give isl_qpolynomial *read_factor(struct isl_stream *s, - __isl_keep isl_basic_map *bmap, struct vars *v) +static __isl_give isl_pw_qpolynomial *read_factor(struct isl_stream *s, + __isl_keep isl_map *map, struct vars *v) { - struct isl_qpolynomial *qp; + isl_pw_qpolynomial *pwqp; struct isl_token *tok; - tok = isl_stream_next_token(s); + tok = next_token(s); if (!tok) { isl_stream_error(s, NULL, "unexpected EOF"); return NULL; } if (tok->type == '(') { + int pow; + isl_token_free(tok); - qp = read_term(s, bmap, v); - if (!qp) + pwqp = read_term(s, map, v); + if (!pwqp) return NULL; if (isl_stream_eat(s, ')')) goto error; + pow = optional_power(s); + pwqp = isl_pw_qpolynomial_pow(pwqp, pow); } else if (tok->type == ISL_TOKEN_VALUE) { struct isl_token *tok2; tok2 = isl_stream_next_token(s); + isl_qpolynomial *qp; if (tok2 && tok2->type == '/') { isl_token_free(tok2); - tok2 = isl_stream_next_token(s); + tok2 = next_token(s); if (!tok2 || tok2->type != ISL_TOKEN_VALUE) { isl_stream_error(s, tok2, "expected denominator"); isl_token_free(tok); isl_token_free(tok2); return NULL; } - qp = isl_qpolynomial_rat_cst(isl_basic_map_get_dim(bmap), + qp = isl_qpolynomial_rat_cst(isl_map_get_space(map), tok->u.v, tok2->u.v); isl_token_free(tok2); } else { isl_stream_push_token(s, tok2); - qp = isl_qpolynomial_cst(isl_basic_map_get_dim(bmap), + qp = isl_qpolynomial_cst(isl_map_get_space(map), tok->u.v); } isl_token_free(tok); + pwqp = isl_pw_qpolynomial_from_qpolynomial(qp); } else if (tok->type == ISL_TOKEN_INFTY) { + isl_qpolynomial *qp; isl_token_free(tok); - qp = isl_qpolynomial_infty(isl_basic_map_get_dim(bmap)); + qp = isl_qpolynomial_infty(isl_map_get_space(map)); + pwqp = isl_pw_qpolynomial_from_qpolynomial(qp); } else if (tok->type == ISL_TOKEN_NAN) { + isl_qpolynomial *qp; isl_token_free(tok); - qp = isl_qpolynomial_nan(isl_basic_map_get_dim(bmap)); + qp = isl_qpolynomial_nan(isl_map_get_space(map)); + pwqp = isl_pw_qpolynomial_from_qpolynomial(qp); } else if (tok->type == ISL_TOKEN_IDENT) { int n = v->n; int pos = vars_pos(v, tok->u.s, -1); int pow; - isl_token_free(tok); - if (pos < 0) - goto error; + isl_qpolynomial *qp; + if (pos < 0) { + isl_token_free(tok); + return NULL; + } if (pos >= n) { + vars_drop(v, v->n - n); isl_stream_error(s, tok, "unknown identifier"); + isl_token_free(tok); return NULL; } + isl_token_free(tok); pow = optional_power(s); - qp = isl_qpolynomial_pow(isl_basic_map_get_dim(bmap), pos, pow); + qp = isl_qpolynomial_var_pow(isl_map_get_space(map), pos, pow); + pwqp = isl_pw_qpolynomial_from_qpolynomial(qp); } else if (tok->type == '[') { - isl_div *div; + isl_pw_aff *pwaff; int pow; isl_stream_push_token(s, tok); - div = read_div(s, bmap, v); + pwaff = accept_affine(s, isl_map_get_space(map), v); pow = optional_power(s); - qp = isl_qpolynomial_div_pow(div, pow); + pwqp = isl_pw_qpolynomial_from_pw_aff(pwaff); + pwqp = isl_pw_qpolynomial_pow(pwqp, pow); } else if (tok->type == '-') { - struct isl_qpolynomial *qp2; - isl_token_free(tok); - qp = isl_qpolynomial_cst(isl_basic_map_get_dim(bmap), - s->ctx->negone); - qp2 = read_factor(s, bmap, v); - qp = isl_qpolynomial_mul(qp, qp2); + pwqp = read_factor(s, map, v); + pwqp = isl_pw_qpolynomial_neg(pwqp); } else { isl_stream_error(s, tok, "unexpected isl_token"); isl_stream_push_token(s, tok); @@ -1224,103 +1567,94 @@ static __isl_give isl_qpolynomial *read_factor(struct isl_stream *s, if (isl_stream_eat_if_available(s, '*') || isl_stream_next_token_is(s, ISL_TOKEN_IDENT)) { - struct isl_qpolynomial *qp2; + isl_pw_qpolynomial *pwqp2; - qp2 = read_factor(s, bmap, v); - qp = isl_qpolynomial_mul(qp, qp2); + pwqp2 = read_factor(s, map, v); + pwqp = isl_pw_qpolynomial_mul(pwqp, pwqp2); } - return qp; + return pwqp; error: - isl_qpolynomial_free(qp); + isl_pw_qpolynomial_free(pwqp); return NULL; } -static __isl_give isl_qpolynomial *read_term(struct isl_stream *s, - __isl_keep isl_basic_map *bmap, struct vars *v) +static __isl_give isl_pw_qpolynomial *read_term(struct isl_stream *s, + __isl_keep isl_map *map, struct vars *v) { struct isl_token *tok; - struct isl_qpolynomial *qp; + isl_pw_qpolynomial *pwqp; - qp = read_factor(s, bmap, v); + pwqp = read_factor(s, map, v); for (;;) { - tok = isl_stream_next_token(s); + tok = next_token(s); if (!tok) - return qp; + return pwqp; if (tok->type == '+') { - struct isl_qpolynomial *qp2; + isl_pw_qpolynomial *pwqp2; isl_token_free(tok); - qp2 = read_factor(s, bmap, v); - qp = isl_qpolynomial_add(qp, qp2); + pwqp2 = read_factor(s, map, v); + pwqp = isl_pw_qpolynomial_add(pwqp, pwqp2); } else if (tok->type == '-') { - struct isl_qpolynomial *qp2; + isl_pw_qpolynomial *pwqp2; isl_token_free(tok); - qp2 = read_factor(s, bmap, v); - qp = isl_qpolynomial_sub(qp, qp2); + pwqp2 = read_factor(s, map, v); + pwqp = isl_pw_qpolynomial_sub(pwqp, pwqp2); } else if (tok->type == ISL_TOKEN_VALUE && isl_int_is_neg(tok->u.v)) { - struct isl_qpolynomial *qp2; + isl_pw_qpolynomial *pwqp2; - qp2 = isl_qpolynomial_cst(isl_basic_map_get_dim(bmap), - tok->u.v); - isl_token_free(tok); - qp = isl_qpolynomial_add(qp, qp2); + isl_stream_push_token(s, tok); + pwqp2 = read_factor(s, map, v); + pwqp = isl_pw_qpolynomial_add(pwqp, pwqp2); } else { isl_stream_push_token(s, tok); break; } } - return qp; + return pwqp; } static __isl_give isl_map *read_optional_disjuncts(struct isl_stream *s, - __isl_take isl_basic_map *bmap, struct vars *v) + __isl_take isl_map *map, struct vars *v) { struct isl_token *tok; - struct isl_map *map; tok = isl_stream_next_token(s); if (!tok) { isl_stream_error(s, NULL, "unexpected EOF"); goto error; } - map = isl_map_from_basic_map(isl_basic_map_copy(bmap)); - if (tok->type == ':') { + if (tok->type == ':' || + (tok->type == ISL_TOKEN_OR && !strcmp(tok->u.s, "|"))) { isl_token_free(tok); - map = isl_map_intersect(map, - read_disjuncts(s, v, isl_basic_map_get_dim(bmap))); + map = read_disjuncts(s, v, map); } else isl_stream_push_token(s, tok); - isl_basic_map_free(bmap); - return map; error: - isl_basic_map_free(bmap); + isl_map_free(map); return NULL; } static struct isl_obj obj_read_poly(struct isl_stream *s, - __isl_take isl_basic_map *bmap, struct vars *v, int n) + __isl_take isl_map *map, struct vars *v, int n) { struct isl_obj obj = { isl_obj_pw_qpolynomial, NULL }; - struct isl_pw_qpolynomial *pwqp; - struct isl_qpolynomial *qp; - struct isl_map *map; + isl_pw_qpolynomial *pwqp; struct isl_set *set; - bmap = isl_basic_map_reverse(bmap); - - qp = read_term(s, bmap, v); - map = read_optional_disjuncts(s, bmap, v); + pwqp = read_term(s, map, v); + map = read_optional_disjuncts(s, map, v); set = isl_map_range(map); - pwqp = isl_pw_qpolynomial_alloc(set, qp); + pwqp = isl_pw_qpolynomial_intersect_domain(pwqp, set); vars_drop(v, v->n - n); @@ -1328,67 +1662,112 @@ static struct isl_obj obj_read_poly(struct isl_stream *s, return obj; } -static int next_is_tuple(struct isl_stream *s) +static struct isl_obj obj_read_poly_or_fold(struct isl_stream *s, + __isl_take isl_set *set, struct vars *v, int n) +{ + struct isl_obj obj = { isl_obj_pw_qpolynomial_fold, NULL }; + isl_pw_qpolynomial *pwqp; + isl_pw_qpolynomial_fold *pwf = NULL; + + if (!isl_stream_eat_if_available(s, ISL_TOKEN_MAX)) + return obj_read_poly(s, set, v, n); + + if (isl_stream_eat(s, '(')) + goto error; + + pwqp = read_term(s, set, v); + pwf = isl_pw_qpolynomial_fold_from_pw_qpolynomial(isl_fold_max, pwqp); + + while (isl_stream_eat_if_available(s, ',')) { + isl_pw_qpolynomial_fold *pwf_i; + pwqp = read_term(s, set, v); + pwf_i = isl_pw_qpolynomial_fold_from_pw_qpolynomial(isl_fold_max, + pwqp); + pwf = isl_pw_qpolynomial_fold_fold(pwf, pwf_i); + } + + if (isl_stream_eat(s, ')')) + goto error; + + set = read_optional_disjuncts(s, set, v); + pwf = isl_pw_qpolynomial_fold_intersect_domain(pwf, set); + + vars_drop(v, v->n - n); + + obj.v = pwf; + return obj; +error: + isl_set_free(set); + isl_pw_qpolynomial_fold_free(pwf); + obj.type = isl_obj_none; + return obj; +} + +static int is_rational(struct isl_stream *s) { struct isl_token *tok; - int is_tuple; tok = isl_stream_next_token(s); if (!tok) return 0; - if (tok->type == '[') { - isl_stream_push_token(s, tok); + if (tok->type == ISL_TOKEN_RAT && isl_stream_next_token_is(s, ':')) { + isl_token_free(tok); + isl_stream_eat(s, ':'); return 1; } - if (tok->type != ISL_TOKEN_IDENT) { - isl_stream_push_token(s, tok); - return 0; - } - - is_tuple = isl_stream_next_token_is(s, '['); isl_stream_push_token(s, tok); - return is_tuple; + return 0; } static struct isl_obj obj_read_body(struct isl_stream *s, - __isl_take isl_basic_map *bmap, struct vars *v) + __isl_take isl_map *map, struct vars *v) { - struct isl_map *map = NULL; struct isl_token *tok; struct isl_obj obj = { isl_obj_set, NULL }; int n = v->n; + if (is_rational(s)) + map = isl_map_set_rational(map); + + if (isl_stream_next_token_is(s, ':')) { + obj.type = isl_obj_set; + obj.v = read_optional_disjuncts(s, map, v); + return obj; + } + if (!next_is_tuple(s)) - return obj_read_poly(s, bmap, v, n); + return obj_read_poly_or_fold(s, map, v, n); - bmap = read_tuple(s, bmap, isl_dim_in, v); - if (!bmap) + map = read_tuple(s, map, isl_dim_in, v); + if (!map) goto error; tok = isl_stream_next_token(s); if (tok && tok->type == ISL_TOKEN_TO) { obj.type = isl_obj_map; isl_token_free(tok); - if (!next_is_tuple(s)) - return obj_read_poly(s, bmap, v, n); - bmap = read_tuple(s, bmap, isl_dim_out, v); - if (!bmap) + if (!next_is_tuple(s)) { + isl_set *set = isl_map_domain(map); + return obj_read_poly_or_fold(s, set, v, n); + } + map = read_tuple(s, map, isl_dim_out, v); + if (!map) goto error; } else { - bmap = isl_basic_map_reverse(bmap); + map = isl_map_reverse(map); if (tok) isl_stream_push_token(s, tok); } - map = read_optional_disjuncts(s, bmap, v); + map = read_optional_disjuncts(s, map, v); vars_drop(v, v->n - n); obj.v = map; return obj; error: - isl_basic_map_free(bmap); + isl_map_free(map); obj.type = isl_obj_none; return obj; } @@ -1440,21 +1819,21 @@ static struct isl_obj obj_add(struct isl_ctx *ctx, obj2.type == isl_obj_pw_qpolynomial_fold) obj2 = to_union(ctx, obj2); isl_assert(ctx, obj1.type == obj2.type, goto error); - if (obj1.type == isl_obj_map && !isl_map_has_equal_dim(obj1.v, obj2.v)) { + if (obj1.type == isl_obj_map && !isl_map_has_equal_space(obj1.v, obj2.v)) { obj1 = to_union(ctx, obj1); obj2 = to_union(ctx, obj2); } - if (obj1.type == isl_obj_set && !isl_set_has_equal_dim(obj1.v, obj2.v)) { + if (obj1.type == isl_obj_set && !isl_set_has_equal_space(obj1.v, obj2.v)) { obj1 = to_union(ctx, obj1); obj2 = to_union(ctx, obj2); } if (obj1.type == isl_obj_pw_qpolynomial && - !isl_pw_qpolynomial_has_equal_dim(obj1.v, obj2.v)) { + !isl_pw_qpolynomial_has_equal_space(obj1.v, obj2.v)) { obj1 = to_union(ctx, obj1); obj2 = to_union(ctx, obj2); } if (obj1.type == isl_obj_pw_qpolynomial_fold && - !isl_pw_qpolynomial_fold_has_equal_dim(obj1.v, obj2.v)) { + !isl_pw_qpolynomial_fold_has_equal_space(obj1.v, obj2.v)) { obj1 = to_union(ctx, obj1); obj2 = to_union(ctx, obj2); } @@ -1470,18 +1849,31 @@ error: static struct isl_obj obj_read(struct isl_stream *s, int nparam) { - struct isl_basic_map *bmap = NULL; + isl_map *map = NULL; struct isl_token *tok; struct vars *v = NULL; struct isl_obj obj = { isl_obj_set, NULL }; - tok = isl_stream_next_token(s); + tok = next_token(s); if (!tok) { isl_stream_error(s, NULL, "unexpected EOF"); goto error; } if (tok->type == ISL_TOKEN_VALUE) { + struct isl_token *tok2; struct isl_map *map; + + tok2 = isl_stream_next_token(s); + if (!tok2 || tok2->type != ISL_TOKEN_VALUE || + isl_int_is_neg(tok2->u.v)) { + if (tok2) + isl_stream_push_token(s, tok2); + obj.type = isl_obj_int; + obj.v = isl_int_obj_alloc(s->ctx, tok->u.v); + isl_token_free(tok); + return obj; + } + isl_stream_push_token(s, tok2); isl_stream_push_token(s, tok); map = map_read_polylib(s, nparam); if (!map) @@ -1496,11 +1888,11 @@ static struct isl_obj obj_read(struct isl_stream *s, int nparam) isl_stream_push_token(s, tok); goto error; } - bmap = isl_basic_map_alloc(s->ctx, 0, 0, 0, 0, 0, 0); + map = isl_map_universe(isl_space_params_alloc(s->ctx, 0)); if (tok->type == '[') { isl_stream_push_token(s, tok); - bmap = read_tuple(s, bmap, isl_dim_param, v); - if (!bmap) + map = read_tuple(s, map, isl_dim_param, v); + if (!map) goto error; if (nparam >= 0) isl_assert(s->ctx, nparam == v->n, goto error); @@ -1514,7 +1906,7 @@ static struct isl_obj obj_read(struct isl_stream *s, int nparam) isl_token_free(tok); tok = isl_stream_next_token(s); } else if (nparam > 0) - bmap = isl_basic_map_add(bmap, isl_dim_param, nparam); + map = isl_map_add_dims(map, isl_dim_param, nparam); if (!tok || tok->type != '{') { isl_stream_error(s, tok, "expecting '{'"); if (tok) @@ -1530,14 +1922,14 @@ static struct isl_obj obj_read(struct isl_stream *s, int nparam) isl_token_free(tok); if (isl_stream_eat(s, '=')) goto error; - bmap = read_tuple(s, bmap, isl_dim_param, v); - if (!bmap) + map = read_tuple(s, map, isl_dim_param, v); + if (!map) goto error; if (nparam >= 0) isl_assert(s->ctx, nparam == v->n, goto error); } else if (tok->type == '}') { obj.type = isl_obj_union_set; - obj.v = isl_union_set_empty(isl_basic_map_get_dim(bmap)); + obj.v = isl_union_set_empty(isl_map_get_space(map)); isl_token_free(tok); goto done; } else @@ -1546,20 +1938,24 @@ static struct isl_obj obj_read(struct isl_stream *s, int nparam) for (;;) { struct isl_obj o; tok = NULL; - o = obj_read_body(s, isl_basic_map_copy(bmap), v); - if (o.type == isl_obj_none) - break; + o = obj_read_body(s, isl_map_copy(map), v); + if (o.type == isl_obj_none || !o.v) + goto error; if (!obj.v) obj = o; else { obj = obj_add(s->ctx, obj, o); - if (obj.type == isl_obj_none) - break; + if (obj.type == isl_obj_none || !obj.v) + goto error; } tok = isl_stream_next_token(s); if (!tok || tok->type != ';') break; isl_token_free(tok); + if (isl_stream_next_token_is(s, '}')) { + tok = isl_stream_next_token(s); + break; + } } if (tok && tok->type == '}') { @@ -1572,11 +1968,11 @@ static struct isl_obj obj_read(struct isl_stream *s, int nparam) } done: vars_free(v); - isl_basic_map_free(bmap); + isl_map_free(map); return obj; error: - isl_basic_map_free(bmap); + isl_map_free(map); obj.type->free(obj.v); if (v) vars_free(v); @@ -1592,7 +1988,6 @@ struct isl_obj isl_stream_read_obj(struct isl_stream *s) __isl_give isl_map *isl_stream_read_map(struct isl_stream *s, int nparam) { struct isl_obj obj; - struct isl_map *map; obj = obj_read(s, nparam); if (obj.v) @@ -1608,7 +2003,6 @@ error: __isl_give isl_set *isl_stream_read_set(struct isl_stream *s, int nparam) { struct isl_obj obj; - struct isl_set *set; obj = obj_read(s, nparam); if (obj.v) @@ -1620,6 +2014,47 @@ error: return NULL; } +__isl_give isl_union_map *isl_stream_read_union_map(struct isl_stream *s) +{ + struct isl_obj obj; + + obj = obj_read(s, -1); + if (obj.type == isl_obj_map) { + obj.type = isl_obj_union_map; + obj.v = isl_union_map_from_map(obj.v); + } + if (obj.type == isl_obj_set) { + obj.type = isl_obj_union_set; + obj.v = isl_union_set_from_set(obj.v); + } + if (obj.v) + isl_assert(s->ctx, obj.type == isl_obj_union_map || + obj.type == isl_obj_union_set, goto error); + + return obj.v; +error: + obj.type->free(obj.v); + return NULL; +} + +__isl_give isl_union_set *isl_stream_read_union_set(struct isl_stream *s) +{ + struct isl_obj obj; + + obj = obj_read(s, -1); + if (obj.type == isl_obj_set) { + obj.type = isl_obj_union_set; + obj.v = isl_union_set_from_set(obj.v); + } + if (obj.v) + isl_assert(s->ctx, obj.type == isl_obj_union_set, goto error); + + return obj.v; +error: + obj.type->free(obj.v); + return NULL; +} + static struct isl_basic_map *basic_map_read(struct isl_stream *s, int nparam) { struct isl_obj obj; @@ -1750,67 +2185,109 @@ error: return NULL; } -static char *next_line(FILE *input, char *line, unsigned len) +__isl_give isl_union_map *isl_union_map_read_from_file(isl_ctx *ctx, + FILE *input) +{ + isl_union_map *umap; + struct isl_stream *s = isl_stream_new_file(ctx, input); + if (!s) + return NULL; + umap = isl_stream_read_union_map(s); + isl_stream_free(s); + return umap; +} + +__isl_give isl_union_map *isl_union_map_read_from_str(struct isl_ctx *ctx, + const char *str) { - char *p; + isl_union_map *umap; + struct isl_stream *s = isl_stream_new_str(ctx, str); + if (!s) + return NULL; + umap = isl_stream_read_union_map(s); + isl_stream_free(s); + return umap; +} - do { - if (!(p = fgets(line, len, input))) - return NULL; - while (isspace(*p) && *p != '\n') - ++p; - } while (*p == '#' || *p == '\n'); +__isl_give isl_union_set *isl_union_set_read_from_file(isl_ctx *ctx, + FILE *input) +{ + isl_union_set *uset; + struct isl_stream *s = isl_stream_new_file(ctx, input); + if (!s) + return NULL; + uset = isl_stream_read_union_set(s); + isl_stream_free(s); + return uset; +} - return p; +__isl_give isl_union_set *isl_union_set_read_from_str(struct isl_ctx *ctx, + const char *str) +{ + isl_union_set *uset; + struct isl_stream *s = isl_stream_new_str(ctx, str); + if (!s) + return NULL; + uset = isl_stream_read_union_set(s); + isl_stream_free(s); + return uset; } -static struct isl_vec *isl_vec_read_from_file_polylib(struct isl_ctx *ctx, - FILE *input) +static __isl_give isl_vec *isl_vec_read_polylib(struct isl_stream *s) { struct isl_vec *vec = NULL; - char line[1024]; - char val[1024]; - char *p; + struct isl_token *tok; unsigned size; int j; - int n; - int offset; - isl_assert(ctx, next_line(input, line, sizeof(line)), return NULL); - isl_assert(ctx, sscanf(line, "%u", &size) == 1, return NULL); + tok = isl_stream_next_token(s); + if (!tok || tok->type != ISL_TOKEN_VALUE) { + isl_stream_error(s, tok, "expecting vector length"); + goto error; + } - vec = isl_vec_alloc(ctx, size); + size = isl_int_get_si(tok->u.v); + isl_token_free(tok); - p = next_line(input, line, sizeof(line)); - isl_assert(ctx, p, goto error); + vec = isl_vec_alloc(s->ctx, size); for (j = 0; j < size; ++j) { - n = sscanf(p, "%s%n", val, &offset); - isl_assert(ctx, n != 0, goto error); - isl_int_read(vec->el[j], val); - p += offset; + tok = isl_stream_next_token(s); + if (!tok || tok->type != ISL_TOKEN_VALUE) { + isl_stream_error(s, tok, "expecting constant value"); + goto error; + } + isl_int_set(vec->el[j], tok->u.v); + isl_token_free(tok); } return vec; error: + isl_token_free(tok); isl_vec_free(vec); return NULL; } -struct isl_vec *isl_vec_read_from_file(struct isl_ctx *ctx, - FILE *input, unsigned input_format) +static __isl_give isl_vec *vec_read(struct isl_stream *s) { - if (input_format == ISL_FORMAT_POLYLIB) - return isl_vec_read_from_file_polylib(ctx, input); - else - isl_assert(ctx, 0, return NULL); + return isl_vec_read_polylib(s); +} + +__isl_give isl_vec *isl_vec_read_from_file(isl_ctx *ctx, FILE *input) +{ + isl_vec *v; + struct isl_stream *s = isl_stream_new_file(ctx, input); + if (!s) + return NULL; + v = vec_read(s); + isl_stream_free(s); + return v; } __isl_give isl_pw_qpolynomial *isl_stream_read_pw_qpolynomial( struct isl_stream *s) { struct isl_obj obj; - struct isl_pw_qpolynomial *pwqp; obj = obj_read(s, -1); if (obj.v) @@ -1822,3 +2299,27 @@ error: obj.type->free(obj.v); return NULL; } + +__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_read_from_str(isl_ctx *ctx, + const char *str) +{ + isl_pw_qpolynomial *pwqp; + struct isl_stream *s = isl_stream_new_str(ctx, str); + if (!s) + return NULL; + pwqp = isl_stream_read_pw_qpolynomial(s); + isl_stream_free(s); + return pwqp; +} + +__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_read_from_file(isl_ctx *ctx, + FILE *input) +{ + isl_pw_qpolynomial *pwqp; + struct isl_stream *s = isl_stream_new_file(ctx, input); + if (!s) + return NULL; + pwqp = isl_stream_read_pw_qpolynomial(s); + isl_stream_free(s); + return pwqp; +}