add isl_pw_*_intersect_params
[platform/upstream/isl.git] / isl_input.c
index 4436459..320703a 100644 (file)
@@ -899,7 +899,7 @@ static __isl_give isl_map *read_tuple(struct isl_stream *s,
                nested = read_nested_tuple(s, isl_map_universe(dim), v);
                if (type == isl_dim_in) {
                        nested = isl_map_reverse(nested);
                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);
+                       map = isl_map_intersect_params(nested, map);
                } else {
                        isl_set *set;
                        dim = isl_set_get_space(nested);
                } else {
                        isl_set *set;
                        dim = isl_set_get_space(nested);
@@ -1058,9 +1058,14 @@ static int resolve_paren_expr(struct isl_stream *s,
        if (!tok || tok->type != '(')
                goto error;
 
        if (!tok || tok->type != '(')
                goto error;
 
+       if (isl_stream_next_token_is(s, '('))
+               if (resolve_paren_expr(s, v, isl_map_copy(map)))
+                       goto error;
+
        if (isl_stream_next_token_is(s, ISL_TOKEN_EXISTS) ||
            isl_stream_next_token_is(s, ISL_TOKEN_TRUE) ||
        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)) {
+           isl_stream_next_token_is(s, ISL_TOKEN_FALSE) ||
+           isl_stream_next_token_is(s, ISL_TOKEN_MAP)) {
                map = read_disjuncts(s, v, map);
                if (isl_stream_eat(s, ')'))
                        goto error;
                map = read_disjuncts(s, v, map);
                if (isl_stream_eat(s, ')'))
                        goto error;
@@ -2334,3 +2339,347 @@ __isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_read_from_file(isl_ctx *ctx,
        isl_stream_free(s);
        return pwqp;
 }
        isl_stream_free(s);
        return pwqp;
 }
+
+/* Read an affine expression from "s" with domain (space) "dom".
+ * We call accept_affine to parse a possibly piecewise affine expression
+ * and then check that the result is a single affine expression on
+ * a universe domain.
+ */
+static __isl_give isl_aff *read_aff_with_dom(struct isl_stream *s,
+       __isl_take isl_set *dom, struct vars *v)
+{
+       isl_aff *aff = NULL;
+       isl_pw_aff *pwaff = NULL;
+
+       if (!isl_set_plain_is_universe(dom))
+               isl_die(s->ctx, isl_error_invalid,
+                       "expecting universe domain", goto error);
+
+       if (!isl_set_is_params(dom) && isl_stream_eat(s, ISL_TOKEN_TO))
+               goto error;
+
+       if (isl_stream_eat(s, '['))
+               goto error;
+
+       pwaff = accept_affine(s, isl_set_get_space(dom), v);
+
+       if (isl_stream_eat(s, ']'))
+               goto error;
+       if (isl_stream_eat(s, '}'))
+               goto error;
+
+       if (!pwaff)
+               goto error;
+
+       if (pwaff->n != 1)
+               isl_die(s->ctx, isl_error_invalid,
+                       "expecting single affine expression", goto error);
+       if (!isl_set_plain_is_universe(pwaff->p[0].set))
+               isl_die(s->ctx, isl_error_invalid,
+                       "expecting universe domain", goto error);
+
+       aff = isl_aff_copy(pwaff->p[0].aff);
+
+       vars_free(v);
+       isl_pw_aff_free(pwaff);
+       isl_set_free(dom);
+       return aff;
+error:
+       vars_free(v);
+       isl_pw_aff_free(pwaff);
+       isl_set_free(dom);
+       return NULL;
+}
+
+/* Is the next token an identifer not in "v"?
+ */
+static int next_is_fresh_ident(struct isl_stream *s, struct vars *v)
+{
+       int n = v->n;
+       int fresh;
+       struct isl_token *tok;
+
+       tok = isl_stream_next_token(s);
+       if (!tok)
+               return 0;
+       fresh = tok->type == ISL_TOKEN_IDENT && vars_pos(v, tok->u.s, -1) >= n;
+       isl_stream_push_token(s, tok);
+
+       vars_drop(v, v->n - n);
+
+       return fresh;
+}
+
+/* First read the domain of the affine expression, which may be
+ * a parameter space or a set.
+ * The tricky part is that we don't know if the domain is a set or not,
+ * so when we are trying to read the domain, we may actually be reading
+ * the affine expression itself (defined on a parameter domains)
+ * If the tuple we are reading is named, we assume it's the domain.
+ * Also, if inside the tuple, the first thing we find is a nested tuple
+ * or a new identifier, we again assume it's the domain.
+ * Otherwise, we assume we are reading an affine expression.
+ */
+static __isl_give isl_set *read_aff_domain(struct isl_stream *s,
+       __isl_take isl_set *dom, struct vars *v)
+{
+       struct isl_token *tok;
+
+       tok = isl_stream_next_token(s);
+       if (tok && (tok->type == ISL_TOKEN_IDENT || tok->is_keyword)) {
+               isl_stream_push_token(s, tok);
+               return read_tuple(s, dom, isl_dim_set, v);
+       }
+       if (!tok || tok->type != '[') {
+               isl_stream_error(s, tok, "expecting '['");
+               goto error;
+       }
+       if (next_is_tuple(s) || next_is_fresh_ident(s, v)) {
+               isl_stream_push_token(s, tok);
+               dom = read_tuple(s, dom, isl_dim_set, v);
+       } else
+               isl_stream_push_token(s, tok);
+
+       return dom;
+error:
+       if (tok)
+               isl_stream_push_token(s, tok);
+       vars_free(v);
+       isl_set_free(dom);
+       return NULL;
+}
+
+/* Read an affine expression from "s".
+ * We first read the domain of the affine expression, which may be
+ * a parameter space or a set, and then call read_aff_with_dom.
+ */
+__isl_give isl_aff *isl_stream_read_aff(struct isl_stream *s)
+{
+       struct vars *v;
+       isl_set *dom = NULL;
+
+       v = vars_new(s->ctx);
+       if (!v)
+               return NULL;
+
+       dom = isl_set_universe(isl_space_params_alloc(s->ctx, 0));
+       if (next_is_tuple(s)) {
+               dom = read_tuple(s, dom, isl_dim_param, v);
+               if (isl_stream_eat(s, ISL_TOKEN_TO))
+                       goto error;
+       }
+       if (isl_stream_eat(s, '{'))
+               goto error;
+
+       dom = read_aff_domain(s, dom, v);
+       return read_aff_with_dom(s, dom, v);
+error:
+       vars_free(v);
+       isl_set_free(dom);
+       return NULL;
+}
+
+/* Read a piecewise affine expression from "s" with domain (space) "dom".
+ */
+static __isl_give isl_pw_aff *read_pw_aff_with_dom(struct isl_stream *s,
+       __isl_take isl_set *dom, struct vars *v)
+{
+       isl_pw_aff *pwaff = NULL;
+
+       if (!isl_set_is_params(dom) && isl_stream_eat(s, ISL_TOKEN_TO))
+               goto error;
+
+       if (isl_stream_eat(s, '['))
+               goto error;
+
+       pwaff = accept_affine(s, isl_set_get_space(dom), v);
+
+       if (isl_stream_eat(s, ']'))
+               goto error;
+
+       dom = read_optional_disjuncts(s, dom, v);
+       pwaff = isl_pw_aff_intersect_domain(pwaff, dom);
+
+       return pwaff;
+error:
+       isl_set_free(dom);
+       isl_pw_aff_free(pwaff);
+       return NULL;
+}
+
+__isl_give isl_pw_aff *isl_stream_read_pw_aff(struct isl_stream *s)
+{
+       struct vars *v;
+       isl_set *dom = NULL;
+       isl_set *aff_dom;
+       isl_pw_aff *pa = NULL;
+       int n;
+
+       v = vars_new(s->ctx);
+       if (!v)
+               return NULL;
+
+       dom = isl_set_universe(isl_space_params_alloc(s->ctx, 0));
+       if (next_is_tuple(s)) {
+               dom = read_tuple(s, dom, isl_dim_param, v);
+               if (isl_stream_eat(s, ISL_TOKEN_TO))
+                       goto error;
+       }
+       if (isl_stream_eat(s, '{'))
+               goto error;
+
+       n = v->n;
+       aff_dom = read_aff_domain(s, isl_set_copy(dom), v);
+       pa = read_pw_aff_with_dom(s, aff_dom, v);
+       vars_drop(v, v->n - n);
+
+       while (isl_stream_eat_if_available(s, ';')) {
+               isl_pw_aff *pa_i;
+
+               n = v->n;
+               aff_dom = read_aff_domain(s, isl_set_copy(dom), v);
+               pa_i = read_pw_aff_with_dom(s, aff_dom, v);
+               vars_drop(v, v->n - n);
+
+               pa = isl_pw_aff_add(pa, pa_i);
+       }
+
+       if (isl_stream_eat(s, '}'))
+               goto error;
+
+       vars_free(v);
+       isl_set_free(dom);
+       return pa;
+error:
+       vars_free(v);
+       isl_set_free(dom);
+       isl_pw_aff_free(pa);
+       return NULL;
+}
+
+__isl_give isl_aff *isl_aff_read_from_str(isl_ctx *ctx, const char *str)
+{
+       isl_aff *aff;
+       struct isl_stream *s = isl_stream_new_str(ctx, str);
+       if (!s)
+               return NULL;
+       aff = isl_stream_read_aff(s);
+       isl_stream_free(s);
+       return aff;
+}
+
+__isl_give isl_pw_aff *isl_pw_aff_read_from_str(isl_ctx *ctx, const char *str)
+{
+       isl_pw_aff *pa;
+       struct isl_stream *s = isl_stream_new_str(ctx, str);
+       if (!s)
+               return NULL;
+       pa = isl_stream_read_pw_aff(s);
+       isl_stream_free(s);
+       return pa;
+}
+
+/* Read an isl_pw_multi_aff from "s".
+ * We currently read a generic object and if it turns out to be a set or
+ * a map, we convert that to an isl_pw_multi_aff.
+ * It would be more efficient if we were to construct the isl_pw_multi_aff
+ * directly.
+ */
+__isl_give isl_pw_multi_aff *isl_stream_read_pw_multi_aff(struct isl_stream *s)
+{
+       struct isl_obj obj;
+
+       obj = obj_read(s);
+       if (!obj.v)
+               return NULL;
+
+       if (obj.type == isl_obj_map)
+               return isl_pw_multi_aff_from_map(obj.v);
+       if (obj.type == isl_obj_set)
+               return isl_pw_multi_aff_from_set(obj.v);
+
+       obj.type->free(obj.v);
+       isl_die(s->ctx, isl_error_invalid, "unexpected object type",
+               return NULL);
+}
+
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_read_from_str(isl_ctx *ctx,
+       const char *str)
+{
+       isl_pw_multi_aff *pma;
+       struct isl_stream *s = isl_stream_new_str(ctx, str);
+       if (!s)
+               return NULL;
+       pma = isl_stream_read_pw_multi_aff(s);
+       isl_stream_free(s);
+       return pma;
+}
+
+/* Read a multi-affine expression from "s".
+ * We call isl_stream_read_pw_multi_aff to parse a possibly piecewise
+ * multi-affine expression and then check that the result is
+ * a single multi-affine expression on a universe domain.
+ */
+__isl_give isl_multi_aff *isl_stream_read_multi_aff(struct isl_stream *s)
+{
+       isl_pw_multi_aff *pma;
+       isl_multi_aff *maff;
+
+       pma = isl_stream_read_pw_multi_aff(s);
+       if (!pma)
+               return NULL;
+       if (pma->n != 1)
+               isl_die(s->ctx, isl_error_invalid,
+                       "expecting single list of affine expressions",
+                       return isl_pw_multi_aff_free(pma));
+       if (!isl_set_plain_is_universe(pma->p[0].set))
+               isl_die(s->ctx, isl_error_invalid, "expecting universe domain",
+                       return isl_pw_multi_aff_free(pma));
+       maff = isl_multi_aff_copy(pma->p[0].maff);
+       isl_pw_multi_aff_free(pma);
+       return maff;
+}
+
+__isl_give isl_multi_aff *isl_multi_aff_read_from_str(isl_ctx *ctx,
+       const char *str)
+{
+       isl_multi_aff *maff;
+       struct isl_stream *s = isl_stream_new_str(ctx, str);
+       if (!s)
+               return NULL;
+       maff = isl_stream_read_multi_aff(s);
+       isl_stream_free(s);
+       return maff;
+}
+
+__isl_give isl_union_pw_qpolynomial *isl_stream_read_union_pw_qpolynomial(
+       struct isl_stream *s)
+{
+       struct isl_obj obj;
+
+       obj = obj_read(s);
+       if (obj.type == isl_obj_pw_qpolynomial) {
+               obj.type = isl_obj_union_pw_qpolynomial;
+               obj.v = isl_union_pw_qpolynomial_from_pw_qpolynomial(obj.v);
+       }
+       if (obj.v)
+               isl_assert(s->ctx, obj.type == isl_obj_union_pw_qpolynomial,
+                          goto error);
+
+       return obj.v;
+error:
+       obj.type->free(obj.v);
+       return NULL;
+}
+
+__isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_read_from_str(
+       isl_ctx *ctx, const char *str)
+{
+       isl_union_pw_qpolynomial *upwqp;
+       struct isl_stream *s = isl_stream_new_str(ctx, str);
+       if (!s)
+               return NULL;
+       upwqp = isl_stream_read_union_pw_qpolynomial(s);
+       isl_stream_free(s);
+       return upwqp;
+}