2 * Copyright 2008-2009 Katholieke Universiteit Leuven
3 * Copyright 2010 INRIA Saclay
4 * Copyright 2012-2013 Ecole Normale Superieure
6 * Use of this software is governed by the MIT license
8 * Written by Sven Verdoolaege, K.U.Leuven, Departement
9 * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
10 * and INRIA Saclay - Ile-de-France, Parc Club Orsay Universite,
11 * ZAC des vignes, 4 rue Jacques Monod, 91893 Orsay, France
12 * and Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France
18 #include <isl_ctx_private.h>
19 #include <isl_map_private.h>
20 #include <isl_id_private.h>
23 #include <isl_stream_private.h>
25 #include "isl_polynomial_private.h"
26 #include <isl/union_set.h>
27 #include <isl/union_map.h>
28 #include <isl_mat_private.h>
29 #include <isl_aff_private.h>
30 #include <isl_vec_private.h>
32 #include <isl_val_private.h>
37 struct variable
*next
;
46 static struct vars
*vars_new(struct isl_ctx
*ctx
)
49 v
= isl_alloc_type(ctx
, struct vars
);
58 static void variable_free(struct variable
*var
)
61 struct variable
*next
= var
->next
;
68 static void vars_free(struct vars
*v
)
76 static void vars_drop(struct vars
*v
, int n
)
87 struct variable
*next
= var
->next
;
95 static struct variable
*variable_new(struct vars
*v
, const char *name
, int len
,
99 var
= isl_calloc_type(v
->ctx
, struct variable
);
102 var
->name
= strdup(name
);
103 var
->name
[len
] = '\0';
112 static int vars_pos(struct vars
*v
, const char *s
, int len
)
119 for (q
= v
->v
; q
; q
= q
->next
) {
120 if (strncmp(q
->name
, s
, len
) == 0 && q
->name
[len
] == '\0')
127 v
->v
= variable_new(v
, s
, len
, v
->n
);
135 static int vars_add_anon(struct vars
*v
)
137 v
->v
= variable_new(v
, "", 0, v
->n
);
146 /* Obtain next token, with some preprocessing.
147 * In particular, evaluate expressions of the form x^y,
148 * with x and y values.
150 static struct isl_token
*next_token(__isl_keep isl_stream
*s
)
152 struct isl_token
*tok
, *tok2
;
154 tok
= isl_stream_next_token(s
);
155 if (!tok
|| tok
->type
!= ISL_TOKEN_VALUE
)
157 if (!isl_stream_eat_if_available(s
, '^'))
159 tok2
= isl_stream_next_token(s
);
160 if (!tok2
|| tok2
->type
!= ISL_TOKEN_VALUE
) {
161 isl_stream_error(s
, tok2
, "expecting constant value");
165 isl_int_pow_ui(tok
->u
.v
, tok
->u
.v
, isl_int_get_ui(tok2
->u
.v
));
167 isl_token_free(tok2
);
171 isl_token_free(tok2
);
175 /* Read an isl_val from "s".
177 * The following token sequences are recognized
180 * "-" "infty" -> -infty
185 * where n, d and v are integer constants.
187 __isl_give isl_val
*isl_stream_read_val(__isl_keep isl_stream
*s
)
189 struct isl_token
*tok
= NULL
;
190 struct isl_token
*tok2
= NULL
;
195 isl_stream_error(s
, NULL
, "unexpected EOF");
198 if (tok
->type
== ISL_TOKEN_INFTY
) {
200 return isl_val_infty(s
->ctx
);
202 if (tok
->type
== '-' &&
203 isl_stream_eat_if_available(s
, ISL_TOKEN_INFTY
)) {
205 return isl_val_neginfty(s
->ctx
);
207 if (tok
->type
== ISL_TOKEN_NAN
) {
209 return isl_val_nan(s
->ctx
);
211 if (tok
->type
!= ISL_TOKEN_VALUE
) {
212 isl_stream_error(s
, tok
, "expecting value");
216 if (isl_stream_eat_if_available(s
, '/')) {
217 tok2
= next_token(s
);
219 isl_stream_error(s
, NULL
, "unexpected EOF");
222 if (tok2
->type
!= ISL_TOKEN_VALUE
) {
223 isl_stream_error(s
, tok2
, "expecting value");
226 val
= isl_val_rat_from_isl_int(s
->ctx
, tok
->u
.v
, tok2
->u
.v
);
227 val
= isl_val_normalize(val
);
229 val
= isl_val_int_from_isl_int(s
->ctx
, tok
->u
.v
);
233 isl_token_free(tok2
);
237 isl_token_free(tok2
);
241 /* Read an isl_val from "str".
243 struct isl_val
*isl_val_read_from_str(struct isl_ctx
*ctx
,
247 isl_stream
*s
= isl_stream_new_str(ctx
, str
);
250 val
= isl_stream_read_val(s
);
255 static int accept_cst_factor(__isl_keep isl_stream
*s
, isl_int
*f
)
257 struct isl_token
*tok
;
260 if (!tok
|| tok
->type
!= ISL_TOKEN_VALUE
) {
261 isl_stream_error(s
, tok
, "expecting constant value");
265 isl_int_mul(*f
, *f
, tok
->u
.v
);
269 if (isl_stream_eat_if_available(s
, '*'))
270 return accept_cst_factor(s
, f
);
278 /* Given an affine expression aff, return an affine expression
279 * for aff % d, with d the next token on the stream, which is
280 * assumed to be a constant.
282 * We introduce an integer division q = [aff/d] and the result
283 * is set to aff - d q.
285 static __isl_give isl_pw_aff
*affine_mod(__isl_keep isl_stream
*s
,
286 struct vars
*v
, __isl_take isl_pw_aff
*aff
)
288 struct isl_token
*tok
;
292 if (!tok
|| tok
->type
!= ISL_TOKEN_VALUE
) {
293 isl_stream_error(s
, tok
, "expecting constant value");
297 q
= isl_pw_aff_copy(aff
);
298 q
= isl_pw_aff_scale_down(q
, tok
->u
.v
);
299 q
= isl_pw_aff_floor(q
);
300 q
= isl_pw_aff_scale(q
, tok
->u
.v
);
302 aff
= isl_pw_aff_sub(aff
, q
);
307 isl_pw_aff_free(aff
);
312 static __isl_give isl_pw_aff
*accept_affine(__isl_keep isl_stream
*s
,
313 __isl_take isl_space
*space
, struct vars
*v
);
314 static __isl_give isl_pw_aff_list
*accept_affine_list(__isl_keep isl_stream
*s
,
315 __isl_take isl_space
*dim
, struct vars
*v
);
317 static __isl_give isl_pw_aff
*accept_minmax(__isl_keep isl_stream
*s
,
318 __isl_take isl_space
*dim
, struct vars
*v
)
320 struct isl_token
*tok
;
321 isl_pw_aff_list
*list
= NULL
;
324 tok
= isl_stream_next_token(s
);
327 min
= tok
->type
== ISL_TOKEN_MIN
;
330 if (isl_stream_eat(s
, '('))
333 list
= accept_affine_list(s
, isl_space_copy(dim
), v
);
337 if (isl_stream_eat(s
, ')'))
341 return min
? isl_pw_aff_list_min(list
) : isl_pw_aff_list_max(list
);
344 isl_pw_aff_list_free(list
);
348 /* Is "tok" the start of an integer division?
350 static int is_start_of_div(struct isl_token
*tok
)
354 if (tok
->type
== '[')
356 if (tok
->type
== ISL_TOKEN_FLOOR
)
358 if (tok
->type
== ISL_TOKEN_CEIL
)
360 if (tok
->type
== ISL_TOKEN_FLOORD
)
362 if (tok
->type
== ISL_TOKEN_CEILD
)
367 /* Read an integer division from "s" and return it as an isl_pw_aff.
369 * The integer division can be of the form
371 * [<affine expression>]
372 * floor(<affine expression>)
373 * ceil(<affine expression>)
374 * floord(<affine expression>,<denominator>)
375 * ceild(<affine expression>,<denominator>)
377 static __isl_give isl_pw_aff
*accept_div(__isl_keep isl_stream
*s
,
378 __isl_take isl_space
*dim
, struct vars
*v
)
380 struct isl_token
*tok
;
384 isl_pw_aff
*pwaff
= NULL
;
386 if (isl_stream_eat_if_available(s
, ISL_TOKEN_FLOORD
))
388 else if (isl_stream_eat_if_available(s
, ISL_TOKEN_CEILD
))
390 else if (isl_stream_eat_if_available(s
, ISL_TOKEN_FLOOR
))
392 else if (isl_stream_eat_if_available(s
, ISL_TOKEN_CEIL
))
395 if (isl_stream_eat(s
, '('))
398 if (isl_stream_eat(s
, '['))
402 pwaff
= accept_affine(s
, isl_space_copy(dim
), v
);
405 if (isl_stream_eat(s
, ','))
411 if (tok
->type
!= ISL_TOKEN_VALUE
) {
412 isl_stream_error(s
, tok
, "expected denominator");
413 isl_stream_push_token(s
, tok
);
416 pwaff
= isl_pw_aff_scale_down(pwaff
, tok
->u
.v
);
421 pwaff
= isl_pw_aff_ceil(pwaff
);
423 pwaff
= isl_pw_aff_floor(pwaff
);
426 if (isl_stream_eat(s
, ')'))
429 if (isl_stream_eat(s
, ']'))
437 isl_pw_aff_free(pwaff
);
441 static __isl_give isl_pw_aff
*accept_affine_factor(__isl_keep isl_stream
*s
,
442 __isl_take isl_space
*dim
, struct vars
*v
)
444 struct isl_token
*tok
= NULL
;
445 isl_pw_aff
*res
= NULL
;
449 isl_stream_error(s
, NULL
, "unexpected EOF");
453 if (tok
->type
== ISL_TOKEN_AFF
) {
454 res
= isl_pw_aff_copy(tok
->u
.pwaff
);
456 } else if (tok
->type
== ISL_TOKEN_IDENT
) {
458 int pos
= vars_pos(v
, tok
->u
.s
, -1);
464 vars_drop(v
, v
->n
- n
);
465 isl_stream_error(s
, tok
, "unknown identifier");
469 aff
= isl_aff_zero_on_domain(isl_local_space_from_space(isl_space_copy(dim
)));
472 isl_int_set_si(aff
->v
->el
[2 + pos
], 1);
473 res
= isl_pw_aff_from_aff(aff
);
475 } else if (tok
->type
== ISL_TOKEN_VALUE
) {
476 if (isl_stream_eat_if_available(s
, '*')) {
477 res
= accept_affine_factor(s
, isl_space_copy(dim
), v
);
478 res
= isl_pw_aff_scale(res
, tok
->u
.v
);
482 ls
= isl_local_space_from_space(isl_space_copy(dim
));
483 aff
= isl_aff_zero_on_domain(ls
);
484 aff
= isl_aff_add_constant(aff
, tok
->u
.v
);
485 res
= isl_pw_aff_from_aff(aff
);
488 } else if (tok
->type
== '(') {
491 res
= accept_affine(s
, isl_space_copy(dim
), v
);
494 if (isl_stream_eat(s
, ')'))
496 } else if (is_start_of_div(tok
)) {
497 isl_stream_push_token(s
, tok
);
499 res
= accept_div(s
, isl_space_copy(dim
), v
);
500 } else if (tok
->type
== ISL_TOKEN_MIN
|| tok
->type
== ISL_TOKEN_MAX
) {
501 isl_stream_push_token(s
, tok
);
503 res
= accept_minmax(s
, isl_space_copy(dim
), v
);
505 isl_stream_error(s
, tok
, "expecting factor");
508 if (isl_stream_eat_if_available(s
, '%') ||
509 isl_stream_eat_if_available(s
, ISL_TOKEN_MOD
)) {
511 return affine_mod(s
, v
, res
);
513 if (isl_stream_eat_if_available(s
, '*')) {
516 isl_int_set_si(f
, 1);
517 if (accept_cst_factor(s
, &f
) < 0) {
521 res
= isl_pw_aff_scale(res
, f
);
524 if (isl_stream_eat_if_available(s
, '/')) {
527 isl_int_set_si(f
, 1);
528 if (accept_cst_factor(s
, &f
) < 0) {
532 res
= isl_pw_aff_scale_down(res
, f
);
541 isl_pw_aff_free(res
);
546 static __isl_give isl_pw_aff
*add_cst(__isl_take isl_pw_aff
*pwaff
, isl_int v
)
551 space
= isl_pw_aff_get_domain_space(pwaff
);
552 aff
= isl_aff_zero_on_domain(isl_local_space_from_space(space
));
553 aff
= isl_aff_add_constant(aff
, v
);
555 return isl_pw_aff_add(pwaff
, isl_pw_aff_from_aff(aff
));
558 /* Return a piecewise affine expression defined on the specified domain
559 * that represents NaN.
561 static __isl_give isl_pw_aff
*nan_on_domain(__isl_keep isl_space
*space
)
565 ls
= isl_local_space_from_space(isl_space_copy(space
));
566 return isl_pw_aff_nan_on_domain(ls
);
569 static __isl_give isl_pw_aff
*accept_affine(__isl_keep isl_stream
*s
,
570 __isl_take isl_space
*space
, struct vars
*v
)
572 struct isl_token
*tok
= NULL
;
577 ls
= isl_local_space_from_space(isl_space_copy(space
));
578 res
= isl_pw_aff_from_aff(isl_aff_zero_on_domain(ls
));
585 isl_stream_error(s
, NULL
, "unexpected EOF");
588 if (tok
->type
== '-') {
593 if (tok
->type
== '(' || is_start_of_div(tok
) ||
594 tok
->type
== ISL_TOKEN_MIN
|| tok
->type
== ISL_TOKEN_MAX
||
595 tok
->type
== ISL_TOKEN_IDENT
||
596 tok
->type
== ISL_TOKEN_AFF
) {
598 isl_stream_push_token(s
, tok
);
600 term
= accept_affine_factor(s
,
601 isl_space_copy(space
), v
);
603 res
= isl_pw_aff_sub(res
, term
);
605 res
= isl_pw_aff_add(res
, term
);
609 } else if (tok
->type
== ISL_TOKEN_VALUE
) {
611 isl_int_neg(tok
->u
.v
, tok
->u
.v
);
612 if (isl_stream_eat_if_available(s
, '*') ||
613 isl_stream_next_token_is(s
, ISL_TOKEN_IDENT
)) {
615 term
= accept_affine_factor(s
,
616 isl_space_copy(space
), v
);
617 term
= isl_pw_aff_scale(term
, tok
->u
.v
);
618 res
= isl_pw_aff_add(res
, term
);
622 res
= add_cst(res
, tok
->u
.v
);
625 } else if (tok
->type
== ISL_TOKEN_NAN
) {
626 res
= isl_pw_aff_add(res
, nan_on_domain(space
));
628 isl_stream_error(s
, tok
, "unexpected isl_token");
629 isl_stream_push_token(s
, tok
);
630 isl_pw_aff_free(res
);
631 isl_space_free(space
);
637 if (tok
&& tok
->type
== '-') {
640 } else if (tok
&& tok
->type
== '+') {
643 } else if (tok
&& tok
->type
== ISL_TOKEN_VALUE
&&
644 isl_int_is_neg(tok
->u
.v
)) {
645 isl_stream_push_token(s
, tok
);
648 isl_stream_push_token(s
, tok
);
653 isl_space_free(space
);
656 isl_space_free(space
);
658 isl_pw_aff_free(res
);
662 /* Is "type" the type of a comparison operator between lists
663 * of affine expressions?
665 static int is_list_comparator_type(int type
)
668 case ISL_TOKEN_LEX_LT
:
669 case ISL_TOKEN_LEX_GT
:
670 case ISL_TOKEN_LEX_LE
:
671 case ISL_TOKEN_LEX_GE
:
678 static int is_comparator(struct isl_token
*tok
)
682 if (is_list_comparator_type(tok
->type
))
698 static __isl_give isl_map
*read_formula(__isl_keep isl_stream
*s
,
699 struct vars
*v
, __isl_take isl_map
*map
, int rational
);
700 static __isl_give isl_pw_aff
*accept_extended_affine(__isl_keep isl_stream
*s
,
701 __isl_take isl_space
*dim
, struct vars
*v
, int rational
);
703 /* Accept a ternary operator, given the first argument.
705 static __isl_give isl_pw_aff
*accept_ternary(__isl_keep isl_stream
*s
,
706 __isl_take isl_map
*cond
, struct vars
*v
, int rational
)
709 isl_pw_aff
*pwaff1
= NULL
, *pwaff2
= NULL
, *pa_cond
;
714 if (isl_stream_eat(s
, '?'))
717 space
= isl_space_wrap(isl_map_get_space(cond
));
718 pwaff1
= accept_extended_affine(s
, space
, v
, rational
);
722 if (isl_stream_eat(s
, ':'))
725 space
= isl_pw_aff_get_domain_space(pwaff1
);
726 pwaff2
= accept_extended_affine(s
, space
, v
, rational
);
730 pa_cond
= isl_set_indicator_function(isl_map_wrap(cond
));
731 return isl_pw_aff_cond(pa_cond
, pwaff1
, pwaff2
);
734 isl_pw_aff_free(pwaff1
);
735 isl_pw_aff_free(pwaff2
);
739 /* Set *line and *col to those of the next token, if any.
741 static void set_current_line_col(__isl_keep isl_stream
*s
, int *line
, int *col
)
743 struct isl_token
*tok
;
745 tok
= isl_stream_next_token(s
);
751 isl_stream_push_token(s
, tok
);
754 /* Push a token encapsulating "pa" onto "s", with the given
757 static isl_stat
push_aff(__isl_keep isl_stream
*s
, int line
, int col
,
758 __isl_take isl_pw_aff
*pa
)
760 struct isl_token
*tok
;
762 tok
= isl_token_new(s
->ctx
, line
, col
, 0);
765 tok
->type
= ISL_TOKEN_AFF
;
767 isl_stream_push_token(s
, tok
);
772 return isl_stat_error
;
775 /* Is the next token a comparison operator?
777 static int next_is_comparator(__isl_keep isl_stream
*s
)
780 struct isl_token
*tok
;
782 tok
= isl_stream_next_token(s
);
786 is_comp
= is_comparator(tok
);
787 isl_stream_push_token(s
, tok
);
792 /* Accept an affine expression that may involve ternary operators.
793 * We first read an affine expression.
794 * If it is not followed by a comparison operator, we simply return it.
795 * Otherwise, we assume the affine expression is part of the first
796 * argument of a ternary operator and try to parse that.
798 static __isl_give isl_pw_aff
*accept_extended_affine(__isl_keep isl_stream
*s
,
799 __isl_take isl_space
*dim
, struct vars
*v
, int rational
)
804 int line
= -1, col
= -1;
806 set_current_line_col(s
, &line
, &col
);
808 pwaff
= accept_affine(s
, dim
, v
);
810 pwaff
= isl_pw_aff_set_rational(pwaff
);
813 if (!next_is_comparator(s
))
816 space
= isl_pw_aff_get_domain_space(pwaff
);
817 cond
= isl_map_universe(isl_space_unwrap(space
));
819 if (push_aff(s
, line
, col
, pwaff
) < 0)
820 cond
= isl_map_free(cond
);
824 cond
= read_formula(s
, v
, cond
, rational
);
826 return accept_ternary(s
, cond
, v
, rational
);
829 static __isl_give isl_map
*read_var_def(__isl_keep isl_stream
*s
,
830 __isl_take isl_map
*map
, enum isl_dim_type type
, struct vars
*v
,
837 if (type
== isl_dim_param
)
838 pos
= isl_map_dim(map
, isl_dim_param
);
840 pos
= isl_map_dim(map
, isl_dim_in
);
841 if (type
== isl_dim_out
) {
842 isl_size n_out
= isl_map_dim(map
, isl_dim_out
);
843 if (pos
< 0 || n_out
< 0)
844 return isl_map_free(map
);
850 return isl_map_free(map
);
853 def
= accept_extended_affine(s
, isl_space_wrap(isl_map_get_space(map
)),
855 def_map
= isl_map_from_pw_aff(def
);
856 def_map
= isl_map_equate(def_map
, type
, pos
, isl_dim_out
, 0);
857 def_map
= isl_set_unwrap(isl_map_domain(def_map
));
859 map
= isl_map_intersect(map
, def_map
);
864 static __isl_give isl_pw_aff_list
*accept_affine_list(__isl_keep isl_stream
*s
,
865 __isl_take isl_space
*dim
, struct vars
*v
)
868 isl_pw_aff_list
*list
;
869 struct isl_token
*tok
= NULL
;
871 pwaff
= accept_affine(s
, isl_space_copy(dim
), v
);
872 list
= isl_pw_aff_list_from_pw_aff(pwaff
);
877 tok
= isl_stream_next_token(s
);
879 isl_stream_error(s
, NULL
, "unexpected EOF");
882 if (tok
->type
!= ',') {
883 isl_stream_push_token(s
, tok
);
888 pwaff
= accept_affine(s
, isl_space_copy(dim
), v
);
889 list
= isl_pw_aff_list_concat(list
,
890 isl_pw_aff_list_from_pw_aff(pwaff
));
899 isl_pw_aff_list_free(list
);
903 static __isl_give isl_map
*read_defined_var_list(__isl_keep isl_stream
*s
,
904 struct vars
*v
, __isl_take isl_map
*map
, int rational
)
906 struct isl_token
*tok
;
908 while ((tok
= isl_stream_next_token(s
)) != NULL
) {
912 if (tok
->type
!= ISL_TOKEN_IDENT
)
915 p
= vars_pos(v
, tok
->u
.s
, -1);
919 isl_stream_error(s
, tok
, "expecting unique identifier");
923 map
= isl_map_add_dims(map
, isl_dim_out
, 1);
926 tok
= isl_stream_next_token(s
);
927 if (tok
&& tok
->type
== '=') {
929 map
= read_var_def(s
, map
, isl_dim_out
, v
, rational
);
930 tok
= isl_stream_next_token(s
);
933 if (!tok
|| tok
->type
!= ',')
939 isl_stream_push_token(s
, tok
);
948 static int next_is_tuple(__isl_keep isl_stream
*s
)
950 struct isl_token
*tok
;
953 tok
= isl_stream_next_token(s
);
956 if (tok
->type
== '[') {
957 isl_stream_push_token(s
, tok
);
960 if (tok
->type
!= ISL_TOKEN_IDENT
&& !tok
->is_keyword
) {
961 isl_stream_push_token(s
, tok
);
965 is_tuple
= isl_stream_next_token_is(s
, '[');
967 isl_stream_push_token(s
, tok
);
972 /* Is the next token one that necessarily forms the start of a condition?
974 static int next_is_condition_start(__isl_keep isl_stream
*s
)
976 return isl_stream_next_token_is(s
, ISL_TOKEN_EXISTS
) ||
977 isl_stream_next_token_is(s
, ISL_TOKEN_NOT
) ||
978 isl_stream_next_token_is(s
, ISL_TOKEN_TRUE
) ||
979 isl_stream_next_token_is(s
, ISL_TOKEN_FALSE
) ||
980 isl_stream_next_token_is(s
, ISL_TOKEN_MAP
);
983 /* Is "pa" an expression in term of earlier dimensions?
984 * The alternative is that the dimension is defined to be equal to itself,
985 * meaning that it has a universe domain and an expression that depends
986 * on itself. "i" is the position of the expression in a sequence
987 * of "n" expressions. The final dimensions of "pa" correspond to
988 * these "n" expressions.
990 static isl_bool
pw_aff_is_expr(__isl_keep isl_pw_aff
*pa
, int i
, int n
)
995 return isl_bool_error
;
997 return isl_bool_true
;
998 if (!isl_set_plain_is_universe(pa
->p
[0].set
))
999 return isl_bool_true
;
1002 if (isl_int_is_zero(aff
->v
->el
[aff
->v
->size
- n
+ i
]))
1003 return isl_bool_true
;
1004 return isl_bool_false
;
1007 /* Does the tuple contain any dimensions that are defined
1008 * in terms of earlier dimensions?
1010 static isl_bool
tuple_has_expr(__isl_keep isl_multi_pw_aff
*tuple
)
1014 isl_bool has_expr
= isl_bool_false
;
1017 n
= isl_multi_pw_aff_dim(tuple
, isl_dim_out
);
1019 return isl_bool_error
;
1020 for (i
= 0; i
< n
; ++i
) {
1021 pa
= isl_multi_pw_aff_get_pw_aff(tuple
, i
);
1022 has_expr
= pw_aff_is_expr(pa
, i
, n
);
1023 isl_pw_aff_free(pa
);
1024 if (has_expr
< 0 || has_expr
)
1031 /* Set the name of dimension "pos" in "space" to "name".
1032 * During printing, we add primes if the same name appears more than once
1033 * to distinguish the occurrences. Here, we remove those primes from "name"
1034 * before setting the name of the dimension.
1036 static __isl_give isl_space
*space_set_dim_name(__isl_take isl_space
*space
,
1037 int pos
, char *name
)
1044 prime
= strchr(name
, '\'');
1047 space
= isl_space_set_dim_name(space
, isl_dim_out
, pos
, name
);
1054 /* Construct an isl_pw_aff defined on a "space" (with v->n variables)
1055 * that is equal to the last of those variables.
1057 static __isl_give isl_pw_aff
*identity_tuple_el_on_space(
1058 __isl_take isl_space
*space
, struct vars
*v
)
1062 aff
= isl_aff_zero_on_domain(isl_local_space_from_space(space
));
1063 aff
= isl_aff_add_coefficient_si(aff
, isl_dim_in
, v
->n
- 1, 1);
1064 return isl_pw_aff_from_aff(aff
);
1067 /* Construct a piecewise affine expression corresponding
1068 * to the last variable in "v" that ranges between "pa" and "pa2".
1070 * In particular, if D is the domain space of "pa" (and "pa2"),
1071 * then construct the expression
1075 * construct the conditions
1077 * D[..., i] : i >= pa
1078 * D[..., i] : i <= pa2
1082 * D[..., i] -> i : pa <= i <= pa2
1084 static __isl_give isl_pw_aff
*construct_range(__isl_take isl_pw_aff
*pa
,
1085 __isl_take isl_pw_aff
*pa2
, struct vars
*v
)
1087 isl_set
*range1
, *range2
;
1089 isl_pw_aff
*range_pa
;
1091 space
= isl_pw_aff_get_domain_space(pa
);
1092 range_pa
= identity_tuple_el_on_space(space
, v
);
1093 range1
= isl_pw_aff_ge_set(isl_pw_aff_copy(range_pa
), pa
);
1094 range2
= isl_pw_aff_le_set(isl_pw_aff_copy(range_pa
), pa2
);
1095 range_pa
= isl_pw_aff_intersect_domain(range_pa
, range1
);
1096 range_pa
= isl_pw_aff_intersect_domain(range_pa
, range2
);
1101 static int resolve_paren_expr(__isl_keep isl_stream
*s
,
1102 struct vars
*v
, __isl_take isl_map
*map
, int rational
);
1104 /* Given that the (piecewise) affine expression "pa"
1105 * has just been parsed, followed by a colon,
1106 * continue parsing as part of a piecewise affine expression.
1108 * In particular, check if the colon is followed by a condition.
1109 * If so, parse the conditions(a) on "pa" and include them in the domain.
1110 * Otherwise, if the colon is followed by another (piecewise) affine expression
1111 * then consider the two expressions as endpoints of a range of values and
1112 * return a piecewise affine expression that takes values in that range.
1113 * Note that an affine expression followed by a comparison operator
1114 * is considered to be part of a condition.
1116 static __isl_give isl_pw_aff
*update_piecewise_affine_colon(
1117 __isl_take isl_pw_aff
*pa
, __isl_keep isl_stream
*s
,
1118 struct vars
*v
, int rational
)
1120 isl_space
*dom_space
;
1123 dom_space
= isl_pw_aff_get_domain_space(pa
);
1124 map
= isl_map_universe(isl_space_from_domain(dom_space
));
1126 if (isl_stream_next_token_is(s
, '('))
1127 if (resolve_paren_expr(s
, v
, isl_map_copy(map
), rational
))
1129 if (!next_is_condition_start(s
)) {
1130 int line
= -1, col
= -1;
1134 set_current_line_col(s
, &line
, &col
);
1135 space
= isl_space_wrap(isl_map_get_space(map
));
1136 pa2
= accept_affine(s
, space
, v
);
1138 pa2
= isl_pw_aff_set_rational(pa2
);
1139 if (!next_is_comparator(s
)) {
1141 pa2
= isl_pw_aff_domain_factor_domain(pa2
);
1142 return construct_range(pa
, pa2
, v
);
1144 if (push_aff(s
, line
, col
, pa2
) < 0)
1148 map
= read_formula(s
, v
, map
, rational
);
1149 pa
= isl_pw_aff_intersect_domain(pa
, isl_map_domain(map
));
1154 isl_pw_aff_free(pa
);
1158 /* Accept a piecewise affine expression.
1160 * At the outer level, the piecewise affine expression may be of the form
1162 * aff1 : condition1; aff2 : conditions2; ...
1168 * each of the affine expressions may in turn include ternary operators.
1170 * There may be parentheses around some subexpression of "aff1"
1171 * around "aff1" itself, around "aff1 : condition1" and/or
1172 * around the entire piecewise affine expression.
1173 * We therefore remove the opening parenthesis (if any) from the stream
1174 * in case the closing parenthesis follows the colon, but if the closing
1175 * parenthesis is the first thing in the stream after the parsed affine
1176 * expression, we push the parsed expression onto the stream and parse
1177 * again in case the parentheses enclose some subexpression of "aff1".
1179 static __isl_give isl_pw_aff
*accept_piecewise_affine(__isl_keep isl_stream
*s
,
1180 __isl_take isl_space
*space
, struct vars
*v
, int rational
)
1183 isl_space
*res_space
;
1185 res_space
= isl_space_from_domain(isl_space_copy(space
));
1186 res_space
= isl_space_add_dims(res_space
, isl_dim_out
, 1);
1187 res
= isl_pw_aff_empty(res_space
);
1191 int line
= -1, col
= -1;
1193 set_current_line_col(s
, &line
, &col
);
1194 seen_paren
= isl_stream_eat_if_available(s
, '(');
1196 pa
= accept_piecewise_affine(s
, isl_space_copy(space
),
1199 pa
= accept_extended_affine(s
, isl_space_copy(space
),
1201 if (seen_paren
&& isl_stream_eat_if_available(s
, ')')) {
1203 if (push_aff(s
, line
, col
, pa
) < 0)
1205 pa
= accept_extended_affine(s
, isl_space_copy(space
),
1208 if (isl_stream_eat_if_available(s
, ':'))
1209 pa
= update_piecewise_affine_colon(pa
, s
, v
, rational
);
1211 res
= isl_pw_aff_union_add(res
, pa
);
1213 if (seen_paren
&& isl_stream_eat(s
, ')'))
1215 } while (isl_stream_eat_if_available(s
, ';'));
1217 isl_space_free(space
);
1221 isl_space_free(space
);
1222 return isl_pw_aff_free(res
);
1225 /* Read an affine expression from "s" for use in read_tuple.
1227 * accept_extended_affine requires a wrapped space as input.
1228 * read_tuple on the other hand expects each isl_pw_aff
1229 * to have an anonymous space. We therefore adjust the space
1230 * of the isl_pw_aff before returning it.
1232 static __isl_give isl_pw_aff
*read_tuple_var_def(__isl_keep isl_stream
*s
,
1233 struct vars
*v
, int rational
)
1238 space
= isl_space_wrap(isl_space_alloc(s
->ctx
, 0, v
->n
, 0));
1240 def
= accept_piecewise_affine(s
, space
, v
, rational
);
1241 def
= isl_pw_aff_domain_factor_domain(def
);
1246 /* Read a list of tuple elements by calling "read_el" on each of them and
1247 * return a space with the same number of set dimensions derived from
1248 * the parameter space "space" and possibly updated by "read_el".
1249 * The elements in the list are separated by either "," or "][".
1250 * If "comma" is set then only "," is allowed.
1252 static __isl_give isl_space
*read_tuple_list(__isl_keep isl_stream
*s
,
1253 struct vars
*v
, __isl_take isl_space
*space
, int rational
, int comma
,
1254 __isl_give isl_space
*(*read_el
)(__isl_keep isl_stream
*s
,
1255 struct vars
*v
, __isl_take isl_space
*space
, int rational
,
1262 space
= isl_space_set_from_params(space
);
1264 if (isl_stream_next_token_is(s
, ']'))
1268 struct isl_token
*tok
;
1270 space
= isl_space_add_dims(space
, isl_dim_set
, 1);
1272 space
= read_el(s
, v
, space
, rational
, user
);
1276 tok
= isl_stream_next_token(s
);
1277 if (!comma
&& tok
&& tok
->type
== ']' &&
1278 isl_stream_next_token_is(s
, '[')) {
1279 isl_token_free(tok
);
1280 tok
= isl_stream_next_token(s
);
1281 } else if (!tok
|| tok
->type
!= ',') {
1283 isl_stream_push_token(s
, tok
);
1287 isl_token_free(tok
);
1293 /* Read a tuple space from "s" derived from the parameter space "space".
1294 * Call "read_el" on each element in the tuples.
1296 static __isl_give isl_space
*read_tuple_space(__isl_keep isl_stream
*s
,
1297 struct vars
*v
, __isl_take isl_space
*space
, int rational
, int comma
,
1298 __isl_give isl_space
*(*read_el
)(__isl_keep isl_stream
*s
,
1299 struct vars
*v
, __isl_take isl_space
*space
, int rational
,
1303 struct isl_token
*tok
;
1305 isl_space
*res
= NULL
;
1307 tok
= isl_stream_next_token(s
);
1310 if (tok
->type
== ISL_TOKEN_IDENT
|| tok
->is_keyword
) {
1311 name
= strdup(tok
->u
.s
);
1312 isl_token_free(tok
);
1316 isl_stream_push_token(s
, tok
);
1317 if (isl_stream_eat(s
, '['))
1319 if (next_is_tuple(s
)) {
1321 res
= read_tuple_space(s
, v
, isl_space_copy(space
),
1322 rational
, comma
, read_el
, user
);
1323 if (isl_stream_eat(s
, ISL_TOKEN_TO
))
1325 out
= read_tuple_space(s
, v
, isl_space_copy(space
),
1326 rational
, comma
, read_el
, user
);
1327 res
= isl_space_product(res
, out
);
1329 res
= read_tuple_list(s
, v
, isl_space_copy(space
),
1330 rational
, comma
, read_el
, user
);
1331 if (isl_stream_eat(s
, ']'))
1335 res
= isl_space_set_tuple_name(res
, isl_dim_set
, name
);
1339 isl_space_free(space
);
1343 isl_space_free(res
);
1344 isl_space_free(space
);
1348 /* Construct an isl_pw_aff defined on a space with v->n variables
1349 * that is equal to the last of those variables.
1351 static __isl_give isl_pw_aff
*identity_tuple_el(struct vars
*v
)
1355 space
= isl_space_set_alloc(v
->ctx
, 0, v
->n
);
1356 return identity_tuple_el_on_space(space
, v
);
1359 /* This function is called for each element in a tuple inside read_tuple.
1360 * Add a new variable to "v" and construct a corresponding isl_pw_aff defined
1361 * over a space containing all variables in "v" defined so far.
1362 * The isl_pw_aff expresses the new variable in terms of earlier variables
1363 * if a definition is provided. Otherwise, it is represented as being
1365 * Add the isl_pw_aff to *list.
1366 * If the new variable was named, then adjust "space" accordingly and
1367 * return the updated space.
1369 static __isl_give isl_space
*read_tuple_pw_aff_el(__isl_keep isl_stream
*s
,
1370 struct vars
*v
, __isl_take isl_space
*space
, int rational
, void *user
)
1372 isl_pw_aff_list
**list
= (isl_pw_aff_list
**) user
;
1374 struct isl_token
*tok
;
1377 tok
= next_token(s
);
1379 isl_stream_error(s
, NULL
, "unexpected EOF");
1380 return isl_space_free(space
);
1383 if (tok
->type
== ISL_TOKEN_IDENT
) {
1385 int p
= vars_pos(v
, tok
->u
.s
, -1);
1391 if (tok
->type
== '*') {
1392 if (vars_add_anon(v
) < 0)
1394 isl_token_free(tok
);
1395 pa
= identity_tuple_el(v
);
1396 } else if (new_name
) {
1397 isl_size pos
= isl_space_dim(space
, isl_dim_out
);
1401 space
= space_set_dim_name(space
, pos
, v
->v
->name
);
1402 isl_token_free(tok
);
1403 if (isl_stream_eat_if_available(s
, '='))
1404 pa
= read_tuple_var_def(s
, v
, rational
);
1406 pa
= identity_tuple_el(v
);
1408 isl_stream_push_token(s
, tok
);
1410 if (vars_add_anon(v
) < 0)
1412 pa
= read_tuple_var_def(s
, v
, rational
);
1415 *list
= isl_pw_aff_list_add(*list
, pa
);
1417 return isl_space_free(space
);
1421 isl_token_free(tok
);
1422 return isl_space_free(space
);
1425 /* Read a tuple and represent it as an isl_multi_pw_aff.
1426 * The range space of the isl_multi_pw_aff is the space of the tuple.
1427 * The domain space is an anonymous space
1428 * with a dimension for each variable in the set of variables in "v",
1429 * including the variables in the range.
1430 * If a given dimension is not defined in terms of earlier dimensions in
1431 * the input, then the corresponding isl_pw_aff is set equal to one time
1432 * the variable corresponding to the dimension being defined.
1434 * The elements in the tuple are collected in a list by read_tuple_pw_aff_el.
1435 * Each element in this list is defined over a space representing
1436 * the variables defined so far. We need to adjust the earlier
1437 * elements to have as many variables in the domain as the final
1438 * element in the list.
1440 static __isl_give isl_multi_pw_aff
*read_tuple(__isl_keep isl_stream
*s
,
1441 struct vars
*v
, int rational
, int comma
)
1446 isl_pw_aff_list
*list
;
1448 space
= isl_space_params_alloc(v
->ctx
, 0);
1449 list
= isl_pw_aff_list_alloc(s
->ctx
, 0);
1450 space
= read_tuple_space(s
, v
, space
, rational
, comma
,
1451 &read_tuple_pw_aff_el
, &list
);
1452 n
= isl_space_dim(space
, isl_dim_set
);
1454 space
= isl_space_free(space
);
1455 for (i
= 0; i
+ 1 < n
; ++i
) {
1458 pa
= isl_pw_aff_list_get_pw_aff(list
, i
);
1459 pa
= isl_pw_aff_add_dims(pa
, isl_dim_in
, n
- (i
+ 1));
1460 list
= isl_pw_aff_list_set_pw_aff(list
, i
, pa
);
1463 space
= isl_space_from_range(space
);
1464 space
= isl_space_add_dims(space
, isl_dim_in
, v
->n
);
1465 return isl_multi_pw_aff_from_pw_aff_list(space
, list
);
1468 /* Add the tuple represented by the isl_multi_pw_aff "tuple" to "map".
1469 * We first create the appropriate space in "map" based on the range
1470 * space of this isl_multi_pw_aff. Then, we add equalities based
1471 * on the affine expressions. These live in an anonymous space,
1472 * however, so we first need to reset the space to that of "map".
1474 static __isl_give isl_map
*map_from_tuple(__isl_take isl_multi_pw_aff
*tuple
,
1475 __isl_take isl_map
*map
, enum isl_dim_type type
, struct vars
*v
,
1481 isl_space
*space
= NULL
;
1483 n
= isl_multi_pw_aff_dim(tuple
, isl_dim_out
);
1486 ctx
= isl_multi_pw_aff_get_ctx(tuple
);
1487 space
= isl_space_range(isl_multi_pw_aff_get_space(tuple
));
1491 if (type
== isl_dim_param
) {
1492 if (isl_space_has_tuple_name(space
, isl_dim_set
) ||
1493 isl_space_is_wrapping(space
)) {
1494 isl_die(ctx
, isl_error_invalid
,
1495 "parameter tuples cannot be named or nested",
1498 map
= isl_map_add_dims(map
, type
, n
);
1499 for (i
= 0; i
< n
; ++i
) {
1501 if (!isl_space_has_dim_name(space
, isl_dim_set
, i
))
1502 isl_die(ctx
, isl_error_invalid
,
1503 "parameters must be named",
1505 id
= isl_space_get_dim_id(space
, isl_dim_set
, i
);
1506 map
= isl_map_set_dim_id(map
, isl_dim_param
, i
, id
);
1508 } else if (type
== isl_dim_in
) {
1511 set
= isl_set_universe(isl_space_copy(space
));
1513 set
= isl_set_set_rational(set
);
1514 set
= isl_set_intersect_params(set
, isl_map_params(map
));
1515 map
= isl_map_from_domain(set
);
1519 set
= isl_set_universe(isl_space_copy(space
));
1521 set
= isl_set_set_rational(set
);
1522 map
= isl_map_from_domain_and_range(isl_map_domain(map
), set
);
1525 for (i
= 0; i
< n
; ++i
) {
1532 pa
= isl_multi_pw_aff_get_pw_aff(tuple
, i
);
1533 space
= isl_pw_aff_get_domain_space(pa
);
1534 aff
= isl_aff_zero_on_domain(isl_local_space_from_space(space
));
1535 aff
= isl_aff_add_coefficient_si(aff
,
1536 isl_dim_in
, v
->n
- n
+ i
, -1);
1537 pa
= isl_pw_aff_add(pa
, isl_pw_aff_from_aff(aff
));
1539 pa
= isl_pw_aff_set_rational(pa
);
1540 set
= isl_pw_aff_zero_set(pa
);
1541 map_i
= isl_map_from_range(set
);
1542 map_i
= isl_map_reset_space(map_i
, isl_map_get_space(map
));
1543 map
= isl_map_intersect(map
, map_i
);
1546 isl_space_free(space
);
1547 isl_multi_pw_aff_free(tuple
);
1550 isl_space_free(space
);
1551 isl_multi_pw_aff_free(tuple
);
1556 /* Read a tuple from "s" and add it to "map".
1557 * The tuple is initially represented as an isl_multi_pw_aff and
1558 * then added to "map".
1560 static __isl_give isl_map
*read_map_tuple(__isl_keep isl_stream
*s
,
1561 __isl_take isl_map
*map
, enum isl_dim_type type
, struct vars
*v
,
1562 int rational
, int comma
)
1564 isl_multi_pw_aff
*tuple
;
1566 tuple
= read_tuple(s
, v
, rational
, comma
);
1568 return isl_map_free(map
);
1570 return map_from_tuple(tuple
, map
, type
, v
, rational
);
1573 /* Given two equal-length lists of piecewise affine expression with the space
1574 * of "set" as domain, construct a set in the same space that expresses
1575 * that "left" and "right" satisfy the comparison "type".
1577 * A space is constructed of the same dimension as the number of elements
1578 * in the two lists. The comparison is then expressed in a map from
1579 * this space to itself and wrapped into a set. Finally the two lists
1580 * of piecewise affine expressions are plugged into this set.
1582 * Let S be the space of "set" and T the constructed space.
1583 * The lists are first changed into two isl_multi_pw_affs in S -> T and
1584 * then combined into an isl_multi_pw_aff in S -> [T -> T],
1585 * while the comparison is first expressed in T -> T, then [T -> T]
1588 static __isl_give isl_set
*list_cmp(__isl_keep isl_set
*set
, int type
,
1589 __isl_take isl_pw_aff_list
*left
, __isl_take isl_pw_aff_list
*right
)
1593 isl_multi_pw_aff
*mpa1
, *mpa2
;
1595 n
= isl_pw_aff_list_n_pw_aff(left
);
1596 if (!set
|| n
< 0 || !right
)
1599 space
= isl_set_get_space(set
);
1600 space
= isl_space_from_domain(space
);
1601 space
= isl_space_add_dims(space
, isl_dim_out
, n
);
1602 mpa1
= isl_multi_pw_aff_from_pw_aff_list(isl_space_copy(space
), left
);
1603 mpa2
= isl_multi_pw_aff_from_pw_aff_list(isl_space_copy(space
), right
);
1604 mpa1
= isl_multi_pw_aff_range_product(mpa1
, mpa2
);
1606 space
= isl_space_range(space
);
1608 case ISL_TOKEN_LEX_LT
:
1609 set
= isl_map_wrap(isl_map_lex_lt(space
));
1611 case ISL_TOKEN_LEX_GT
:
1612 set
= isl_map_wrap(isl_map_lex_gt(space
));
1614 case ISL_TOKEN_LEX_LE
:
1615 set
= isl_map_wrap(isl_map_lex_le(space
));
1617 case ISL_TOKEN_LEX_GE
:
1618 set
= isl_map_wrap(isl_map_lex_ge(space
));
1621 isl_multi_pw_aff_free(mpa1
);
1622 isl_space_free(space
);
1623 isl_die(isl_set_get_ctx(set
), isl_error_internal
,
1624 "unhandled list comparison type", return NULL
);
1626 set
= isl_set_preimage_multi_pw_aff(set
, mpa1
);
1629 isl_pw_aff_list_free(left
);
1630 isl_pw_aff_list_free(right
);
1634 /* Construct constraints of the form
1638 * where a is an element in "left", op is an operator of type "type" and
1639 * b is an element in "right", add the constraints to "set" and return
1641 * "rational" is set if the constraints should be treated as
1642 * a rational constraints.
1644 * If "type" is the type of a comparison operator between lists
1645 * of affine expressions, then a single (compound) constraint
1646 * is constructed by list_cmp instead.
1648 static __isl_give isl_set
*construct_constraints(
1649 __isl_take isl_set
*set
, int type
,
1650 __isl_keep isl_pw_aff_list
*left
, __isl_keep isl_pw_aff_list
*right
,
1655 left
= isl_pw_aff_list_copy(left
);
1656 right
= isl_pw_aff_list_copy(right
);
1658 left
= isl_pw_aff_list_set_rational(left
);
1659 right
= isl_pw_aff_list_set_rational(right
);
1661 if (is_list_comparator_type(type
))
1662 cond
= list_cmp(set
, type
, left
, right
);
1663 else if (type
== ISL_TOKEN_LE
)
1664 cond
= isl_pw_aff_list_le_set(left
, right
);
1665 else if (type
== ISL_TOKEN_GE
)
1666 cond
= isl_pw_aff_list_ge_set(left
, right
);
1667 else if (type
== ISL_TOKEN_LT
)
1668 cond
= isl_pw_aff_list_lt_set(left
, right
);
1669 else if (type
== ISL_TOKEN_GT
)
1670 cond
= isl_pw_aff_list_gt_set(left
, right
);
1671 else if (type
== ISL_TOKEN_NE
)
1672 cond
= isl_pw_aff_list_ne_set(left
, right
);
1674 cond
= isl_pw_aff_list_eq_set(left
, right
);
1676 return isl_set_intersect(set
, cond
);
1679 /* Read a constraint from "s", add it to "map" and return the result.
1680 * "v" contains a description of the identifiers parsed so far.
1681 * "rational" is set if the constraint should be treated as
1682 * a rational constraint.
1683 * The constraint read from "s" may be applied to multiple pairs
1684 * of affine expressions and may be chained.
1685 * In particular, a list of affine expressions is read, followed
1686 * by a comparison operator and another list of affine expressions.
1687 * The comparison operator is then applied to each pair of elements
1688 * in the two lists and the results are added to "map".
1689 * However, if the operator expects two lists of affine expressions,
1690 * then it is applied directly to those lists and the two lists
1691 * are required to have the same length.
1692 * If the next token is another comparison operator, then another
1693 * list of affine expressions is read and the process repeats.
1695 * The processing is performed on a wrapped copy of "map" because
1696 * an affine expression cannot have a binary relation as domain.
1698 static __isl_give isl_map
*add_constraint(__isl_keep isl_stream
*s
,
1699 struct vars
*v
, __isl_take isl_map
*map
, int rational
)
1701 struct isl_token
*tok
;
1703 isl_pw_aff_list
*list1
= NULL
, *list2
= NULL
;
1707 set
= isl_map_wrap(map
);
1708 list1
= accept_affine_list(s
, isl_set_get_space(set
), v
);
1711 tok
= isl_stream_next_token(s
);
1712 if (!is_comparator(tok
)) {
1713 isl_stream_error(s
, tok
, "missing operator");
1715 isl_stream_push_token(s
, tok
);
1719 isl_token_free(tok
);
1721 list2
= accept_affine_list(s
, isl_set_get_space(set
), v
);
1722 n1
= isl_pw_aff_list_n_pw_aff(list1
);
1723 n2
= isl_pw_aff_list_n_pw_aff(list2
);
1724 if (n1
< 0 || n2
< 0)
1726 if (is_list_comparator_type(type
) && n1
!= n2
) {
1727 isl_stream_error(s
, NULL
,
1728 "list arguments not of same size");
1732 set
= construct_constraints(set
, type
, list1
, list2
, rational
);
1733 isl_pw_aff_list_free(list1
);
1736 if (!next_is_comparator(s
))
1738 tok
= isl_stream_next_token(s
);
1740 isl_token_free(tok
);
1742 isl_pw_aff_list_free(list1
);
1744 return isl_set_unwrap(set
);
1746 isl_pw_aff_list_free(list1
);
1747 isl_pw_aff_list_free(list2
);
1752 static __isl_give isl_map
*read_exists(__isl_keep isl_stream
*s
,
1753 struct vars
*v
, __isl_take isl_map
*map
, int rational
)
1756 int seen_paren
= isl_stream_eat_if_available(s
, '(');
1758 map
= isl_map_from_domain(isl_map_wrap(map
));
1759 map
= read_defined_var_list(s
, v
, map
, rational
);
1761 if (isl_stream_eat(s
, ':'))
1764 map
= read_formula(s
, v
, map
, rational
);
1765 map
= isl_set_unwrap(isl_map_domain(map
));
1767 vars_drop(v
, v
->n
- n
);
1768 if (seen_paren
&& isl_stream_eat(s
, ')'))
1777 /* Parse an expression between parentheses and push the result
1778 * back on the stream.
1780 * The parsed expression may be either an affine expression
1781 * or a condition. The first type is pushed onto the stream
1782 * as an isl_pw_aff, while the second is pushed as an isl_map.
1784 * If the initial token indicates the start of a condition,
1785 * we parse it as such.
1786 * Otherwise, we first parse an affine expression and push
1787 * that onto the stream. If the affine expression covers the
1788 * entire expression between parentheses, we return.
1789 * Otherwise, we assume that the affine expression is the
1790 * start of a condition and continue parsing.
1792 static int resolve_paren_expr(__isl_keep isl_stream
*s
,
1793 struct vars
*v
, __isl_take isl_map
*map
, int rational
)
1795 struct isl_token
*tok
, *tok2
;
1800 tok
= isl_stream_next_token(s
);
1801 if (!tok
|| tok
->type
!= '(')
1804 if (isl_stream_next_token_is(s
, '('))
1805 if (resolve_paren_expr(s
, v
, isl_map_copy(map
), rational
))
1808 if (next_is_condition_start(s
)) {
1809 map
= read_formula(s
, v
, map
, rational
);
1810 if (isl_stream_eat(s
, ')'))
1812 tok
->type
= ISL_TOKEN_MAP
;
1814 isl_stream_push_token(s
, tok
);
1818 tok2
= isl_stream_next_token(s
);
1823 isl_stream_push_token(s
, tok2
);
1825 pwaff
= accept_affine(s
, isl_space_wrap(isl_map_get_space(map
)), v
);
1829 has_paren
= isl_stream_eat_if_available(s
, ')');
1831 if (push_aff(s
, line
, col
, pwaff
) < 0)
1835 isl_token_free(tok
);
1840 map
= read_formula(s
, v
, map
, rational
);
1841 if (isl_stream_eat(s
, ')'))
1844 tok
->type
= ISL_TOKEN_MAP
;
1846 isl_stream_push_token(s
, tok
);
1850 isl_token_free(tok
);
1855 static __isl_give isl_map
*read_conjunct(__isl_keep isl_stream
*s
,
1856 struct vars
*v
, __isl_take isl_map
*map
, int rational
)
1858 if (isl_stream_next_token_is(s
, '('))
1859 if (resolve_paren_expr(s
, v
, isl_map_copy(map
), rational
))
1862 if (isl_stream_next_token_is(s
, ISL_TOKEN_MAP
)) {
1863 struct isl_token
*tok
;
1864 tok
= isl_stream_next_token(s
);
1868 map
= isl_map_copy(tok
->u
.map
);
1869 isl_token_free(tok
);
1873 if (isl_stream_eat_if_available(s
, ISL_TOKEN_EXISTS
))
1874 return read_exists(s
, v
, map
, rational
);
1876 if (isl_stream_eat_if_available(s
, ISL_TOKEN_TRUE
))
1879 if (isl_stream_eat_if_available(s
, ISL_TOKEN_FALSE
)) {
1880 isl_space
*dim
= isl_map_get_space(map
);
1882 return isl_map_empty(dim
);
1885 return add_constraint(s
, v
, map
, rational
);
1891 static __isl_give isl_map
*read_conjuncts(__isl_keep isl_stream
*s
,
1892 struct vars
*v
, __isl_take isl_map
*map
, int rational
)
1897 negate
= isl_stream_eat_if_available(s
, ISL_TOKEN_NOT
);
1898 res
= read_conjunct(s
, v
, isl_map_copy(map
), rational
);
1900 res
= isl_map_subtract(isl_map_copy(map
), res
);
1902 while (res
&& isl_stream_eat_if_available(s
, ISL_TOKEN_AND
)) {
1905 negate
= isl_stream_eat_if_available(s
, ISL_TOKEN_NOT
);
1906 res_i
= read_conjunct(s
, v
, isl_map_copy(map
), rational
);
1908 res
= isl_map_subtract(res
, res_i
);
1910 res
= isl_map_intersect(res
, res_i
);
1917 static struct isl_map
*read_disjuncts(__isl_keep isl_stream
*s
,
1918 struct vars
*v
, __isl_take isl_map
*map
, int rational
)
1922 if (isl_stream_next_token_is(s
, '}'))
1925 res
= read_conjuncts(s
, v
, isl_map_copy(map
), rational
);
1926 while (isl_stream_eat_if_available(s
, ISL_TOKEN_OR
)) {
1929 res_i
= read_conjuncts(s
, v
, isl_map_copy(map
), rational
);
1930 res
= isl_map_union(res
, res_i
);
1937 /* Read a first order formula from "s", add the corresponding
1938 * constraints to "map" and return the result.
1940 * In particular, read a formula of the form
1948 * where a and b are disjunctions.
1950 * In the first case, map is replaced by
1952 * map \cap { [..] : a }
1954 * In the second case, it is replaced by
1956 * (map \setminus { [..] : a}) \cup (map \cap { [..] : b })
1958 static __isl_give isl_map
*read_formula(__isl_keep isl_stream
*s
,
1959 struct vars
*v
, __isl_take isl_map
*map
, int rational
)
1963 res
= read_disjuncts(s
, v
, isl_map_copy(map
), rational
);
1965 if (isl_stream_eat_if_available(s
, ISL_TOKEN_IMPLIES
)) {
1968 res
= isl_map_subtract(isl_map_copy(map
), res
);
1969 res2
= read_disjuncts(s
, v
, map
, rational
);
1970 res
= isl_map_union(res
, res2
);
1977 static isl_size
polylib_pos_to_isl_pos(__isl_keep isl_basic_map
*bmap
, int pos
)
1979 isl_size n_out
, n_in
, n_param
, n_div
;
1981 n_param
= isl_basic_map_dim(bmap
, isl_dim_param
);
1982 n_in
= isl_basic_map_dim(bmap
, isl_dim_in
);
1983 n_out
= isl_basic_map_dim(bmap
, isl_dim_out
);
1984 n_div
= isl_basic_map_dim(bmap
, isl_dim_div
);
1985 if (n_param
< 0 || n_in
< 0 || n_out
< 0 || n_div
< 0)
1986 return isl_size_error
;
1989 return 1 + n_param
+ n_in
+ pos
;
1993 return 1 + n_param
+ pos
;
1997 return 1 + n_param
+ n_in
+ n_out
+ pos
;
2006 static __isl_give isl_basic_map
*basic_map_read_polylib_constraint(
2007 __isl_keep isl_stream
*s
, __isl_take isl_basic_map
*bmap
)
2010 struct isl_token
*tok
;
2019 tok
= isl_stream_next_token(s
);
2020 if (!tok
|| tok
->type
!= ISL_TOKEN_VALUE
) {
2021 isl_stream_error(s
, tok
, "expecting coefficient");
2023 isl_stream_push_token(s
, tok
);
2026 if (!tok
->on_new_line
) {
2027 isl_stream_error(s
, tok
, "coefficient should appear on new line");
2028 isl_stream_push_token(s
, tok
);
2032 type
= isl_int_get_si(tok
->u
.v
);
2033 isl_token_free(tok
);
2035 isl_assert(s
->ctx
, type
== 0 || type
== 1, goto error
);
2037 k
= isl_basic_map_alloc_equality(bmap
);
2040 k
= isl_basic_map_alloc_inequality(bmap
);
2046 total
= isl_basic_map_dim(bmap
, isl_dim_all
);
2048 return isl_basic_map_free(bmap
);
2049 for (j
= 0; j
< 1 + total
; ++j
) {
2051 tok
= isl_stream_next_token(s
);
2052 if (!tok
|| tok
->type
!= ISL_TOKEN_VALUE
) {
2053 isl_stream_error(s
, tok
, "expecting coefficient");
2055 isl_stream_push_token(s
, tok
);
2058 if (tok
->on_new_line
) {
2059 isl_stream_error(s
, tok
,
2060 "coefficient should not appear on new line");
2061 isl_stream_push_token(s
, tok
);
2064 pos
= polylib_pos_to_isl_pos(bmap
, j
);
2066 isl_int_set(c
[pos
], tok
->u
.v
);
2067 isl_token_free(tok
);
2069 return isl_basic_map_free(bmap
);
2074 isl_basic_map_free(bmap
);
2078 static __isl_give isl_basic_map
*basic_map_read_polylib(
2079 __isl_keep isl_stream
*s
)
2082 struct isl_token
*tok
;
2083 struct isl_token
*tok2
;
2086 unsigned in
= 0, out
, local
= 0;
2087 struct isl_basic_map
*bmap
= NULL
;
2090 tok
= isl_stream_next_token(s
);
2092 isl_stream_error(s
, NULL
, "unexpected EOF");
2095 tok2
= isl_stream_next_token(s
);
2097 isl_token_free(tok
);
2098 isl_stream_error(s
, NULL
, "unexpected EOF");
2101 if (tok
->type
!= ISL_TOKEN_VALUE
|| tok2
->type
!= ISL_TOKEN_VALUE
) {
2102 isl_stream_push_token(s
, tok2
);
2103 isl_stream_push_token(s
, tok
);
2104 isl_stream_error(s
, NULL
,
2105 "expecting constraint matrix dimensions");
2108 n_row
= isl_int_get_si(tok
->u
.v
);
2109 n_col
= isl_int_get_si(tok2
->u
.v
);
2110 on_new_line
= tok2
->on_new_line
;
2111 isl_token_free(tok2
);
2112 isl_token_free(tok
);
2113 isl_assert(s
->ctx
, !on_new_line
, return NULL
);
2114 isl_assert(s
->ctx
, n_row
>= 0, return NULL
);
2115 isl_assert(s
->ctx
, n_col
>= 2 + nparam
, return NULL
);
2116 tok
= isl_stream_next_token_on_same_line(s
);
2118 if (tok
->type
!= ISL_TOKEN_VALUE
) {
2119 isl_stream_error(s
, tok
,
2120 "expecting number of output dimensions");
2121 isl_stream_push_token(s
, tok
);
2124 out
= isl_int_get_si(tok
->u
.v
);
2125 isl_token_free(tok
);
2127 tok
= isl_stream_next_token_on_same_line(s
);
2128 if (!tok
|| tok
->type
!= ISL_TOKEN_VALUE
) {
2129 isl_stream_error(s
, tok
,
2130 "expecting number of input dimensions");
2132 isl_stream_push_token(s
, tok
);
2135 in
= isl_int_get_si(tok
->u
.v
);
2136 isl_token_free(tok
);
2138 tok
= isl_stream_next_token_on_same_line(s
);
2139 if (!tok
|| tok
->type
!= ISL_TOKEN_VALUE
) {
2140 isl_stream_error(s
, tok
,
2141 "expecting number of existentials");
2143 isl_stream_push_token(s
, tok
);
2146 local
= isl_int_get_si(tok
->u
.v
);
2147 isl_token_free(tok
);
2149 tok
= isl_stream_next_token_on_same_line(s
);
2150 if (!tok
|| tok
->type
!= ISL_TOKEN_VALUE
) {
2151 isl_stream_error(s
, tok
,
2152 "expecting number of parameters");
2154 isl_stream_push_token(s
, tok
);
2157 nparam
= isl_int_get_si(tok
->u
.v
);
2158 isl_token_free(tok
);
2159 if (n_col
!= 1 + out
+ in
+ local
+ nparam
+ 1) {
2160 isl_stream_error(s
, NULL
,
2161 "dimensions don't match");
2165 out
= n_col
- 2 - nparam
;
2166 bmap
= isl_basic_map_alloc(s
->ctx
, nparam
, in
, out
, local
, n_row
, n_row
);
2170 for (i
= 0; i
< local
; ++i
) {
2171 int k
= isl_basic_map_alloc_div(bmap
);
2174 isl_seq_clr(bmap
->div
[k
], 1 + 1 + nparam
+ in
+ out
+ local
);
2177 for (i
= 0; i
< n_row
; ++i
)
2178 bmap
= basic_map_read_polylib_constraint(s
, bmap
);
2180 tok
= isl_stream_next_token_on_same_line(s
);
2182 isl_stream_error(s
, tok
, "unexpected extra token on line");
2183 isl_stream_push_token(s
, tok
);
2187 bmap
= isl_basic_map_simplify(bmap
);
2188 bmap
= isl_basic_map_finalize(bmap
);
2191 isl_basic_map_free(bmap
);
2195 static struct isl_map
*map_read_polylib(__isl_keep isl_stream
*s
)
2197 struct isl_token
*tok
;
2198 struct isl_token
*tok2
;
2200 struct isl_map
*map
;
2202 tok
= isl_stream_next_token(s
);
2204 isl_stream_error(s
, NULL
, "unexpected EOF");
2207 tok2
= isl_stream_next_token_on_same_line(s
);
2208 if (tok2
&& tok2
->type
== ISL_TOKEN_VALUE
) {
2209 isl_stream_push_token(s
, tok2
);
2210 isl_stream_push_token(s
, tok
);
2211 return isl_map_from_basic_map(basic_map_read_polylib(s
));
2214 isl_stream_error(s
, tok2
, "unexpected token");
2215 isl_stream_push_token(s
, tok2
);
2216 isl_stream_push_token(s
, tok
);
2219 n
= isl_int_get_si(tok
->u
.v
);
2220 isl_token_free(tok
);
2222 isl_assert(s
->ctx
, n
>= 1, return NULL
);
2224 map
= isl_map_from_basic_map(basic_map_read_polylib(s
));
2226 for (i
= 1; map
&& i
< n
; ++i
)
2227 map
= isl_map_union(map
,
2228 isl_map_from_basic_map(basic_map_read_polylib(s
)));
2233 static int optional_power(__isl_keep isl_stream
*s
)
2236 struct isl_token
*tok
;
2238 tok
= isl_stream_next_token(s
);
2241 if (tok
->type
!= '^') {
2242 isl_stream_push_token(s
, tok
);
2245 isl_token_free(tok
);
2246 tok
= isl_stream_next_token(s
);
2247 if (!tok
|| tok
->type
!= ISL_TOKEN_VALUE
) {
2248 isl_stream_error(s
, tok
, "expecting exponent");
2250 isl_stream_push_token(s
, tok
);
2253 pow
= isl_int_get_si(tok
->u
.v
);
2254 isl_token_free(tok
);
2258 static __isl_give isl_pw_qpolynomial
*read_term(__isl_keep isl_stream
*s
,
2259 __isl_keep isl_map
*map
, struct vars
*v
);
2261 static __isl_give isl_pw_qpolynomial
*read_factor(__isl_keep isl_stream
*s
,
2262 __isl_keep isl_map
*map
, struct vars
*v
)
2264 isl_pw_qpolynomial
*pwqp
;
2265 struct isl_token
*tok
;
2267 tok
= next_token(s
);
2269 isl_stream_error(s
, NULL
, "unexpected EOF");
2272 if (tok
->type
== '(') {
2275 isl_token_free(tok
);
2276 pwqp
= read_term(s
, map
, v
);
2279 if (isl_stream_eat(s
, ')'))
2281 pow
= optional_power(s
);
2282 pwqp
= isl_pw_qpolynomial_pow(pwqp
, pow
);
2283 } else if (tok
->type
== ISL_TOKEN_VALUE
) {
2284 struct isl_token
*tok2
;
2285 isl_qpolynomial
*qp
;
2287 tok2
= isl_stream_next_token(s
);
2288 if (tok2
&& tok2
->type
== '/') {
2289 isl_token_free(tok2
);
2290 tok2
= next_token(s
);
2291 if (!tok2
|| tok2
->type
!= ISL_TOKEN_VALUE
) {
2292 isl_stream_error(s
, tok2
, "expected denominator");
2293 isl_token_free(tok
);
2294 isl_token_free(tok2
);
2297 qp
= isl_qpolynomial_rat_cst_on_domain(isl_map_get_space(map
),
2298 tok
->u
.v
, tok2
->u
.v
);
2299 isl_token_free(tok2
);
2301 isl_stream_push_token(s
, tok2
);
2302 qp
= isl_qpolynomial_cst_on_domain(isl_map_get_space(map
),
2305 isl_token_free(tok
);
2306 pwqp
= isl_pw_qpolynomial_from_qpolynomial(qp
);
2307 } else if (tok
->type
== ISL_TOKEN_INFTY
) {
2308 isl_qpolynomial
*qp
;
2309 isl_token_free(tok
);
2310 qp
= isl_qpolynomial_infty_on_domain(isl_map_get_space(map
));
2311 pwqp
= isl_pw_qpolynomial_from_qpolynomial(qp
);
2312 } else if (tok
->type
== ISL_TOKEN_NAN
) {
2313 isl_qpolynomial
*qp
;
2314 isl_token_free(tok
);
2315 qp
= isl_qpolynomial_nan_on_domain(isl_map_get_space(map
));
2316 pwqp
= isl_pw_qpolynomial_from_qpolynomial(qp
);
2317 } else if (tok
->type
== ISL_TOKEN_IDENT
) {
2319 int pos
= vars_pos(v
, tok
->u
.s
, -1);
2321 isl_qpolynomial
*qp
;
2323 isl_token_free(tok
);
2327 vars_drop(v
, v
->n
- n
);
2328 isl_stream_error(s
, tok
, "unknown identifier");
2329 isl_token_free(tok
);
2332 isl_token_free(tok
);
2333 pow
= optional_power(s
);
2334 qp
= isl_qpolynomial_var_pow_on_domain(isl_map_get_space(map
), pos
, pow
);
2335 pwqp
= isl_pw_qpolynomial_from_qpolynomial(qp
);
2336 } else if (is_start_of_div(tok
)) {
2340 isl_stream_push_token(s
, tok
);
2341 pwaff
= accept_div(s
, isl_map_get_space(map
), v
);
2342 pow
= optional_power(s
);
2343 pwqp
= isl_pw_qpolynomial_from_pw_aff(pwaff
);
2344 pwqp
= isl_pw_qpolynomial_pow(pwqp
, pow
);
2345 } else if (tok
->type
== '-') {
2346 isl_token_free(tok
);
2347 pwqp
= read_factor(s
, map
, v
);
2348 pwqp
= isl_pw_qpolynomial_neg(pwqp
);
2350 isl_stream_error(s
, tok
, "unexpected isl_token");
2351 isl_stream_push_token(s
, tok
);
2355 if (isl_stream_eat_if_available(s
, '*') ||
2356 isl_stream_next_token_is(s
, ISL_TOKEN_IDENT
)) {
2357 isl_pw_qpolynomial
*pwqp2
;
2359 pwqp2
= read_factor(s
, map
, v
);
2360 pwqp
= isl_pw_qpolynomial_mul(pwqp
, pwqp2
);
2365 isl_pw_qpolynomial_free(pwqp
);
2369 static __isl_give isl_pw_qpolynomial
*read_term(__isl_keep isl_stream
*s
,
2370 __isl_keep isl_map
*map
, struct vars
*v
)
2372 struct isl_token
*tok
;
2373 isl_pw_qpolynomial
*pwqp
;
2375 pwqp
= read_factor(s
, map
, v
);
2378 tok
= next_token(s
);
2382 if (tok
->type
== '+') {
2383 isl_pw_qpolynomial
*pwqp2
;
2385 isl_token_free(tok
);
2386 pwqp2
= read_factor(s
, map
, v
);
2387 pwqp
= isl_pw_qpolynomial_add(pwqp
, pwqp2
);
2388 } else if (tok
->type
== '-') {
2389 isl_pw_qpolynomial
*pwqp2
;
2391 isl_token_free(tok
);
2392 pwqp2
= read_factor(s
, map
, v
);
2393 pwqp
= isl_pw_qpolynomial_sub(pwqp
, pwqp2
);
2394 } else if (tok
->type
== ISL_TOKEN_VALUE
&&
2395 isl_int_is_neg(tok
->u
.v
)) {
2396 isl_pw_qpolynomial
*pwqp2
;
2398 isl_stream_push_token(s
, tok
);
2399 pwqp2
= read_factor(s
, map
, v
);
2400 pwqp
= isl_pw_qpolynomial_add(pwqp
, pwqp2
);
2402 isl_stream_push_token(s
, tok
);
2410 static __isl_give isl_map
*read_optional_formula(__isl_keep isl_stream
*s
,
2411 __isl_take isl_map
*map
, struct vars
*v
, int rational
)
2413 struct isl_token
*tok
;
2415 tok
= isl_stream_next_token(s
);
2417 isl_stream_error(s
, NULL
, "unexpected EOF");
2420 if (tok
->type
== ':' ||
2421 (tok
->type
== ISL_TOKEN_OR
&& !strcmp(tok
->u
.s
, "|"))) {
2422 isl_token_free(tok
);
2423 map
= read_formula(s
, v
, map
, rational
);
2425 isl_stream_push_token(s
, tok
);
2433 static struct isl_obj
obj_read_poly(__isl_keep isl_stream
*s
,
2434 __isl_take isl_map
*map
, struct vars
*v
, int n
)
2436 struct isl_obj obj
= { isl_obj_pw_qpolynomial
, NULL
};
2437 isl_pw_qpolynomial
*pwqp
;
2438 struct isl_set
*set
;
2440 pwqp
= read_term(s
, map
, v
);
2441 map
= read_optional_formula(s
, map
, v
, 0);
2442 set
= isl_map_range(map
);
2444 pwqp
= isl_pw_qpolynomial_intersect_domain(pwqp
, set
);
2446 vars_drop(v
, v
->n
- n
);
2452 static struct isl_obj
obj_read_poly_or_fold(__isl_keep isl_stream
*s
,
2453 __isl_take isl_set
*set
, struct vars
*v
, int n
)
2455 struct isl_obj obj
= { isl_obj_pw_qpolynomial_fold
, NULL
};
2456 isl_pw_qpolynomial
*pwqp
;
2457 isl_pw_qpolynomial_fold
*pwf
= NULL
;
2459 if (!isl_stream_eat_if_available(s
, ISL_TOKEN_MAX
))
2460 return obj_read_poly(s
, set
, v
, n
);
2462 if (isl_stream_eat(s
, '('))
2465 pwqp
= read_term(s
, set
, v
);
2466 pwf
= isl_pw_qpolynomial_fold_from_pw_qpolynomial(isl_fold_max
, pwqp
);
2468 while (isl_stream_eat_if_available(s
, ',')) {
2469 isl_pw_qpolynomial_fold
*pwf_i
;
2470 pwqp
= read_term(s
, set
, v
);
2471 pwf_i
= isl_pw_qpolynomial_fold_from_pw_qpolynomial(isl_fold_max
,
2473 pwf
= isl_pw_qpolynomial_fold_fold(pwf
, pwf_i
);
2476 if (isl_stream_eat(s
, ')'))
2479 set
= read_optional_formula(s
, set
, v
, 0);
2480 pwf
= isl_pw_qpolynomial_fold_intersect_domain(pwf
, set
);
2482 vars_drop(v
, v
->n
- n
);
2488 isl_pw_qpolynomial_fold_free(pwf
);
2489 obj
.type
= isl_obj_none
;
2493 static int is_rational(__isl_keep isl_stream
*s
)
2495 struct isl_token
*tok
;
2497 tok
= isl_stream_next_token(s
);
2500 if (tok
->type
== ISL_TOKEN_RAT
&& isl_stream_next_token_is(s
, ':')) {
2501 isl_token_free(tok
);
2502 isl_stream_eat(s
, ':');
2506 isl_stream_push_token(s
, tok
);
2511 static struct isl_obj
obj_read_body(__isl_keep isl_stream
*s
,
2512 __isl_take isl_map
*map
, struct vars
*v
)
2514 struct isl_token
*tok
;
2515 struct isl_obj obj
= { isl_obj_set
, NULL
};
2519 rational
= is_rational(s
);
2521 map
= isl_map_set_rational(map
);
2523 if (isl_stream_next_token_is(s
, ':')) {
2524 obj
.type
= isl_obj_set
;
2525 obj
.v
= read_optional_formula(s
, map
, v
, rational
);
2529 if (!next_is_tuple(s
))
2530 return obj_read_poly_or_fold(s
, map
, v
, n
);
2532 map
= read_map_tuple(s
, map
, isl_dim_in
, v
, rational
, 0);
2535 tok
= isl_stream_next_token(s
);
2538 if (tok
->type
== ISL_TOKEN_TO
) {
2539 obj
.type
= isl_obj_map
;
2540 isl_token_free(tok
);
2541 if (!next_is_tuple(s
)) {
2542 isl_set
*set
= isl_map_domain(map
);
2543 return obj_read_poly_or_fold(s
, set
, v
, n
);
2545 map
= read_map_tuple(s
, map
, isl_dim_out
, v
, rational
, 0);
2549 map
= isl_map_domain(map
);
2550 isl_stream_push_token(s
, tok
);
2553 map
= read_optional_formula(s
, map
, v
, rational
);
2555 vars_drop(v
, v
->n
- n
);
2561 obj
.type
= isl_obj_none
;
2565 static struct isl_obj
to_union(isl_ctx
*ctx
, struct isl_obj obj
)
2567 if (obj
.type
== isl_obj_map
) {
2568 obj
.v
= isl_union_map_from_map(obj
.v
);
2569 obj
.type
= isl_obj_union_map
;
2570 } else if (obj
.type
== isl_obj_set
) {
2571 obj
.v
= isl_union_set_from_set(obj
.v
);
2572 obj
.type
= isl_obj_union_set
;
2573 } else if (obj
.type
== isl_obj_pw_qpolynomial
) {
2574 obj
.v
= isl_union_pw_qpolynomial_from_pw_qpolynomial(obj
.v
);
2575 obj
.type
= isl_obj_union_pw_qpolynomial
;
2576 } else if (obj
.type
== isl_obj_pw_qpolynomial_fold
) {
2577 obj
.v
= isl_union_pw_qpolynomial_fold_from_pw_qpolynomial_fold(obj
.v
);
2578 obj
.type
= isl_obj_union_pw_qpolynomial_fold
;
2580 isl_assert(ctx
, 0, goto error
);
2583 obj
.type
->free(obj
.v
);
2584 obj
.type
= isl_obj_none
;
2588 static struct isl_obj
obj_add(__isl_keep isl_stream
*s
,
2589 struct isl_obj obj1
, struct isl_obj obj2
)
2591 if (obj2
.type
== isl_obj_none
|| !obj2
.v
)
2593 if (obj1
.type
== isl_obj_set
&& obj2
.type
== isl_obj_union_set
)
2594 obj1
= to_union(s
->ctx
, obj1
);
2595 if (obj1
.type
== isl_obj_union_set
&& obj2
.type
== isl_obj_set
)
2596 obj2
= to_union(s
->ctx
, obj2
);
2597 if (obj1
.type
== isl_obj_map
&& obj2
.type
== isl_obj_union_map
)
2598 obj1
= to_union(s
->ctx
, obj1
);
2599 if (obj1
.type
== isl_obj_union_map
&& obj2
.type
== isl_obj_map
)
2600 obj2
= to_union(s
->ctx
, obj2
);
2601 if (obj1
.type
== isl_obj_pw_qpolynomial
&&
2602 obj2
.type
== isl_obj_union_pw_qpolynomial
)
2603 obj1
= to_union(s
->ctx
, obj1
);
2604 if (obj1
.type
== isl_obj_union_pw_qpolynomial
&&
2605 obj2
.type
== isl_obj_pw_qpolynomial
)
2606 obj2
= to_union(s
->ctx
, obj2
);
2607 if (obj1
.type
== isl_obj_pw_qpolynomial_fold
&&
2608 obj2
.type
== isl_obj_union_pw_qpolynomial_fold
)
2609 obj1
= to_union(s
->ctx
, obj1
);
2610 if (obj1
.type
== isl_obj_union_pw_qpolynomial_fold
&&
2611 obj2
.type
== isl_obj_pw_qpolynomial_fold
)
2612 obj2
= to_union(s
->ctx
, obj2
);
2613 if (obj1
.type
!= obj2
.type
) {
2614 isl_stream_error(s
, NULL
,
2615 "attempt to combine incompatible objects");
2618 if (!obj1
.type
->add
)
2619 isl_die(s
->ctx
, isl_error_internal
,
2620 "combination not supported on object type", goto error
);
2621 if (obj1
.type
== isl_obj_map
&& !isl_map_has_equal_space(obj1
.v
, obj2
.v
)) {
2622 obj1
= to_union(s
->ctx
, obj1
);
2623 obj2
= to_union(s
->ctx
, obj2
);
2625 if (obj1
.type
== isl_obj_set
&& !isl_set_has_equal_space(obj1
.v
, obj2
.v
)) {
2626 obj1
= to_union(s
->ctx
, obj1
);
2627 obj2
= to_union(s
->ctx
, obj2
);
2629 if (obj1
.type
== isl_obj_pw_qpolynomial
&&
2630 !isl_pw_qpolynomial_has_equal_space(obj1
.v
, obj2
.v
)) {
2631 obj1
= to_union(s
->ctx
, obj1
);
2632 obj2
= to_union(s
->ctx
, obj2
);
2634 if (obj1
.type
== isl_obj_pw_qpolynomial_fold
&&
2635 !isl_pw_qpolynomial_fold_has_equal_space(obj1
.v
, obj2
.v
)) {
2636 obj1
= to_union(s
->ctx
, obj1
);
2637 obj2
= to_union(s
->ctx
, obj2
);
2639 obj1
.v
= obj1
.type
->add(obj1
.v
, obj2
.v
);
2642 obj1
.type
->free(obj1
.v
);
2643 obj2
.type
->free(obj2
.v
);
2644 obj1
.type
= isl_obj_none
;
2649 /* Are the first two tokens on "s", "domain" (either as a string
2650 * or as an identifier) followed by ":"?
2652 static int next_is_domain_colon(__isl_keep isl_stream
*s
)
2654 struct isl_token
*tok
;
2658 tok
= isl_stream_next_token(s
);
2661 if (tok
->type
!= ISL_TOKEN_IDENT
&& tok
->type
!= ISL_TOKEN_STRING
) {
2662 isl_stream_push_token(s
, tok
);
2666 name
= isl_token_get_str(s
->ctx
, tok
);
2667 res
= !strcmp(name
, "domain") && isl_stream_next_token_is(s
, ':');
2670 isl_stream_push_token(s
, tok
);
2675 /* Do the first tokens on "s" look like a schedule?
2677 * The root of a schedule is always a domain node, so the first thing
2678 * we expect in the stream is a domain key, i.e., "domain" followed
2679 * by ":". If the schedule was printed in YAML flow style, then
2680 * we additionally expect a "{" to open the outer mapping.
2682 static int next_is_schedule(__isl_keep isl_stream
*s
)
2684 struct isl_token
*tok
;
2687 tok
= isl_stream_next_token(s
);
2690 if (tok
->type
!= '{') {
2691 isl_stream_push_token(s
, tok
);
2692 return next_is_domain_colon(s
);
2695 is_schedule
= next_is_domain_colon(s
);
2696 isl_stream_push_token(s
, tok
);
2701 /* Read an isl_schedule from "s" and store it in an isl_obj.
2703 static struct isl_obj
schedule_read(__isl_keep isl_stream
*s
)
2707 obj
.type
= isl_obj_schedule
;
2708 obj
.v
= isl_stream_read_schedule(s
);
2713 /* Read a disjunction of object bodies from "s".
2714 * That is, read the inside of the braces, but not the braces themselves.
2715 * "v" contains a description of the identifiers parsed so far.
2716 * "map" contains information about the parameters.
2718 static struct isl_obj
obj_read_disjuncts(__isl_keep isl_stream
*s
,
2719 struct vars
*v
, __isl_keep isl_map
*map
)
2721 struct isl_obj obj
= { isl_obj_set
, NULL
};
2723 if (isl_stream_next_token_is(s
, '}')) {
2724 obj
.type
= isl_obj_union_set
;
2725 obj
.v
= isl_union_set_empty(isl_map_get_space(map
));
2731 o
= obj_read_body(s
, isl_map_copy(map
), v
);
2735 obj
= obj_add(s
, obj
, o
);
2736 if (obj
.type
== isl_obj_none
|| !obj
.v
)
2738 if (!isl_stream_eat_if_available(s
, ';'))
2740 if (isl_stream_next_token_is(s
, '}'))
2747 static struct isl_obj
obj_read(__isl_keep isl_stream
*s
)
2749 isl_map
*map
= NULL
;
2750 struct isl_token
*tok
;
2751 struct vars
*v
= NULL
;
2752 struct isl_obj obj
= { isl_obj_set
, NULL
};
2754 if (next_is_schedule(s
))
2755 return schedule_read(s
);
2757 tok
= next_token(s
);
2759 isl_stream_error(s
, NULL
, "unexpected EOF");
2762 if (tok
->type
== ISL_TOKEN_VALUE
) {
2763 struct isl_token
*tok2
;
2764 struct isl_map
*map
;
2766 tok2
= isl_stream_next_token(s
);
2767 if (!tok2
|| tok2
->type
!= ISL_TOKEN_VALUE
||
2768 isl_int_is_neg(tok2
->u
.v
)) {
2770 isl_stream_push_token(s
, tok2
);
2771 obj
.type
= isl_obj_val
;
2772 obj
.v
= isl_val_int_from_isl_int(s
->ctx
, tok
->u
.v
);
2773 isl_token_free(tok
);
2776 isl_stream_push_token(s
, tok2
);
2777 isl_stream_push_token(s
, tok
);
2778 map
= map_read_polylib(s
);
2781 if (isl_map_may_be_set(map
))
2782 obj
.v
= isl_map_range(map
);
2784 obj
.type
= isl_obj_map
;
2789 v
= vars_new(s
->ctx
);
2791 isl_stream_push_token(s
, tok
);
2794 map
= isl_map_universe(isl_space_params_alloc(s
->ctx
, 0));
2795 if (tok
->type
== '[') {
2796 isl_stream_push_token(s
, tok
);
2797 map
= read_map_tuple(s
, map
, isl_dim_param
, v
, 0, 0);
2800 tok
= isl_stream_next_token(s
);
2801 if (!tok
|| tok
->type
!= ISL_TOKEN_TO
) {
2802 isl_stream_error(s
, tok
, "expecting '->'");
2804 isl_stream_push_token(s
, tok
);
2807 isl_token_free(tok
);
2808 tok
= isl_stream_next_token(s
);
2810 if (!tok
|| tok
->type
!= '{') {
2811 isl_stream_error(s
, tok
, "expecting '{'");
2813 isl_stream_push_token(s
, tok
);
2816 isl_token_free(tok
);
2818 tok
= isl_stream_next_token(s
);
2821 else if (tok
->type
== ISL_TOKEN_IDENT
&& !strcmp(tok
->u
.s
, "Sym")) {
2822 isl_token_free(tok
);
2823 if (isl_stream_eat(s
, '='))
2825 map
= read_map_tuple(s
, map
, isl_dim_param
, v
, 0, 1);
2829 isl_stream_push_token(s
, tok
);
2831 obj
= obj_read_disjuncts(s
, v
, map
);
2832 if (obj
.type
== isl_obj_none
|| !obj
.v
)
2835 tok
= isl_stream_next_token(s
);
2836 if (tok
&& tok
->type
== '}') {
2837 isl_token_free(tok
);
2839 isl_stream_error(s
, tok
, "unexpected isl_token");
2841 isl_token_free(tok
);
2851 obj
.type
->free(obj
.v
);
2858 struct isl_obj
isl_stream_read_obj(__isl_keep isl_stream
*s
)
2863 __isl_give isl_map
*isl_stream_read_map(__isl_keep isl_stream
*s
)
2869 isl_assert(s
->ctx
, obj
.type
== isl_obj_map
||
2870 obj
.type
== isl_obj_set
, goto error
);
2872 if (obj
.type
== isl_obj_set
)
2873 obj
.v
= isl_map_from_range(obj
.v
);
2877 obj
.type
->free(obj
.v
);
2881 __isl_give isl_set
*isl_stream_read_set(__isl_keep isl_stream
*s
)
2887 if (obj
.type
== isl_obj_map
&& isl_map_may_be_set(obj
.v
)) {
2888 obj
.v
= isl_map_range(obj
.v
);
2889 obj
.type
= isl_obj_set
;
2891 isl_assert(s
->ctx
, obj
.type
== isl_obj_set
, goto error
);
2896 obj
.type
->free(obj
.v
);
2900 __isl_give isl_union_map
*isl_stream_read_union_map(__isl_keep isl_stream
*s
)
2905 if (obj
.type
== isl_obj_map
) {
2906 obj
.type
= isl_obj_union_map
;
2907 obj
.v
= isl_union_map_from_map(obj
.v
);
2909 if (obj
.type
== isl_obj_set
) {
2910 obj
.type
= isl_obj_union_set
;
2911 obj
.v
= isl_union_set_from_set(obj
.v
);
2913 if (obj
.v
&& obj
.type
== isl_obj_union_set
&&
2914 isl_union_set_is_empty(obj
.v
))
2915 obj
.type
= isl_obj_union_map
;
2916 if (obj
.v
&& obj
.type
!= isl_obj_union_map
)
2917 isl_die(s
->ctx
, isl_error_invalid
, "invalid input", goto error
);
2921 obj
.type
->free(obj
.v
);
2925 /* Extract an isl_union_set from "obj".
2926 * This only works if the object was detected as either a set
2927 * (in which case it is converted to a union set) or a union set.
2929 static __isl_give isl_union_set
*extract_union_set(isl_ctx
*ctx
,
2932 if (obj
.type
== isl_obj_set
) {
2933 obj
.type
= isl_obj_union_set
;
2934 obj
.v
= isl_union_set_from_set(obj
.v
);
2937 isl_assert(ctx
, obj
.type
== isl_obj_union_set
, goto error
);
2941 obj
.type
->free(obj
.v
);
2945 /* Read an isl_union_set from "s".
2946 * First read a generic object and then try and extract
2947 * an isl_union_set from that.
2949 __isl_give isl_union_set
*isl_stream_read_union_set(__isl_keep isl_stream
*s
)
2954 return extract_union_set(s
->ctx
, obj
);
2957 static __isl_give isl_basic_map
*basic_map_read(__isl_keep isl_stream
*s
)
2960 struct isl_map
*map
;
2961 struct isl_basic_map
*bmap
;
2964 if (obj
.v
&& (obj
.type
!= isl_obj_map
&& obj
.type
!= isl_obj_set
))
2965 isl_die(s
->ctx
, isl_error_invalid
, "not a (basic) set or map",
2972 isl_die(s
->ctx
, isl_error_invalid
,
2973 "set or map description involves "
2974 "more than one disjunct", goto error
);
2977 bmap
= isl_basic_map_empty(isl_map_get_space(map
));
2979 bmap
= isl_basic_map_copy(map
->p
[0]);
2985 obj
.type
->free(obj
.v
);
2989 static __isl_give isl_basic_set
*basic_set_read(__isl_keep isl_stream
*s
)
2991 isl_basic_map
*bmap
;
2992 bmap
= basic_map_read(s
);
2995 if (!isl_basic_map_may_be_set(bmap
))
2996 isl_die(s
->ctx
, isl_error_invalid
,
2997 "input is not a set", goto error
);
2998 return isl_basic_map_range(bmap
);
3000 isl_basic_map_free(bmap
);
3004 __isl_give isl_basic_map
*isl_basic_map_read_from_file(isl_ctx
*ctx
,
3007 struct isl_basic_map
*bmap
;
3008 isl_stream
*s
= isl_stream_new_file(ctx
, input
);
3011 bmap
= basic_map_read(s
);
3016 __isl_give isl_basic_set
*isl_basic_set_read_from_file(isl_ctx
*ctx
,
3019 isl_basic_set
*bset
;
3020 isl_stream
*s
= isl_stream_new_file(ctx
, input
);
3023 bset
= basic_set_read(s
);
3028 struct isl_basic_map
*isl_basic_map_read_from_str(struct isl_ctx
*ctx
,
3031 struct isl_basic_map
*bmap
;
3032 isl_stream
*s
= isl_stream_new_str(ctx
, str
);
3035 bmap
= basic_map_read(s
);
3040 struct isl_basic_set
*isl_basic_set_read_from_str(struct isl_ctx
*ctx
,
3043 isl_basic_set
*bset
;
3044 isl_stream
*s
= isl_stream_new_str(ctx
, str
);
3047 bset
= basic_set_read(s
);
3052 __isl_give isl_map
*isl_map_read_from_file(struct isl_ctx
*ctx
,
3055 struct isl_map
*map
;
3056 isl_stream
*s
= isl_stream_new_file(ctx
, input
);
3059 map
= isl_stream_read_map(s
);
3064 __isl_give isl_map
*isl_map_read_from_str(struct isl_ctx
*ctx
,
3067 struct isl_map
*map
;
3068 isl_stream
*s
= isl_stream_new_str(ctx
, str
);
3071 map
= isl_stream_read_map(s
);
3076 __isl_give isl_set
*isl_set_read_from_file(struct isl_ctx
*ctx
,
3080 isl_stream
*s
= isl_stream_new_file(ctx
, input
);
3083 set
= isl_stream_read_set(s
);
3088 struct isl_set
*isl_set_read_from_str(struct isl_ctx
*ctx
,
3092 isl_stream
*s
= isl_stream_new_str(ctx
, str
);
3095 set
= isl_stream_read_set(s
);
3100 __isl_give isl_union_map
*isl_union_map_read_from_file(isl_ctx
*ctx
,
3103 isl_union_map
*umap
;
3104 isl_stream
*s
= isl_stream_new_file(ctx
, input
);
3107 umap
= isl_stream_read_union_map(s
);
3112 __isl_give isl_union_map
*isl_union_map_read_from_str(struct isl_ctx
*ctx
,
3115 isl_union_map
*umap
;
3116 isl_stream
*s
= isl_stream_new_str(ctx
, str
);
3119 umap
= isl_stream_read_union_map(s
);
3124 __isl_give isl_union_set
*isl_union_set_read_from_file(isl_ctx
*ctx
,
3127 isl_union_set
*uset
;
3128 isl_stream
*s
= isl_stream_new_file(ctx
, input
);
3131 uset
= isl_stream_read_union_set(s
);
3136 __isl_give isl_union_set
*isl_union_set_read_from_str(struct isl_ctx
*ctx
,
3139 isl_union_set
*uset
;
3140 isl_stream
*s
= isl_stream_new_str(ctx
, str
);
3143 uset
= isl_stream_read_union_set(s
);
3148 static __isl_give isl_vec
*isl_vec_read_polylib(__isl_keep isl_stream
*s
)
3150 struct isl_vec
*vec
= NULL
;
3151 struct isl_token
*tok
;
3155 tok
= isl_stream_next_token(s
);
3156 if (!tok
|| tok
->type
!= ISL_TOKEN_VALUE
) {
3157 isl_stream_error(s
, tok
, "expecting vector length");
3161 size
= isl_int_get_si(tok
->u
.v
);
3162 isl_token_free(tok
);
3164 vec
= isl_vec_alloc(s
->ctx
, size
);
3166 for (j
= 0; j
< size
; ++j
) {
3167 tok
= isl_stream_next_token(s
);
3168 if (!tok
|| tok
->type
!= ISL_TOKEN_VALUE
) {
3169 isl_stream_error(s
, tok
, "expecting constant value");
3172 isl_int_set(vec
->el
[j
], tok
->u
.v
);
3173 isl_token_free(tok
);
3178 isl_token_free(tok
);
3183 static __isl_give isl_vec
*vec_read(__isl_keep isl_stream
*s
)
3185 return isl_vec_read_polylib(s
);
3188 __isl_give isl_vec
*isl_vec_read_from_file(isl_ctx
*ctx
, FILE *input
)
3191 isl_stream
*s
= isl_stream_new_file(ctx
, input
);
3199 __isl_give isl_pw_qpolynomial
*isl_stream_read_pw_qpolynomial(
3200 __isl_keep isl_stream
*s
)
3206 isl_assert(s
->ctx
, obj
.type
== isl_obj_pw_qpolynomial
,
3211 obj
.type
->free(obj
.v
);
3215 __isl_give isl_pw_qpolynomial
*isl_pw_qpolynomial_read_from_str(isl_ctx
*ctx
,
3218 isl_pw_qpolynomial
*pwqp
;
3219 isl_stream
*s
= isl_stream_new_str(ctx
, str
);
3222 pwqp
= isl_stream_read_pw_qpolynomial(s
);
3227 __isl_give isl_pw_qpolynomial
*isl_pw_qpolynomial_read_from_file(isl_ctx
*ctx
,
3230 isl_pw_qpolynomial
*pwqp
;
3231 isl_stream
*s
= isl_stream_new_file(ctx
, input
);
3234 pwqp
= isl_stream_read_pw_qpolynomial(s
);
3239 /* Is the next token an identifer not in "v"?
3241 static int next_is_fresh_ident(__isl_keep isl_stream
*s
, struct vars
*v
)
3245 struct isl_token
*tok
;
3247 tok
= isl_stream_next_token(s
);
3250 fresh
= tok
->type
== ISL_TOKEN_IDENT
&& vars_pos(v
, tok
->u
.s
, -1) >= n
;
3251 isl_stream_push_token(s
, tok
);
3253 vars_drop(v
, v
->n
- n
);
3258 /* First read the domain of the affine expression, which may be
3259 * a parameter space or a set.
3260 * The tricky part is that we don't know if the domain is a set or not,
3261 * so when we are trying to read the domain, we may actually be reading
3262 * the affine expression itself (defined on a parameter domains)
3263 * If the tuple we are reading is named, we assume it's the domain.
3264 * Also, if inside the tuple, the first thing we find is a nested tuple
3265 * or a new identifier, we again assume it's the domain.
3266 * Finally, if the tuple is empty, then it must be the domain
3267 * since it does not contain an affine expression.
3268 * Otherwise, we assume we are reading an affine expression.
3270 static __isl_give isl_set
*read_aff_domain(__isl_keep isl_stream
*s
,
3271 __isl_take isl_set
*dom
, struct vars
*v
)
3273 struct isl_token
*tok
, *tok2
;
3276 tok
= isl_stream_next_token(s
);
3277 if (tok
&& (tok
->type
== ISL_TOKEN_IDENT
|| tok
->is_keyword
)) {
3278 isl_stream_push_token(s
, tok
);
3279 return read_map_tuple(s
, dom
, isl_dim_set
, v
, 0, 0);
3281 if (!tok
|| tok
->type
!= '[') {
3282 isl_stream_error(s
, tok
, "expecting '['");
3285 tok2
= isl_stream_next_token(s
);
3286 is_empty
= tok2
&& tok2
->type
== ']';
3288 isl_stream_push_token(s
, tok2
);
3289 if (is_empty
|| next_is_tuple(s
) || next_is_fresh_ident(s
, v
)) {
3290 isl_stream_push_token(s
, tok
);
3291 dom
= read_map_tuple(s
, dom
, isl_dim_set
, v
, 0, 0);
3293 isl_stream_push_token(s
, tok
);
3298 isl_stream_push_token(s
, tok
);
3303 /* Read an affine expression from "s".
3305 __isl_give isl_aff
*isl_stream_read_aff(__isl_keep isl_stream
*s
)
3311 ma
= isl_stream_read_multi_aff(s
);
3312 dim
= isl_multi_aff_dim(ma
, isl_dim_out
);
3316 isl_die(s
->ctx
, isl_error_invalid
,
3317 "expecting single affine expression",
3320 aff
= isl_multi_aff_get_aff(ma
, 0);
3321 isl_multi_aff_free(ma
);
3324 isl_multi_aff_free(ma
);
3328 /* Read a piecewise affine expression from "s" with domain (space) "dom".
3330 static __isl_give isl_pw_aff
*read_pw_aff_with_dom(__isl_keep isl_stream
*s
,
3331 __isl_take isl_set
*dom
, struct vars
*v
)
3333 isl_pw_aff
*pwaff
= NULL
;
3335 if (!isl_set_is_params(dom
) && isl_stream_eat(s
, ISL_TOKEN_TO
))
3338 if (isl_stream_eat(s
, '['))
3341 pwaff
= accept_affine(s
, isl_set_get_space(dom
), v
);
3343 if (isl_stream_eat(s
, ']'))
3346 dom
= read_optional_formula(s
, dom
, v
, 0);
3347 pwaff
= isl_pw_aff_intersect_domain(pwaff
, dom
);
3352 isl_pw_aff_free(pwaff
);
3356 __isl_give isl_pw_aff
*isl_stream_read_pw_aff(__isl_keep isl_stream
*s
)
3359 isl_set
*dom
= NULL
;
3361 isl_pw_aff
*pa
= NULL
;
3364 v
= vars_new(s
->ctx
);
3368 dom
= isl_set_universe(isl_space_params_alloc(s
->ctx
, 0));
3369 if (next_is_tuple(s
)) {
3370 dom
= read_map_tuple(s
, dom
, isl_dim_param
, v
, 1, 0);
3371 if (isl_stream_eat(s
, ISL_TOKEN_TO
))
3374 if (isl_stream_eat(s
, '{'))
3378 aff_dom
= read_aff_domain(s
, isl_set_copy(dom
), v
);
3379 pa
= read_pw_aff_with_dom(s
, aff_dom
, v
);
3380 vars_drop(v
, v
->n
- n
);
3382 while (isl_stream_eat_if_available(s
, ';')) {
3386 aff_dom
= read_aff_domain(s
, isl_set_copy(dom
), v
);
3387 pa_i
= read_pw_aff_with_dom(s
, aff_dom
, v
);
3388 vars_drop(v
, v
->n
- n
);
3390 pa
= isl_pw_aff_union_add(pa
, pa_i
);
3393 if (isl_stream_eat(s
, '}'))
3402 isl_pw_aff_free(pa
);
3406 __isl_give isl_aff
*isl_aff_read_from_str(isl_ctx
*ctx
, const char *str
)
3409 isl_stream
*s
= isl_stream_new_str(ctx
, str
);
3412 aff
= isl_stream_read_aff(s
);
3417 __isl_give isl_pw_aff
*isl_pw_aff_read_from_str(isl_ctx
*ctx
, const char *str
)
3420 isl_stream
*s
= isl_stream_new_str(ctx
, str
);
3423 pa
= isl_stream_read_pw_aff(s
);
3428 /* Extract an isl_multi_pw_aff with domain space "dom_space"
3429 * from a tuple "tuple" read by read_tuple.
3431 * Note that the function read_tuple accepts tuples where some output or
3432 * set dimensions are defined in terms of other output or set dimensions
3433 * since this function is also used to read maps. As a special case,
3434 * read_tuple also accept dimensions that are defined in terms of themselves
3435 * (i.e., that are not defined).
3436 * These cases are not allowed when extracting an isl_multi_pw_aff so check
3437 * that the definitions of the output/set dimensions do not involve any
3438 * output/set dimensions.
3439 * Finally, drop the output dimensions from the domain of the result
3440 * of read_tuple (which is of the form [input, output] -> [output],
3441 * with anonymous domain) and reset the space.
3443 static __isl_give isl_multi_pw_aff
*extract_mpa_from_tuple(
3444 __isl_take isl_space
*dom_space
, __isl_keep isl_multi_pw_aff
*tuple
)
3449 isl_multi_pw_aff
*mpa
;
3451 n
= isl_multi_pw_aff_dim(tuple
, isl_dim_out
);
3452 dim
= isl_space_dim(dom_space
, isl_dim_all
);
3453 if (n
< 0 || dim
< 0)
3454 dom_space
= isl_space_free(dom_space
);
3455 space
= isl_space_range(isl_multi_pw_aff_get_space(tuple
));
3456 space
= isl_space_align_params(space
, isl_space_copy(dom_space
));
3457 if (!isl_space_is_params(dom_space
))
3458 space
= isl_space_map_from_domain_and_range(
3459 isl_space_copy(dom_space
), space
);
3460 isl_space_free(dom_space
);
3461 mpa
= isl_multi_pw_aff_alloc(space
);
3463 for (i
= 0; i
< n
; ++i
) {
3465 pa
= isl_multi_pw_aff_get_pw_aff(tuple
, i
);
3467 return isl_multi_pw_aff_free(mpa
);
3468 if (isl_pw_aff_involves_dims(pa
, isl_dim_in
, dim
, i
+ 1)) {
3469 isl_ctx
*ctx
= isl_pw_aff_get_ctx(pa
);
3470 isl_pw_aff_free(pa
);
3471 isl_die(ctx
, isl_error_invalid
,
3472 "not an affine expression",
3473 return isl_multi_pw_aff_free(mpa
));
3475 pa
= isl_pw_aff_drop_dims(pa
, isl_dim_in
, dim
, n
);
3476 space
= isl_multi_pw_aff_get_domain_space(mpa
);
3477 pa
= isl_pw_aff_reset_domain_space(pa
, space
);
3478 mpa
= isl_multi_pw_aff_set_pw_aff(mpa
, i
, pa
);
3484 /* Read a tuple of affine expressions, together with optional constraints
3485 * on the domain from "s". "dom" represents the initial constraints
3488 * The isl_multi_aff may live in either a set or a map space.
3489 * First read the first tuple and check if it is followed by a "->".
3490 * If so, convert the tuple into the domain of the isl_multi_pw_aff and
3491 * read in the next tuple. This tuple (or the first tuple if it was
3492 * not followed by a "->") is then converted into an isl_multi_pw_aff
3493 * through a call to extract_mpa_from_tuple.
3494 * The result is converted to an isl_pw_multi_aff and
3495 * its domain is intersected with the domain.
3497 static __isl_give isl_pw_multi_aff
*read_conditional_multi_aff(
3498 __isl_keep isl_stream
*s
, __isl_take isl_set
*dom
, struct vars
*v
)
3500 isl_multi_pw_aff
*tuple
;
3501 isl_multi_pw_aff
*mpa
;
3502 isl_pw_multi_aff
*pma
;
3505 tuple
= read_tuple(s
, v
, 0, 0);
3508 if (isl_stream_eat_if_available(s
, ISL_TOKEN_TO
)) {
3509 isl_map
*map
= map_from_tuple(tuple
, dom
, isl_dim_in
, v
, 0);
3510 dom
= isl_map_domain(map
);
3511 tuple
= read_tuple(s
, v
, 0, 0);
3516 dom
= read_optional_formula(s
, dom
, v
, 0);
3518 vars_drop(v
, v
->n
- n
);
3520 mpa
= extract_mpa_from_tuple(isl_set_get_space(dom
), tuple
);
3521 isl_multi_pw_aff_free(tuple
);
3522 pma
= isl_pw_multi_aff_from_multi_pw_aff(mpa
);
3523 pma
= isl_pw_multi_aff_intersect_domain(pma
, dom
);
3531 /* Read an isl_pw_multi_aff from "s".
3533 * In particular, first read the parameters and then read a sequence
3534 * of one or more tuples of affine expressions with optional conditions and
3537 __isl_give isl_pw_multi_aff
*isl_stream_read_pw_multi_aff(
3538 __isl_keep isl_stream
*s
)
3542 isl_pw_multi_aff
*pma
= NULL
;
3544 v
= vars_new(s
->ctx
);
3548 dom
= isl_set_universe(isl_space_params_alloc(s
->ctx
, 0));
3549 if (next_is_tuple(s
)) {
3550 dom
= read_map_tuple(s
, dom
, isl_dim_param
, v
, 1, 0);
3551 if (isl_stream_eat(s
, ISL_TOKEN_TO
))
3554 if (isl_stream_eat(s
, '{'))
3557 pma
= read_conditional_multi_aff(s
, isl_set_copy(dom
), v
);
3559 while (isl_stream_eat_if_available(s
, ';')) {
3560 isl_pw_multi_aff
*pma2
;
3562 pma2
= read_conditional_multi_aff(s
, isl_set_copy(dom
), v
);
3563 pma
= isl_pw_multi_aff_union_add(pma
, pma2
);
3568 if (isl_stream_eat(s
, '}'))
3575 isl_pw_multi_aff_free(pma
);
3581 __isl_give isl_pw_multi_aff
*isl_pw_multi_aff_read_from_str(isl_ctx
*ctx
,
3584 isl_pw_multi_aff
*pma
;
3585 isl_stream
*s
= isl_stream_new_str(ctx
, str
);
3588 pma
= isl_stream_read_pw_multi_aff(s
);
3593 /* Read an isl_union_pw_multi_aff from "s".
3594 * We currently read a generic object and if it turns out to be a set or
3595 * a map, we convert that to an isl_union_pw_multi_aff.
3596 * It would be more efficient if we were to construct
3597 * the isl_union_pw_multi_aff directly.
3599 __isl_give isl_union_pw_multi_aff
*isl_stream_read_union_pw_multi_aff(
3600 __isl_keep isl_stream
*s
)
3608 if (obj
.type
== isl_obj_map
|| obj
.type
== isl_obj_set
)
3609 obj
= to_union(s
->ctx
, obj
);
3610 if (obj
.type
== isl_obj_union_map
)
3611 return isl_union_pw_multi_aff_from_union_map(obj
.v
);
3612 if (obj
.type
== isl_obj_union_set
)
3613 return isl_union_pw_multi_aff_from_union_set(obj
.v
);
3615 obj
.type
->free(obj
.v
);
3616 isl_die(s
->ctx
, isl_error_invalid
, "unexpected object type",
3620 /* Read an isl_union_pw_multi_aff from "str".
3622 __isl_give isl_union_pw_multi_aff
*isl_union_pw_multi_aff_read_from_str(
3623 isl_ctx
*ctx
, const char *str
)
3625 isl_union_pw_multi_aff
*upma
;
3626 isl_stream
*s
= isl_stream_new_str(ctx
, str
);
3629 upma
= isl_stream_read_union_pw_multi_aff(s
);
3634 /* Assuming "pa" represents a single affine expression defined on a universe
3635 * domain, extract this affine expression.
3637 static __isl_give isl_aff
*aff_from_pw_aff(__isl_take isl_pw_aff
*pa
)
3644 isl_die(isl_pw_aff_get_ctx(pa
), isl_error_invalid
,
3645 "expecting single affine expression",
3647 if (!isl_set_plain_is_universe(pa
->p
[0].set
))
3648 isl_die(isl_pw_aff_get_ctx(pa
), isl_error_invalid
,
3649 "expecting universe domain",
3652 aff
= isl_aff_copy(pa
->p
[0].aff
);
3653 isl_pw_aff_free(pa
);
3656 isl_pw_aff_free(pa
);
3663 #include <isl_multi_read_no_explicit_domain_templ.c>
3668 #include <isl_multi_read_no_explicit_domain_templ.c>
3670 /* Read a multi-affine expression from "s".
3671 * If the multi-affine expression has a domain, then the tuple
3672 * representing this domain cannot involve any affine expressions.
3673 * The tuple representing the actual expressions needs to consist
3674 * of only affine expressions. Moreover, these expressions can
3675 * only depend on parameters and input dimensions and not on other
3676 * output dimensions.
3678 __isl_give isl_multi_aff
*isl_stream_read_multi_aff(__isl_keep isl_stream
*s
)
3681 isl_set
*dom
= NULL
;
3682 isl_multi_pw_aff
*tuple
= NULL
;
3685 isl_space
*space
, *dom_space
;
3686 isl_multi_aff
*ma
= NULL
;
3688 v
= vars_new(s
->ctx
);
3692 dom
= isl_set_universe(isl_space_params_alloc(s
->ctx
, 0));
3693 if (next_is_tuple(s
)) {
3694 dom
= read_map_tuple(s
, dom
, isl_dim_param
, v
, 1, 0);
3695 if (isl_stream_eat(s
, ISL_TOKEN_TO
))
3698 if (!isl_set_plain_is_universe(dom
))
3699 isl_die(s
->ctx
, isl_error_invalid
,
3700 "expecting universe parameter domain", goto error
);
3701 if (isl_stream_eat(s
, '{'))
3704 tuple
= read_tuple(s
, v
, 0, 0);
3707 if (isl_stream_eat_if_available(s
, ISL_TOKEN_TO
)) {
3712 has_expr
= tuple_has_expr(tuple
);
3716 isl_die(s
->ctx
, isl_error_invalid
,
3717 "expecting universe domain", goto error
);
3718 space
= isl_space_range(isl_multi_pw_aff_get_space(tuple
));
3719 set
= isl_set_universe(space
);
3720 dom
= isl_set_intersect_params(set
, dom
);
3721 isl_multi_pw_aff_free(tuple
);
3722 tuple
= read_tuple(s
, v
, 0, 0);
3727 if (isl_stream_eat(s
, '}'))
3730 n
= isl_multi_pw_aff_dim(tuple
, isl_dim_out
);
3731 dim
= isl_set_dim(dom
, isl_dim_all
);
3732 if (n
< 0 || dim
< 0)
3734 dom_space
= isl_set_get_space(dom
);
3735 space
= isl_space_range(isl_multi_pw_aff_get_space(tuple
));
3736 space
= isl_space_align_params(space
, isl_space_copy(dom_space
));
3737 if (!isl_space_is_params(dom_space
))
3738 space
= isl_space_map_from_domain_and_range(
3739 isl_space_copy(dom_space
), space
);
3740 isl_space_free(dom_space
);
3741 ma
= isl_multi_aff_alloc(space
);
3743 for (i
= 0; i
< n
; ++i
) {
3746 pa
= isl_multi_pw_aff_get_pw_aff(tuple
, i
);
3747 aff
= aff_from_pw_aff(pa
);
3750 if (isl_aff_involves_dims(aff
, isl_dim_in
, dim
, i
+ 1)) {
3752 isl_die(s
->ctx
, isl_error_invalid
,
3753 "not an affine expression", goto error
);
3755 aff
= isl_aff_drop_dims(aff
, isl_dim_in
, dim
, n
);
3756 space
= isl_multi_aff_get_domain_space(ma
);
3757 aff
= isl_aff_reset_domain_space(aff
, space
);
3758 ma
= isl_multi_aff_set_aff(ma
, i
, aff
);
3761 isl_multi_pw_aff_free(tuple
);
3766 isl_multi_pw_aff_free(tuple
);
3769 isl_multi_aff_free(ma
);
3773 __isl_give isl_multi_aff
*isl_multi_aff_read_from_str(isl_ctx
*ctx
,
3776 isl_multi_aff
*maff
;
3777 isl_stream
*s
= isl_stream_new_str(ctx
, str
);
3780 maff
= isl_stream_read_multi_aff(s
);
3785 /* Read an isl_multi_pw_aff from "s".
3787 * The input format is similar to that of map, except that any conditions
3788 * on the domains should be specified inside the tuple since each
3789 * piecewise affine expression may have a different domain.
3790 * However, additional, shared conditions can also be specified.
3791 * This is especially useful for setting the explicit domain
3792 * of a zero-dimensional isl_multi_pw_aff.
3794 * Since we do not know in advance if the isl_multi_pw_aff lives
3795 * in a set or a map space, we first read the first tuple and check
3796 * if it is followed by a "->". If so, we convert the tuple into
3797 * the domain of the isl_multi_pw_aff and read in the next tuple.
3798 * This tuple (or the first tuple if it was not followed by a "->")
3799 * is then converted into the isl_multi_pw_aff through a call
3800 * to extract_mpa_from_tuple and the domain of the result
3801 * is intersected with the domain.
3803 __isl_give isl_multi_pw_aff
*isl_stream_read_multi_pw_aff(
3804 __isl_keep isl_stream
*s
)
3807 isl_set
*dom
= NULL
;
3808 isl_multi_pw_aff
*tuple
= NULL
;
3809 isl_multi_pw_aff
*mpa
= NULL
;
3811 v
= vars_new(s
->ctx
);
3815 dom
= isl_set_universe(isl_space_params_alloc(s
->ctx
, 0));
3816 if (next_is_tuple(s
)) {
3817 dom
= read_map_tuple(s
, dom
, isl_dim_param
, v
, 1, 0);
3818 if (isl_stream_eat(s
, ISL_TOKEN_TO
))
3821 if (isl_stream_eat(s
, '{'))
3824 tuple
= read_tuple(s
, v
, 0, 0);
3827 if (isl_stream_eat_if_available(s
, ISL_TOKEN_TO
)) {
3828 isl_map
*map
= map_from_tuple(tuple
, dom
, isl_dim_in
, v
, 0);
3829 dom
= isl_map_domain(map
);
3830 tuple
= read_tuple(s
, v
, 0, 0);
3835 if (isl_stream_eat_if_available(s
, ':'))
3836 dom
= read_formula(s
, v
, dom
, 0);
3838 if (isl_stream_eat(s
, '}'))
3841 mpa
= extract_mpa_from_tuple(isl_set_get_space(dom
), tuple
);
3843 isl_multi_pw_aff_free(tuple
);
3845 mpa
= isl_multi_pw_aff_intersect_domain(mpa
, dom
);
3848 isl_multi_pw_aff_free(tuple
);
3851 isl_multi_pw_aff_free(mpa
);
3855 /* Read an isl_multi_pw_aff from "str".
3857 __isl_give isl_multi_pw_aff
*isl_multi_pw_aff_read_from_str(isl_ctx
*ctx
,
3860 isl_multi_pw_aff
*mpa
;
3861 isl_stream
*s
= isl_stream_new_str(ctx
, str
);
3864 mpa
= isl_stream_read_multi_pw_aff(s
);
3869 /* Read the body of an isl_union_pw_aff from "s" with parameter domain "dom".
3871 static __isl_give isl_union_pw_aff
*read_union_pw_aff_with_dom(
3872 __isl_keep isl_stream
*s
, __isl_take isl_set
*dom
, struct vars
*v
)
3875 isl_union_pw_aff
*upa
= NULL
;
3880 aff_dom
= read_aff_domain(s
, isl_set_copy(dom
), v
);
3881 pa
= read_pw_aff_with_dom(s
, aff_dom
, v
);
3882 vars_drop(v
, v
->n
- n
);
3884 upa
= isl_union_pw_aff_from_pw_aff(pa
);
3886 while (isl_stream_eat_if_available(s
, ';')) {
3888 isl_union_pw_aff
*upa_i
;
3891 aff_dom
= read_aff_domain(s
, isl_set_copy(dom
), v
);
3892 pa_i
= read_pw_aff_with_dom(s
, aff_dom
, v
);
3893 vars_drop(v
, v
->n
- n
);
3895 upa_i
= isl_union_pw_aff_from_pw_aff(pa_i
);
3896 upa
= isl_union_pw_aff_union_add(upa
, upa_i
);
3903 /* Read an isl_union_pw_aff from "s".
3905 * First check if there are any paramters, then read in the opening brace
3906 * and use read_union_pw_aff_with_dom to read in the body of
3907 * the isl_union_pw_aff. Finally, read the closing brace.
3909 __isl_give isl_union_pw_aff
*isl_stream_read_union_pw_aff(
3910 __isl_keep isl_stream
*s
)
3914 isl_union_pw_aff
*upa
= NULL
;
3916 v
= vars_new(s
->ctx
);
3920 dom
= isl_set_universe(isl_space_params_alloc(s
->ctx
, 0));
3921 if (next_is_tuple(s
)) {
3922 dom
= read_map_tuple(s
, dom
, isl_dim_param
, v
, 1, 0);
3923 if (isl_stream_eat(s
, ISL_TOKEN_TO
))
3926 if (isl_stream_eat(s
, '{'))
3929 upa
= read_union_pw_aff_with_dom(s
, isl_set_copy(dom
), v
);
3931 if (isl_stream_eat(s
, '}'))
3940 isl_union_pw_aff_free(upa
);
3944 /* Read an isl_union_pw_aff from "str".
3946 __isl_give isl_union_pw_aff
*isl_union_pw_aff_read_from_str(isl_ctx
*ctx
,
3949 isl_union_pw_aff
*upa
;
3950 isl_stream
*s
= isl_stream_new_str(ctx
, str
);
3953 upa
= isl_stream_read_union_pw_aff(s
);
3958 /* This function is called for each element in a tuple inside
3959 * isl_stream_read_multi_union_pw_aff.
3961 * Read a '{', the union piecewise affine expression body and a '}' and
3962 * add the isl_union_pw_aff to *list.
3964 static __isl_give isl_space
*read_union_pw_aff_el(__isl_keep isl_stream
*s
,
3965 struct vars
*v
, __isl_take isl_space
*space
, int rational
, void *user
)
3968 isl_union_pw_aff
*upa
;
3969 isl_union_pw_aff_list
**list
= (isl_union_pw_aff_list
**) user
;
3971 dom
= isl_set_universe(isl_space_params(isl_space_copy(space
)));
3972 if (isl_stream_eat(s
, '{'))
3974 upa
= read_union_pw_aff_with_dom(s
, dom
, v
);
3975 *list
= isl_union_pw_aff_list_add(*list
, upa
);
3976 if (isl_stream_eat(s
, '}'))
3977 return isl_space_free(space
);
3979 return isl_space_free(space
);
3983 return isl_space_free(space
);
3986 /* Do the next tokens in "s" correspond to an empty tuple?
3987 * In particular, does the stream start with a '[', followed by a ']',
3988 * not followed by a "->"?
3990 static int next_is_empty_tuple(__isl_keep isl_stream
*s
)
3992 struct isl_token
*tok
, *tok2
, *tok3
;
3993 int is_empty_tuple
= 0;
3995 tok
= isl_stream_next_token(s
);
3998 if (tok
->type
!= '[') {
3999 isl_stream_push_token(s
, tok
);
4003 tok2
= isl_stream_next_token(s
);
4004 if (tok2
&& tok2
->type
== ']') {
4005 tok3
= isl_stream_next_token(s
);
4006 is_empty_tuple
= !tok
|| tok
->type
!= ISL_TOKEN_TO
;
4008 isl_stream_push_token(s
, tok3
);
4011 isl_stream_push_token(s
, tok2
);
4012 isl_stream_push_token(s
, tok
);
4014 return is_empty_tuple
;
4017 /* Do the next tokens in "s" correspond to a tuple of parameters?
4018 * In particular, does the stream start with a '[' that is not
4019 * followed by a '{' or a nested tuple?
4021 static int next_is_param_tuple(__isl_keep isl_stream
*s
)
4023 struct isl_token
*tok
, *tok2
;
4026 tok
= isl_stream_next_token(s
);
4029 if (tok
->type
!= '[' || next_is_tuple(s
)) {
4030 isl_stream_push_token(s
, tok
);
4034 tok2
= isl_stream_next_token(s
);
4035 is_tuple
= tok2
&& tok2
->type
!= '{';
4037 isl_stream_push_token(s
, tok2
);
4038 isl_stream_push_token(s
, tok
);
4043 /* Read the core of a body of an isl_multi_union_pw_aff from "s",
4044 * i.e., everything except the parameter specification and
4045 * without shared domain constraints.
4046 * "v" contains a description of the identifiers parsed so far.
4047 * The parameters, if any, are specified by "space".
4049 * The body is of the form
4051 * [{ [..] : ... ; [..] : ... }, { [..] : ... ; [..] : ... }]
4053 * Read the tuple, collecting the individual isl_union_pw_aff
4054 * elements in a list and construct the result from the tuple space and
4057 static __isl_give isl_multi_union_pw_aff
*read_multi_union_pw_aff_body_core(
4058 __isl_keep isl_stream
*s
, struct vars
*v
, __isl_take isl_space
*space
)
4060 isl_union_pw_aff_list
*list
;
4061 isl_multi_union_pw_aff
*mupa
;
4063 list
= isl_union_pw_aff_list_alloc(s
->ctx
, 0);
4064 space
= read_tuple_space(s
, v
, space
, 1, 0,
4065 &read_union_pw_aff_el
, &list
);
4066 mupa
= isl_multi_union_pw_aff_from_union_pw_aff_list(space
, list
);
4071 /* Read the body of an isl_union_set from "s",
4072 * i.e., everything except the parameter specification.
4073 * "v" contains a description of the identifiers parsed so far.
4074 * The parameters, if any, are specified by "space".
4076 * First read a generic disjunction of object bodies and then try and extract
4077 * an isl_union_set from that.
4079 static __isl_give isl_union_set
*read_union_set_body(__isl_keep isl_stream
*s
,
4080 struct vars
*v
, __isl_take isl_space
*space
)
4082 struct isl_obj obj
= { isl_obj_set
, NULL
};
4085 map
= isl_set_universe(space
);
4086 if (isl_stream_eat(s
, '{') < 0)
4088 obj
= obj_read_disjuncts(s
, v
, map
);
4089 if (isl_stream_eat(s
, '}') < 0)
4093 return extract_union_set(s
->ctx
, obj
);
4095 obj
.type
->free(obj
.v
);
4100 /* Read the body of an isl_multi_union_pw_aff from "s",
4101 * i.e., everything except the parameter specification.
4102 * "v" contains a description of the identifiers parsed so far.
4103 * The parameters, if any, are specified by "space".
4105 * In particular, handle the special case with shared domain constraints.
4106 * These are specified as
4110 * and are especially useful for setting the explicit domain
4111 * of a zero-dimensional isl_multi_union_pw_aff.
4112 * The core isl_multi_union_pw_aff body ([...]) is read by
4113 * read_multi_union_pw_aff_body_core.
4115 static __isl_give isl_multi_union_pw_aff
*read_multi_union_pw_aff_body(
4116 __isl_keep isl_stream
*s
, struct vars
*v
, __isl_take isl_space
*space
)
4118 isl_multi_union_pw_aff
*mupa
;
4120 if (!isl_stream_next_token_is(s
, '('))
4121 return read_multi_union_pw_aff_body_core(s
, v
, space
);
4123 if (isl_stream_eat(s
, '(') < 0)
4125 mupa
= read_multi_union_pw_aff_body_core(s
, v
, isl_space_copy(space
));
4126 if (isl_stream_eat_if_available(s
, ':')) {
4129 dom
= read_union_set_body(s
, v
, space
);
4130 mupa
= isl_multi_union_pw_aff_intersect_domain(mupa
, dom
);
4132 isl_space_free(space
);
4134 if (isl_stream_eat(s
, ')') < 0)
4135 return isl_multi_union_pw_aff_free(mupa
);
4139 isl_space_free(space
);
4143 /* Read an isl_multi_union_pw_aff from "s".
4145 * The input has the form
4147 * [{ [..] : ... ; [..] : ... }, { [..] : ... ; [..] : ... }]
4151 * [..] -> [{ [..] : ... ; [..] : ... }, { [..] : ... ; [..] : ... }]
4153 * Additionally, a shared domain may be specified as
4159 * [..] -> ([..] : ...)
4161 * The first case is handled by the caller, the second case
4162 * is handled by read_multi_union_pw_aff_body.
4164 * We first check for the special case of an empty tuple "[]".
4165 * Then we check if there are any parameters.
4166 * Finally, read the tuple and construct the result.
4168 static __isl_give isl_multi_union_pw_aff
*read_multi_union_pw_aff_core(
4169 __isl_keep isl_stream
*s
)
4172 isl_set
*dom
= NULL
;
4174 isl_multi_union_pw_aff
*mupa
= NULL
;
4176 if (next_is_empty_tuple(s
)) {
4177 if (isl_stream_eat(s
, '['))
4179 if (isl_stream_eat(s
, ']'))
4181 space
= isl_space_set_alloc(s
->ctx
, 0, 0);
4182 return isl_multi_union_pw_aff_zero(space
);
4185 v
= vars_new(s
->ctx
);
4189 dom
= isl_set_universe(isl_space_params_alloc(s
->ctx
, 0));
4190 if (next_is_param_tuple(s
)) {
4191 dom
= read_map_tuple(s
, dom
, isl_dim_param
, v
, 1, 0);
4192 if (isl_stream_eat(s
, ISL_TOKEN_TO
))
4195 space
= isl_set_get_space(dom
);
4197 mupa
= read_multi_union_pw_aff_body(s
, v
, space
);
4205 isl_multi_union_pw_aff_free(mupa
);
4209 /* Read an isl_multi_union_pw_aff from "s".
4211 * In particular, handle the special case with shared domain constraints.
4212 * These are specified as
4216 * and are especially useful for setting the explicit domain
4217 * of a zero-dimensional isl_multi_union_pw_aff.
4218 * The core isl_multi_union_pw_aff ([...]) is read by
4219 * read_multi_union_pw_aff_core.
4221 __isl_give isl_multi_union_pw_aff
*isl_stream_read_multi_union_pw_aff(
4222 __isl_keep isl_stream
*s
)
4224 isl_multi_union_pw_aff
*mupa
;
4226 if (!isl_stream_next_token_is(s
, '('))
4227 return read_multi_union_pw_aff_core(s
);
4229 if (isl_stream_eat(s
, '(') < 0)
4231 mupa
= read_multi_union_pw_aff_core(s
);
4232 if (isl_stream_eat_if_available(s
, ':')) {
4235 dom
= isl_stream_read_union_set(s
);
4236 mupa
= isl_multi_union_pw_aff_intersect_domain(mupa
, dom
);
4238 if (isl_stream_eat(s
, ')') < 0)
4239 return isl_multi_union_pw_aff_free(mupa
);
4243 /* Read an isl_multi_union_pw_aff from "str".
4245 __isl_give isl_multi_union_pw_aff
*isl_multi_union_pw_aff_read_from_str(
4246 isl_ctx
*ctx
, const char *str
)
4248 isl_multi_union_pw_aff
*mupa
;
4249 isl_stream
*s
= isl_stream_new_str(ctx
, str
);
4252 mupa
= isl_stream_read_multi_union_pw_aff(s
);
4257 __isl_give isl_union_pw_qpolynomial
*isl_stream_read_union_pw_qpolynomial(
4258 __isl_keep isl_stream
*s
)
4263 if (obj
.type
== isl_obj_pw_qpolynomial
) {
4264 obj
.type
= isl_obj_union_pw_qpolynomial
;
4265 obj
.v
= isl_union_pw_qpolynomial_from_pw_qpolynomial(obj
.v
);
4268 isl_assert(s
->ctx
, obj
.type
== isl_obj_union_pw_qpolynomial
,
4273 obj
.type
->free(obj
.v
);
4277 __isl_give isl_union_pw_qpolynomial
*isl_union_pw_qpolynomial_read_from_str(
4278 isl_ctx
*ctx
, const char *str
)
4280 isl_union_pw_qpolynomial
*upwqp
;
4281 isl_stream
*s
= isl_stream_new_str(ctx
, str
);
4284 upwqp
= isl_stream_read_union_pw_qpolynomial(s
);