2 * Copyright 2008-2009 Katholieke Universiteit Leuven
3 * Copyright 2010 INRIA Saclay
4 * Copyright 2012-2013 Ecole Normale Superieure
5 * Copyright 2019 Cerebras Systems
7 * Use of this software is governed by the MIT license
9 * Written by Sven Verdoolaege, K.U.Leuven, Departement
10 * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
11 * and INRIA Saclay - Ile-de-France, Parc Club Orsay Universite,
12 * ZAC des vignes, 4 rue Jacques Monod, 91893 Orsay, France
13 * and Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France
14 * and Cerebras Systems, 175 S San Antonio Rd, Los Altos, CA, USA
20 #include <isl_ctx_private.h>
21 #include <isl_map_private.h>
22 #include <isl_id_private.h>
25 #include <isl_stream_private.h>
27 #include "isl_polynomial_private.h"
28 #include <isl/union_set.h>
29 #include <isl/union_map.h>
30 #include <isl_mat_private.h>
31 #include <isl_aff_private.h>
32 #include <isl_vec_private.h>
34 #include <isl_val_private.h>
39 struct variable
*next
;
48 static struct vars
*vars_new(struct isl_ctx
*ctx
)
51 v
= isl_alloc_type(ctx
, struct vars
);
60 static void variable_free(struct variable
*var
)
63 struct variable
*next
= var
->next
;
70 static void vars_free(struct vars
*v
)
78 static void vars_drop(struct vars
*v
, int n
)
89 struct variable
*next
= var
->next
;
97 static struct variable
*variable_new(struct vars
*v
, const char *name
, int len
,
100 struct variable
*var
;
101 var
= isl_calloc_type(v
->ctx
, struct variable
);
104 var
->name
= strdup(name
);
105 var
->name
[len
] = '\0';
114 static int vars_pos(struct vars
*v
, const char *s
, int len
)
121 for (q
= v
->v
; q
; q
= q
->next
) {
122 if (strncmp(q
->name
, s
, len
) == 0 && q
->name
[len
] == '\0')
129 v
->v
= variable_new(v
, s
, len
, v
->n
);
137 static int vars_add_anon(struct vars
*v
)
139 v
->v
= variable_new(v
, "", 0, v
->n
);
148 /* Obtain next token, with some preprocessing.
149 * In particular, evaluate expressions of the form x^y,
150 * with x and y values.
152 static struct isl_token
*next_token(__isl_keep isl_stream
*s
)
154 struct isl_token
*tok
, *tok2
;
156 tok
= isl_stream_next_token(s
);
157 if (!tok
|| tok
->type
!= ISL_TOKEN_VALUE
)
159 if (!isl_stream_eat_if_available(s
, '^'))
161 tok2
= isl_stream_next_token(s
);
162 if (!tok2
|| tok2
->type
!= ISL_TOKEN_VALUE
) {
163 isl_stream_error(s
, tok2
, "expecting constant value");
167 isl_int_pow_ui(tok
->u
.v
, tok
->u
.v
, isl_int_get_ui(tok2
->u
.v
));
169 isl_token_free(tok2
);
173 isl_token_free(tok2
);
177 /* Read an isl_val from "s".
179 * The following token sequences are recognized
182 * "-" "infty" -> -infty
187 * where n, d and v are integer constants.
189 __isl_give isl_val
*isl_stream_read_val(__isl_keep isl_stream
*s
)
191 struct isl_token
*tok
= NULL
;
192 struct isl_token
*tok2
= NULL
;
197 isl_stream_error(s
, NULL
, "unexpected EOF");
200 if (tok
->type
== ISL_TOKEN_INFTY
) {
202 return isl_val_infty(s
->ctx
);
204 if (tok
->type
== '-' &&
205 isl_stream_eat_if_available(s
, ISL_TOKEN_INFTY
)) {
207 return isl_val_neginfty(s
->ctx
);
209 if (tok
->type
== ISL_TOKEN_NAN
) {
211 return isl_val_nan(s
->ctx
);
213 if (tok
->type
!= ISL_TOKEN_VALUE
) {
214 isl_stream_error(s
, tok
, "expecting value");
218 if (isl_stream_eat_if_available(s
, '/')) {
219 tok2
= next_token(s
);
221 isl_stream_error(s
, NULL
, "unexpected EOF");
224 if (tok2
->type
!= ISL_TOKEN_VALUE
) {
225 isl_stream_error(s
, tok2
, "expecting value");
228 val
= isl_val_rat_from_isl_int(s
->ctx
, tok
->u
.v
, tok2
->u
.v
);
229 val
= isl_val_normalize(val
);
231 val
= isl_val_int_from_isl_int(s
->ctx
, tok
->u
.v
);
235 isl_token_free(tok2
);
239 isl_token_free(tok2
);
243 /* Read an isl_val from "str".
245 __isl_give isl_val
*isl_val_read_from_str(isl_ctx
*ctx
, const char *str
)
248 isl_stream
*s
= isl_stream_new_str(ctx
, str
);
251 val
= isl_stream_read_val(s
);
256 /* Perform an integer division on *f and
257 * an integer value read from the stream.
259 static isl_stat
int_div_by_cst(__isl_keep isl_stream
*s
, isl_int
*f
)
261 struct isl_token
*tok
;
264 if (!tok
|| tok
->type
!= ISL_TOKEN_VALUE
) {
265 isl_stream_error(s
, tok
, "expecting constant value");
269 isl_int_fdiv_q(*f
, *f
, tok
->u
.v
);
276 return isl_stat_error
;
279 static isl_stat
accept_cst_factor(__isl_keep isl_stream
*s
, isl_int
*f
)
281 struct isl_token
*tok
;
284 if (!tok
|| tok
->type
!= ISL_TOKEN_VALUE
) {
285 isl_stream_error(s
, tok
, "expecting constant value");
289 isl_int_mul(*f
, *f
, tok
->u
.v
);
293 if (isl_stream_eat_if_available(s
, '*'))
294 return accept_cst_factor(s
, f
);
299 return isl_stat_error
;
302 /* Given an affine expression aff, return an affine expression
303 * for aff % d, with d the next token on the stream, which is
304 * assumed to be a constant.
306 * We introduce an integer division q = [aff/d] and the result
307 * is set to aff - d q.
309 static __isl_give isl_pw_aff
*affine_mod(__isl_keep isl_stream
*s
,
310 struct vars
*v
, __isl_take isl_pw_aff
*aff
)
312 struct isl_token
*tok
;
316 if (!tok
|| tok
->type
!= ISL_TOKEN_VALUE
) {
317 isl_stream_error(s
, tok
, "expecting constant value");
321 q
= isl_pw_aff_copy(aff
);
322 q
= isl_pw_aff_scale_down(q
, tok
->u
.v
);
323 q
= isl_pw_aff_floor(q
);
324 q
= isl_pw_aff_scale(q
, tok
->u
.v
);
326 aff
= isl_pw_aff_sub(aff
, q
);
331 isl_pw_aff_free(aff
);
336 static __isl_give isl_pw_aff
*accept_affine(__isl_keep isl_stream
*s
,
337 __isl_take isl_space
*space
, struct vars
*v
);
338 static __isl_give isl_pw_aff_list
*accept_affine_list(__isl_keep isl_stream
*s
,
339 __isl_take isl_space
*space
, struct vars
*v
);
341 static __isl_give isl_pw_aff
*accept_minmax(__isl_keep isl_stream
*s
,
342 __isl_take isl_space
*space
, struct vars
*v
)
344 struct isl_token
*tok
;
345 isl_pw_aff_list
*list
= NULL
;
348 tok
= isl_stream_next_token(s
);
351 min
= tok
->type
== ISL_TOKEN_MIN
;
354 if (isl_stream_eat(s
, '('))
357 list
= accept_affine_list(s
, isl_space_copy(space
), v
);
361 if (isl_stream_eat(s
, ')'))
364 isl_space_free(space
);
365 return min
? isl_pw_aff_list_min(list
) : isl_pw_aff_list_max(list
);
367 isl_space_free(space
);
368 isl_pw_aff_list_free(list
);
372 /* Is "tok" the start of an integer division?
374 static int is_start_of_div(struct isl_token
*tok
)
378 if (tok
->type
== '[')
380 if (tok
->type
== ISL_TOKEN_FLOOR
)
382 if (tok
->type
== ISL_TOKEN_CEIL
)
384 if (tok
->type
== ISL_TOKEN_FLOORD
)
386 if (tok
->type
== ISL_TOKEN_CEILD
)
391 /* Read an integer division from "s" and return it as an isl_pw_aff.
393 * The integer division can be of the form
395 * [<affine expression>]
396 * floor(<affine expression>)
397 * ceil(<affine expression>)
398 * floord(<affine expression>,<denominator>)
399 * ceild(<affine expression>,<denominator>)
401 static __isl_give isl_pw_aff
*accept_div(__isl_keep isl_stream
*s
,
402 __isl_take isl_space
*space
, struct vars
*v
)
404 struct isl_token
*tok
;
408 isl_pw_aff
*pwaff
= NULL
;
410 if (isl_stream_eat_if_available(s
, ISL_TOKEN_FLOORD
))
412 else if (isl_stream_eat_if_available(s
, ISL_TOKEN_CEILD
))
414 else if (isl_stream_eat_if_available(s
, ISL_TOKEN_FLOOR
))
416 else if (isl_stream_eat_if_available(s
, ISL_TOKEN_CEIL
))
419 if (isl_stream_eat(s
, '('))
422 if (isl_stream_eat(s
, '['))
426 pwaff
= accept_affine(s
, isl_space_copy(space
), v
);
429 if (isl_stream_eat(s
, ','))
435 if (tok
->type
!= ISL_TOKEN_VALUE
) {
436 isl_stream_error(s
, tok
, "expected denominator");
437 isl_stream_push_token(s
, tok
);
440 pwaff
= isl_pw_aff_scale_down(pwaff
, tok
->u
.v
);
445 pwaff
= isl_pw_aff_ceil(pwaff
);
447 pwaff
= isl_pw_aff_floor(pwaff
);
450 if (isl_stream_eat(s
, ')'))
453 if (isl_stream_eat(s
, ']'))
457 isl_space_free(space
);
460 isl_space_free(space
);
461 isl_pw_aff_free(pwaff
);
465 /* Divide "pa" by an integer constant read from the stream.
467 static __isl_give isl_pw_aff
*pw_aff_div_by_cst(__isl_keep isl_stream
*s
,
468 __isl_take isl_pw_aff
*pa
)
472 isl_int_set_si(f
, 1);
473 if (accept_cst_factor(s
, &f
) < 0)
474 pa
= isl_pw_aff_free(pa
);
475 pa
= isl_pw_aff_scale_down(pa
, f
);
481 static __isl_give isl_pw_aff
*accept_affine_factor(__isl_keep isl_stream
*s
,
482 __isl_take isl_space
*space
, struct vars
*v
)
484 struct isl_token
*tok
= NULL
;
485 isl_pw_aff
*res
= NULL
;
489 isl_stream_error(s
, NULL
, "unexpected EOF");
493 if (tok
->type
== ISL_TOKEN_AFF
) {
494 res
= isl_pw_aff_copy(tok
->u
.pwaff
);
496 } else if (tok
->type
== ISL_TOKEN_IDENT
) {
498 int pos
= vars_pos(v
, tok
->u
.s
, -1);
504 vars_drop(v
, v
->n
- n
);
505 isl_stream_error(s
, tok
, "unknown identifier");
509 aff
= isl_aff_zero_on_domain(isl_local_space_from_space(isl_space_copy(space
)));
512 isl_int_set_si(aff
->v
->el
[2 + pos
], 1);
513 res
= isl_pw_aff_from_aff(aff
);
515 } else if (tok
->type
== ISL_TOKEN_VALUE
) {
516 if (isl_stream_eat_if_available(s
, '*')) {
517 res
= accept_affine_factor(s
, isl_space_copy(space
), v
);
518 res
= isl_pw_aff_scale(res
, tok
->u
.v
);
522 ls
= isl_local_space_from_space(isl_space_copy(space
));
523 aff
= isl_aff_zero_on_domain(ls
);
524 aff
= isl_aff_add_constant(aff
, tok
->u
.v
);
525 res
= isl_pw_aff_from_aff(aff
);
528 } else if (tok
->type
== '(') {
531 res
= accept_affine(s
, isl_space_copy(space
), v
);
534 if (isl_stream_eat(s
, ')'))
536 } else if (is_start_of_div(tok
)) {
537 isl_stream_push_token(s
, tok
);
539 res
= accept_div(s
, isl_space_copy(space
), v
);
540 } else if (tok
->type
== ISL_TOKEN_MIN
|| tok
->type
== ISL_TOKEN_MAX
) {
541 isl_stream_push_token(s
, tok
);
543 res
= accept_minmax(s
, isl_space_copy(space
), v
);
545 isl_stream_error(s
, tok
, "expecting factor");
548 if (isl_stream_eat_if_available(s
, '%') ||
549 isl_stream_eat_if_available(s
, ISL_TOKEN_MOD
)) {
550 isl_space_free(space
);
551 return affine_mod(s
, v
, res
);
553 if (isl_stream_eat_if_available(s
, '*')) {
556 isl_int_set_si(f
, 1);
557 if (accept_cst_factor(s
, &f
) < 0) {
561 res
= isl_pw_aff_scale(res
, f
);
564 if (isl_stream_eat_if_available(s
, '/'))
565 res
= pw_aff_div_by_cst(s
, res
);
566 if (isl_stream_eat_if_available(s
, ISL_TOKEN_INT_DIV
))
567 res
= isl_pw_aff_floor(pw_aff_div_by_cst(s
, res
));
569 isl_space_free(space
);
574 isl_pw_aff_free(res
);
575 isl_space_free(space
);
579 static __isl_give isl_pw_aff
*add_cst(__isl_take isl_pw_aff
*pwaff
, isl_int v
)
584 space
= isl_pw_aff_get_domain_space(pwaff
);
585 aff
= isl_aff_zero_on_domain(isl_local_space_from_space(space
));
586 aff
= isl_aff_add_constant(aff
, v
);
588 return isl_pw_aff_add(pwaff
, isl_pw_aff_from_aff(aff
));
591 /* Return a piecewise affine expression defined on the specified domain
592 * that represents NaN.
594 static __isl_give isl_pw_aff
*nan_on_domain(__isl_keep isl_space
*space
)
596 return isl_pw_aff_nan_on_domain_space(isl_space_copy(space
));
599 static __isl_give isl_pw_aff
*accept_affine(__isl_keep isl_stream
*s
,
600 __isl_take isl_space
*space
, struct vars
*v
)
602 struct isl_token
*tok
= NULL
;
607 ls
= isl_local_space_from_space(isl_space_copy(space
));
608 res
= isl_pw_aff_from_aff(isl_aff_zero_on_domain(ls
));
615 isl_stream_error(s
, NULL
, "unexpected EOF");
618 if (tok
->type
== '-') {
623 if (tok
->type
== '(' || is_start_of_div(tok
) ||
624 tok
->type
== ISL_TOKEN_MIN
|| tok
->type
== ISL_TOKEN_MAX
||
625 tok
->type
== ISL_TOKEN_IDENT
||
626 tok
->type
== ISL_TOKEN_AFF
) {
628 isl_stream_push_token(s
, tok
);
630 term
= accept_affine_factor(s
,
631 isl_space_copy(space
), v
);
633 res
= isl_pw_aff_sub(res
, term
);
635 res
= isl_pw_aff_add(res
, term
);
639 } else if (tok
->type
== ISL_TOKEN_VALUE
) {
641 isl_int_neg(tok
->u
.v
, tok
->u
.v
);
642 if (isl_stream_eat_if_available(s
, '*') ||
643 isl_stream_next_token_is(s
, ISL_TOKEN_IDENT
)) {
645 term
= accept_affine_factor(s
,
646 isl_space_copy(space
), v
);
647 term
= isl_pw_aff_scale(term
, tok
->u
.v
);
648 res
= isl_pw_aff_add(res
, term
);
652 if (isl_stream_eat_if_available(s
,
653 ISL_TOKEN_INT_DIV
) &&
654 int_div_by_cst(s
, &tok
->u
.v
) < 0)
656 res
= add_cst(res
, tok
->u
.v
);
659 } else if (tok
->type
== ISL_TOKEN_NAN
) {
660 res
= isl_pw_aff_add(res
, nan_on_domain(space
));
662 isl_stream_error(s
, tok
, "unexpected isl_token");
663 isl_stream_push_token(s
, tok
);
664 isl_pw_aff_free(res
);
665 isl_space_free(space
);
671 if (tok
&& tok
->type
== '-') {
674 } else if (tok
&& tok
->type
== '+') {
677 } else if (tok
&& tok
->type
== ISL_TOKEN_VALUE
&&
678 isl_int_is_neg(tok
->u
.v
)) {
679 isl_stream_push_token(s
, tok
);
682 isl_stream_push_token(s
, tok
);
687 isl_space_free(space
);
690 isl_space_free(space
);
692 isl_pw_aff_free(res
);
696 /* Is "type" the type of a comparison operator between lists
697 * of affine expressions?
699 static int is_list_comparator_type(int type
)
702 case ISL_TOKEN_LEX_LT
:
703 case ISL_TOKEN_LEX_GT
:
704 case ISL_TOKEN_LEX_LE
:
705 case ISL_TOKEN_LEX_GE
:
712 static int is_comparator(struct isl_token
*tok
)
716 if (is_list_comparator_type(tok
->type
))
732 static __isl_give isl_map
*read_formula(__isl_keep isl_stream
*s
,
733 struct vars
*v
, __isl_take isl_map
*map
, int rational
);
734 static __isl_give isl_pw_aff
*accept_extended_affine(__isl_keep isl_stream
*s
,
735 __isl_take isl_space
*space
, struct vars
*v
, int rational
);
737 /* Accept a ternary operator, given the first argument.
739 static __isl_give isl_pw_aff
*accept_ternary(__isl_keep isl_stream
*s
,
740 __isl_take isl_map
*cond
, struct vars
*v
, int rational
)
743 isl_pw_aff
*pwaff1
= NULL
, *pwaff2
= NULL
, *pa_cond
;
748 if (isl_stream_eat(s
, '?'))
751 space
= isl_space_wrap(isl_map_get_space(cond
));
752 pwaff1
= accept_extended_affine(s
, space
, v
, rational
);
756 if (isl_stream_eat(s
, ':'))
759 space
= isl_pw_aff_get_domain_space(pwaff1
);
760 pwaff2
= accept_extended_affine(s
, space
, v
, rational
);
764 pa_cond
= isl_set_indicator_function(isl_map_wrap(cond
));
765 return isl_pw_aff_cond(pa_cond
, pwaff1
, pwaff2
);
768 isl_pw_aff_free(pwaff1
);
769 isl_pw_aff_free(pwaff2
);
773 /* Set *line and *col to those of the next token, if any.
775 static void set_current_line_col(__isl_keep isl_stream
*s
, int *line
, int *col
)
777 struct isl_token
*tok
;
779 tok
= isl_stream_next_token(s
);
785 isl_stream_push_token(s
, tok
);
788 /* Push a token encapsulating "pa" onto "s", with the given
791 static isl_stat
push_aff(__isl_keep isl_stream
*s
, int line
, int col
,
792 __isl_take isl_pw_aff
*pa
)
794 struct isl_token
*tok
;
796 tok
= isl_token_new(s
->ctx
, line
, col
, 0);
799 tok
->type
= ISL_TOKEN_AFF
;
801 isl_stream_push_token(s
, tok
);
806 return isl_stat_error
;
809 /* Is the next token a comparison operator?
811 static int next_is_comparator(__isl_keep isl_stream
*s
)
814 struct isl_token
*tok
;
816 tok
= isl_stream_next_token(s
);
820 is_comp
= is_comparator(tok
);
821 isl_stream_push_token(s
, tok
);
826 /* Accept an affine expression that may involve ternary operators.
827 * We first read an affine expression.
828 * If it is not followed by a comparison operator, we simply return it.
829 * Otherwise, we assume the affine expression is part of the first
830 * argument of a ternary operator and try to parse that.
832 static __isl_give isl_pw_aff
*accept_extended_affine(__isl_keep isl_stream
*s
,
833 __isl_take isl_space
*space
, struct vars
*v
, int rational
)
837 int line
= -1, col
= -1;
839 set_current_line_col(s
, &line
, &col
);
841 pwaff
= accept_affine(s
, space
, v
);
843 pwaff
= isl_pw_aff_set_rational(pwaff
);
846 if (!next_is_comparator(s
))
849 space
= isl_pw_aff_get_domain_space(pwaff
);
850 cond
= isl_map_universe(isl_space_unwrap(space
));
852 if (push_aff(s
, line
, col
, pwaff
) < 0)
853 cond
= isl_map_free(cond
);
857 cond
= read_formula(s
, v
, cond
, rational
);
859 return accept_ternary(s
, cond
, v
, rational
);
862 static __isl_give isl_map
*read_var_def(__isl_keep isl_stream
*s
,
863 __isl_take isl_map
*map
, enum isl_dim_type type
, struct vars
*v
,
870 if (type
== isl_dim_param
)
871 pos
= isl_map_dim(map
, isl_dim_param
);
873 pos
= isl_map_dim(map
, isl_dim_in
);
874 if (type
== isl_dim_out
) {
875 isl_size n_out
= isl_map_dim(map
, isl_dim_out
);
876 if (pos
< 0 || n_out
< 0)
877 return isl_map_free(map
);
883 return isl_map_free(map
);
886 def
= accept_extended_affine(s
, isl_space_wrap(isl_map_get_space(map
)),
888 def_map
= isl_map_from_pw_aff(def
);
889 def_map
= isl_map_equate(def_map
, type
, pos
, isl_dim_out
, 0);
890 def_map
= isl_set_unwrap(isl_map_domain(def_map
));
892 map
= isl_map_intersect(map
, def_map
);
897 static __isl_give isl_pw_aff_list
*accept_affine_list(__isl_keep isl_stream
*s
,
898 __isl_take isl_space
*space
, struct vars
*v
)
901 isl_pw_aff_list
*list
;
902 struct isl_token
*tok
= NULL
;
904 pwaff
= accept_affine(s
, isl_space_copy(space
), v
);
905 list
= isl_pw_aff_list_from_pw_aff(pwaff
);
910 tok
= isl_stream_next_token(s
);
912 isl_stream_error(s
, NULL
, "unexpected EOF");
915 if (tok
->type
!= ',') {
916 isl_stream_push_token(s
, tok
);
921 pwaff
= accept_affine(s
, isl_space_copy(space
), v
);
922 list
= isl_pw_aff_list_concat(list
,
923 isl_pw_aff_list_from_pw_aff(pwaff
));
928 isl_space_free(space
);
931 isl_space_free(space
);
932 isl_pw_aff_list_free(list
);
936 static __isl_give isl_map
*read_defined_var_list(__isl_keep isl_stream
*s
,
937 struct vars
*v
, __isl_take isl_map
*map
, int rational
)
939 struct isl_token
*tok
;
941 while ((tok
= isl_stream_next_token(s
)) != NULL
) {
945 if (tok
->type
!= ISL_TOKEN_IDENT
)
948 p
= vars_pos(v
, tok
->u
.s
, -1);
952 isl_stream_error(s
, tok
, "expecting unique identifier");
956 map
= isl_map_add_dims(map
, isl_dim_out
, 1);
959 tok
= isl_stream_next_token(s
);
960 if (tok
&& tok
->type
== '=') {
962 map
= read_var_def(s
, map
, isl_dim_out
, v
, rational
);
963 tok
= isl_stream_next_token(s
);
966 if (!tok
|| tok
->type
!= ',')
972 isl_stream_push_token(s
, tok
);
981 static int next_is_tuple(__isl_keep isl_stream
*s
)
983 struct isl_token
*tok
;
986 tok
= isl_stream_next_token(s
);
989 if (tok
->type
== '[') {
990 isl_stream_push_token(s
, tok
);
993 if (tok
->type
!= ISL_TOKEN_IDENT
&& !tok
->is_keyword
) {
994 isl_stream_push_token(s
, tok
);
998 is_tuple
= isl_stream_next_token_is(s
, '[');
1000 isl_stream_push_token(s
, tok
);
1005 /* Does the next token mark the end of a tuple element?
1007 static int next_is_end_tuple_element(__isl_keep isl_stream
*s
)
1009 return isl_stream_next_token_is(s
, ',') ||
1010 isl_stream_next_token_is(s
, ']');
1013 /* Is the next token one that necessarily forms the start of a condition?
1015 static int next_is_condition_start(__isl_keep isl_stream
*s
)
1017 return isl_stream_next_token_is(s
, ISL_TOKEN_EXISTS
) ||
1018 isl_stream_next_token_is(s
, ISL_TOKEN_NOT
) ||
1019 isl_stream_next_token_is(s
, ISL_TOKEN_TRUE
) ||
1020 isl_stream_next_token_is(s
, ISL_TOKEN_FALSE
) ||
1021 isl_stream_next_token_is(s
, ISL_TOKEN_MAP
);
1024 /* Is "pa" an expression in term of earlier dimensions?
1025 * The alternative is that the dimension is defined to be equal to itself,
1026 * meaning that it has a universe domain and an expression that depends
1027 * on itself. "i" is the position of the expression in a sequence
1028 * of "n" expressions. The final dimensions of "pa" correspond to
1029 * these "n" expressions.
1031 static isl_bool
pw_aff_is_expr(__isl_keep isl_pw_aff
*pa
, int i
, int n
)
1036 return isl_bool_error
;
1038 return isl_bool_true
;
1039 if (!isl_set_plain_is_universe(pa
->p
[0].set
))
1040 return isl_bool_true
;
1043 if (isl_int_is_zero(aff
->v
->el
[aff
->v
->size
- n
+ i
]))
1044 return isl_bool_true
;
1045 return isl_bool_false
;
1048 /* Does the tuple contain any dimensions that are defined
1049 * in terms of earlier dimensions?
1051 static isl_bool
tuple_has_expr(__isl_keep isl_multi_pw_aff
*tuple
)
1055 isl_bool has_expr
= isl_bool_false
;
1058 n
= isl_multi_pw_aff_dim(tuple
, isl_dim_out
);
1060 return isl_bool_error
;
1061 for (i
= 0; i
< n
; ++i
) {
1062 pa
= isl_multi_pw_aff_get_pw_aff(tuple
, i
);
1063 has_expr
= pw_aff_is_expr(pa
, i
, n
);
1064 isl_pw_aff_free(pa
);
1065 if (has_expr
< 0 || has_expr
)
1072 /* Set the name of dimension "pos" in "space" to "name".
1073 * During printing, we add primes if the same name appears more than once
1074 * to distinguish the occurrences. Here, we remove those primes from "name"
1075 * before setting the name of the dimension.
1077 static __isl_give isl_space
*space_set_dim_name(__isl_take isl_space
*space
,
1078 int pos
, char *name
)
1085 prime
= strchr(name
, '\'');
1088 space
= isl_space_set_dim_name(space
, isl_dim_out
, pos
, name
);
1095 /* Construct an isl_pw_aff defined on a "space" (with v->n variables)
1096 * that is equal to the last of those variables.
1098 static __isl_give isl_pw_aff
*identity_tuple_el_on_space(
1099 __isl_take isl_space
*space
, struct vars
*v
)
1103 aff
= isl_aff_zero_on_domain(isl_local_space_from_space(space
));
1104 aff
= isl_aff_add_coefficient_si(aff
, isl_dim_in
, v
->n
- 1, 1);
1105 return isl_pw_aff_from_aff(aff
);
1108 /* Construct an isl_pw_aff defined on the domain space of "pa"
1109 * that is equal to the last variable in "v".
1111 * That is, if D is the domain space of "pa", then construct
1115 static __isl_give isl_pw_aff
*init_range(__isl_keep isl_pw_aff
*pa
,
1120 space
= isl_pw_aff_get_domain_space(pa
);
1121 return identity_tuple_el_on_space(space
, v
);
1124 /* Impose the lower bound "lower" on the variable represented by "range_pa".
1126 * In particular, "range_pa" is of the form
1128 * D[..., i] -> i : C
1130 * with D also the domains space of "lower' and "C" some constraints.
1132 * Return the expression
1134 * D[..., i] -> i : C and i >= lower
1136 static __isl_give isl_pw_aff
*set_lower(__isl_take isl_pw_aff
*range_pa
,
1137 __isl_take isl_pw_aff
*lower
)
1141 range
= isl_pw_aff_ge_set(isl_pw_aff_copy(range_pa
), lower
);
1142 return isl_pw_aff_intersect_domain(range_pa
, range
);
1145 /* Impose the upper bound "upper" on the variable represented by "range_pa".
1147 * In particular, "range_pa" is of the form
1149 * D[..., i] -> i : C
1151 * with D also the domains space of "upper' and "C" some constraints.
1153 * Return the expression
1155 * D[..., i] -> i : C and i <= upper
1157 static __isl_give isl_pw_aff
*set_upper(__isl_take isl_pw_aff
*range_pa
,
1158 __isl_take isl_pw_aff
*upper
)
1162 range
= isl_pw_aff_le_set(isl_pw_aff_copy(range_pa
), upper
);
1163 return isl_pw_aff_intersect_domain(range_pa
, range
);
1166 /* Construct a piecewise affine expression corresponding
1167 * to the last variable in "v" that is greater than or equal to "pa".
1169 * In particular, if D is the domain space of "pa",
1170 * then construct the expression
1174 * impose lower bound "pa" and return
1176 * D[..., i] -> i : i >= pa
1178 static __isl_give isl_pw_aff
*construct_lower(__isl_take isl_pw_aff
*pa
,
1181 return set_lower(init_range(pa
, v
), pa
);
1184 /* Construct a piecewise affine expression corresponding
1185 * to the last variable in "v" that is smaller than or equal to "pa".
1187 * In particular, if D is the domain space of "pa",
1188 * then construct the expression
1192 * impose lower bound "pa" and return
1194 * D[..., i] -> i : i <= pa
1196 static __isl_give isl_pw_aff
*construct_upper(__isl_take isl_pw_aff
*pa
,
1199 return set_upper(init_range(pa
, v
), pa
);
1202 /* Construct a piecewise affine expression corresponding
1203 * to the last variable in "v" that ranges between "pa" and "pa2".
1205 * In particular, if D is the domain space of "pa" (and "pa2"),
1206 * then construct the expression
1210 * impose lower bound "pa" and upper bound "pa2" and return
1212 * D[..., i] -> i : pa <= i <= pa2
1214 static __isl_give isl_pw_aff
*construct_range(__isl_take isl_pw_aff
*pa
,
1215 __isl_take isl_pw_aff
*pa2
, struct vars
*v
)
1217 return set_upper(set_lower(init_range(pa
, v
), pa
), pa2
);
1220 static int resolve_paren_expr(__isl_keep isl_stream
*s
,
1221 struct vars
*v
, __isl_take isl_map
*map
, int rational
);
1223 /* Given that the (piecewise) affine expression "pa"
1224 * has just been parsed, followed by a colon,
1225 * continue parsing as part of a piecewise affine expression.
1227 * In particular, check if the colon is followed by a condition.
1228 * If so, parse the conditions(a) on "pa" and include them in the domain.
1229 * Otherwise, if the colon is followed by another (piecewise) affine expression
1230 * then consider the two expressions as endpoints of a range of values and
1231 * return a piecewise affine expression that takes values in that range.
1232 * Note that an affine expression followed by a comparison operator
1233 * is considered to be part of a condition.
1234 * If the colon is not followed by anything (inside the tuple element),
1235 * then consider "pa" as a lower bound on a range of values without upper bound
1236 * and return a piecewise affine expression that takes values in that range.
1238 static __isl_give isl_pw_aff
*update_piecewise_affine_colon(
1239 __isl_take isl_pw_aff
*pa
, __isl_keep isl_stream
*s
,
1240 struct vars
*v
, int rational
)
1242 isl_space
*dom_space
;
1245 dom_space
= isl_pw_aff_get_domain_space(pa
);
1246 map
= isl_map_universe(isl_space_from_domain(dom_space
));
1248 if (isl_stream_next_token_is(s
, '('))
1249 if (resolve_paren_expr(s
, v
, isl_map_copy(map
), rational
))
1251 if (next_is_end_tuple_element(s
)) {
1253 return construct_lower(pa
, v
);
1255 if (!next_is_condition_start(s
)) {
1256 int line
= -1, col
= -1;
1260 set_current_line_col(s
, &line
, &col
);
1261 space
= isl_space_wrap(isl_map_get_space(map
));
1262 pa2
= accept_affine(s
, space
, v
);
1264 pa2
= isl_pw_aff_set_rational(pa2
);
1265 if (!next_is_comparator(s
)) {
1267 pa2
= isl_pw_aff_domain_factor_domain(pa2
);
1268 return construct_range(pa
, pa2
, v
);
1270 if (push_aff(s
, line
, col
, pa2
) < 0)
1274 map
= read_formula(s
, v
, map
, rational
);
1275 pa
= isl_pw_aff_intersect_domain(pa
, isl_map_domain(map
));
1280 isl_pw_aff_free(pa
);
1284 /* Accept a piecewise affine expression.
1286 * At the outer level, the piecewise affine expression may be of the form
1288 * aff1 : condition1; aff2 : conditions2; ...
1301 * each of the affine expressions may in turn include ternary operators.
1303 * If the first token is a colon, then the expression must be
1304 * ":" or ": aff2", depending on whether anything follows the colon
1305 * inside the tuple element.
1306 * The first is considered to represent an arbitrary value.
1307 * The second is considered to represent a range of values
1308 * with the given upper bound and no lower bound.
1310 * There may be parentheses around some subexpression of "aff1"
1311 * around "aff1" itself, around "aff1 : condition1" and/or
1312 * around the entire piecewise affine expression.
1313 * We therefore remove the opening parenthesis (if any) from the stream
1314 * in case the closing parenthesis follows the colon, but if the closing
1315 * parenthesis is the first thing in the stream after the parsed affine
1316 * expression, we push the parsed expression onto the stream and parse
1317 * again in case the parentheses enclose some subexpression of "aff1".
1319 static __isl_give isl_pw_aff
*accept_piecewise_affine(__isl_keep isl_stream
*s
,
1320 __isl_take isl_space
*space
, struct vars
*v
, int rational
)
1323 isl_space
*res_space
;
1325 if (isl_stream_eat_if_available(s
, ':')) {
1326 if (next_is_end_tuple_element(s
))
1327 return identity_tuple_el_on_space(space
, v
);
1329 return construct_upper(accept_affine(s
, space
, v
), v
);
1332 res_space
= isl_space_from_domain(isl_space_copy(space
));
1333 res_space
= isl_space_add_dims(res_space
, isl_dim_out
, 1);
1334 res
= isl_pw_aff_empty(res_space
);
1338 int line
= -1, col
= -1;
1340 set_current_line_col(s
, &line
, &col
);
1341 seen_paren
= isl_stream_eat_if_available(s
, '(');
1343 pa
= accept_piecewise_affine(s
, isl_space_copy(space
),
1346 pa
= accept_extended_affine(s
, isl_space_copy(space
),
1348 if (seen_paren
&& isl_stream_eat_if_available(s
, ')')) {
1350 if (push_aff(s
, line
, col
, pa
) < 0)
1352 pa
= accept_extended_affine(s
, isl_space_copy(space
),
1355 if (isl_stream_eat_if_available(s
, ':'))
1356 pa
= update_piecewise_affine_colon(pa
, s
, v
, rational
);
1358 res
= isl_pw_aff_union_add(res
, pa
);
1360 if (seen_paren
&& isl_stream_eat(s
, ')'))
1362 } while (isl_stream_eat_if_available(s
, ';'));
1364 isl_space_free(space
);
1368 isl_space_free(space
);
1369 return isl_pw_aff_free(res
);
1372 /* Read an affine expression from "s" for use in read_tuple.
1374 * accept_extended_affine requires a wrapped space as input.
1375 * read_tuple on the other hand expects each isl_pw_aff
1376 * to have an anonymous space. We therefore adjust the space
1377 * of the isl_pw_aff before returning it.
1379 static __isl_give isl_pw_aff
*read_tuple_var_def(__isl_keep isl_stream
*s
,
1380 struct vars
*v
, int rational
)
1385 space
= isl_space_wrap(isl_space_alloc(s
->ctx
, 0, v
->n
, 0));
1387 def
= accept_piecewise_affine(s
, space
, v
, rational
);
1388 def
= isl_pw_aff_domain_factor_domain(def
);
1393 /* Read a list of tuple elements by calling "read_el" on each of them and
1394 * return a space with the same number of set dimensions derived from
1395 * the parameter space "space" and possibly updated by "read_el".
1396 * The elements in the list are separated by either "," or "][".
1397 * If "comma" is set then only "," is allowed.
1399 static __isl_give isl_space
*read_tuple_list(__isl_keep isl_stream
*s
,
1400 struct vars
*v
, __isl_take isl_space
*space
, int rational
, int comma
,
1401 __isl_give isl_space
*(*read_el
)(__isl_keep isl_stream
*s
,
1402 struct vars
*v
, __isl_take isl_space
*space
, int rational
,
1409 space
= isl_space_set_from_params(space
);
1411 if (isl_stream_next_token_is(s
, ']'))
1415 struct isl_token
*tok
;
1417 space
= isl_space_add_dims(space
, isl_dim_set
, 1);
1419 space
= read_el(s
, v
, space
, rational
, user
);
1423 tok
= isl_stream_next_token(s
);
1424 if (!comma
&& tok
&& tok
->type
== ']' &&
1425 isl_stream_next_token_is(s
, '[')) {
1426 isl_token_free(tok
);
1427 tok
= isl_stream_next_token(s
);
1428 } else if (!tok
|| tok
->type
!= ',') {
1430 isl_stream_push_token(s
, tok
);
1434 isl_token_free(tok
);
1440 /* Read a tuple space from "s" derived from the parameter space "space".
1441 * Call "read_el" on each element in the tuples.
1443 static __isl_give isl_space
*read_tuple_space(__isl_keep isl_stream
*s
,
1444 struct vars
*v
, __isl_take isl_space
*space
, int rational
, int comma
,
1445 __isl_give isl_space
*(*read_el
)(__isl_keep isl_stream
*s
,
1446 struct vars
*v
, __isl_take isl_space
*space
, int rational
,
1450 struct isl_token
*tok
;
1452 isl_space
*res
= NULL
;
1454 tok
= isl_stream_next_token(s
);
1457 if (tok
->type
== ISL_TOKEN_IDENT
|| tok
->is_keyword
) {
1458 name
= strdup(tok
->u
.s
);
1459 isl_token_free(tok
);
1463 isl_stream_push_token(s
, tok
);
1464 if (isl_stream_eat(s
, '['))
1466 if (next_is_tuple(s
)) {
1468 res
= read_tuple_space(s
, v
, isl_space_copy(space
),
1469 rational
, comma
, read_el
, user
);
1470 if (isl_stream_eat(s
, ISL_TOKEN_TO
))
1472 out
= read_tuple_space(s
, v
, isl_space_copy(space
),
1473 rational
, comma
, read_el
, user
);
1474 res
= isl_space_product(res
, out
);
1476 res
= read_tuple_list(s
, v
, isl_space_copy(space
),
1477 rational
, comma
, read_el
, user
);
1478 if (isl_stream_eat(s
, ']'))
1482 res
= isl_space_set_tuple_name(res
, isl_dim_set
, name
);
1486 isl_space_free(space
);
1490 isl_space_free(res
);
1491 isl_space_free(space
);
1495 /* Construct an isl_pw_aff defined on a space with v->n variables
1496 * that is equal to the last of those variables.
1498 static __isl_give isl_pw_aff
*identity_tuple_el(struct vars
*v
)
1502 space
= isl_space_set_alloc(v
->ctx
, 0, v
->n
);
1503 return identity_tuple_el_on_space(space
, v
);
1506 /* This function is called for each element in a tuple inside read_tuple.
1507 * Add a new variable to "v" and construct a corresponding isl_pw_aff defined
1508 * over a space containing all variables in "v" defined so far.
1509 * The isl_pw_aff expresses the new variable in terms of earlier variables
1510 * if a definition is provided. Otherwise, it is represented as being
1512 * Add the isl_pw_aff to *list.
1513 * If the new variable was named, then adjust "space" accordingly and
1514 * return the updated space.
1516 static __isl_give isl_space
*read_tuple_pw_aff_el(__isl_keep isl_stream
*s
,
1517 struct vars
*v
, __isl_take isl_space
*space
, int rational
, void *user
)
1519 isl_pw_aff_list
**list
= (isl_pw_aff_list
**) user
;
1521 struct isl_token
*tok
;
1524 tok
= next_token(s
);
1526 isl_stream_error(s
, NULL
, "unexpected EOF");
1527 return isl_space_free(space
);
1530 if (tok
->type
== ISL_TOKEN_IDENT
) {
1532 int p
= vars_pos(v
, tok
->u
.s
, -1);
1538 if (tok
->type
== '*') {
1539 if (vars_add_anon(v
) < 0)
1541 isl_token_free(tok
);
1542 pa
= identity_tuple_el(v
);
1543 } else if (new_name
) {
1544 isl_size pos
= isl_space_dim(space
, isl_dim_out
);
1548 space
= space_set_dim_name(space
, pos
, v
->v
->name
);
1549 isl_token_free(tok
);
1550 if (isl_stream_eat_if_available(s
, '='))
1551 pa
= read_tuple_var_def(s
, v
, rational
);
1553 pa
= identity_tuple_el(v
);
1555 isl_stream_push_token(s
, tok
);
1557 if (vars_add_anon(v
) < 0)
1559 pa
= read_tuple_var_def(s
, v
, rational
);
1562 *list
= isl_pw_aff_list_add(*list
, pa
);
1564 return isl_space_free(space
);
1568 isl_token_free(tok
);
1569 return isl_space_free(space
);
1572 /* Read a tuple and represent it as an isl_multi_pw_aff.
1573 * The range space of the isl_multi_pw_aff is the space of the tuple.
1574 * The domain space is an anonymous space
1575 * with a dimension for each variable in the set of variables in "v",
1576 * including the variables in the range.
1577 * If a given dimension is not defined in terms of earlier dimensions in
1578 * the input, then the corresponding isl_pw_aff is set equal to one time
1579 * the variable corresponding to the dimension being defined.
1581 * The elements in the tuple are collected in a list by read_tuple_pw_aff_el.
1582 * Each element in this list is defined over a space representing
1583 * the variables defined so far. We need to adjust the earlier
1584 * elements to have as many variables in the domain as the final
1585 * element in the list.
1587 static __isl_give isl_multi_pw_aff
*read_tuple(__isl_keep isl_stream
*s
,
1588 struct vars
*v
, int rational
, int comma
)
1593 isl_pw_aff_list
*list
;
1595 space
= isl_space_params_alloc(v
->ctx
, 0);
1596 list
= isl_pw_aff_list_alloc(s
->ctx
, 0);
1597 space
= read_tuple_space(s
, v
, space
, rational
, comma
,
1598 &read_tuple_pw_aff_el
, &list
);
1599 n
= isl_space_dim(space
, isl_dim_set
);
1601 space
= isl_space_free(space
);
1602 for (i
= 0; i
+ 1 < n
; ++i
) {
1605 pa
= isl_pw_aff_list_get_pw_aff(list
, i
);
1606 pa
= isl_pw_aff_add_dims(pa
, isl_dim_in
, n
- (i
+ 1));
1607 list
= isl_pw_aff_list_set_pw_aff(list
, i
, pa
);
1610 space
= isl_space_from_range(space
);
1611 space
= isl_space_add_dims(space
, isl_dim_in
, v
->n
);
1612 return isl_multi_pw_aff_from_pw_aff_list(space
, list
);
1615 /* Add the tuple represented by the isl_multi_pw_aff "tuple" to "map".
1616 * We first create the appropriate space in "map" based on the range
1617 * space of this isl_multi_pw_aff. Then, we add equalities based
1618 * on the affine expressions. These live in an anonymous space,
1619 * however, so we first need to reset the space to that of "map".
1621 static __isl_give isl_map
*map_from_tuple(__isl_take isl_multi_pw_aff
*tuple
,
1622 __isl_take isl_map
*map
, enum isl_dim_type type
, struct vars
*v
,
1628 isl_space
*space
= NULL
;
1630 n
= isl_multi_pw_aff_dim(tuple
, isl_dim_out
);
1633 ctx
= isl_multi_pw_aff_get_ctx(tuple
);
1634 space
= isl_space_range(isl_multi_pw_aff_get_space(tuple
));
1638 if (type
== isl_dim_param
) {
1639 if (isl_space_has_tuple_name(space
, isl_dim_set
) ||
1640 isl_space_is_wrapping(space
)) {
1641 isl_die(ctx
, isl_error_invalid
,
1642 "parameter tuples cannot be named or nested",
1645 map
= isl_map_add_dims(map
, type
, n
);
1646 for (i
= 0; i
< n
; ++i
) {
1648 if (!isl_space_has_dim_name(space
, isl_dim_set
, i
))
1649 isl_die(ctx
, isl_error_invalid
,
1650 "parameters must be named",
1652 id
= isl_space_get_dim_id(space
, isl_dim_set
, i
);
1653 map
= isl_map_set_dim_id(map
, isl_dim_param
, i
, id
);
1655 } else if (type
== isl_dim_in
) {
1658 set
= isl_set_universe(isl_space_copy(space
));
1660 set
= isl_set_set_rational(set
);
1661 set
= isl_set_intersect_params(set
, isl_map_params(map
));
1662 map
= isl_map_from_domain(set
);
1666 set
= isl_set_universe(isl_space_copy(space
));
1668 set
= isl_set_set_rational(set
);
1669 map
= isl_map_from_domain_and_range(isl_map_domain(map
), set
);
1672 for (i
= 0; i
< n
; ++i
) {
1679 pa
= isl_multi_pw_aff_get_pw_aff(tuple
, i
);
1680 space
= isl_pw_aff_get_domain_space(pa
);
1681 aff
= isl_aff_zero_on_domain(isl_local_space_from_space(space
));
1682 aff
= isl_aff_add_coefficient_si(aff
,
1683 isl_dim_in
, v
->n
- n
+ i
, -1);
1684 pa
= isl_pw_aff_add(pa
, isl_pw_aff_from_aff(aff
));
1686 pa
= isl_pw_aff_set_rational(pa
);
1687 set
= isl_pw_aff_zero_set(pa
);
1688 map_i
= isl_map_from_range(set
);
1689 map_i
= isl_map_reset_space(map_i
, isl_map_get_space(map
));
1690 map
= isl_map_intersect(map
, map_i
);
1693 isl_space_free(space
);
1694 isl_multi_pw_aff_free(tuple
);
1697 isl_space_free(space
);
1698 isl_multi_pw_aff_free(tuple
);
1703 /* Read a tuple from "s" and add it to "map".
1704 * The tuple is initially represented as an isl_multi_pw_aff and
1705 * then added to "map".
1707 static __isl_give isl_map
*read_map_tuple(__isl_keep isl_stream
*s
,
1708 __isl_take isl_map
*map
, enum isl_dim_type type
, struct vars
*v
,
1709 int rational
, int comma
)
1711 isl_multi_pw_aff
*tuple
;
1713 tuple
= read_tuple(s
, v
, rational
, comma
);
1715 return isl_map_free(map
);
1717 return map_from_tuple(tuple
, map
, type
, v
, rational
);
1720 /* Given two equal-length lists of piecewise affine expression with the space
1721 * of "set" as domain, construct a set in the same space that expresses
1722 * that "left" and "right" satisfy the comparison "type".
1724 * A space is constructed of the same dimension as the number of elements
1725 * in the two lists. The comparison is then expressed in a map from
1726 * this space to itself and wrapped into a set. Finally the two lists
1727 * of piecewise affine expressions are plugged into this set.
1729 * Let S be the space of "set" and T the constructed space.
1730 * The lists are first changed into two isl_multi_pw_affs in S -> T and
1731 * then combined into an isl_multi_pw_aff in S -> [T -> T],
1732 * while the comparison is first expressed in T -> T, then [T -> T]
1735 static __isl_give isl_set
*list_cmp(__isl_keep isl_set
*set
, int type
,
1736 __isl_take isl_pw_aff_list
*left
, __isl_take isl_pw_aff_list
*right
)
1740 isl_multi_pw_aff
*mpa1
, *mpa2
;
1742 n
= isl_pw_aff_list_n_pw_aff(left
);
1743 if (!set
|| n
< 0 || !right
)
1746 space
= isl_set_get_space(set
);
1747 space
= isl_space_from_domain(space
);
1748 space
= isl_space_add_dims(space
, isl_dim_out
, n
);
1749 mpa1
= isl_multi_pw_aff_from_pw_aff_list(isl_space_copy(space
), left
);
1750 mpa2
= isl_multi_pw_aff_from_pw_aff_list(isl_space_copy(space
), right
);
1751 mpa1
= isl_multi_pw_aff_range_product(mpa1
, mpa2
);
1753 space
= isl_space_range(space
);
1755 case ISL_TOKEN_LEX_LT
:
1756 set
= isl_map_wrap(isl_map_lex_lt(space
));
1758 case ISL_TOKEN_LEX_GT
:
1759 set
= isl_map_wrap(isl_map_lex_gt(space
));
1761 case ISL_TOKEN_LEX_LE
:
1762 set
= isl_map_wrap(isl_map_lex_le(space
));
1764 case ISL_TOKEN_LEX_GE
:
1765 set
= isl_map_wrap(isl_map_lex_ge(space
));
1768 isl_multi_pw_aff_free(mpa1
);
1769 isl_space_free(space
);
1770 isl_die(isl_set_get_ctx(set
), isl_error_internal
,
1771 "unhandled list comparison type", return NULL
);
1773 set
= isl_set_preimage_multi_pw_aff(set
, mpa1
);
1776 isl_pw_aff_list_free(left
);
1777 isl_pw_aff_list_free(right
);
1781 /* Construct constraints of the form
1785 * where a is an element in "left", op is an operator of type "type" and
1786 * b is an element in "right", add the constraints to "set" and return
1788 * "rational" is set if the constraints should be treated as
1789 * a rational constraints.
1791 * If "type" is the type of a comparison operator between lists
1792 * of affine expressions, then a single (compound) constraint
1793 * is constructed by list_cmp instead.
1795 static __isl_give isl_set
*construct_constraints(
1796 __isl_take isl_set
*set
, int type
,
1797 __isl_keep isl_pw_aff_list
*left
, __isl_keep isl_pw_aff_list
*right
,
1802 left
= isl_pw_aff_list_copy(left
);
1803 right
= isl_pw_aff_list_copy(right
);
1805 left
= isl_pw_aff_list_set_rational(left
);
1806 right
= isl_pw_aff_list_set_rational(right
);
1808 if (is_list_comparator_type(type
))
1809 cond
= list_cmp(set
, type
, left
, right
);
1810 else if (type
== ISL_TOKEN_LE
)
1811 cond
= isl_pw_aff_list_le_set(left
, right
);
1812 else if (type
== ISL_TOKEN_GE
)
1813 cond
= isl_pw_aff_list_ge_set(left
, right
);
1814 else if (type
== ISL_TOKEN_LT
)
1815 cond
= isl_pw_aff_list_lt_set(left
, right
);
1816 else if (type
== ISL_TOKEN_GT
)
1817 cond
= isl_pw_aff_list_gt_set(left
, right
);
1818 else if (type
== ISL_TOKEN_NE
)
1819 cond
= isl_pw_aff_list_ne_set(left
, right
);
1821 cond
= isl_pw_aff_list_eq_set(left
, right
);
1823 return isl_set_intersect(set
, cond
);
1826 /* Read a constraint from "s", add it to "map" and return the result.
1827 * "v" contains a description of the identifiers parsed so far.
1828 * "rational" is set if the constraint should be treated as
1829 * a rational constraint.
1830 * The constraint read from "s" may be applied to multiple pairs
1831 * of affine expressions and may be chained.
1832 * In particular, a list of affine expressions is read, followed
1833 * by a comparison operator and another list of affine expressions.
1834 * The comparison operator is then applied to each pair of elements
1835 * in the two lists and the results are added to "map".
1836 * However, if the operator expects two lists of affine expressions,
1837 * then it is applied directly to those lists and the two lists
1838 * are required to have the same length.
1839 * If the next token is another comparison operator, then another
1840 * list of affine expressions is read and the process repeats.
1842 * The processing is performed on a wrapped copy of "map" because
1843 * an affine expression cannot have a binary relation as domain.
1845 static __isl_give isl_map
*add_constraint(__isl_keep isl_stream
*s
,
1846 struct vars
*v
, __isl_take isl_map
*map
, int rational
)
1848 struct isl_token
*tok
;
1850 isl_pw_aff_list
*list1
= NULL
, *list2
= NULL
;
1854 set
= isl_map_wrap(map
);
1855 list1
= accept_affine_list(s
, isl_set_get_space(set
), v
);
1858 tok
= isl_stream_next_token(s
);
1859 if (!is_comparator(tok
)) {
1860 isl_stream_error(s
, tok
, "missing operator");
1862 isl_stream_push_token(s
, tok
);
1866 isl_token_free(tok
);
1868 list2
= accept_affine_list(s
, isl_set_get_space(set
), v
);
1869 n1
= isl_pw_aff_list_n_pw_aff(list1
);
1870 n2
= isl_pw_aff_list_n_pw_aff(list2
);
1871 if (n1
< 0 || n2
< 0)
1873 if (is_list_comparator_type(type
) && n1
!= n2
) {
1874 isl_stream_error(s
, NULL
,
1875 "list arguments not of same size");
1879 set
= construct_constraints(set
, type
, list1
, list2
, rational
);
1880 isl_pw_aff_list_free(list1
);
1883 if (!next_is_comparator(s
))
1885 tok
= isl_stream_next_token(s
);
1887 isl_token_free(tok
);
1889 isl_pw_aff_list_free(list1
);
1891 return isl_set_unwrap(set
);
1893 isl_pw_aff_list_free(list1
);
1894 isl_pw_aff_list_free(list2
);
1899 static __isl_give isl_map
*read_exists(__isl_keep isl_stream
*s
,
1900 struct vars
*v
, __isl_take isl_map
*map
, int rational
)
1903 int seen_paren
= isl_stream_eat_if_available(s
, '(');
1905 map
= isl_map_from_domain(isl_map_wrap(map
));
1906 map
= read_defined_var_list(s
, v
, map
, rational
);
1908 if (isl_stream_eat(s
, ':'))
1911 map
= read_formula(s
, v
, map
, rational
);
1912 map
= isl_set_unwrap(isl_map_domain(map
));
1914 vars_drop(v
, v
->n
- n
);
1915 if (seen_paren
&& isl_stream_eat(s
, ')'))
1924 /* Parse an expression between parentheses and push the result
1925 * back on the stream.
1927 * The parsed expression may be either an affine expression
1928 * or a condition. The first type is pushed onto the stream
1929 * as an isl_pw_aff, while the second is pushed as an isl_map.
1931 * If the initial token indicates the start of a condition,
1932 * we parse it as such.
1933 * Otherwise, we first parse an affine expression and push
1934 * that onto the stream. If the affine expression covers the
1935 * entire expression between parentheses, we return.
1936 * Otherwise, we assume that the affine expression is the
1937 * start of a condition and continue parsing.
1939 static int resolve_paren_expr(__isl_keep isl_stream
*s
,
1940 struct vars
*v
, __isl_take isl_map
*map
, int rational
)
1942 struct isl_token
*tok
, *tok2
;
1947 tok
= isl_stream_next_token(s
);
1948 if (!tok
|| tok
->type
!= '(')
1951 if (isl_stream_next_token_is(s
, '('))
1952 if (resolve_paren_expr(s
, v
, isl_map_copy(map
), rational
))
1955 if (next_is_condition_start(s
)) {
1956 map
= read_formula(s
, v
, map
, rational
);
1957 if (isl_stream_eat(s
, ')'))
1959 tok
->type
= ISL_TOKEN_MAP
;
1961 isl_stream_push_token(s
, tok
);
1965 tok2
= isl_stream_next_token(s
);
1970 isl_stream_push_token(s
, tok2
);
1972 pwaff
= accept_affine(s
, isl_space_wrap(isl_map_get_space(map
)), v
);
1976 has_paren
= isl_stream_eat_if_available(s
, ')');
1978 if (push_aff(s
, line
, col
, pwaff
) < 0)
1982 isl_token_free(tok
);
1987 map
= read_formula(s
, v
, map
, rational
);
1988 if (isl_stream_eat(s
, ')'))
1991 tok
->type
= ISL_TOKEN_MAP
;
1993 isl_stream_push_token(s
, tok
);
1997 isl_token_free(tok
);
2002 static __isl_give isl_map
*read_conjunct(__isl_keep isl_stream
*s
,
2003 struct vars
*v
, __isl_take isl_map
*map
, int rational
)
2005 if (isl_stream_next_token_is(s
, '('))
2006 if (resolve_paren_expr(s
, v
, isl_map_copy(map
), rational
))
2009 if (isl_stream_next_token_is(s
, ISL_TOKEN_MAP
)) {
2010 struct isl_token
*tok
;
2011 tok
= isl_stream_next_token(s
);
2015 map
= isl_map_copy(tok
->u
.map
);
2016 isl_token_free(tok
);
2020 if (isl_stream_eat_if_available(s
, ISL_TOKEN_EXISTS
))
2021 return read_exists(s
, v
, map
, rational
);
2023 if (isl_stream_eat_if_available(s
, ISL_TOKEN_TRUE
))
2026 if (isl_stream_eat_if_available(s
, ISL_TOKEN_FALSE
)) {
2027 isl_space
*space
= isl_map_get_space(map
);
2029 return isl_map_empty(space
);
2032 return add_constraint(s
, v
, map
, rational
);
2038 static __isl_give isl_map
*read_conjuncts(__isl_keep isl_stream
*s
,
2039 struct vars
*v
, __isl_take isl_map
*map
, int rational
)
2044 negate
= isl_stream_eat_if_available(s
, ISL_TOKEN_NOT
);
2045 res
= read_conjunct(s
, v
, isl_map_copy(map
), rational
);
2047 res
= isl_map_subtract(isl_map_copy(map
), res
);
2049 while (res
&& isl_stream_eat_if_available(s
, ISL_TOKEN_AND
)) {
2052 negate
= isl_stream_eat_if_available(s
, ISL_TOKEN_NOT
);
2053 res_i
= read_conjunct(s
, v
, isl_map_copy(map
), rational
);
2055 res
= isl_map_subtract(res
, res_i
);
2057 res
= isl_map_intersect(res
, res_i
);
2064 static __isl_give isl_map
*read_disjuncts(__isl_keep isl_stream
*s
,
2065 struct vars
*v
, __isl_take isl_map
*map
, int rational
)
2069 if (isl_stream_next_token_is(s
, '}'))
2072 res
= read_conjuncts(s
, v
, isl_map_copy(map
), rational
);
2073 while (isl_stream_eat_if_available(s
, ISL_TOKEN_OR
)) {
2076 res_i
= read_conjuncts(s
, v
, isl_map_copy(map
), rational
);
2077 res
= isl_map_union(res
, res_i
);
2084 /* Read a first order formula from "s", add the corresponding
2085 * constraints to "map" and return the result.
2087 * In particular, read a formula of the form
2095 * where a and b are disjunctions.
2097 * In the first case, map is replaced by
2099 * map \cap { [..] : a }
2101 * In the second case, it is replaced by
2103 * (map \setminus { [..] : a}) \cup (map \cap { [..] : b })
2105 static __isl_give isl_map
*read_formula(__isl_keep isl_stream
*s
,
2106 struct vars
*v
, __isl_take isl_map
*map
, int rational
)
2110 res
= read_disjuncts(s
, v
, isl_map_copy(map
), rational
);
2112 if (isl_stream_eat_if_available(s
, ISL_TOKEN_IMPLIES
)) {
2115 res
= isl_map_subtract(isl_map_copy(map
), res
);
2116 res2
= read_disjuncts(s
, v
, map
, rational
);
2117 res
= isl_map_union(res
, res2
);
2124 static isl_size
polylib_pos_to_isl_pos(__isl_keep isl_basic_map
*bmap
, int pos
)
2126 isl_size n_out
, n_in
, n_param
, n_div
;
2128 n_param
= isl_basic_map_dim(bmap
, isl_dim_param
);
2129 n_in
= isl_basic_map_dim(bmap
, isl_dim_in
);
2130 n_out
= isl_basic_map_dim(bmap
, isl_dim_out
);
2131 n_div
= isl_basic_map_dim(bmap
, isl_dim_div
);
2132 if (n_param
< 0 || n_in
< 0 || n_out
< 0 || n_div
< 0)
2133 return isl_size_error
;
2136 return 1 + n_param
+ n_in
+ pos
;
2140 return 1 + n_param
+ pos
;
2144 return 1 + n_param
+ n_in
+ n_out
+ pos
;
2153 static __isl_give isl_basic_map
*basic_map_read_polylib_constraint(
2154 __isl_keep isl_stream
*s
, __isl_take isl_basic_map
*bmap
)
2157 struct isl_token
*tok
;
2166 tok
= isl_stream_next_token(s
);
2167 if (!tok
|| tok
->type
!= ISL_TOKEN_VALUE
) {
2168 isl_stream_error(s
, tok
, "expecting coefficient");
2170 isl_stream_push_token(s
, tok
);
2173 if (!tok
->on_new_line
) {
2174 isl_stream_error(s
, tok
, "coefficient should appear on new line");
2175 isl_stream_push_token(s
, tok
);
2179 type
= isl_int_get_si(tok
->u
.v
);
2180 isl_token_free(tok
);
2182 isl_assert(s
->ctx
, type
== 0 || type
== 1, goto error
);
2184 k
= isl_basic_map_alloc_equality(bmap
);
2187 k
= isl_basic_map_alloc_inequality(bmap
);
2193 total
= isl_basic_map_dim(bmap
, isl_dim_all
);
2195 return isl_basic_map_free(bmap
);
2196 for (j
= 0; j
< 1 + total
; ++j
) {
2198 tok
= isl_stream_next_token(s
);
2199 if (!tok
|| tok
->type
!= ISL_TOKEN_VALUE
) {
2200 isl_stream_error(s
, tok
, "expecting coefficient");
2202 isl_stream_push_token(s
, tok
);
2205 if (tok
->on_new_line
) {
2206 isl_stream_error(s
, tok
,
2207 "coefficient should not appear on new line");
2208 isl_stream_push_token(s
, tok
);
2211 pos
= polylib_pos_to_isl_pos(bmap
, j
);
2213 isl_int_set(c
[pos
], tok
->u
.v
);
2214 isl_token_free(tok
);
2216 return isl_basic_map_free(bmap
);
2221 isl_basic_map_free(bmap
);
2225 static __isl_give isl_basic_map
*basic_map_read_polylib(
2226 __isl_keep isl_stream
*s
)
2229 struct isl_token
*tok
;
2230 struct isl_token
*tok2
;
2233 unsigned in
= 0, out
, local
= 0;
2234 struct isl_basic_map
*bmap
= NULL
;
2237 tok
= isl_stream_next_token(s
);
2239 isl_stream_error(s
, NULL
, "unexpected EOF");
2242 tok2
= isl_stream_next_token(s
);
2244 isl_token_free(tok
);
2245 isl_stream_error(s
, NULL
, "unexpected EOF");
2248 if (tok
->type
!= ISL_TOKEN_VALUE
|| tok2
->type
!= ISL_TOKEN_VALUE
) {
2249 isl_stream_push_token(s
, tok2
);
2250 isl_stream_push_token(s
, tok
);
2251 isl_stream_error(s
, NULL
,
2252 "expecting constraint matrix dimensions");
2255 n_row
= isl_int_get_si(tok
->u
.v
);
2256 n_col
= isl_int_get_si(tok2
->u
.v
);
2257 on_new_line
= tok2
->on_new_line
;
2258 isl_token_free(tok2
);
2259 isl_token_free(tok
);
2260 isl_assert(s
->ctx
, !on_new_line
, return NULL
);
2261 isl_assert(s
->ctx
, n_row
>= 0, return NULL
);
2262 isl_assert(s
->ctx
, n_col
>= 2 + nparam
, return NULL
);
2263 tok
= isl_stream_next_token_on_same_line(s
);
2265 if (tok
->type
!= ISL_TOKEN_VALUE
) {
2266 isl_stream_error(s
, tok
,
2267 "expecting number of output dimensions");
2268 isl_stream_push_token(s
, tok
);
2271 out
= isl_int_get_si(tok
->u
.v
);
2272 isl_token_free(tok
);
2274 tok
= isl_stream_next_token_on_same_line(s
);
2275 if (!tok
|| tok
->type
!= ISL_TOKEN_VALUE
) {
2276 isl_stream_error(s
, tok
,
2277 "expecting number of input dimensions");
2279 isl_stream_push_token(s
, tok
);
2282 in
= isl_int_get_si(tok
->u
.v
);
2283 isl_token_free(tok
);
2285 tok
= isl_stream_next_token_on_same_line(s
);
2286 if (!tok
|| tok
->type
!= ISL_TOKEN_VALUE
) {
2287 isl_stream_error(s
, tok
,
2288 "expecting number of existentials");
2290 isl_stream_push_token(s
, tok
);
2293 local
= isl_int_get_si(tok
->u
.v
);
2294 isl_token_free(tok
);
2296 tok
= isl_stream_next_token_on_same_line(s
);
2297 if (!tok
|| tok
->type
!= ISL_TOKEN_VALUE
) {
2298 isl_stream_error(s
, tok
,
2299 "expecting number of parameters");
2301 isl_stream_push_token(s
, tok
);
2304 nparam
= isl_int_get_si(tok
->u
.v
);
2305 isl_token_free(tok
);
2306 if (n_col
!= 1 + out
+ in
+ local
+ nparam
+ 1) {
2307 isl_stream_error(s
, NULL
,
2308 "dimensions don't match");
2312 out
= n_col
- 2 - nparam
;
2313 bmap
= isl_basic_map_alloc(s
->ctx
, nparam
, in
, out
, local
, n_row
, n_row
);
2317 for (i
= 0; i
< local
; ++i
) {
2318 int k
= isl_basic_map_alloc_div(bmap
);
2321 isl_seq_clr(bmap
->div
[k
], 1 + 1 + nparam
+ in
+ out
+ local
);
2324 for (i
= 0; i
< n_row
; ++i
)
2325 bmap
= basic_map_read_polylib_constraint(s
, bmap
);
2327 tok
= isl_stream_next_token_on_same_line(s
);
2329 isl_stream_error(s
, tok
, "unexpected extra token on line");
2330 isl_stream_push_token(s
, tok
);
2334 bmap
= isl_basic_map_simplify(bmap
);
2335 bmap
= isl_basic_map_finalize(bmap
);
2338 isl_basic_map_free(bmap
);
2342 static __isl_give isl_map
*map_read_polylib(__isl_keep isl_stream
*s
)
2344 struct isl_token
*tok
;
2345 struct isl_token
*tok2
;
2347 struct isl_map
*map
;
2349 tok
= isl_stream_next_token(s
);
2351 isl_stream_error(s
, NULL
, "unexpected EOF");
2354 tok2
= isl_stream_next_token_on_same_line(s
);
2355 if (tok2
&& tok2
->type
== ISL_TOKEN_VALUE
) {
2356 isl_stream_push_token(s
, tok2
);
2357 isl_stream_push_token(s
, tok
);
2358 return isl_map_from_basic_map(basic_map_read_polylib(s
));
2361 isl_stream_error(s
, tok2
, "unexpected token");
2362 isl_stream_push_token(s
, tok2
);
2363 isl_stream_push_token(s
, tok
);
2366 n
= isl_int_get_si(tok
->u
.v
);
2367 isl_token_free(tok
);
2369 isl_assert(s
->ctx
, n
>= 1, return NULL
);
2371 map
= isl_map_from_basic_map(basic_map_read_polylib(s
));
2373 for (i
= 1; map
&& i
< n
; ++i
)
2374 map
= isl_map_union(map
,
2375 isl_map_from_basic_map(basic_map_read_polylib(s
)));
2380 static int optional_power(__isl_keep isl_stream
*s
)
2383 struct isl_token
*tok
;
2385 tok
= isl_stream_next_token(s
);
2388 if (tok
->type
!= '^') {
2389 isl_stream_push_token(s
, tok
);
2392 isl_token_free(tok
);
2393 tok
= isl_stream_next_token(s
);
2394 if (!tok
|| tok
->type
!= ISL_TOKEN_VALUE
) {
2395 isl_stream_error(s
, tok
, "expecting exponent");
2397 isl_stream_push_token(s
, tok
);
2400 pow
= isl_int_get_si(tok
->u
.v
);
2401 isl_token_free(tok
);
2405 static __isl_give isl_pw_qpolynomial
*read_term(__isl_keep isl_stream
*s
,
2406 __isl_keep isl_map
*map
, struct vars
*v
);
2408 static __isl_give isl_pw_qpolynomial
*read_factor(__isl_keep isl_stream
*s
,
2409 __isl_keep isl_map
*map
, struct vars
*v
)
2411 isl_pw_qpolynomial
*pwqp
;
2412 struct isl_token
*tok
;
2414 tok
= next_token(s
);
2416 isl_stream_error(s
, NULL
, "unexpected EOF");
2419 if (tok
->type
== '(') {
2422 isl_token_free(tok
);
2423 pwqp
= read_term(s
, map
, v
);
2426 if (isl_stream_eat(s
, ')'))
2428 pow
= optional_power(s
);
2429 pwqp
= isl_pw_qpolynomial_pow(pwqp
, pow
);
2430 } else if (tok
->type
== ISL_TOKEN_VALUE
) {
2431 struct isl_token
*tok2
;
2432 isl_qpolynomial
*qp
;
2434 tok2
= isl_stream_next_token(s
);
2435 if (tok2
&& tok2
->type
== '/') {
2436 isl_token_free(tok2
);
2437 tok2
= next_token(s
);
2438 if (!tok2
|| tok2
->type
!= ISL_TOKEN_VALUE
) {
2439 isl_stream_error(s
, tok2
, "expected denominator");
2440 isl_token_free(tok
);
2441 isl_token_free(tok2
);
2444 qp
= isl_qpolynomial_rat_cst_on_domain(isl_map_get_space(map
),
2445 tok
->u
.v
, tok2
->u
.v
);
2446 isl_token_free(tok2
);
2448 isl_stream_push_token(s
, tok2
);
2449 qp
= isl_qpolynomial_cst_on_domain(isl_map_get_space(map
),
2452 isl_token_free(tok
);
2453 pwqp
= isl_pw_qpolynomial_from_qpolynomial(qp
);
2454 } else if (tok
->type
== ISL_TOKEN_INFTY
) {
2455 isl_qpolynomial
*qp
;
2456 isl_token_free(tok
);
2457 qp
= isl_qpolynomial_infty_on_domain(isl_map_get_space(map
));
2458 pwqp
= isl_pw_qpolynomial_from_qpolynomial(qp
);
2459 } else if (tok
->type
== ISL_TOKEN_NAN
) {
2460 isl_qpolynomial
*qp
;
2461 isl_token_free(tok
);
2462 qp
= isl_qpolynomial_nan_on_domain(isl_map_get_space(map
));
2463 pwqp
= isl_pw_qpolynomial_from_qpolynomial(qp
);
2464 } else if (tok
->type
== ISL_TOKEN_IDENT
) {
2466 int pos
= vars_pos(v
, tok
->u
.s
, -1);
2468 isl_qpolynomial
*qp
;
2470 isl_token_free(tok
);
2474 vars_drop(v
, v
->n
- n
);
2475 isl_stream_error(s
, tok
, "unknown identifier");
2476 isl_token_free(tok
);
2479 isl_token_free(tok
);
2480 pow
= optional_power(s
);
2481 qp
= isl_qpolynomial_var_pow_on_domain(isl_map_get_space(map
), pos
, pow
);
2482 pwqp
= isl_pw_qpolynomial_from_qpolynomial(qp
);
2483 } else if (is_start_of_div(tok
)) {
2487 isl_stream_push_token(s
, tok
);
2488 pwaff
= accept_div(s
, isl_map_get_space(map
), v
);
2489 pow
= optional_power(s
);
2490 pwqp
= isl_pw_qpolynomial_from_pw_aff(pwaff
);
2491 pwqp
= isl_pw_qpolynomial_pow(pwqp
, pow
);
2492 } else if (tok
->type
== '-') {
2493 isl_token_free(tok
);
2494 pwqp
= read_factor(s
, map
, v
);
2495 pwqp
= isl_pw_qpolynomial_neg(pwqp
);
2497 isl_stream_error(s
, tok
, "unexpected isl_token");
2498 isl_stream_push_token(s
, tok
);
2502 if (isl_stream_eat_if_available(s
, '*') ||
2503 isl_stream_next_token_is(s
, ISL_TOKEN_IDENT
)) {
2504 isl_pw_qpolynomial
*pwqp2
;
2506 pwqp2
= read_factor(s
, map
, v
);
2507 pwqp
= isl_pw_qpolynomial_mul(pwqp
, pwqp2
);
2512 isl_pw_qpolynomial_free(pwqp
);
2516 static __isl_give isl_pw_qpolynomial
*read_term(__isl_keep isl_stream
*s
,
2517 __isl_keep isl_map
*map
, struct vars
*v
)
2519 struct isl_token
*tok
;
2520 isl_pw_qpolynomial
*pwqp
;
2522 pwqp
= read_factor(s
, map
, v
);
2525 tok
= next_token(s
);
2529 if (tok
->type
== '+') {
2530 isl_pw_qpolynomial
*pwqp2
;
2532 isl_token_free(tok
);
2533 pwqp2
= read_factor(s
, map
, v
);
2534 pwqp
= isl_pw_qpolynomial_add(pwqp
, pwqp2
);
2535 } else if (tok
->type
== '-') {
2536 isl_pw_qpolynomial
*pwqp2
;
2538 isl_token_free(tok
);
2539 pwqp2
= read_factor(s
, map
, v
);
2540 pwqp
= isl_pw_qpolynomial_sub(pwqp
, pwqp2
);
2541 } else if (tok
->type
== ISL_TOKEN_VALUE
&&
2542 isl_int_is_neg(tok
->u
.v
)) {
2543 isl_pw_qpolynomial
*pwqp2
;
2545 isl_stream_push_token(s
, tok
);
2546 pwqp2
= read_factor(s
, map
, v
);
2547 pwqp
= isl_pw_qpolynomial_add(pwqp
, pwqp2
);
2549 isl_stream_push_token(s
, tok
);
2557 static __isl_give isl_map
*read_optional_formula(__isl_keep isl_stream
*s
,
2558 __isl_take isl_map
*map
, struct vars
*v
, int rational
)
2560 struct isl_token
*tok
;
2562 tok
= isl_stream_next_token(s
);
2564 isl_stream_error(s
, NULL
, "unexpected EOF");
2567 if (tok
->type
== ':' ||
2568 (tok
->type
== ISL_TOKEN_OR
&& !strcmp(tok
->u
.s
, "|"))) {
2569 isl_token_free(tok
);
2570 map
= read_formula(s
, v
, map
, rational
);
2572 isl_stream_push_token(s
, tok
);
2580 static struct isl_obj
obj_read_poly(__isl_keep isl_stream
*s
,
2581 __isl_take isl_map
*map
, struct vars
*v
, int n
)
2583 struct isl_obj obj
= { isl_obj_pw_qpolynomial
, NULL
};
2584 isl_pw_qpolynomial
*pwqp
;
2585 struct isl_set
*set
;
2587 pwqp
= read_term(s
, map
, v
);
2588 map
= read_optional_formula(s
, map
, v
, 0);
2589 set
= isl_map_range(map
);
2591 pwqp
= isl_pw_qpolynomial_intersect_domain(pwqp
, set
);
2593 vars_drop(v
, v
->n
- n
);
2599 static struct isl_obj
obj_read_poly_or_fold(__isl_keep isl_stream
*s
,
2600 __isl_take isl_set
*set
, struct vars
*v
, int n
)
2603 struct isl_obj obj
= { isl_obj_pw_qpolynomial_fold
, NULL
};
2604 isl_pw_qpolynomial
*pwqp
;
2605 isl_pw_qpolynomial_fold
*pwf
= NULL
;
2608 max
= isl_stream_eat_if_available(s
, ISL_TOKEN_MAX
);
2609 min
= !max
&& isl_stream_eat_if_available(s
, ISL_TOKEN_MIN
);
2611 return obj_read_poly(s
, set
, v
, n
);
2612 fold
= max
? isl_fold_max
: isl_fold_min
;
2614 if (isl_stream_eat(s
, '('))
2617 pwqp
= read_term(s
, set
, v
);
2618 pwf
= isl_pw_qpolynomial_fold_from_pw_qpolynomial(fold
, pwqp
);
2620 while (isl_stream_eat_if_available(s
, ',')) {
2621 isl_pw_qpolynomial_fold
*pwf_i
;
2622 pwqp
= read_term(s
, set
, v
);
2623 pwf_i
= isl_pw_qpolynomial_fold_from_pw_qpolynomial(fold
, pwqp
);
2624 pwf
= isl_pw_qpolynomial_fold_fold(pwf
, pwf_i
);
2627 if (isl_stream_eat(s
, ')'))
2630 set
= read_optional_formula(s
, set
, v
, 0);
2631 pwf
= isl_pw_qpolynomial_fold_intersect_domain(pwf
, set
);
2633 vars_drop(v
, v
->n
- n
);
2639 isl_pw_qpolynomial_fold_free(pwf
);
2640 obj
.type
= isl_obj_none
;
2644 static int is_rational(__isl_keep isl_stream
*s
)
2646 struct isl_token
*tok
;
2648 tok
= isl_stream_next_token(s
);
2651 if (tok
->type
== ISL_TOKEN_RAT
&& isl_stream_next_token_is(s
, ':')) {
2652 isl_token_free(tok
);
2653 isl_stream_eat(s
, ':');
2657 isl_stream_push_token(s
, tok
);
2662 static struct isl_obj
obj_read_body(__isl_keep isl_stream
*s
,
2663 __isl_take isl_map
*map
, struct vars
*v
)
2665 struct isl_token
*tok
;
2666 struct isl_obj obj
= { isl_obj_set
, NULL
};
2670 rational
= is_rational(s
);
2672 map
= isl_map_set_rational(map
);
2674 if (isl_stream_next_token_is(s
, ':')) {
2675 obj
.type
= isl_obj_set
;
2676 obj
.v
= read_optional_formula(s
, map
, v
, rational
);
2680 if (!next_is_tuple(s
))
2681 return obj_read_poly_or_fold(s
, map
, v
, n
);
2683 map
= read_map_tuple(s
, map
, isl_dim_in
, v
, rational
, 0);
2686 tok
= isl_stream_next_token(s
);
2689 if (tok
->type
== ISL_TOKEN_TO
) {
2690 obj
.type
= isl_obj_map
;
2691 isl_token_free(tok
);
2692 if (!next_is_tuple(s
)) {
2693 isl_set
*set
= isl_map_domain(map
);
2694 return obj_read_poly_or_fold(s
, set
, v
, n
);
2696 map
= read_map_tuple(s
, map
, isl_dim_out
, v
, rational
, 0);
2700 map
= isl_map_domain(map
);
2701 isl_stream_push_token(s
, tok
);
2704 map
= read_optional_formula(s
, map
, v
, rational
);
2706 vars_drop(v
, v
->n
- n
);
2712 obj
.type
= isl_obj_none
;
2716 static struct isl_obj
to_union(isl_ctx
*ctx
, struct isl_obj obj
)
2718 if (obj
.type
== isl_obj_map
) {
2719 obj
.v
= isl_union_map_from_map(obj
.v
);
2720 obj
.type
= isl_obj_union_map
;
2721 } else if (obj
.type
== isl_obj_set
) {
2722 obj
.v
= isl_union_set_from_set(obj
.v
);
2723 obj
.type
= isl_obj_union_set
;
2724 } else if (obj
.type
== isl_obj_pw_qpolynomial
) {
2725 obj
.v
= isl_union_pw_qpolynomial_from_pw_qpolynomial(obj
.v
);
2726 obj
.type
= isl_obj_union_pw_qpolynomial
;
2727 } else if (obj
.type
== isl_obj_pw_qpolynomial_fold
) {
2728 obj
.v
= isl_union_pw_qpolynomial_fold_from_pw_qpolynomial_fold(obj
.v
);
2729 obj
.type
= isl_obj_union_pw_qpolynomial_fold
;
2731 isl_assert(ctx
, 0, goto error
);
2734 obj
.type
->free(obj
.v
);
2735 obj
.type
= isl_obj_none
;
2739 static struct isl_obj
obj_add(__isl_keep isl_stream
*s
,
2740 struct isl_obj obj1
, struct isl_obj obj2
)
2742 if (obj2
.type
== isl_obj_none
|| !obj2
.v
)
2744 if (obj1
.type
== isl_obj_set
&& obj2
.type
== isl_obj_union_set
)
2745 obj1
= to_union(s
->ctx
, obj1
);
2746 if (obj1
.type
== isl_obj_union_set
&& obj2
.type
== isl_obj_set
)
2747 obj2
= to_union(s
->ctx
, obj2
);
2748 if (obj1
.type
== isl_obj_map
&& obj2
.type
== isl_obj_union_map
)
2749 obj1
= to_union(s
->ctx
, obj1
);
2750 if (obj1
.type
== isl_obj_union_map
&& obj2
.type
== isl_obj_map
)
2751 obj2
= to_union(s
->ctx
, obj2
);
2752 if (obj1
.type
== isl_obj_pw_qpolynomial
&&
2753 obj2
.type
== isl_obj_union_pw_qpolynomial
)
2754 obj1
= to_union(s
->ctx
, obj1
);
2755 if (obj1
.type
== isl_obj_union_pw_qpolynomial
&&
2756 obj2
.type
== isl_obj_pw_qpolynomial
)
2757 obj2
= to_union(s
->ctx
, obj2
);
2758 if (obj1
.type
== isl_obj_pw_qpolynomial_fold
&&
2759 obj2
.type
== isl_obj_union_pw_qpolynomial_fold
)
2760 obj1
= to_union(s
->ctx
, obj1
);
2761 if (obj1
.type
== isl_obj_union_pw_qpolynomial_fold
&&
2762 obj2
.type
== isl_obj_pw_qpolynomial_fold
)
2763 obj2
= to_union(s
->ctx
, obj2
);
2764 if (obj1
.type
!= obj2
.type
) {
2765 isl_stream_error(s
, NULL
,
2766 "attempt to combine incompatible objects");
2769 if (!obj1
.type
->add
)
2770 isl_die(s
->ctx
, isl_error_internal
,
2771 "combination not supported on object type", goto error
);
2772 if (obj1
.type
== isl_obj_map
&& !isl_map_has_equal_space(obj1
.v
, obj2
.v
)) {
2773 obj1
= to_union(s
->ctx
, obj1
);
2774 obj2
= to_union(s
->ctx
, obj2
);
2776 if (obj1
.type
== isl_obj_set
&& !isl_set_has_equal_space(obj1
.v
, obj2
.v
)) {
2777 obj1
= to_union(s
->ctx
, obj1
);
2778 obj2
= to_union(s
->ctx
, obj2
);
2780 if (obj1
.type
== isl_obj_pw_qpolynomial
&&
2781 !isl_pw_qpolynomial_has_equal_space(obj1
.v
, obj2
.v
)) {
2782 obj1
= to_union(s
->ctx
, obj1
);
2783 obj2
= to_union(s
->ctx
, obj2
);
2785 if (obj1
.type
== isl_obj_pw_qpolynomial_fold
&&
2786 !isl_pw_qpolynomial_fold_has_equal_space(obj1
.v
, obj2
.v
)) {
2787 obj1
= to_union(s
->ctx
, obj1
);
2788 obj2
= to_union(s
->ctx
, obj2
);
2790 obj1
.v
= obj1
.type
->add(obj1
.v
, obj2
.v
);
2793 obj1
.type
->free(obj1
.v
);
2794 obj2
.type
->free(obj2
.v
);
2795 obj1
.type
= isl_obj_none
;
2800 /* Are the first two tokens on "s", "domain" (either as a string
2801 * or as an identifier) followed by ":"?
2803 static int next_is_domain_colon(__isl_keep isl_stream
*s
)
2805 struct isl_token
*tok
;
2809 tok
= isl_stream_next_token(s
);
2812 if (tok
->type
!= ISL_TOKEN_IDENT
&& tok
->type
!= ISL_TOKEN_STRING
) {
2813 isl_stream_push_token(s
, tok
);
2817 name
= isl_token_get_str(s
->ctx
, tok
);
2818 res
= !strcmp(name
, "domain") && isl_stream_next_token_is(s
, ':');
2821 isl_stream_push_token(s
, tok
);
2826 /* Do the first tokens on "s" look like a schedule?
2828 * The root of a schedule is always a domain node, so the first thing
2829 * we expect in the stream is a domain key, i.e., "domain" followed
2830 * by ":". If the schedule was printed in YAML flow style, then
2831 * we additionally expect a "{" to open the outer mapping.
2833 static int next_is_schedule(__isl_keep isl_stream
*s
)
2835 struct isl_token
*tok
;
2838 tok
= isl_stream_next_token(s
);
2841 if (tok
->type
!= '{') {
2842 isl_stream_push_token(s
, tok
);
2843 return next_is_domain_colon(s
);
2846 is_schedule
= next_is_domain_colon(s
);
2847 isl_stream_push_token(s
, tok
);
2852 /* Read an isl_schedule from "s" and store it in an isl_obj.
2854 static struct isl_obj
schedule_read(__isl_keep isl_stream
*s
)
2858 obj
.type
= isl_obj_schedule
;
2859 obj
.v
= isl_stream_read_schedule(s
);
2864 /* Read a disjunction of object bodies from "s".
2865 * That is, read the inside of the braces, but not the braces themselves.
2866 * "v" contains a description of the identifiers parsed so far.
2867 * "map" contains information about the parameters.
2869 static struct isl_obj
obj_read_disjuncts(__isl_keep isl_stream
*s
,
2870 struct vars
*v
, __isl_keep isl_map
*map
)
2872 struct isl_obj obj
= { isl_obj_set
, NULL
};
2874 if (isl_stream_next_token_is(s
, '}')) {
2875 obj
.type
= isl_obj_union_set
;
2876 obj
.v
= isl_union_set_empty(isl_map_get_space(map
));
2882 o
= obj_read_body(s
, isl_map_copy(map
), v
);
2886 obj
= obj_add(s
, obj
, o
);
2887 if (obj
.type
== isl_obj_none
|| !obj
.v
)
2889 if (!isl_stream_eat_if_available(s
, ';'))
2891 if (isl_stream_next_token_is(s
, '}'))
2898 static struct isl_obj
obj_read(__isl_keep isl_stream
*s
)
2900 isl_map
*map
= NULL
;
2901 struct isl_token
*tok
;
2902 struct vars
*v
= NULL
;
2903 struct isl_obj obj
= { isl_obj_set
, NULL
};
2905 if (next_is_schedule(s
))
2906 return schedule_read(s
);
2908 tok
= next_token(s
);
2910 isl_stream_error(s
, NULL
, "unexpected EOF");
2913 if (tok
->type
== ISL_TOKEN_VALUE
) {
2914 struct isl_token
*tok2
;
2915 struct isl_map
*map
;
2917 tok2
= isl_stream_next_token(s
);
2918 if (!tok2
|| tok2
->type
!= ISL_TOKEN_VALUE
||
2919 isl_int_is_neg(tok2
->u
.v
)) {
2921 isl_stream_push_token(s
, tok2
);
2922 obj
.type
= isl_obj_val
;
2923 obj
.v
= isl_val_int_from_isl_int(s
->ctx
, tok
->u
.v
);
2924 isl_token_free(tok
);
2927 isl_stream_push_token(s
, tok2
);
2928 isl_stream_push_token(s
, tok
);
2929 map
= map_read_polylib(s
);
2932 if (isl_map_may_be_set(map
))
2933 obj
.v
= isl_map_range(map
);
2935 obj
.type
= isl_obj_map
;
2940 v
= vars_new(s
->ctx
);
2942 isl_stream_push_token(s
, tok
);
2945 map
= isl_map_universe(isl_space_params_alloc(s
->ctx
, 0));
2946 if (tok
->type
== '[') {
2947 isl_stream_push_token(s
, tok
);
2948 map
= read_map_tuple(s
, map
, isl_dim_param
, v
, 0, 0);
2951 tok
= isl_stream_next_token(s
);
2952 if (!tok
|| tok
->type
!= ISL_TOKEN_TO
) {
2953 isl_stream_error(s
, tok
, "expecting '->'");
2955 isl_stream_push_token(s
, tok
);
2958 isl_token_free(tok
);
2959 tok
= isl_stream_next_token(s
);
2961 if (!tok
|| tok
->type
!= '{') {
2962 isl_stream_error(s
, tok
, "expecting '{'");
2964 isl_stream_push_token(s
, tok
);
2967 isl_token_free(tok
);
2969 tok
= isl_stream_next_token(s
);
2972 else if (tok
->type
== ISL_TOKEN_IDENT
&& !strcmp(tok
->u
.s
, "Sym")) {
2973 isl_token_free(tok
);
2974 if (isl_stream_eat(s
, '='))
2976 map
= read_map_tuple(s
, map
, isl_dim_param
, v
, 0, 1);
2980 isl_stream_push_token(s
, tok
);
2982 obj
= obj_read_disjuncts(s
, v
, map
);
2983 if (obj
.type
== isl_obj_none
|| !obj
.v
)
2986 tok
= isl_stream_next_token(s
);
2987 if (tok
&& tok
->type
== '}') {
2988 isl_token_free(tok
);
2990 isl_stream_error(s
, tok
, "unexpected isl_token");
2992 isl_token_free(tok
);
3002 obj
.type
->free(obj
.v
);
3009 struct isl_obj
isl_stream_read_obj(__isl_keep isl_stream
*s
)
3014 __isl_give isl_map
*isl_stream_read_map(__isl_keep isl_stream
*s
)
3020 isl_assert(s
->ctx
, obj
.type
== isl_obj_map
||
3021 obj
.type
== isl_obj_set
, goto error
);
3023 if (obj
.type
== isl_obj_set
)
3024 obj
.v
= isl_map_from_range(obj
.v
);
3028 obj
.type
->free(obj
.v
);
3032 __isl_give isl_set
*isl_stream_read_set(__isl_keep isl_stream
*s
)
3038 if (obj
.type
== isl_obj_map
&& isl_map_may_be_set(obj
.v
)) {
3039 obj
.v
= isl_map_range(obj
.v
);
3040 obj
.type
= isl_obj_set
;
3042 isl_assert(s
->ctx
, obj
.type
== isl_obj_set
, goto error
);
3047 obj
.type
->free(obj
.v
);
3051 __isl_give isl_union_map
*isl_stream_read_union_map(__isl_keep isl_stream
*s
)
3056 if (obj
.type
== isl_obj_map
) {
3057 obj
.type
= isl_obj_union_map
;
3058 obj
.v
= isl_union_map_from_map(obj
.v
);
3060 if (obj
.type
== isl_obj_set
) {
3061 obj
.type
= isl_obj_union_set
;
3062 obj
.v
= isl_union_set_from_set(obj
.v
);
3064 if (obj
.v
&& obj
.type
== isl_obj_union_set
&&
3065 isl_union_set_is_empty(obj
.v
))
3066 obj
.type
= isl_obj_union_map
;
3067 if (obj
.v
&& obj
.type
!= isl_obj_union_map
)
3068 isl_die(s
->ctx
, isl_error_invalid
, "invalid input", goto error
);
3072 obj
.type
->free(obj
.v
);
3076 /* Extract an isl_union_set from "obj".
3077 * This only works if the object was detected as either a set
3078 * (in which case it is converted to a union set) or a union set.
3080 static __isl_give isl_union_set
*extract_union_set(isl_ctx
*ctx
,
3083 if (obj
.type
== isl_obj_set
) {
3084 obj
.type
= isl_obj_union_set
;
3085 obj
.v
= isl_union_set_from_set(obj
.v
);
3088 isl_assert(ctx
, obj
.type
== isl_obj_union_set
, goto error
);
3092 obj
.type
->free(obj
.v
);
3096 /* Read an isl_union_set from "s".
3097 * First read a generic object and then try and extract
3098 * an isl_union_set from that.
3100 __isl_give isl_union_set
*isl_stream_read_union_set(__isl_keep isl_stream
*s
)
3105 return extract_union_set(s
->ctx
, obj
);
3108 static __isl_give isl_basic_map
*basic_map_read(__isl_keep isl_stream
*s
)
3111 struct isl_map
*map
;
3112 struct isl_basic_map
*bmap
;
3115 if (obj
.v
&& (obj
.type
!= isl_obj_map
&& obj
.type
!= isl_obj_set
))
3116 isl_die(s
->ctx
, isl_error_invalid
, "not a (basic) set or map",
3123 isl_die(s
->ctx
, isl_error_invalid
,
3124 "set or map description involves "
3125 "more than one disjunct", goto error
);
3128 bmap
= isl_basic_map_empty(isl_map_get_space(map
));
3130 bmap
= isl_basic_map_copy(map
->p
[0]);
3136 obj
.type
->free(obj
.v
);
3140 static __isl_give isl_basic_set
*basic_set_read(__isl_keep isl_stream
*s
)
3142 isl_basic_map
*bmap
;
3143 bmap
= basic_map_read(s
);
3146 if (!isl_basic_map_may_be_set(bmap
))
3147 isl_die(s
->ctx
, isl_error_invalid
,
3148 "input is not a set", goto error
);
3149 return isl_basic_map_range(bmap
);
3151 isl_basic_map_free(bmap
);
3155 __isl_give isl_basic_map
*isl_basic_map_read_from_file(isl_ctx
*ctx
,
3158 struct isl_basic_map
*bmap
;
3159 isl_stream
*s
= isl_stream_new_file(ctx
, input
);
3162 bmap
= basic_map_read(s
);
3167 __isl_give isl_basic_set
*isl_basic_set_read_from_file(isl_ctx
*ctx
,
3170 isl_basic_set
*bset
;
3171 isl_stream
*s
= isl_stream_new_file(ctx
, input
);
3174 bset
= basic_set_read(s
);
3179 __isl_give isl_basic_map
*isl_basic_map_read_from_str(isl_ctx
*ctx
,
3182 struct isl_basic_map
*bmap
;
3183 isl_stream
*s
= isl_stream_new_str(ctx
, str
);
3186 bmap
= basic_map_read(s
);
3191 __isl_give isl_basic_set
*isl_basic_set_read_from_str(isl_ctx
*ctx
,
3194 isl_basic_set
*bset
;
3195 isl_stream
*s
= isl_stream_new_str(ctx
, str
);
3198 bset
= basic_set_read(s
);
3203 __isl_give isl_map
*isl_map_read_from_file(struct isl_ctx
*ctx
,
3206 struct isl_map
*map
;
3207 isl_stream
*s
= isl_stream_new_file(ctx
, input
);
3210 map
= isl_stream_read_map(s
);
3215 __isl_give isl_map
*isl_map_read_from_str(struct isl_ctx
*ctx
,
3218 struct isl_map
*map
;
3219 isl_stream
*s
= isl_stream_new_str(ctx
, str
);
3222 map
= isl_stream_read_map(s
);
3227 __isl_give isl_set
*isl_set_read_from_file(struct isl_ctx
*ctx
,
3231 isl_stream
*s
= isl_stream_new_file(ctx
, input
);
3234 set
= isl_stream_read_set(s
);
3239 __isl_give isl_set
*isl_set_read_from_str(isl_ctx
*ctx
, const char *str
)
3242 isl_stream
*s
= isl_stream_new_str(ctx
, str
);
3245 set
= isl_stream_read_set(s
);
3250 __isl_give isl_union_map
*isl_union_map_read_from_file(isl_ctx
*ctx
,
3253 isl_union_map
*umap
;
3254 isl_stream
*s
= isl_stream_new_file(ctx
, input
);
3257 umap
= isl_stream_read_union_map(s
);
3262 __isl_give isl_union_map
*isl_union_map_read_from_str(struct isl_ctx
*ctx
,
3265 isl_union_map
*umap
;
3266 isl_stream
*s
= isl_stream_new_str(ctx
, str
);
3269 umap
= isl_stream_read_union_map(s
);
3274 __isl_give isl_union_set
*isl_union_set_read_from_file(isl_ctx
*ctx
,
3277 isl_union_set
*uset
;
3278 isl_stream
*s
= isl_stream_new_file(ctx
, input
);
3281 uset
= isl_stream_read_union_set(s
);
3286 __isl_give isl_union_set
*isl_union_set_read_from_str(struct isl_ctx
*ctx
,
3289 isl_union_set
*uset
;
3290 isl_stream
*s
= isl_stream_new_str(ctx
, str
);
3293 uset
= isl_stream_read_union_set(s
);
3298 static __isl_give isl_vec
*isl_vec_read_polylib(__isl_keep isl_stream
*s
)
3300 struct isl_vec
*vec
= NULL
;
3301 struct isl_token
*tok
;
3305 tok
= isl_stream_next_token(s
);
3306 if (!tok
|| tok
->type
!= ISL_TOKEN_VALUE
) {
3307 isl_stream_error(s
, tok
, "expecting vector length");
3311 size
= isl_int_get_si(tok
->u
.v
);
3312 isl_token_free(tok
);
3314 vec
= isl_vec_alloc(s
->ctx
, size
);
3316 for (j
= 0; j
< size
; ++j
) {
3317 tok
= isl_stream_next_token(s
);
3318 if (!tok
|| tok
->type
!= ISL_TOKEN_VALUE
) {
3319 isl_stream_error(s
, tok
, "expecting constant value");
3322 isl_int_set(vec
->el
[j
], tok
->u
.v
);
3323 isl_token_free(tok
);
3328 isl_token_free(tok
);
3333 static __isl_give isl_vec
*vec_read(__isl_keep isl_stream
*s
)
3335 return isl_vec_read_polylib(s
);
3338 __isl_give isl_vec
*isl_vec_read_from_file(isl_ctx
*ctx
, FILE *input
)
3341 isl_stream
*s
= isl_stream_new_file(ctx
, input
);
3349 __isl_give isl_pw_qpolynomial
*isl_stream_read_pw_qpolynomial(
3350 __isl_keep isl_stream
*s
)
3356 isl_assert(s
->ctx
, obj
.type
== isl_obj_pw_qpolynomial
,
3361 obj
.type
->free(obj
.v
);
3365 __isl_give isl_pw_qpolynomial
*isl_pw_qpolynomial_read_from_str(isl_ctx
*ctx
,
3368 isl_pw_qpolynomial
*pwqp
;
3369 isl_stream
*s
= isl_stream_new_str(ctx
, str
);
3372 pwqp
= isl_stream_read_pw_qpolynomial(s
);
3377 __isl_give isl_pw_qpolynomial
*isl_pw_qpolynomial_read_from_file(isl_ctx
*ctx
,
3380 isl_pw_qpolynomial
*pwqp
;
3381 isl_stream
*s
= isl_stream_new_file(ctx
, input
);
3384 pwqp
= isl_stream_read_pw_qpolynomial(s
);
3389 /* Read an isl_pw_qpolynomial_fold from "s".
3390 * First read a generic object and
3391 * then check that it is an isl_pw_qpolynomial_fold.
3393 __isl_give isl_pw_qpolynomial_fold
*isl_stream_read_pw_qpolynomial_fold(
3394 __isl_keep isl_stream
*s
)
3399 if (obj
.v
&& obj
.type
!= isl_obj_pw_qpolynomial_fold
)
3400 isl_die(s
->ctx
, isl_error_invalid
, "invalid input", goto error
);
3404 obj
.type
->free(obj
.v
);
3408 /* Read an isl_pw_qpolynomial_fold from "str".
3410 __isl_give isl_pw_qpolynomial_fold
*isl_pw_qpolynomial_fold_read_from_str(
3411 isl_ctx
*ctx
, const char *str
)
3413 isl_pw_qpolynomial_fold
*pwqp
;
3416 s
= isl_stream_new_str(ctx
, str
);
3419 pwqp
= isl_stream_read_pw_qpolynomial_fold(s
);
3425 /* Is the next token an identifier not in "v"?
3427 static int next_is_fresh_ident(__isl_keep isl_stream
*s
, struct vars
*v
)
3431 struct isl_token
*tok
;
3433 tok
= isl_stream_next_token(s
);
3436 fresh
= tok
->type
== ISL_TOKEN_IDENT
&& vars_pos(v
, tok
->u
.s
, -1) >= n
;
3437 isl_stream_push_token(s
, tok
);
3439 vars_drop(v
, v
->n
- n
);
3444 /* First read the domain of the affine expression, which may be
3445 * a parameter space or a set.
3446 * The tricky part is that we don't know if the domain is a set or not,
3447 * so when we are trying to read the domain, we may actually be reading
3448 * the affine expression itself (defined on a parameter domains)
3449 * If the tuple we are reading is named, we assume it's the domain.
3450 * Also, if inside the tuple, the first thing we find is a nested tuple
3451 * or a new identifier, we again assume it's the domain.
3452 * Finally, if the tuple is empty, then it must be the domain
3453 * since it does not contain an affine expression.
3454 * Otherwise, we assume we are reading an affine expression.
3456 static __isl_give isl_set
*read_aff_domain(__isl_keep isl_stream
*s
,
3457 __isl_take isl_set
*dom
, struct vars
*v
)
3459 struct isl_token
*tok
, *tok2
;
3462 tok
= isl_stream_next_token(s
);
3463 if (tok
&& (tok
->type
== ISL_TOKEN_IDENT
|| tok
->is_keyword
)) {
3464 isl_stream_push_token(s
, tok
);
3465 return read_map_tuple(s
, dom
, isl_dim_set
, v
, 0, 0);
3467 if (!tok
|| tok
->type
!= '[') {
3468 isl_stream_error(s
, tok
, "expecting '['");
3471 tok2
= isl_stream_next_token(s
);
3472 is_empty
= tok2
&& tok2
->type
== ']';
3474 isl_stream_push_token(s
, tok2
);
3475 if (is_empty
|| next_is_tuple(s
) || next_is_fresh_ident(s
, v
)) {
3476 isl_stream_push_token(s
, tok
);
3477 dom
= read_map_tuple(s
, dom
, isl_dim_set
, v
, 0, 0);
3479 isl_stream_push_token(s
, tok
);
3484 isl_stream_push_token(s
, tok
);
3489 /* Read an affine expression from "s".
3491 __isl_give isl_aff
*isl_stream_read_aff(__isl_keep isl_stream
*s
)
3497 ma
= isl_stream_read_multi_aff(s
);
3498 dim
= isl_multi_aff_dim(ma
, isl_dim_out
);
3502 isl_die(s
->ctx
, isl_error_invalid
,
3503 "expecting single affine expression",
3506 aff
= isl_multi_aff_get_aff(ma
, 0);
3507 isl_multi_aff_free(ma
);
3510 isl_multi_aff_free(ma
);
3514 /* Read a piecewise affine expression from "s" with domain (space) "dom".
3516 static __isl_give isl_pw_aff
*read_pw_aff_with_dom(__isl_keep isl_stream
*s
,
3517 __isl_take isl_set
*dom
, struct vars
*v
)
3519 isl_pw_aff
*pwaff
= NULL
;
3521 if (!isl_set_is_params(dom
) && isl_stream_eat(s
, ISL_TOKEN_TO
))
3524 if (isl_stream_eat(s
, '['))
3527 pwaff
= accept_affine(s
, isl_set_get_space(dom
), v
);
3529 if (isl_stream_eat(s
, ']'))
3532 dom
= read_optional_formula(s
, dom
, v
, 0);
3533 pwaff
= isl_pw_aff_intersect_domain(pwaff
, dom
);
3538 isl_pw_aff_free(pwaff
);
3542 __isl_give isl_pw_aff
*isl_stream_read_pw_aff(__isl_keep isl_stream
*s
)
3545 isl_set
*dom
= NULL
;
3547 isl_pw_aff
*pa
= NULL
;
3550 v
= vars_new(s
->ctx
);
3554 dom
= isl_set_universe(isl_space_params_alloc(s
->ctx
, 0));
3555 if (next_is_tuple(s
)) {
3556 dom
= read_map_tuple(s
, dom
, isl_dim_param
, v
, 1, 0);
3557 if (isl_stream_eat(s
, ISL_TOKEN_TO
))
3560 if (isl_stream_eat(s
, '{'))
3564 aff_dom
= read_aff_domain(s
, isl_set_copy(dom
), v
);
3565 pa
= read_pw_aff_with_dom(s
, aff_dom
, v
);
3566 vars_drop(v
, v
->n
- n
);
3568 while (isl_stream_eat_if_available(s
, ';')) {
3572 aff_dom
= read_aff_domain(s
, isl_set_copy(dom
), v
);
3573 pa_i
= read_pw_aff_with_dom(s
, aff_dom
, v
);
3574 vars_drop(v
, v
->n
- n
);
3576 pa
= isl_pw_aff_union_add(pa
, pa_i
);
3579 if (isl_stream_eat(s
, '}'))
3588 isl_pw_aff_free(pa
);
3592 __isl_give isl_aff
*isl_aff_read_from_str(isl_ctx
*ctx
, const char *str
)
3595 isl_stream
*s
= isl_stream_new_str(ctx
, str
);
3598 aff
= isl_stream_read_aff(s
);
3603 __isl_give isl_pw_aff
*isl_pw_aff_read_from_str(isl_ctx
*ctx
, const char *str
)
3606 isl_stream
*s
= isl_stream_new_str(ctx
, str
);
3609 pa
= isl_stream_read_pw_aff(s
);
3614 /* Extract an isl_multi_pw_aff with domain space "dom_space"
3615 * from a tuple "tuple" read by read_tuple.
3617 * Note that the function read_tuple accepts tuples where some output or
3618 * set dimensions are defined in terms of other output or set dimensions
3619 * since this function is also used to read maps. As a special case,
3620 * read_tuple also accept dimensions that are defined in terms of themselves
3621 * (i.e., that are not defined).
3622 * These cases are not allowed when extracting an isl_multi_pw_aff so check
3623 * that the definitions of the output/set dimensions do not involve any
3624 * output/set dimensions.
3625 * Finally, drop the output dimensions from the domain of the result
3626 * of read_tuple (which is of the form [input, output] -> [output],
3627 * with anonymous domain) and reset the space.
3629 static __isl_give isl_multi_pw_aff
*extract_mpa_from_tuple(
3630 __isl_take isl_space
*dom_space
, __isl_keep isl_multi_pw_aff
*tuple
)
3635 isl_multi_pw_aff
*mpa
;
3637 n
= isl_multi_pw_aff_dim(tuple
, isl_dim_out
);
3638 dim
= isl_space_dim(dom_space
, isl_dim_all
);
3639 if (n
< 0 || dim
< 0)
3640 dom_space
= isl_space_free(dom_space
);
3641 space
= isl_space_range(isl_multi_pw_aff_get_space(tuple
));
3642 space
= isl_space_align_params(space
, isl_space_copy(dom_space
));
3643 if (!isl_space_is_params(dom_space
))
3644 space
= isl_space_map_from_domain_and_range(
3645 isl_space_copy(dom_space
), space
);
3646 isl_space_free(dom_space
);
3647 mpa
= isl_multi_pw_aff_alloc(space
);
3649 for (i
= 0; i
< n
; ++i
) {
3651 pa
= isl_multi_pw_aff_get_pw_aff(tuple
, i
);
3653 return isl_multi_pw_aff_free(mpa
);
3654 if (isl_pw_aff_involves_dims(pa
, isl_dim_in
, dim
, i
+ 1)) {
3655 isl_ctx
*ctx
= isl_pw_aff_get_ctx(pa
);
3656 isl_pw_aff_free(pa
);
3657 isl_die(ctx
, isl_error_invalid
,
3658 "not an affine expression",
3659 return isl_multi_pw_aff_free(mpa
));
3661 pa
= isl_pw_aff_drop_dims(pa
, isl_dim_in
, dim
, n
);
3662 space
= isl_multi_pw_aff_get_domain_space(mpa
);
3663 pa
= isl_pw_aff_reset_domain_space(pa
, space
);
3664 mpa
= isl_multi_pw_aff_set_pw_aff(mpa
, i
, pa
);
3670 /* Read a tuple of affine expressions, together with optional constraints
3671 * on the domain from "s". "dom" represents the initial constraints
3674 * The isl_multi_aff may live in either a set or a map space.
3675 * First read the first tuple and check if it is followed by a "->".
3676 * If so, convert the tuple into the domain of the isl_multi_pw_aff and
3677 * read in the next tuple. This tuple (or the first tuple if it was
3678 * not followed by a "->") is then converted into an isl_multi_pw_aff
3679 * through a call to extract_mpa_from_tuple.
3680 * The result is converted to an isl_pw_multi_aff and
3681 * its domain is intersected with the domain.
3683 static __isl_give isl_pw_multi_aff
*read_conditional_multi_aff(
3684 __isl_keep isl_stream
*s
, __isl_take isl_set
*dom
, struct vars
*v
)
3686 isl_multi_pw_aff
*tuple
;
3687 isl_multi_pw_aff
*mpa
;
3688 isl_pw_multi_aff
*pma
;
3691 tuple
= read_tuple(s
, v
, 0, 0);
3694 if (isl_stream_eat_if_available(s
, ISL_TOKEN_TO
)) {
3695 isl_map
*map
= map_from_tuple(tuple
, dom
, isl_dim_in
, v
, 0);
3696 dom
= isl_map_domain(map
);
3697 tuple
= read_tuple(s
, v
, 0, 0);
3701 mpa
= extract_mpa_from_tuple(isl_set_get_space(dom
), tuple
);
3702 isl_multi_pw_aff_free(tuple
);
3704 dom
= isl_set_free(dom
);
3706 dom
= read_optional_formula(s
, dom
, v
, 0);
3708 vars_drop(v
, v
->n
- n
);
3710 pma
= isl_pw_multi_aff_from_multi_pw_aff(mpa
);
3711 pma
= isl_pw_multi_aff_intersect_domain(pma
, dom
);
3719 /* Read an isl_union_pw_multi_aff from "s".
3721 * In particular, first read the parameters and then read a sequence
3722 * of zero or more tuples of affine expressions with optional conditions and
3725 __isl_give isl_union_pw_multi_aff
*isl_stream_read_union_pw_multi_aff(
3726 __isl_keep isl_stream
*s
)
3730 isl_union_pw_multi_aff
*upma
= NULL
;
3732 v
= vars_new(s
->ctx
);
3736 dom
= isl_set_universe(isl_space_params_alloc(s
->ctx
, 0));
3737 if (next_is_tuple(s
)) {
3738 dom
= read_map_tuple(s
, dom
, isl_dim_param
, v
, 1, 0);
3739 if (isl_stream_eat(s
, ISL_TOKEN_TO
))
3742 if (isl_stream_eat(s
, '{'))
3745 upma
= isl_union_pw_multi_aff_empty(isl_set_get_space(dom
));
3748 isl_pw_multi_aff
*pma
;
3749 isl_union_pw_multi_aff
*upma2
;
3751 if (isl_stream_next_token_is(s
, '}'))
3754 pma
= read_conditional_multi_aff(s
, isl_set_copy(dom
), v
);
3755 upma2
= isl_union_pw_multi_aff_from_pw_multi_aff(pma
);
3756 upma
= isl_union_pw_multi_aff_union_add(upma
, upma2
);
3759 } while (isl_stream_eat_if_available(s
, ';'));
3761 if (isl_stream_eat(s
, '}'))
3768 isl_union_pw_multi_aff_free(upma
);
3774 /* Read an isl_pw_multi_aff from "s".
3776 * Read a more generic isl_union_pw_multi_aff first and
3777 * then check that the result lives in a single space.
3779 __isl_give isl_pw_multi_aff
*isl_stream_read_pw_multi_aff(
3780 __isl_keep isl_stream
*s
)
3782 isl_bool single_space
;
3783 isl_union_pw_multi_aff
*upma
;
3785 upma
= isl_stream_read_union_pw_multi_aff(s
);
3786 single_space
= isl_union_pw_multi_aff_isa_pw_multi_aff(upma
);
3787 if (single_space
< 0)
3788 upma
= isl_union_pw_multi_aff_free(upma
);
3789 else if (!single_space
)
3790 isl_die(s
->ctx
, isl_error_invalid
,
3791 "expecting expression in single space",
3792 upma
= isl_union_pw_multi_aff_free(upma
));
3793 return isl_union_pw_multi_aff_as_pw_multi_aff(upma
);
3796 __isl_give isl_pw_multi_aff
*isl_pw_multi_aff_read_from_str(isl_ctx
*ctx
,
3799 isl_pw_multi_aff
*pma
;
3800 isl_stream
*s
= isl_stream_new_str(ctx
, str
);
3803 pma
= isl_stream_read_pw_multi_aff(s
);
3808 /* Read an isl_union_pw_multi_aff from "str".
3810 __isl_give isl_union_pw_multi_aff
*isl_union_pw_multi_aff_read_from_str(
3811 isl_ctx
*ctx
, const char *str
)
3813 isl_union_pw_multi_aff
*upma
;
3814 isl_stream
*s
= isl_stream_new_str(ctx
, str
);
3817 upma
= isl_stream_read_union_pw_multi_aff(s
);
3822 /* Assuming "pa" represents a single affine expression defined on a universe
3823 * domain, extract this affine expression.
3825 static __isl_give isl_aff
*aff_from_pw_aff(__isl_take isl_pw_aff
*pa
)
3832 isl_die(isl_pw_aff_get_ctx(pa
), isl_error_invalid
,
3833 "expecting single affine expression",
3835 if (!isl_set_plain_is_universe(pa
->p
[0].set
))
3836 isl_die(isl_pw_aff_get_ctx(pa
), isl_error_invalid
,
3837 "expecting universe domain",
3840 aff
= isl_aff_copy(pa
->p
[0].aff
);
3841 isl_pw_aff_free(pa
);
3844 isl_pw_aff_free(pa
);
3851 #include <isl_multi_read_no_explicit_domain_templ.c>
3856 #include <isl_multi_read_no_explicit_domain_templ.c>
3858 /* Read a multi-affine expression from "s".
3859 * If the multi-affine expression has a domain, then the tuple
3860 * representing this domain cannot involve any affine expressions.
3861 * The tuple representing the actual expressions needs to consist
3862 * of only affine expressions. Moreover, these expressions can
3863 * only depend on parameters and input dimensions and not on other
3864 * output dimensions.
3866 __isl_give isl_multi_aff
*isl_stream_read_multi_aff(__isl_keep isl_stream
*s
)
3869 isl_set
*dom
= NULL
;
3870 isl_multi_pw_aff
*tuple
= NULL
;
3873 isl_space
*space
, *dom_space
;
3874 isl_multi_aff
*ma
= NULL
;
3876 v
= vars_new(s
->ctx
);
3880 dom
= isl_set_universe(isl_space_params_alloc(s
->ctx
, 0));
3881 if (next_is_tuple(s
)) {
3882 dom
= read_map_tuple(s
, dom
, isl_dim_param
, v
, 1, 0);
3883 if (isl_stream_eat(s
, ISL_TOKEN_TO
))
3886 if (!isl_set_plain_is_universe(dom
))
3887 isl_die(s
->ctx
, isl_error_invalid
,
3888 "expecting universe parameter domain", goto error
);
3889 if (isl_stream_eat(s
, '{'))
3892 tuple
= read_tuple(s
, v
, 0, 0);
3895 if (isl_stream_eat_if_available(s
, ISL_TOKEN_TO
)) {
3900 has_expr
= tuple_has_expr(tuple
);
3904 isl_die(s
->ctx
, isl_error_invalid
,
3905 "expecting universe domain", goto error
);
3906 space
= isl_space_range(isl_multi_pw_aff_get_space(tuple
));
3907 set
= isl_set_universe(space
);
3908 dom
= isl_set_intersect_params(set
, dom
);
3909 isl_multi_pw_aff_free(tuple
);
3910 tuple
= read_tuple(s
, v
, 0, 0);
3915 if (isl_stream_eat(s
, '}'))
3918 n
= isl_multi_pw_aff_dim(tuple
, isl_dim_out
);
3919 dim
= isl_set_dim(dom
, isl_dim_all
);
3920 if (n
< 0 || dim
< 0)
3922 dom_space
= isl_set_get_space(dom
);
3923 space
= isl_space_range(isl_multi_pw_aff_get_space(tuple
));
3924 space
= isl_space_align_params(space
, isl_space_copy(dom_space
));
3925 if (!isl_space_is_params(dom_space
))
3926 space
= isl_space_map_from_domain_and_range(
3927 isl_space_copy(dom_space
), space
);
3928 isl_space_free(dom_space
);
3929 ma
= isl_multi_aff_alloc(space
);
3931 for (i
= 0; i
< n
; ++i
) {
3934 pa
= isl_multi_pw_aff_get_pw_aff(tuple
, i
);
3935 aff
= aff_from_pw_aff(pa
);
3938 if (isl_aff_involves_dims(aff
, isl_dim_in
, dim
, i
+ 1)) {
3940 isl_die(s
->ctx
, isl_error_invalid
,
3941 "not an affine expression", goto error
);
3943 aff
= isl_aff_drop_dims(aff
, isl_dim_in
, dim
, n
);
3944 space
= isl_multi_aff_get_domain_space(ma
);
3945 aff
= isl_aff_reset_domain_space(aff
, space
);
3946 ma
= isl_multi_aff_set_aff(ma
, i
, aff
);
3949 isl_multi_pw_aff_free(tuple
);
3954 isl_multi_pw_aff_free(tuple
);
3957 isl_multi_aff_free(ma
);
3961 __isl_give isl_multi_aff
*isl_multi_aff_read_from_str(isl_ctx
*ctx
,
3964 isl_multi_aff
*maff
;
3965 isl_stream
*s
= isl_stream_new_str(ctx
, str
);
3968 maff
= isl_stream_read_multi_aff(s
);
3973 /* Read an isl_multi_pw_aff from "s".
3975 * The input format is similar to that of map, except that any conditions
3976 * on the domains should be specified inside the tuple since each
3977 * piecewise affine expression may have a different domain.
3978 * However, additional, shared conditions can also be specified.
3979 * This is especially useful for setting the explicit domain
3980 * of a zero-dimensional isl_multi_pw_aff.
3982 * Since we do not know in advance if the isl_multi_pw_aff lives
3983 * in a set or a map space, we first read the first tuple and check
3984 * if it is followed by a "->". If so, we convert the tuple into
3985 * the domain of the isl_multi_pw_aff and read in the next tuple.
3986 * This tuple (or the first tuple if it was not followed by a "->")
3987 * is then converted into the isl_multi_pw_aff through a call
3988 * to extract_mpa_from_tuple and the domain of the result
3989 * is intersected with the domain.
3991 __isl_give isl_multi_pw_aff
*isl_stream_read_multi_pw_aff(
3992 __isl_keep isl_stream
*s
)
3995 isl_set
*dom
= NULL
;
3996 isl_multi_pw_aff
*tuple
= NULL
;
3997 isl_multi_pw_aff
*mpa
= NULL
;
3999 v
= vars_new(s
->ctx
);
4003 dom
= isl_set_universe(isl_space_params_alloc(s
->ctx
, 0));
4004 if (next_is_tuple(s
)) {
4005 dom
= read_map_tuple(s
, dom
, isl_dim_param
, v
, 1, 0);
4006 if (isl_stream_eat(s
, ISL_TOKEN_TO
))
4009 if (isl_stream_eat(s
, '{'))
4012 tuple
= read_tuple(s
, v
, 0, 0);
4015 if (isl_stream_eat_if_available(s
, ISL_TOKEN_TO
)) {
4016 isl_map
*map
= map_from_tuple(tuple
, dom
, isl_dim_in
, v
, 0);
4017 dom
= isl_map_domain(map
);
4018 tuple
= read_tuple(s
, v
, 0, 0);
4023 if (isl_stream_eat_if_available(s
, ':'))
4024 dom
= read_formula(s
, v
, dom
, 0);
4026 if (isl_stream_eat(s
, '}'))
4029 mpa
= extract_mpa_from_tuple(isl_set_get_space(dom
), tuple
);
4031 isl_multi_pw_aff_free(tuple
);
4033 mpa
= isl_multi_pw_aff_intersect_domain(mpa
, dom
);
4036 isl_multi_pw_aff_free(tuple
);
4039 isl_multi_pw_aff_free(mpa
);
4043 /* Read an isl_multi_pw_aff from "str".
4045 __isl_give isl_multi_pw_aff
*isl_multi_pw_aff_read_from_str(isl_ctx
*ctx
,
4048 isl_multi_pw_aff
*mpa
;
4049 isl_stream
*s
= isl_stream_new_str(ctx
, str
);
4052 mpa
= isl_stream_read_multi_pw_aff(s
);
4057 /* Read the body of an isl_union_pw_aff from "s" with parameter domain "dom".
4059 static __isl_give isl_union_pw_aff
*read_union_pw_aff_with_dom(
4060 __isl_keep isl_stream
*s
, __isl_take isl_set
*dom
, struct vars
*v
)
4063 isl_union_pw_aff
*upa
= NULL
;
4068 aff_dom
= read_aff_domain(s
, isl_set_copy(dom
), v
);
4069 pa
= read_pw_aff_with_dom(s
, aff_dom
, v
);
4070 vars_drop(v
, v
->n
- n
);
4072 upa
= isl_union_pw_aff_from_pw_aff(pa
);
4074 while (isl_stream_eat_if_available(s
, ';')) {
4076 isl_union_pw_aff
*upa_i
;
4079 aff_dom
= read_aff_domain(s
, isl_set_copy(dom
), v
);
4080 pa_i
= read_pw_aff_with_dom(s
, aff_dom
, v
);
4081 vars_drop(v
, v
->n
- n
);
4083 upa_i
= isl_union_pw_aff_from_pw_aff(pa_i
);
4084 upa
= isl_union_pw_aff_union_add(upa
, upa_i
);
4091 /* Read an isl_union_pw_aff from "s".
4093 * First check if there are any paramters, then read in the opening brace
4094 * and use read_union_pw_aff_with_dom to read in the body of
4095 * the isl_union_pw_aff. Finally, read the closing brace.
4097 __isl_give isl_union_pw_aff
*isl_stream_read_union_pw_aff(
4098 __isl_keep isl_stream
*s
)
4102 isl_union_pw_aff
*upa
= NULL
;
4104 v
= vars_new(s
->ctx
);
4108 dom
= isl_set_universe(isl_space_params_alloc(s
->ctx
, 0));
4109 if (next_is_tuple(s
)) {
4110 dom
= read_map_tuple(s
, dom
, isl_dim_param
, v
, 1, 0);
4111 if (isl_stream_eat(s
, ISL_TOKEN_TO
))
4114 if (isl_stream_eat(s
, '{'))
4117 upa
= read_union_pw_aff_with_dom(s
, isl_set_copy(dom
), v
);
4119 if (isl_stream_eat(s
, '}'))
4128 isl_union_pw_aff_free(upa
);
4132 /* Read an isl_union_pw_aff from "str".
4134 __isl_give isl_union_pw_aff
*isl_union_pw_aff_read_from_str(isl_ctx
*ctx
,
4137 isl_union_pw_aff
*upa
;
4138 isl_stream
*s
= isl_stream_new_str(ctx
, str
);
4141 upa
= isl_stream_read_union_pw_aff(s
);
4146 /* This function is called for each element in a tuple inside
4147 * isl_stream_read_multi_union_pw_aff.
4149 * Read a '{', the union piecewise affine expression body and a '}' and
4150 * add the isl_union_pw_aff to *list.
4152 static __isl_give isl_space
*read_union_pw_aff_el(__isl_keep isl_stream
*s
,
4153 struct vars
*v
, __isl_take isl_space
*space
, int rational
, void *user
)
4156 isl_union_pw_aff
*upa
;
4157 isl_union_pw_aff_list
**list
= (isl_union_pw_aff_list
**) user
;
4159 dom
= isl_set_universe(isl_space_params(isl_space_copy(space
)));
4160 if (isl_stream_eat(s
, '{'))
4162 upa
= read_union_pw_aff_with_dom(s
, dom
, v
);
4163 *list
= isl_union_pw_aff_list_add(*list
, upa
);
4164 if (isl_stream_eat(s
, '}'))
4165 return isl_space_free(space
);
4167 return isl_space_free(space
);
4171 return isl_space_free(space
);
4174 /* Do the next tokens in "s" correspond to an empty tuple?
4175 * In particular, does the stream start with a '[', followed by a ']',
4176 * not followed by a "->"?
4178 static int next_is_empty_tuple(__isl_keep isl_stream
*s
)
4180 struct isl_token
*tok
, *tok2
, *tok3
;
4181 int is_empty_tuple
= 0;
4183 tok
= isl_stream_next_token(s
);
4186 if (tok
->type
!= '[') {
4187 isl_stream_push_token(s
, tok
);
4191 tok2
= isl_stream_next_token(s
);
4192 if (tok2
&& tok2
->type
== ']') {
4193 tok3
= isl_stream_next_token(s
);
4194 is_empty_tuple
= !tok
|| tok
->type
!= ISL_TOKEN_TO
;
4196 isl_stream_push_token(s
, tok3
);
4199 isl_stream_push_token(s
, tok2
);
4200 isl_stream_push_token(s
, tok
);
4202 return is_empty_tuple
;
4205 /* Do the next tokens in "s" correspond to a tuple of parameters?
4206 * In particular, does the stream start with a '[' that is not
4207 * followed by a '{' or a nested tuple?
4209 static int next_is_param_tuple(__isl_keep isl_stream
*s
)
4211 struct isl_token
*tok
, *tok2
;
4214 tok
= isl_stream_next_token(s
);
4217 if (tok
->type
!= '[' || next_is_tuple(s
)) {
4218 isl_stream_push_token(s
, tok
);
4222 tok2
= isl_stream_next_token(s
);
4223 is_tuple
= tok2
&& tok2
->type
!= '{';
4225 isl_stream_push_token(s
, tok2
);
4226 isl_stream_push_token(s
, tok
);
4231 /* Read the core of a body of an isl_multi_union_pw_aff from "s",
4232 * i.e., everything except the parameter specification and
4233 * without shared domain constraints.
4234 * "v" contains a description of the identifiers parsed so far.
4235 * The parameters, if any, are specified by "space".
4237 * The body is of the form
4239 * [{ [..] : ... ; [..] : ... }, { [..] : ... ; [..] : ... }]
4241 * Read the tuple, collecting the individual isl_union_pw_aff
4242 * elements in a list and construct the result from the tuple space and
4245 static __isl_give isl_multi_union_pw_aff
*read_multi_union_pw_aff_body_core(
4246 __isl_keep isl_stream
*s
, struct vars
*v
, __isl_take isl_space
*space
)
4248 isl_union_pw_aff_list
*list
;
4249 isl_multi_union_pw_aff
*mupa
;
4251 list
= isl_union_pw_aff_list_alloc(s
->ctx
, 0);
4252 space
= read_tuple_space(s
, v
, space
, 1, 0,
4253 &read_union_pw_aff_el
, &list
);
4254 mupa
= isl_multi_union_pw_aff_from_union_pw_aff_list(space
, list
);
4259 /* Read the body of an isl_union_set from "s",
4260 * i.e., everything except the parameter specification.
4261 * "v" contains a description of the identifiers parsed so far.
4262 * The parameters, if any, are specified by "space".
4264 * First read a generic disjunction of object bodies and then try and extract
4265 * an isl_union_set from that.
4267 static __isl_give isl_union_set
*read_union_set_body(__isl_keep isl_stream
*s
,
4268 struct vars
*v
, __isl_take isl_space
*space
)
4270 struct isl_obj obj
= { isl_obj_set
, NULL
};
4273 map
= isl_set_universe(space
);
4274 if (isl_stream_eat(s
, '{') < 0)
4276 obj
= obj_read_disjuncts(s
, v
, map
);
4277 if (isl_stream_eat(s
, '}') < 0)
4281 return extract_union_set(s
->ctx
, obj
);
4283 obj
.type
->free(obj
.v
);
4288 /* Read the body of an isl_multi_union_pw_aff from "s",
4289 * i.e., everything except the parameter specification.
4290 * "v" contains a description of the identifiers parsed so far.
4291 * The parameters, if any, are specified by "space".
4293 * In particular, handle the special case with shared domain constraints.
4294 * These are specified as
4298 * and are especially useful for setting the explicit domain
4299 * of a zero-dimensional isl_multi_union_pw_aff.
4300 * The core isl_multi_union_pw_aff body ([...]) is read by
4301 * read_multi_union_pw_aff_body_core.
4303 static __isl_give isl_multi_union_pw_aff
*read_multi_union_pw_aff_body(
4304 __isl_keep isl_stream
*s
, struct vars
*v
, __isl_take isl_space
*space
)
4306 isl_multi_union_pw_aff
*mupa
;
4308 if (!isl_stream_next_token_is(s
, '('))
4309 return read_multi_union_pw_aff_body_core(s
, v
, space
);
4311 if (isl_stream_eat(s
, '(') < 0)
4313 mupa
= read_multi_union_pw_aff_body_core(s
, v
, isl_space_copy(space
));
4314 if (isl_stream_eat_if_available(s
, ':')) {
4317 dom
= read_union_set_body(s
, v
, space
);
4318 mupa
= isl_multi_union_pw_aff_intersect_domain(mupa
, dom
);
4320 isl_space_free(space
);
4322 if (isl_stream_eat(s
, ')') < 0)
4323 return isl_multi_union_pw_aff_free(mupa
);
4327 isl_space_free(space
);
4331 /* Read an isl_multi_union_pw_aff from "s".
4333 * The input has the form
4335 * [{ [..] : ... ; [..] : ... }, { [..] : ... ; [..] : ... }]
4339 * [..] -> [{ [..] : ... ; [..] : ... }, { [..] : ... ; [..] : ... }]
4341 * Additionally, a shared domain may be specified as
4347 * [..] -> ([..] : ...)
4349 * The first case is handled by the caller, the second case
4350 * is handled by read_multi_union_pw_aff_body.
4352 * We first check for the special case of an empty tuple "[]".
4353 * Then we check if there are any parameters.
4354 * Finally, read the tuple and construct the result.
4356 static __isl_give isl_multi_union_pw_aff
*read_multi_union_pw_aff_core(
4357 __isl_keep isl_stream
*s
)
4360 isl_set
*dom
= NULL
;
4362 isl_multi_union_pw_aff
*mupa
= NULL
;
4364 if (next_is_empty_tuple(s
)) {
4365 if (isl_stream_eat(s
, '['))
4367 if (isl_stream_eat(s
, ']'))
4369 space
= isl_space_set_alloc(s
->ctx
, 0, 0);
4370 return isl_multi_union_pw_aff_zero(space
);
4373 v
= vars_new(s
->ctx
);
4377 dom
= isl_set_universe(isl_space_params_alloc(s
->ctx
, 0));
4378 if (next_is_param_tuple(s
)) {
4379 dom
= read_map_tuple(s
, dom
, isl_dim_param
, v
, 1, 0);
4380 if (isl_stream_eat(s
, ISL_TOKEN_TO
))
4383 space
= isl_set_get_space(dom
);
4385 mupa
= read_multi_union_pw_aff_body(s
, v
, space
);
4393 isl_multi_union_pw_aff_free(mupa
);
4397 /* Read an isl_multi_union_pw_aff from "s".
4399 * In particular, handle the special case with shared domain constraints.
4400 * These are specified as
4404 * and are especially useful for setting the explicit domain
4405 * of a zero-dimensional isl_multi_union_pw_aff.
4406 * The core isl_multi_union_pw_aff ([...]) is read by
4407 * read_multi_union_pw_aff_core.
4409 __isl_give isl_multi_union_pw_aff
*isl_stream_read_multi_union_pw_aff(
4410 __isl_keep isl_stream
*s
)
4412 isl_multi_union_pw_aff
*mupa
;
4414 if (!isl_stream_next_token_is(s
, '('))
4415 return read_multi_union_pw_aff_core(s
);
4417 if (isl_stream_eat(s
, '(') < 0)
4419 mupa
= read_multi_union_pw_aff_core(s
);
4420 if (isl_stream_eat_if_available(s
, ':')) {
4423 dom
= isl_stream_read_union_set(s
);
4424 mupa
= isl_multi_union_pw_aff_intersect_domain(mupa
, dom
);
4426 if (isl_stream_eat(s
, ')') < 0)
4427 return isl_multi_union_pw_aff_free(mupa
);
4431 /* Read an isl_multi_union_pw_aff from "str".
4433 __isl_give isl_multi_union_pw_aff
*isl_multi_union_pw_aff_read_from_str(
4434 isl_ctx
*ctx
, const char *str
)
4436 isl_multi_union_pw_aff
*mupa
;
4437 isl_stream
*s
= isl_stream_new_str(ctx
, str
);
4440 mupa
= isl_stream_read_multi_union_pw_aff(s
);
4445 __isl_give isl_union_pw_qpolynomial
*isl_stream_read_union_pw_qpolynomial(
4446 __isl_keep isl_stream
*s
)
4451 if (obj
.type
== isl_obj_pw_qpolynomial
) {
4452 obj
.type
= isl_obj_union_pw_qpolynomial
;
4453 obj
.v
= isl_union_pw_qpolynomial_from_pw_qpolynomial(obj
.v
);
4456 isl_assert(s
->ctx
, obj
.type
== isl_obj_union_pw_qpolynomial
,
4461 obj
.type
->free(obj
.v
);
4465 __isl_give isl_union_pw_qpolynomial
*isl_union_pw_qpolynomial_read_from_str(
4466 isl_ctx
*ctx
, const char *str
)
4468 isl_union_pw_qpolynomial
*upwqp
;
4469 isl_stream
*s
= isl_stream_new_str(ctx
, str
);
4472 upwqp
= isl_stream_read_union_pw_qpolynomial(s
);