2 * Copyright 2008-2009 Katholieke Universiteit Leuven
3 * Copyright 2010 INRIA Saclay
4 * Copyright 2012-2013 Ecole Normale Superieure
5 * Copyright 2019,2022 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
185 * "-" n "/" d -> -n/d
189 * where n, d and v are integer constants.
191 __isl_give isl_val
*isl_stream_read_val(__isl_keep isl_stream
*s
)
193 struct isl_token
*tok
= NULL
;
194 struct isl_token
*tok2
= NULL
;
198 if (isl_stream_eat_if_available(s
, '-'))
202 isl_stream_error(s
, NULL
, "unexpected EOF");
205 if (tok
->type
== ISL_TOKEN_INFTY
) {
208 return isl_val_infty(s
->ctx
);
210 return isl_val_neginfty(s
->ctx
);
212 if (sign
> 0 && tok
->type
== ISL_TOKEN_NAN
) {
214 return isl_val_nan(s
->ctx
);
216 if (tok
->type
!= ISL_TOKEN_VALUE
) {
217 isl_stream_error(s
, tok
, "expecting value");
222 isl_int_neg(tok
->u
.v
, tok
->u
.v
);
224 if (isl_stream_eat_if_available(s
, '/')) {
225 tok2
= next_token(s
);
227 isl_stream_error(s
, NULL
, "unexpected EOF");
230 if (tok2
->type
!= ISL_TOKEN_VALUE
) {
231 isl_stream_error(s
, tok2
, "expecting value");
234 val
= isl_val_rat_from_isl_int(s
->ctx
, tok
->u
.v
, tok2
->u
.v
);
235 val
= isl_val_normalize(val
);
237 val
= isl_val_int_from_isl_int(s
->ctx
, tok
->u
.v
);
241 isl_token_free(tok2
);
245 isl_token_free(tok2
);
250 #define TYPE_BASE val
251 #include "isl_read_from_str_templ.c"
253 static isl_stat
accept_cst_factor(__isl_keep isl_stream
*s
, isl_int
*f
)
255 struct isl_token
*tok
;
257 if (isl_stream_eat_if_available(s
, '-'))
260 if (!tok
|| tok
->type
!= ISL_TOKEN_VALUE
) {
261 isl_stream_error(s
, tok
, "expecting constant value");
265 isl_int_mul(*f
, *f
, tok
->u
.v
);
269 if (isl_stream_eat_if_available(s
, '*'))
270 return accept_cst_factor(s
, f
);
275 return isl_stat_error
;
278 /* Given an affine expression aff, return an affine expression
279 * for aff % d, with d the next token on the stream, which is
280 * assumed to be a constant.
282 * We introduce an integer division q = [aff/d] and the result
283 * is set to aff - d q.
285 static __isl_give isl_pw_aff
*affine_mod(__isl_keep isl_stream
*s
,
286 struct vars
*v
, __isl_take isl_pw_aff
*aff
)
288 struct isl_token
*tok
;
292 if (!tok
|| tok
->type
!= ISL_TOKEN_VALUE
) {
293 isl_stream_error(s
, tok
, "expecting constant value");
297 q
= isl_pw_aff_copy(aff
);
298 q
= isl_pw_aff_scale_down(q
, tok
->u
.v
);
299 q
= isl_pw_aff_floor(q
);
300 q
= isl_pw_aff_scale(q
, tok
->u
.v
);
302 aff
= isl_pw_aff_sub(aff
, q
);
307 isl_pw_aff_free(aff
);
312 static __isl_give isl_pw_aff
*accept_affine(__isl_keep isl_stream
*s
,
313 __isl_take isl_space
*space
, struct vars
*v
);
314 static __isl_give isl_pw_aff_list
*accept_affine_list(__isl_keep isl_stream
*s
,
315 __isl_take isl_space
*space
, struct vars
*v
);
317 static __isl_give isl_pw_aff
*accept_minmax(__isl_keep isl_stream
*s
,
318 __isl_take isl_space
*space
, struct vars
*v
)
320 struct isl_token
*tok
;
321 isl_pw_aff_list
*list
= NULL
;
324 tok
= isl_stream_next_token(s
);
327 min
= tok
->type
== ISL_TOKEN_MIN
;
330 if (isl_stream_eat(s
, '('))
333 list
= accept_affine_list(s
, isl_space_copy(space
), v
);
337 if (isl_stream_eat(s
, ')'))
340 isl_space_free(space
);
341 return min
? isl_pw_aff_list_min(list
) : isl_pw_aff_list_max(list
);
343 isl_space_free(space
);
344 isl_pw_aff_list_free(list
);
348 /* Divide "pa" by an integer constant read from the stream.
350 static __isl_give isl_pw_aff
*pw_aff_div_by_cst(__isl_keep isl_stream
*s
,
351 __isl_take isl_pw_aff
*pa
)
353 struct isl_token
*tok
;
356 if (!tok
|| tok
->type
!= ISL_TOKEN_VALUE
) {
357 isl_stream_error(s
, tok
, "expecting denominator");
359 return isl_pw_aff_free(pa
);
362 pa
= isl_pw_aff_scale_down(pa
, tok
->u
.v
);
369 /* Return the (signed) value that is next on the stream,
370 * using "next" to read the next token and printing "msg" in case of an error.
372 static struct isl_token
*next_signed_value_fn(__isl_keep isl_stream
*s
,
373 struct isl_token
*(*next
)(__isl_keep isl_stream
*s
), char *msg
)
375 struct isl_token
*tok
;
378 if (isl_stream_eat_if_available(s
, '-'))
381 if (!tok
|| tok
->type
!= ISL_TOKEN_VALUE
) {
382 isl_stream_error(s
, tok
, msg
);
387 isl_int_neg(tok
->u
.v
, tok
->u
.v
);
391 /* Return the (signed) value that is next on the stream,
392 * printing "msg" in case of an error.
394 static struct isl_token
*next_signed_value(__isl_keep isl_stream
*s
, char *msg
)
396 return next_signed_value_fn(s
, &isl_stream_next_token
, msg
);
399 /* Return the (signed) value that is next on the stream,
400 * provided it is on the same line,
401 * printing "msg" in case of an error.
403 static struct isl_token
*next_signed_value_on_same_line(
404 __isl_keep isl_stream
*s
, char *msg
)
406 return next_signed_value_fn(s
,
407 &isl_stream_next_token_on_same_line
, msg
);
410 /* Is "tok" the start of an integer division?
412 static int is_start_of_div(struct isl_token
*tok
)
416 if (tok
->type
== '[')
418 if (tok
->type
== ISL_TOKEN_FLOOR
)
420 if (tok
->type
== ISL_TOKEN_CEIL
)
422 if (tok
->type
== ISL_TOKEN_FLOORD
)
424 if (tok
->type
== ISL_TOKEN_CEILD
)
429 /* Read an integer division from "s" and return it as an isl_pw_aff.
431 * The integer division can be of the form
433 * [<affine expression>]
434 * floor(<affine expression>)
435 * ceil(<affine expression>)
436 * floord(<affine expression>,<denominator>)
437 * ceild(<affine expression>,<denominator>)
439 static __isl_give isl_pw_aff
*accept_div(__isl_keep isl_stream
*s
,
440 __isl_take isl_space
*space
, struct vars
*v
)
445 isl_pw_aff
*pwaff
= NULL
;
447 if (isl_stream_eat_if_available(s
, ISL_TOKEN_FLOORD
))
449 else if (isl_stream_eat_if_available(s
, ISL_TOKEN_CEILD
))
451 else if (isl_stream_eat_if_available(s
, ISL_TOKEN_FLOOR
))
453 else if (isl_stream_eat_if_available(s
, ISL_TOKEN_CEIL
))
456 if (isl_stream_eat(s
, '('))
459 if (isl_stream_eat(s
, '['))
463 pwaff
= accept_affine(s
, isl_space_copy(space
), v
);
466 if (isl_stream_eat(s
, ','))
469 pwaff
= pw_aff_div_by_cst(s
, pwaff
);
473 pwaff
= isl_pw_aff_ceil(pwaff
);
475 pwaff
= isl_pw_aff_floor(pwaff
);
478 if (isl_stream_eat(s
, ')'))
481 if (isl_stream_eat(s
, ']'))
485 isl_space_free(space
);
488 isl_space_free(space
);
489 isl_pw_aff_free(pwaff
);
493 static __isl_give isl_pw_aff
*accept_affine_factor(__isl_keep isl_stream
*s
,
494 __isl_take isl_space
*space
, struct vars
*v
)
496 struct isl_token
*tok
= NULL
;
497 isl_pw_aff
*res
= NULL
;
501 isl_stream_error(s
, NULL
, "unexpected EOF");
505 if (tok
->type
== ISL_TOKEN_AFF
) {
506 res
= isl_pw_aff_copy(tok
->u
.pwaff
);
508 } else if (tok
->type
== ISL_TOKEN_IDENT
) {
510 int pos
= vars_pos(v
, tok
->u
.s
, -1);
516 vars_drop(v
, v
->n
- n
);
517 isl_stream_error(s
, tok
, "unknown identifier");
521 aff
= isl_aff_zero_on_domain(isl_local_space_from_space(isl_space_copy(space
)));
524 aff
->v
= isl_vec_set_element_si(aff
->v
, 2 + pos
, 1);
526 aff
= isl_aff_free(aff
);
527 res
= isl_pw_aff_from_aff(aff
);
529 } else if (tok
->type
== ISL_TOKEN_VALUE
) {
530 if (isl_stream_eat_if_available(s
, '*') ||
531 isl_stream_next_token_is(s
, ISL_TOKEN_IDENT
)) {
532 if (isl_stream_eat_if_available(s
, '-'))
533 isl_int_neg(tok
->u
.v
, tok
->u
.v
);
534 res
= accept_affine_factor(s
, isl_space_copy(space
), v
);
535 res
= isl_pw_aff_scale(res
, tok
->u
.v
);
539 ls
= isl_local_space_from_space(isl_space_copy(space
));
540 aff
= isl_aff_zero_on_domain(ls
);
541 aff
= isl_aff_add_constant(aff
, tok
->u
.v
);
542 res
= isl_pw_aff_from_aff(aff
);
545 } else if (tok
->type
== '(') {
548 res
= accept_affine(s
, isl_space_copy(space
), v
);
551 if (isl_stream_eat(s
, ')'))
553 } else if (is_start_of_div(tok
)) {
554 isl_stream_push_token(s
, tok
);
556 res
= accept_div(s
, isl_space_copy(space
), v
);
557 } else if (tok
->type
== ISL_TOKEN_MIN
|| tok
->type
== ISL_TOKEN_MAX
) {
558 isl_stream_push_token(s
, tok
);
560 res
= accept_minmax(s
, isl_space_copy(space
), v
);
562 isl_stream_error(s
, tok
, "expecting factor");
565 if (isl_stream_eat_if_available(s
, '%') ||
566 isl_stream_eat_if_available(s
, ISL_TOKEN_MOD
)) {
567 isl_space_free(space
);
568 return affine_mod(s
, v
, res
);
570 if (isl_stream_eat_if_available(s
, '*')) {
573 isl_int_set_si(f
, 1);
574 if (accept_cst_factor(s
, &f
) < 0) {
578 res
= isl_pw_aff_scale(res
, f
);
581 if (isl_stream_eat_if_available(s
, '/'))
582 res
= pw_aff_div_by_cst(s
, res
);
583 if (isl_stream_eat_if_available(s
, ISL_TOKEN_INT_DIV
))
584 res
= isl_pw_aff_floor(pw_aff_div_by_cst(s
, res
));
586 isl_space_free(space
);
591 isl_pw_aff_free(res
);
592 isl_space_free(space
);
596 /* Return a piecewise affine expression defined on the specified domain
597 * that represents NaN.
599 static __isl_give isl_pw_aff
*nan_on_domain(__isl_keep isl_space
*space
)
601 return isl_pw_aff_nan_on_domain_space(isl_space_copy(space
));
604 static __isl_give isl_pw_aff
*accept_affine(__isl_keep isl_stream
*s
,
605 __isl_take isl_space
*space
, struct vars
*v
)
607 struct isl_token
*tok
= NULL
;
613 ls
= isl_local_space_from_space(isl_space_copy(space
));
614 res
= isl_pw_aff_from_aff(isl_aff_zero_on_domain(ls
));
621 isl_stream_error(s
, NULL
, "unexpected EOF");
624 if (tok
->type
== '-') {
629 if (tok
->type
== '(' || is_start_of_div(tok
) ||
630 tok
->type
== ISL_TOKEN_MIN
|| tok
->type
== ISL_TOKEN_MAX
||
631 tok
->type
== ISL_TOKEN_IDENT
||
632 tok
->type
== ISL_TOKEN_VALUE
||
633 tok
->type
== ISL_TOKEN_AFF
) {
635 if (tok
->type
== ISL_TOKEN_VALUE
&& sign
< 0) {
636 isl_int_neg(tok
->u
.v
, tok
->u
.v
);
639 isl_stream_push_token(s
, tok
);
641 term
= accept_affine_factor(s
,
642 isl_space_copy(space
), v
);
644 res
= isl_pw_aff_sub(res
, term
);
646 res
= isl_pw_aff_add(res
, term
);
649 } else if (tok
->type
== ISL_TOKEN_NAN
) {
650 res
= isl_pw_aff_add(res
, nan_on_domain(space
));
652 isl_stream_error(s
, tok
, "unexpected isl_token");
653 isl_stream_push_token(s
, tok
);
654 isl_pw_aff_free(res
);
655 isl_space_free(space
);
662 if (tok
&& tok
->type
== '-') {
665 } else if (tok
&& tok
->type
== '+') {
670 isl_stream_push_token(s
, tok
);
675 isl_space_free(space
);
678 isl_space_free(space
);
680 isl_pw_aff_free(res
);
684 /* Is "type" the type of a comparison operator between lists
685 * of affine expressions?
687 static int is_list_comparator_type(int type
)
690 case ISL_TOKEN_LEX_LT
:
691 case ISL_TOKEN_LEX_GT
:
692 case ISL_TOKEN_LEX_LE
:
693 case ISL_TOKEN_LEX_GE
:
700 static int is_comparator(struct isl_token
*tok
)
704 if (is_list_comparator_type(tok
->type
))
720 static __isl_give isl_map
*read_formula(__isl_keep isl_stream
*s
,
721 struct vars
*v
, __isl_take isl_map
*map
, int rational
);
722 static __isl_give isl_pw_aff
*accept_extended_affine(__isl_keep isl_stream
*s
,
723 __isl_take isl_space
*space
, struct vars
*v
, int rational
);
725 /* Accept a ternary operator, given the first argument.
727 static __isl_give isl_pw_aff
*accept_ternary(__isl_keep isl_stream
*s
,
728 __isl_take isl_map
*cond
, struct vars
*v
, int rational
)
731 isl_pw_aff
*pwaff1
= NULL
, *pwaff2
= NULL
, *pa_cond
;
736 if (isl_stream_eat(s
, '?'))
739 space
= isl_space_wrap(isl_map_get_space(cond
));
740 pwaff1
= accept_extended_affine(s
, space
, v
, rational
);
744 if (isl_stream_eat(s
, ':'))
747 space
= isl_pw_aff_get_domain_space(pwaff1
);
748 pwaff2
= accept_extended_affine(s
, space
, v
, rational
);
752 pa_cond
= isl_set_indicator_function(isl_map_wrap(cond
));
753 return isl_pw_aff_cond(pa_cond
, pwaff1
, pwaff2
);
756 isl_pw_aff_free(pwaff1
);
757 isl_pw_aff_free(pwaff2
);
761 /* Set *line and *col to those of the next token, if any.
763 static void set_current_line_col(__isl_keep isl_stream
*s
, int *line
, int *col
)
765 struct isl_token
*tok
;
767 tok
= isl_stream_next_token(s
);
773 isl_stream_push_token(s
, tok
);
776 /* Push a token encapsulating "pa" onto "s", with the given
779 static isl_stat
push_aff(__isl_keep isl_stream
*s
, int line
, int col
,
780 __isl_take isl_pw_aff
*pa
)
782 struct isl_token
*tok
;
784 tok
= isl_token_new(s
->ctx
, line
, col
, 0);
787 tok
->type
= ISL_TOKEN_AFF
;
789 isl_stream_push_token(s
, tok
);
794 return isl_stat_error
;
797 /* Is the next token a comparison operator?
799 static int next_is_comparator(__isl_keep isl_stream
*s
)
802 struct isl_token
*tok
;
804 tok
= isl_stream_next_token(s
);
808 is_comp
= is_comparator(tok
);
809 isl_stream_push_token(s
, tok
);
814 /* Accept an affine expression that may involve ternary operators.
815 * We first read an affine expression.
816 * If it is not followed by a comparison operator, we simply return it.
817 * Otherwise, we assume the affine expression is part of the first
818 * argument of a ternary operator and try to parse that.
820 static __isl_give isl_pw_aff
*accept_extended_affine(__isl_keep isl_stream
*s
,
821 __isl_take isl_space
*space
, struct vars
*v
, int rational
)
825 int line
= -1, col
= -1;
827 set_current_line_col(s
, &line
, &col
);
829 pwaff
= accept_affine(s
, space
, v
);
831 pwaff
= isl_pw_aff_set_rational(pwaff
);
834 if (!next_is_comparator(s
))
837 space
= isl_pw_aff_get_domain_space(pwaff
);
838 cond
= isl_map_universe(isl_space_unwrap(space
));
840 if (push_aff(s
, line
, col
, pwaff
) < 0)
841 cond
= isl_map_free(cond
);
845 cond
= read_formula(s
, v
, cond
, rational
);
847 return accept_ternary(s
, cond
, v
, rational
);
850 static __isl_give isl_map
*read_var_def(__isl_keep isl_stream
*s
,
851 __isl_take isl_map
*map
, enum isl_dim_type type
, struct vars
*v
,
858 if (type
== isl_dim_param
)
859 pos
= isl_map_dim(map
, isl_dim_param
);
861 pos
= isl_map_dim(map
, isl_dim_in
);
862 if (type
== isl_dim_out
) {
863 isl_size n_out
= isl_map_dim(map
, isl_dim_out
);
864 if (pos
< 0 || n_out
< 0)
865 return isl_map_free(map
);
871 return isl_map_free(map
);
874 def
= accept_extended_affine(s
, isl_space_wrap(isl_map_get_space(map
)),
876 def_map
= isl_map_from_pw_aff(def
);
877 def_map
= isl_map_equate(def_map
, type
, pos
, isl_dim_out
, 0);
878 def_map
= isl_set_unwrap(isl_map_domain(def_map
));
880 map
= isl_map_intersect(map
, def_map
);
885 static __isl_give isl_pw_aff_list
*accept_affine_list(__isl_keep isl_stream
*s
,
886 __isl_take isl_space
*space
, struct vars
*v
)
889 isl_pw_aff_list
*list
;
890 struct isl_token
*tok
= NULL
;
892 pwaff
= accept_affine(s
, isl_space_copy(space
), v
);
893 list
= isl_pw_aff_list_from_pw_aff(pwaff
);
898 tok
= isl_stream_next_token(s
);
900 isl_stream_error(s
, NULL
, "unexpected EOF");
903 if (tok
->type
!= ',') {
904 isl_stream_push_token(s
, tok
);
909 pwaff
= accept_affine(s
, isl_space_copy(space
), v
);
910 list
= isl_pw_aff_list_concat(list
,
911 isl_pw_aff_list_from_pw_aff(pwaff
));
916 isl_space_free(space
);
919 isl_space_free(space
);
920 isl_pw_aff_list_free(list
);
924 static __isl_give isl_map
*read_defined_var_list(__isl_keep isl_stream
*s
,
925 struct vars
*v
, __isl_take isl_map
*map
, int rational
)
927 struct isl_token
*tok
;
929 while ((tok
= isl_stream_next_token(s
)) != NULL
) {
933 if (tok
->type
!= ISL_TOKEN_IDENT
)
936 p
= vars_pos(v
, tok
->u
.s
, -1);
940 isl_stream_error(s
, tok
, "expecting unique identifier");
944 map
= isl_map_add_dims(map
, isl_dim_out
, 1);
947 tok
= isl_stream_next_token(s
);
948 if (tok
&& tok
->type
== '=') {
950 map
= read_var_def(s
, map
, isl_dim_out
, v
, rational
);
951 tok
= isl_stream_next_token(s
);
954 if (!tok
|| tok
->type
!= ',')
960 isl_stream_push_token(s
, tok
);
969 static int next_is_tuple(__isl_keep isl_stream
*s
)
971 struct isl_token
*tok
;
974 tok
= isl_stream_next_token(s
);
977 if (tok
->type
== '[') {
978 isl_stream_push_token(s
, tok
);
981 if (tok
->type
!= ISL_TOKEN_IDENT
&& !tok
->is_keyword
) {
982 isl_stream_push_token(s
, tok
);
986 is_tuple
= isl_stream_next_token_is(s
, '[');
988 isl_stream_push_token(s
, tok
);
993 /* Does the next token mark the end of a tuple element?
995 static int next_is_end_tuple_element(__isl_keep isl_stream
*s
)
997 return isl_stream_next_token_is(s
, ',') ||
998 isl_stream_next_token_is(s
, ']');
1001 /* Is the next token one that necessarily forms the start of a condition?
1003 static int next_is_condition_start(__isl_keep isl_stream
*s
)
1005 return isl_stream_next_token_is(s
, ISL_TOKEN_EXISTS
) ||
1006 isl_stream_next_token_is(s
, ISL_TOKEN_NOT
) ||
1007 isl_stream_next_token_is(s
, ISL_TOKEN_TRUE
) ||
1008 isl_stream_next_token_is(s
, ISL_TOKEN_FALSE
) ||
1009 isl_stream_next_token_is(s
, ISL_TOKEN_MAP
);
1012 /* Is "pa" an expression in term of earlier dimensions?
1013 * The alternative is that the dimension is defined to be equal to itself,
1014 * meaning that it has a universe domain and an expression that depends
1015 * on itself. "i" is the position of the expression in a sequence
1016 * of "n" expressions. The final dimensions of "pa" correspond to
1017 * these "n" expressions.
1019 static isl_bool
pw_aff_is_expr(__isl_keep isl_pw_aff
*pa
, int i
, int n
)
1024 return isl_bool_error
;
1026 return isl_bool_true
;
1027 if (!isl_set_plain_is_universe(pa
->p
[0].set
))
1028 return isl_bool_true
;
1031 if (isl_int_is_zero(aff
->v
->el
[aff
->v
->size
- n
+ i
]))
1032 return isl_bool_true
;
1033 return isl_bool_false
;
1036 /* Does the tuple contain any dimensions that are defined
1037 * in terms of earlier dimensions?
1039 static isl_bool
tuple_has_expr(__isl_keep isl_multi_pw_aff
*tuple
)
1043 isl_bool has_expr
= isl_bool_false
;
1046 n
= isl_multi_pw_aff_dim(tuple
, isl_dim_out
);
1048 return isl_bool_error
;
1049 for (i
= 0; i
< n
; ++i
) {
1050 pa
= isl_multi_pw_aff_get_pw_aff(tuple
, i
);
1051 has_expr
= pw_aff_is_expr(pa
, i
, n
);
1052 isl_pw_aff_free(pa
);
1053 if (has_expr
< 0 || has_expr
)
1060 /* Set the name of dimension "pos" in "space" to "name".
1061 * During printing, we add primes if the same name appears more than once
1062 * to distinguish the occurrences. Here, we remove those primes from "name"
1063 * before setting the name of the dimension.
1065 static __isl_give isl_space
*space_set_dim_name(__isl_take isl_space
*space
,
1066 int pos
, char *name
)
1073 prime
= strchr(name
, '\'');
1076 space
= isl_space_set_dim_name(space
, isl_dim_out
, pos
, name
);
1083 /* Set the name of the last (output) dimension of "space" to "name",
1084 * ignoring any primes in "name".
1086 static __isl_give isl_space
*space_set_last_dim_name(
1087 __isl_take isl_space
*space
, char *name
)
1091 pos
= isl_space_dim(space
, isl_dim_out
);
1093 return isl_space_free(space
);
1094 return space_set_dim_name(space
, pos
- 1, name
);
1097 /* Construct an isl_pw_aff defined on a "space" (with v->n variables)
1098 * that is equal to the last of those variables.
1100 static __isl_give isl_pw_aff
*identity_tuple_el_on_space(
1101 __isl_take isl_space
*space
, struct vars
*v
)
1105 aff
= isl_aff_zero_on_domain(isl_local_space_from_space(space
));
1106 aff
= isl_aff_add_coefficient_si(aff
, isl_dim_in
, v
->n
- 1, 1);
1107 return isl_pw_aff_from_aff(aff
);
1110 /* Construct an isl_pw_aff defined on the domain space of "pa"
1111 * that is equal to the last variable in "v".
1113 * That is, if D is the domain space of "pa", then construct
1117 static __isl_give isl_pw_aff
*init_range(__isl_keep isl_pw_aff
*pa
,
1122 space
= isl_pw_aff_get_domain_space(pa
);
1123 return identity_tuple_el_on_space(space
, v
);
1126 /* Impose the lower bound "lower" on the variable represented by "range_pa".
1128 * In particular, "range_pa" is of the form
1130 * D[..., i] -> i : C
1132 * with D also the domains space of "lower' and "C" some constraints.
1134 * Return the expression
1136 * D[..., i] -> i : C and i >= lower
1138 static __isl_give isl_pw_aff
*set_lower(__isl_take isl_pw_aff
*range_pa
,
1139 __isl_take isl_pw_aff
*lower
)
1143 range
= isl_pw_aff_ge_set(isl_pw_aff_copy(range_pa
), lower
);
1144 return isl_pw_aff_intersect_domain(range_pa
, range
);
1147 /* Impose the upper bound "upper" on the variable represented by "range_pa".
1149 * In particular, "range_pa" is of the form
1151 * D[..., i] -> i : C
1153 * with D also the domains space of "upper' and "C" some constraints.
1155 * Return the expression
1157 * D[..., i] -> i : C and i <= upper
1159 static __isl_give isl_pw_aff
*set_upper(__isl_take isl_pw_aff
*range_pa
,
1160 __isl_take isl_pw_aff
*upper
)
1164 range
= isl_pw_aff_le_set(isl_pw_aff_copy(range_pa
), upper
);
1165 return isl_pw_aff_intersect_domain(range_pa
, range
);
1168 /* Construct a piecewise affine expression corresponding
1169 * to the last variable in "v" that is greater than or equal to "pa".
1171 * In particular, if D is the domain space of "pa",
1172 * then construct the expression
1176 * impose lower bound "pa" and return
1178 * D[..., i] -> i : i >= pa
1180 static __isl_give isl_pw_aff
*construct_lower(__isl_take isl_pw_aff
*pa
,
1183 return set_lower(init_range(pa
, v
), pa
);
1186 /* Construct a piecewise affine expression corresponding
1187 * to the last variable in "v" that is smaller than or equal to "pa".
1189 * In particular, if D is the domain space of "pa",
1190 * then construct the expression
1194 * impose lower bound "pa" and return
1196 * D[..., i] -> i : i <= pa
1198 static __isl_give isl_pw_aff
*construct_upper(__isl_take isl_pw_aff
*pa
,
1201 return set_upper(init_range(pa
, v
), pa
);
1204 /* Construct a piecewise affine expression corresponding
1205 * to the last variable in "v" that ranges between "pa" and "pa2".
1207 * In particular, if D is the domain space of "pa" (and "pa2"),
1208 * then construct the expression
1212 * impose lower bound "pa" and upper bound "pa2" and return
1214 * D[..., i] -> i : pa <= i <= pa2
1216 static __isl_give isl_pw_aff
*construct_range(__isl_take isl_pw_aff
*pa
,
1217 __isl_take isl_pw_aff
*pa2
, struct vars
*v
)
1219 return set_upper(set_lower(init_range(pa
, v
), pa
), pa2
);
1222 static int resolve_paren_expr(__isl_keep isl_stream
*s
,
1223 struct vars
*v
, __isl_take isl_map
*map
, int rational
);
1225 /* Given that the (piecewise) affine expression "pa"
1226 * has just been parsed, followed by a colon,
1227 * continue parsing as part of a piecewise affine expression.
1229 * In particular, check if the colon is followed by a condition.
1230 * If so, parse the conditions(a) on "pa" and include them in the domain.
1231 * Otherwise, if the colon is followed by another (piecewise) affine expression
1232 * then consider the two expressions as endpoints of a range of values and
1233 * return a piecewise affine expression that takes values in that range.
1234 * Note that an affine expression followed by a comparison operator
1235 * is considered to be part of a condition.
1236 * If the colon is not followed by anything (inside the tuple element),
1237 * then consider "pa" as a lower bound on a range of values without upper bound
1238 * and return a piecewise affine expression that takes values in that range.
1240 static __isl_give isl_pw_aff
*update_piecewise_affine_colon(
1241 __isl_take isl_pw_aff
*pa
, __isl_keep isl_stream
*s
,
1242 struct vars
*v
, int rational
)
1244 isl_space
*dom_space
;
1247 dom_space
= isl_pw_aff_get_domain_space(pa
);
1248 map
= isl_map_universe(isl_space_from_domain(dom_space
));
1250 if (isl_stream_next_token_is(s
, '('))
1251 if (resolve_paren_expr(s
, v
, isl_map_copy(map
), rational
))
1253 if (next_is_end_tuple_element(s
)) {
1255 return construct_lower(pa
, v
);
1257 if (!next_is_condition_start(s
)) {
1258 int line
= -1, col
= -1;
1262 set_current_line_col(s
, &line
, &col
);
1263 space
= isl_space_wrap(isl_map_get_space(map
));
1264 pa2
= accept_affine(s
, space
, v
);
1266 pa2
= isl_pw_aff_set_rational(pa2
);
1267 if (!next_is_comparator(s
)) {
1269 pa2
= isl_pw_aff_domain_factor_domain(pa2
);
1270 return construct_range(pa
, pa2
, v
);
1272 if (push_aff(s
, line
, col
, pa2
) < 0)
1276 map
= read_formula(s
, v
, map
, rational
);
1277 pa
= isl_pw_aff_intersect_domain(pa
, isl_map_domain(map
));
1282 isl_pw_aff_free(pa
);
1286 /* Accept a piecewise affine expression.
1288 * At the outer level, the piecewise affine expression may be of the form
1290 * aff1 : condition1; aff2 : conditions2; ...
1303 * each of the affine expressions may in turn include ternary operators.
1305 * If the first token is a colon, then the expression must be
1306 * ":" or ": aff2", depending on whether anything follows the colon
1307 * inside the tuple element.
1308 * The first is considered to represent an arbitrary value.
1309 * The second is considered to represent a range of values
1310 * with the given upper bound and no lower bound.
1312 * There may be parentheses around some subexpression of "aff1"
1313 * around "aff1" itself, around "aff1 : condition1" and/or
1314 * around the entire piecewise affine expression.
1315 * We therefore remove the opening parenthesis (if any) from the stream
1316 * in case the closing parenthesis follows the colon, but if the closing
1317 * parenthesis is the first thing in the stream after the parsed affine
1318 * expression, we push the parsed expression onto the stream and parse
1319 * again in case the parentheses enclose some subexpression of "aff1".
1321 static __isl_give isl_pw_aff
*accept_piecewise_affine(__isl_keep isl_stream
*s
,
1322 __isl_take isl_space
*space
, struct vars
*v
, int rational
)
1325 isl_space
*res_space
;
1327 if (isl_stream_eat_if_available(s
, ':')) {
1328 if (next_is_end_tuple_element(s
))
1329 return identity_tuple_el_on_space(space
, v
);
1331 return construct_upper(accept_affine(s
, space
, v
), v
);
1334 res_space
= isl_space_from_domain(isl_space_copy(space
));
1335 res_space
= isl_space_add_dims(res_space
, isl_dim_out
, 1);
1336 res
= isl_pw_aff_empty(res_space
);
1340 int line
= -1, col
= -1;
1342 set_current_line_col(s
, &line
, &col
);
1343 seen_paren
= isl_stream_eat_if_available(s
, '(');
1345 pa
= accept_piecewise_affine(s
, isl_space_copy(space
),
1348 pa
= accept_extended_affine(s
, isl_space_copy(space
),
1350 if (seen_paren
&& isl_stream_eat_if_available(s
, ')')) {
1352 if (push_aff(s
, line
, col
, pa
) < 0)
1354 pa
= accept_extended_affine(s
, isl_space_copy(space
),
1357 if (pa
&& isl_stream_eat_if_available(s
, ':'))
1358 pa
= update_piecewise_affine_colon(pa
, s
, v
, rational
);
1360 res
= isl_pw_aff_union_add(res
, pa
);
1362 if (!res
|| (seen_paren
&& isl_stream_eat(s
, ')')))
1364 } while (isl_stream_eat_if_available(s
, ';'));
1366 isl_space_free(space
);
1370 isl_space_free(space
);
1371 return isl_pw_aff_free(res
);
1374 /* Read an affine expression from "s" for use in read_tuple.
1376 * accept_extended_affine requires a wrapped space as input.
1377 * read_tuple on the other hand expects each isl_pw_aff
1378 * to have an anonymous space. We therefore adjust the space
1379 * of the isl_pw_aff before returning it.
1381 static __isl_give isl_pw_aff
*read_tuple_var_def(__isl_keep isl_stream
*s
,
1382 struct vars
*v
, int rational
)
1387 space
= isl_space_wrap(isl_space_alloc(s
->ctx
, 0, v
->n
, 0));
1389 def
= accept_piecewise_affine(s
, space
, v
, rational
);
1390 def
= isl_pw_aff_domain_factor_domain(def
);
1395 /* Read a list of tuple elements by calling "read_el" on each of them and
1396 * return a space with the same number of set dimensions derived from
1397 * the parameter space "space" and possibly updated by "read_el".
1398 * The elements in the list are separated by either "," or "][".
1399 * If "comma" is set then only "," is allowed.
1401 static __isl_give isl_space
*read_tuple_list(__isl_keep isl_stream
*s
,
1402 struct vars
*v
, __isl_take isl_space
*space
, int rational
, int comma
,
1403 __isl_give isl_space
*(*read_el
)(__isl_keep isl_stream
*s
,
1404 struct vars
*v
, __isl_take isl_space
*space
, int rational
,
1411 space
= isl_space_set_from_params(space
);
1413 if (isl_stream_next_token_is(s
, ']'))
1417 struct isl_token
*tok
;
1419 space
= isl_space_add_dims(space
, isl_dim_set
, 1);
1421 space
= read_el(s
, v
, space
, rational
, user
);
1425 tok
= isl_stream_next_token(s
);
1426 if (!comma
&& tok
&& tok
->type
== ']' &&
1427 isl_stream_next_token_is(s
, '[')) {
1428 isl_token_free(tok
);
1429 tok
= isl_stream_next_token(s
);
1430 } else if (!tok
|| tok
->type
!= ',') {
1432 isl_stream_push_token(s
, tok
);
1436 isl_token_free(tok
);
1442 /* Read a tuple space from "s" derived from the parameter space "space".
1443 * Call "read_el" on each element in the tuples.
1445 static __isl_give isl_space
*read_tuple_space(__isl_keep isl_stream
*s
,
1446 struct vars
*v
, __isl_take isl_space
*space
, int rational
, int comma
,
1447 __isl_give isl_space
*(*read_el
)(__isl_keep isl_stream
*s
,
1448 struct vars
*v
, __isl_take isl_space
*space
, int rational
,
1452 struct isl_token
*tok
;
1454 isl_space
*res
= NULL
;
1456 tok
= isl_stream_next_token(s
);
1459 if (tok
->type
== ISL_TOKEN_IDENT
|| tok
->is_keyword
) {
1460 name
= strdup(tok
->u
.s
);
1461 isl_token_free(tok
);
1465 isl_stream_push_token(s
, tok
);
1466 if (isl_stream_eat(s
, '['))
1468 if (next_is_tuple(s
)) {
1470 res
= read_tuple_space(s
, v
, isl_space_copy(space
),
1471 rational
, comma
, read_el
, user
);
1472 if (isl_stream_eat(s
, ISL_TOKEN_TO
))
1474 out
= read_tuple_space(s
, v
, isl_space_copy(space
),
1475 rational
, comma
, read_el
, user
);
1476 res
= isl_space_product(res
, out
);
1478 res
= read_tuple_list(s
, v
, isl_space_copy(space
),
1479 rational
, comma
, read_el
, user
);
1480 if (!res
|| isl_stream_eat(s
, ']'))
1484 res
= isl_space_set_tuple_name(res
, isl_dim_set
, name
);
1488 isl_space_free(space
);
1492 isl_space_free(res
);
1493 isl_space_free(space
);
1497 /* Construct an isl_pw_aff defined on a space with v->n variables
1498 * that is equal to the last of those variables.
1500 static __isl_give isl_pw_aff
*identity_tuple_el(struct vars
*v
)
1504 space
= isl_space_set_alloc(v
->ctx
, 0, v
->n
);
1505 return identity_tuple_el_on_space(space
, v
);
1508 /* This function is called for each element in a tuple inside read_tuple.
1509 * Add a new variable to "v" and construct a corresponding isl_pw_aff defined
1510 * over a space containing all variables in "v" defined so far.
1511 * The isl_pw_aff expresses the new variable in terms of earlier variables
1512 * if a definition is provided. Otherwise, it is represented as being
1514 * Add the isl_pw_aff to *list.
1515 * If the new variable was named, then adjust "space" accordingly and
1516 * return the updated space.
1518 static __isl_give isl_space
*read_tuple_pw_aff_el(__isl_keep isl_stream
*s
,
1519 struct vars
*v
, __isl_take isl_space
*space
, int rational
, void *user
)
1521 isl_pw_aff_list
**list
= (isl_pw_aff_list
**) user
;
1523 struct isl_token
*tok
;
1526 tok
= next_token(s
);
1528 isl_stream_error(s
, NULL
, "unexpected EOF");
1529 return isl_space_free(space
);
1532 if (tok
->type
== ISL_TOKEN_IDENT
) {
1534 int p
= vars_pos(v
, tok
->u
.s
, -1);
1540 if (tok
->type
== '*') {
1541 if (vars_add_anon(v
) < 0)
1543 isl_token_free(tok
);
1544 pa
= identity_tuple_el(v
);
1545 } else if (new_name
) {
1546 space
= space_set_last_dim_name(space
, v
->v
->name
);
1547 isl_token_free(tok
);
1548 if (isl_stream_eat_if_available(s
, '='))
1549 pa
= read_tuple_var_def(s
, v
, rational
);
1551 pa
= identity_tuple_el(v
);
1553 isl_stream_push_token(s
, tok
);
1555 if (vars_add_anon(v
) < 0)
1557 pa
= read_tuple_var_def(s
, v
, rational
);
1560 *list
= isl_pw_aff_list_add(*list
, pa
);
1562 return isl_space_free(space
);
1566 isl_token_free(tok
);
1567 return isl_space_free(space
);
1570 /* Read a tuple and represent it as an isl_multi_pw_aff.
1571 * The range space of the isl_multi_pw_aff is the space of the tuple.
1572 * The domain space is an anonymous space
1573 * with a dimension for each variable in the set of variables in "v",
1574 * including the variables in the range.
1575 * If a given dimension is not defined in terms of earlier dimensions in
1576 * the input, then the corresponding isl_pw_aff is set equal to one time
1577 * the variable corresponding to the dimension being defined.
1579 * The elements in the tuple are collected in a list by read_tuple_pw_aff_el.
1580 * Each element in this list is defined over a space representing
1581 * the variables defined so far. We need to adjust the earlier
1582 * elements to have as many variables in the domain as the final
1583 * element in the list.
1585 static __isl_give isl_multi_pw_aff
*read_tuple(__isl_keep isl_stream
*s
,
1586 struct vars
*v
, int rational
, int comma
)
1591 isl_pw_aff_list
*list
;
1593 space
= isl_space_params_alloc(v
->ctx
, 0);
1594 list
= isl_pw_aff_list_alloc(s
->ctx
, 0);
1595 space
= read_tuple_space(s
, v
, space
, rational
, comma
,
1596 &read_tuple_pw_aff_el
, &list
);
1597 n
= isl_space_dim(space
, isl_dim_set
);
1599 space
= isl_space_free(space
);
1600 for (i
= 0; i
+ 1 < n
; ++i
) {
1603 pa
= isl_pw_aff_list_get_pw_aff(list
, i
);
1604 pa
= isl_pw_aff_add_dims(pa
, isl_dim_in
, n
- (i
+ 1));
1605 list
= isl_pw_aff_list_set_pw_aff(list
, i
, pa
);
1608 space
= isl_space_from_range(space
);
1609 space
= isl_space_add_dims(space
, isl_dim_in
, v
->n
);
1610 return isl_multi_pw_aff_from_pw_aff_list(space
, list
);
1613 /* Add the tuple represented by the isl_multi_pw_aff "tuple" to "map".
1614 * We first create the appropriate space in "map" based on the range
1615 * space of this isl_multi_pw_aff. Then, we add equalities based
1616 * on the affine expressions. These live in an anonymous space,
1617 * however, so we first need to reset the space to that of "map".
1619 static __isl_give isl_map
*map_from_tuple(__isl_take isl_multi_pw_aff
*tuple
,
1620 __isl_take isl_map
*map
, enum isl_dim_type type
, struct vars
*v
,
1626 isl_space
*space
= NULL
;
1628 n
= isl_multi_pw_aff_dim(tuple
, isl_dim_out
);
1631 ctx
= isl_multi_pw_aff_get_ctx(tuple
);
1632 space
= isl_space_range(isl_multi_pw_aff_get_space(tuple
));
1636 if (type
== isl_dim_param
) {
1637 if (isl_space_has_tuple_name(space
, isl_dim_set
) ||
1638 isl_space_is_wrapping(space
)) {
1639 isl_die(ctx
, isl_error_invalid
,
1640 "parameter tuples cannot be named or nested",
1643 map
= isl_map_add_dims(map
, type
, n
);
1644 for (i
= 0; i
< n
; ++i
) {
1646 if (!isl_space_has_dim_name(space
, isl_dim_set
, i
))
1647 isl_die(ctx
, isl_error_invalid
,
1648 "parameters must be named",
1650 id
= isl_space_get_dim_id(space
, isl_dim_set
, i
);
1651 map
= isl_map_set_dim_id(map
, isl_dim_param
, i
, id
);
1653 } else if (type
== isl_dim_in
) {
1656 set
= isl_set_universe(isl_space_copy(space
));
1658 set
= isl_set_set_rational(set
);
1659 set
= isl_set_intersect_params(set
, isl_map_params(map
));
1660 map
= isl_map_from_domain(set
);
1664 set
= isl_set_universe(isl_space_copy(space
));
1666 set
= isl_set_set_rational(set
);
1667 map
= isl_map_from_domain_and_range(isl_map_domain(map
), set
);
1670 for (i
= 0; i
< n
; ++i
) {
1677 pa
= isl_multi_pw_aff_get_pw_aff(tuple
, i
);
1678 space
= isl_pw_aff_get_domain_space(pa
);
1679 aff
= isl_aff_zero_on_domain(isl_local_space_from_space(space
));
1680 aff
= isl_aff_add_coefficient_si(aff
,
1681 isl_dim_in
, v
->n
- n
+ i
, -1);
1682 pa
= isl_pw_aff_add(pa
, isl_pw_aff_from_aff(aff
));
1684 pa
= isl_pw_aff_set_rational(pa
);
1685 set
= isl_pw_aff_zero_set(pa
);
1686 map_i
= isl_map_from_range(set
);
1687 map_i
= isl_map_reset_space(map_i
, isl_map_get_space(map
));
1688 map
= isl_map_intersect(map
, map_i
);
1691 isl_space_free(space
);
1692 isl_multi_pw_aff_free(tuple
);
1695 isl_space_free(space
);
1696 isl_multi_pw_aff_free(tuple
);
1701 /* Read a tuple from "s" and add it to "map".
1702 * The tuple is initially represented as an isl_multi_pw_aff and
1703 * then added to "map".
1705 static __isl_give isl_map
*read_map_tuple(__isl_keep isl_stream
*s
,
1706 __isl_take isl_map
*map
, enum isl_dim_type type
, struct vars
*v
,
1710 isl_multi_pw_aff
*tuple
;
1712 rational
= isl_map_is_rational(map
);
1714 return isl_map_free(map
);
1715 tuple
= read_tuple(s
, v
, rational
, comma
);
1717 return isl_map_free(map
);
1719 return map_from_tuple(tuple
, map
, type
, v
, rational
);
1722 /* Read the parameter domain of an expression from "s" (if any) and
1723 * check that it does not involve any constraints.
1724 * "v" contains a description of the identifiers parsed so far
1725 * (of which there should not be any at this point) and is extended
1728 static __isl_give isl_set
*read_universe_params(__isl_keep isl_stream
*s
,
1733 dom
= isl_set_universe(isl_space_params_alloc(s
->ctx
, 0));
1734 if (next_is_tuple(s
)) {
1735 dom
= read_map_tuple(s
, dom
, isl_dim_param
, v
, 0);
1736 if (isl_stream_eat(s
, ISL_TOKEN_TO
))
1737 return isl_set_free(dom
);
1739 if (!isl_set_plain_is_universe(dom
))
1740 isl_die(s
->ctx
, isl_error_invalid
,
1741 "expecting universe parameter domain",
1742 return isl_set_free(dom
));
1747 /* Read the parameter domain of an expression from "s" (if any),
1748 * check that it does not involve any constraints and return its space.
1749 * "v" contains a description of the identifiers parsed so far
1750 * (of which there should not be any at this point) and is extended
1753 static __isl_give isl_space
*read_params(__isl_keep isl_stream
*s
,
1759 set
= read_universe_params(s
, v
);
1760 space
= isl_set_get_space(set
);
1766 /* This function is called for each element in a tuple inside read_space_tuples.
1767 * Add a new variable to "v" and adjust "space" accordingly
1768 * if the variable has a name.
1770 static __isl_give isl_space
*read_tuple_id(__isl_keep isl_stream
*s
,
1771 struct vars
*v
, __isl_take isl_space
*space
, int rational
, void *user
)
1773 struct isl_token
*tok
;
1775 tok
= next_token(s
);
1777 isl_stream_error(s
, NULL
, "unexpected EOF");
1778 return isl_space_free(space
);
1781 if (tok
->type
== ISL_TOKEN_IDENT
) {
1783 int p
= vars_pos(v
, tok
->u
.s
, -1);
1787 isl_stream_error(s
, tok
, "expecting fresh identifier");
1790 space
= space_set_last_dim_name(space
, v
->v
->name
);
1791 } else if (tok
->type
== '*') {
1792 if (vars_add_anon(v
) < 0)
1795 isl_stream_error(s
, tok
, "expecting identifier or '*'");
1799 isl_token_free(tok
);
1802 isl_token_free(tok
);
1803 return isl_space_free(space
);
1806 /* Given a parameter space "params", extend it with one or two tuples
1808 * "v" contains a description of the identifiers parsed so far and is extended
1811 static __isl_give isl_space
*read_space_tuples(__isl_keep isl_stream
*s
,
1812 struct vars
*v
, __isl_take isl_space
*params
)
1814 isl_space
*space
, *ran
;
1816 space
= read_tuple_space(s
, v
, isl_space_copy(params
), 1, 1,
1817 &read_tuple_id
, NULL
);
1818 if (isl_stream_eat_if_available(s
, ISL_TOKEN_TO
)) {
1819 ran
= read_tuple_space(s
, v
, isl_space_copy(params
), 1, 1,
1820 &read_tuple_id
, NULL
);
1821 space
= isl_space_unwrap(isl_space_product(space
, ran
));
1823 isl_space_free(params
);
1828 /* Read an isl_space object from "s".
1830 * First read the parameters (if any).
1832 * Then check if the description is of the special form "{ : }",
1833 * in which case it represents a parameter space.
1834 * Otherwise, it has one or two tuples.
1836 __isl_give isl_space
*isl_stream_read_space(__isl_keep isl_stream
*s
)
1841 v
= vars_new(s
->ctx
);
1844 space
= read_params(s
, v
);
1846 if (isl_stream_eat(s
, '{'))
1849 if (!isl_stream_eat_if_available(s
, ':'))
1850 space
= read_space_tuples(s
, v
, space
);
1852 if (isl_stream_eat(s
, '}'))
1859 isl_space_free(space
);
1864 #define TYPE_BASE space
1865 #include "isl_read_from_str_templ.c"
1867 /* Given two equal-length lists of piecewise affine expression with the space
1868 * of "set" as domain, construct a set in the same space that expresses
1869 * that "left" and "right" satisfy the comparison "type".
1871 * A space is constructed of the same dimension as the number of elements
1872 * in the two lists. The comparison is then expressed in a map from
1873 * this space to itself and wrapped into a set. Finally the two lists
1874 * of piecewise affine expressions are plugged into this set.
1876 * Let S be the space of "set" and T the constructed space.
1877 * The lists are first changed into two isl_multi_pw_affs in S -> T and
1878 * then combined into an isl_multi_pw_aff in S -> [T -> T],
1879 * while the comparison is first expressed in T -> T, then [T -> T]
1882 static __isl_give isl_set
*list_cmp(__isl_keep isl_set
*set
, int type
,
1883 __isl_take isl_pw_aff_list
*left
, __isl_take isl_pw_aff_list
*right
)
1887 isl_multi_pw_aff
*mpa1
, *mpa2
;
1889 n
= isl_pw_aff_list_n_pw_aff(left
);
1890 if (!set
|| n
< 0 || !right
)
1893 space
= isl_set_get_space(set
);
1894 space
= isl_space_from_domain(space
);
1895 space
= isl_space_add_dims(space
, isl_dim_out
, n
);
1896 mpa1
= isl_multi_pw_aff_from_pw_aff_list(isl_space_copy(space
), left
);
1897 mpa2
= isl_multi_pw_aff_from_pw_aff_list(isl_space_copy(space
), right
);
1898 mpa1
= isl_multi_pw_aff_range_product(mpa1
, mpa2
);
1900 space
= isl_space_range(space
);
1902 case ISL_TOKEN_LEX_LT
:
1903 set
= isl_map_wrap(isl_map_lex_lt(space
));
1905 case ISL_TOKEN_LEX_GT
:
1906 set
= isl_map_wrap(isl_map_lex_gt(space
));
1908 case ISL_TOKEN_LEX_LE
:
1909 set
= isl_map_wrap(isl_map_lex_le(space
));
1911 case ISL_TOKEN_LEX_GE
:
1912 set
= isl_map_wrap(isl_map_lex_ge(space
));
1915 isl_multi_pw_aff_free(mpa1
);
1916 isl_space_free(space
);
1917 isl_die(isl_set_get_ctx(set
), isl_error_internal
,
1918 "unhandled list comparison type", return NULL
);
1920 set
= isl_set_preimage_multi_pw_aff(set
, mpa1
);
1923 isl_pw_aff_list_free(left
);
1924 isl_pw_aff_list_free(right
);
1928 /* Construct constraints of the form
1932 * where a is an element in "left", op is an operator of type "type" and
1933 * b is an element in "right", add the constraints to "set" and return
1935 * "rational" is set if the constraints should be treated as
1936 * a rational constraints.
1938 * If "type" is the type of a comparison operator between lists
1939 * of affine expressions, then a single (compound) constraint
1940 * is constructed by list_cmp instead.
1942 static __isl_give isl_set
*construct_constraints(
1943 __isl_take isl_set
*set
, int type
,
1944 __isl_keep isl_pw_aff_list
*left
, __isl_keep isl_pw_aff_list
*right
,
1949 left
= isl_pw_aff_list_copy(left
);
1950 right
= isl_pw_aff_list_copy(right
);
1952 left
= isl_pw_aff_list_set_rational(left
);
1953 right
= isl_pw_aff_list_set_rational(right
);
1955 if (is_list_comparator_type(type
))
1956 cond
= list_cmp(set
, type
, left
, right
);
1957 else if (type
== ISL_TOKEN_LE
)
1958 cond
= isl_pw_aff_list_le_set(left
, right
);
1959 else if (type
== ISL_TOKEN_GE
)
1960 cond
= isl_pw_aff_list_ge_set(left
, right
);
1961 else if (type
== ISL_TOKEN_LT
)
1962 cond
= isl_pw_aff_list_lt_set(left
, right
);
1963 else if (type
== ISL_TOKEN_GT
)
1964 cond
= isl_pw_aff_list_gt_set(left
, right
);
1965 else if (type
== ISL_TOKEN_NE
)
1966 cond
= isl_pw_aff_list_ne_set(left
, right
);
1968 cond
= isl_pw_aff_list_eq_set(left
, right
);
1970 return isl_set_intersect(set
, cond
);
1973 /* Read a constraint from "s", add it to "map" and return the result.
1974 * "v" contains a description of the identifiers parsed so far.
1975 * "rational" is set if the constraint should be treated as
1976 * a rational constraint.
1977 * The constraint read from "s" may be applied to multiple pairs
1978 * of affine expressions and may be chained.
1979 * In particular, a list of affine expressions is read, followed
1980 * by a comparison operator and another list of affine expressions.
1981 * The comparison operator is then applied to each pair of elements
1982 * in the two lists and the results are added to "map".
1983 * However, if the operator expects two lists of affine expressions,
1984 * then it is applied directly to those lists and the two lists
1985 * are required to have the same length.
1986 * If the next token is another comparison operator, then another
1987 * list of affine expressions is read and the process repeats.
1989 * The processing is performed on a wrapped copy of "map" because
1990 * an affine expression cannot have a binary relation as domain.
1992 static __isl_give isl_map
*add_constraint(__isl_keep isl_stream
*s
,
1993 struct vars
*v
, __isl_take isl_map
*map
, int rational
)
1995 struct isl_token
*tok
;
1997 isl_pw_aff_list
*list1
= NULL
, *list2
= NULL
;
2001 set
= isl_map_wrap(map
);
2002 list1
= accept_affine_list(s
, isl_set_get_space(set
), v
);
2005 tok
= isl_stream_next_token(s
);
2006 if (!is_comparator(tok
)) {
2007 isl_stream_error(s
, tok
, "missing operator");
2009 isl_stream_push_token(s
, tok
);
2013 isl_token_free(tok
);
2015 list2
= accept_affine_list(s
, isl_set_get_space(set
), v
);
2016 n1
= isl_pw_aff_list_n_pw_aff(list1
);
2017 n2
= isl_pw_aff_list_n_pw_aff(list2
);
2018 if (n1
< 0 || n2
< 0)
2020 if (is_list_comparator_type(type
) && n1
!= n2
) {
2021 isl_stream_error(s
, NULL
,
2022 "list arguments not of same size");
2026 set
= construct_constraints(set
, type
, list1
, list2
, rational
);
2027 isl_pw_aff_list_free(list1
);
2030 if (!next_is_comparator(s
))
2032 tok
= isl_stream_next_token(s
);
2034 isl_token_free(tok
);
2036 isl_pw_aff_list_free(list1
);
2038 return isl_set_unwrap(set
);
2040 isl_pw_aff_list_free(list1
);
2041 isl_pw_aff_list_free(list2
);
2046 static __isl_give isl_map
*read_exists(__isl_keep isl_stream
*s
,
2047 struct vars
*v
, __isl_take isl_map
*map
, int rational
)
2050 int seen_paren
= isl_stream_eat_if_available(s
, '(');
2052 map
= isl_map_from_domain(isl_map_wrap(map
));
2053 map
= read_defined_var_list(s
, v
, map
, rational
);
2055 if (isl_stream_eat(s
, ':'))
2058 map
= read_formula(s
, v
, map
, rational
);
2059 map
= isl_set_unwrap(isl_map_domain(map
));
2061 vars_drop(v
, v
->n
- n
);
2062 if (seen_paren
&& isl_stream_eat(s
, ')'))
2071 /* Parse an expression between parentheses and push the result
2072 * back on the stream.
2074 * The parsed expression may be either an affine expression
2075 * or a condition. The first type is pushed onto the stream
2076 * as an isl_pw_aff, while the second is pushed as an isl_map.
2078 * If the initial token indicates the start of a condition,
2079 * we parse it as such.
2080 * Otherwise, we first parse an affine expression and push
2081 * that onto the stream. If the affine expression covers the
2082 * entire expression between parentheses, we return.
2083 * Otherwise, we assume that the affine expression is the
2084 * start of a condition and continue parsing.
2086 static int resolve_paren_expr(__isl_keep isl_stream
*s
,
2087 struct vars
*v
, __isl_take isl_map
*map
, int rational
)
2089 struct isl_token
*tok
, *tok2
;
2094 tok
= isl_stream_next_token(s
);
2095 if (!tok
|| tok
->type
!= '(')
2098 if (isl_stream_next_token_is(s
, '('))
2099 if (resolve_paren_expr(s
, v
, isl_map_copy(map
), rational
))
2102 if (next_is_condition_start(s
)) {
2103 map
= read_formula(s
, v
, map
, rational
);
2104 if (isl_stream_eat(s
, ')'))
2106 tok
->type
= ISL_TOKEN_MAP
;
2108 isl_stream_push_token(s
, tok
);
2112 tok2
= isl_stream_next_token(s
);
2117 isl_stream_push_token(s
, tok2
);
2119 pwaff
= accept_affine(s
, isl_space_wrap(isl_map_get_space(map
)), v
);
2123 has_paren
= isl_stream_eat_if_available(s
, ')');
2125 if (push_aff(s
, line
, col
, pwaff
) < 0)
2129 isl_token_free(tok
);
2134 map
= read_formula(s
, v
, map
, rational
);
2135 if (isl_stream_eat(s
, ')'))
2138 tok
->type
= ISL_TOKEN_MAP
;
2140 isl_stream_push_token(s
, tok
);
2144 isl_token_free(tok
);
2149 static __isl_give isl_map
*read_conjunct(__isl_keep isl_stream
*s
,
2150 struct vars
*v
, __isl_take isl_map
*map
, int rational
)
2152 if (isl_stream_next_token_is(s
, '('))
2153 if (resolve_paren_expr(s
, v
, isl_map_copy(map
), rational
))
2156 if (isl_stream_next_token_is(s
, ISL_TOKEN_MAP
)) {
2157 struct isl_token
*tok
;
2158 tok
= isl_stream_next_token(s
);
2162 map
= isl_map_copy(tok
->u
.map
);
2163 isl_token_free(tok
);
2167 if (isl_stream_eat_if_available(s
, ISL_TOKEN_EXISTS
))
2168 return read_exists(s
, v
, map
, rational
);
2170 if (isl_stream_eat_if_available(s
, ISL_TOKEN_TRUE
))
2173 if (isl_stream_eat_if_available(s
, ISL_TOKEN_FALSE
)) {
2174 isl_space
*space
= isl_map_get_space(map
);
2176 return isl_map_empty(space
);
2179 return add_constraint(s
, v
, map
, rational
);
2185 static __isl_give isl_map
*read_conjuncts(__isl_keep isl_stream
*s
,
2186 struct vars
*v
, __isl_take isl_map
*map
, int rational
)
2191 negate
= isl_stream_eat_if_available(s
, ISL_TOKEN_NOT
);
2192 res
= read_conjunct(s
, v
, isl_map_copy(map
), rational
);
2194 res
= isl_map_subtract(isl_map_copy(map
), res
);
2196 while (res
&& isl_stream_eat_if_available(s
, ISL_TOKEN_AND
)) {
2199 negate
= isl_stream_eat_if_available(s
, ISL_TOKEN_NOT
);
2200 res_i
= read_conjunct(s
, v
, isl_map_copy(map
), rational
);
2202 res
= isl_map_subtract(res
, res_i
);
2204 res
= isl_map_intersect(res
, res_i
);
2211 static __isl_give isl_map
*read_disjuncts(__isl_keep isl_stream
*s
,
2212 struct vars
*v
, __isl_take isl_map
*map
, int rational
)
2216 if (isl_stream_next_token_is(s
, '}'))
2219 res
= read_conjuncts(s
, v
, isl_map_copy(map
), rational
);
2220 while (isl_stream_eat_if_available(s
, ISL_TOKEN_OR
)) {
2223 res_i
= read_conjuncts(s
, v
, isl_map_copy(map
), rational
);
2224 res
= isl_map_union(res
, res_i
);
2231 /* Read a first order formula from "s", add the corresponding
2232 * constraints to "map" and return the result.
2234 * In particular, read a formula of the form
2242 * where a and b are disjunctions.
2244 * In the first case, map is replaced by
2246 * map \cap { [..] : a }
2248 * In the second case, it is replaced by
2250 * (map \setminus { [..] : a}) \cup (map \cap { [..] : b })
2252 static __isl_give isl_map
*read_formula(__isl_keep isl_stream
*s
,
2253 struct vars
*v
, __isl_take isl_map
*map
, int rational
)
2257 res
= read_disjuncts(s
, v
, isl_map_copy(map
), rational
);
2259 if (isl_stream_eat_if_available(s
, ISL_TOKEN_IMPLIES
)) {
2262 res
= isl_map_subtract(isl_map_copy(map
), res
);
2263 res2
= read_disjuncts(s
, v
, map
, rational
);
2264 res
= isl_map_union(res
, res2
);
2271 static isl_size
polylib_pos_to_isl_pos(__isl_keep isl_basic_map
*bmap
, int pos
)
2273 isl_size n_out
, n_in
, n_param
, n_div
;
2275 n_param
= isl_basic_map_dim(bmap
, isl_dim_param
);
2276 n_in
= isl_basic_map_dim(bmap
, isl_dim_in
);
2277 n_out
= isl_basic_map_dim(bmap
, isl_dim_out
);
2278 n_div
= isl_basic_map_dim(bmap
, isl_dim_div
);
2279 if (n_param
< 0 || n_in
< 0 || n_out
< 0 || n_div
< 0)
2280 return isl_size_error
;
2283 return 1 + n_param
+ n_in
+ pos
;
2287 return 1 + n_param
+ pos
;
2291 return 1 + n_param
+ n_in
+ n_out
+ pos
;
2300 static __isl_give isl_basic_map
*basic_map_read_polylib_constraint(
2301 __isl_keep isl_stream
*s
, __isl_take isl_basic_map
*bmap
)
2304 struct isl_token
*tok
;
2313 tok
= isl_stream_next_token(s
);
2314 if (!tok
|| tok
->type
!= ISL_TOKEN_VALUE
) {
2315 isl_stream_error(s
, tok
, "expecting coefficient");
2316 isl_token_free(tok
);
2319 if (!tok
->on_new_line
) {
2320 isl_stream_error(s
, tok
, "coefficient should appear on new line");
2321 isl_token_free(tok
);
2325 type
= isl_int_get_si(tok
->u
.v
);
2326 isl_token_free(tok
);
2328 isl_assert(s
->ctx
, type
== 0 || type
== 1, goto error
);
2330 k
= isl_basic_map_alloc_equality(bmap
);
2333 k
= isl_basic_map_alloc_inequality(bmap
);
2339 total
= isl_basic_map_dim(bmap
, isl_dim_all
);
2341 return isl_basic_map_free(bmap
);
2342 for (j
= 0; j
< 1 + total
; ++j
) {
2344 tok
= next_signed_value_on_same_line(s
,
2345 "expecting coefficient on same line");
2348 pos
= polylib_pos_to_isl_pos(bmap
, j
);
2350 isl_int_set(c
[pos
], tok
->u
.v
);
2351 isl_token_free(tok
);
2353 return isl_basic_map_free(bmap
);
2358 isl_basic_map_free(bmap
);
2362 static __isl_give isl_basic_map
*basic_map_read_polylib(
2363 __isl_keep isl_stream
*s
)
2366 struct isl_token
*tok
;
2367 struct isl_token
*tok2
;
2370 unsigned in
= 0, out
, local
= 0;
2371 struct isl_basic_map
*bmap
= NULL
;
2374 tok
= isl_stream_next_token(s
);
2376 isl_stream_error(s
, NULL
, "unexpected EOF");
2379 tok2
= isl_stream_next_token(s
);
2381 isl_token_free(tok
);
2382 isl_stream_error(s
, NULL
, "unexpected EOF");
2385 if (tok
->type
!= ISL_TOKEN_VALUE
|| tok2
->type
!= ISL_TOKEN_VALUE
) {
2386 isl_token_free(tok2
);
2387 isl_token_free(tok
);
2388 isl_stream_error(s
, NULL
,
2389 "expecting constraint matrix dimensions");
2392 n_row
= isl_int_get_si(tok
->u
.v
);
2393 n_col
= isl_int_get_si(tok2
->u
.v
);
2394 on_new_line
= tok2
->on_new_line
;
2395 isl_token_free(tok2
);
2396 isl_token_free(tok
);
2397 isl_assert(s
->ctx
, !on_new_line
, return NULL
);
2398 isl_assert(s
->ctx
, n_row
>= 0, return NULL
);
2399 isl_assert(s
->ctx
, n_col
>= 2 + nparam
, return NULL
);
2400 tok
= isl_stream_next_token_on_same_line(s
);
2402 if (tok
->type
!= ISL_TOKEN_VALUE
) {
2403 isl_stream_error(s
, tok
,
2404 "expecting number of output dimensions");
2405 isl_token_free(tok
);
2408 out
= isl_int_get_si(tok
->u
.v
);
2409 isl_token_free(tok
);
2411 tok
= isl_stream_next_token_on_same_line(s
);
2412 if (!tok
|| tok
->type
!= ISL_TOKEN_VALUE
) {
2413 isl_stream_error(s
, tok
,
2414 "expecting number of input dimensions");
2415 isl_token_free(tok
);
2418 in
= isl_int_get_si(tok
->u
.v
);
2419 isl_token_free(tok
);
2421 tok
= isl_stream_next_token_on_same_line(s
);
2422 if (!tok
|| tok
->type
!= ISL_TOKEN_VALUE
) {
2423 isl_stream_error(s
, tok
,
2424 "expecting number of existentials");
2425 isl_token_free(tok
);
2428 local
= isl_int_get_si(tok
->u
.v
);
2429 isl_token_free(tok
);
2431 tok
= isl_stream_next_token_on_same_line(s
);
2432 if (!tok
|| tok
->type
!= ISL_TOKEN_VALUE
) {
2433 isl_stream_error(s
, tok
,
2434 "expecting number of parameters");
2435 isl_token_free(tok
);
2438 nparam
= isl_int_get_si(tok
->u
.v
);
2439 isl_token_free(tok
);
2440 if (n_col
!= 1 + out
+ in
+ local
+ nparam
+ 1) {
2441 isl_stream_error(s
, NULL
,
2442 "dimensions don't match");
2446 out
= n_col
- 2 - nparam
;
2447 bmap
= isl_basic_map_alloc(s
->ctx
, nparam
, in
, out
, local
, n_row
, n_row
);
2451 for (i
= 0; i
< local
; ++i
) {
2452 int k
= isl_basic_map_alloc_div(bmap
);
2455 isl_seq_clr(bmap
->div
[k
], 1 + 1 + nparam
+ in
+ out
+ local
);
2458 for (i
= 0; i
< n_row
; ++i
)
2459 bmap
= basic_map_read_polylib_constraint(s
, bmap
);
2464 tok
= isl_stream_next_token_on_same_line(s
);
2466 isl_stream_error(s
, tok
, "unexpected extra token on line");
2467 isl_token_free(tok
);
2471 bmap
= isl_basic_map_simplify(bmap
);
2472 bmap
= isl_basic_map_finalize(bmap
);
2475 isl_basic_map_free(bmap
);
2479 static __isl_give isl_map
*map_read_polylib(__isl_keep isl_stream
*s
)
2481 struct isl_token
*tok
;
2482 struct isl_token
*tok2
;
2484 struct isl_map
*map
;
2486 tok
= isl_stream_next_token(s
);
2488 isl_stream_error(s
, NULL
, "unexpected EOF");
2491 tok2
= isl_stream_next_token_on_same_line(s
);
2492 if (tok2
&& tok2
->type
== ISL_TOKEN_VALUE
) {
2493 isl_stream_push_token(s
, tok2
);
2494 isl_stream_push_token(s
, tok
);
2495 return isl_map_from_basic_map(basic_map_read_polylib(s
));
2498 isl_stream_error(s
, tok2
, "unexpected token");
2499 isl_stream_push_token(s
, tok2
);
2500 isl_stream_push_token(s
, tok
);
2503 n
= isl_int_get_si(tok
->u
.v
);
2504 isl_token_free(tok
);
2506 isl_assert(s
->ctx
, n
>= 1, return NULL
);
2508 map
= isl_map_from_basic_map(basic_map_read_polylib(s
));
2510 for (i
= 1; map
&& i
< n
; ++i
)
2511 map
= isl_map_union(map
,
2512 isl_map_from_basic_map(basic_map_read_polylib(s
)));
2517 static int optional_power(__isl_keep isl_stream
*s
)
2520 struct isl_token
*tok
;
2522 tok
= isl_stream_next_token(s
);
2525 if (tok
->type
!= '^') {
2526 isl_stream_push_token(s
, tok
);
2529 isl_token_free(tok
);
2530 tok
= isl_stream_next_token(s
);
2531 if (!tok
|| tok
->type
!= ISL_TOKEN_VALUE
) {
2532 isl_stream_error(s
, tok
, "expecting exponent");
2534 isl_stream_push_token(s
, tok
);
2537 pow
= isl_int_get_si(tok
->u
.v
);
2538 isl_token_free(tok
);
2542 static __isl_give isl_pw_qpolynomial
*read_term(__isl_keep isl_stream
*s
,
2543 __isl_keep isl_map
*map
, struct vars
*v
);
2545 static __isl_give isl_pw_qpolynomial
*read_factor(__isl_keep isl_stream
*s
,
2546 __isl_keep isl_map
*map
, struct vars
*v
)
2548 isl_pw_qpolynomial
*pwqp
;
2549 struct isl_token
*tok
;
2551 tok
= next_token(s
);
2553 isl_stream_error(s
, NULL
, "unexpected EOF");
2556 if (tok
->type
== '(') {
2559 isl_token_free(tok
);
2560 pwqp
= read_term(s
, map
, v
);
2563 if (isl_stream_eat(s
, ')'))
2565 pow
= optional_power(s
);
2566 pwqp
= isl_pw_qpolynomial_pow(pwqp
, pow
);
2567 } else if (tok
->type
== ISL_TOKEN_VALUE
) {
2568 struct isl_token
*tok2
;
2569 isl_qpolynomial
*qp
;
2571 tok2
= isl_stream_next_token(s
);
2572 if (tok2
&& tok2
->type
== '/') {
2573 isl_token_free(tok2
);
2574 tok2
= next_token(s
);
2575 if (!tok2
|| tok2
->type
!= ISL_TOKEN_VALUE
) {
2576 isl_stream_error(s
, tok2
, "expected denominator");
2577 isl_token_free(tok
);
2578 isl_token_free(tok2
);
2581 qp
= isl_qpolynomial_rat_cst_on_domain(isl_map_get_space(map
),
2582 tok
->u
.v
, tok2
->u
.v
);
2583 isl_token_free(tok2
);
2585 isl_stream_push_token(s
, tok2
);
2586 qp
= isl_qpolynomial_cst_on_domain(isl_map_get_space(map
),
2589 isl_token_free(tok
);
2590 pwqp
= isl_pw_qpolynomial_from_qpolynomial(qp
);
2591 } else if (tok
->type
== ISL_TOKEN_INFTY
) {
2592 isl_qpolynomial
*qp
;
2593 isl_token_free(tok
);
2594 qp
= isl_qpolynomial_infty_on_domain(isl_map_get_space(map
));
2595 pwqp
= isl_pw_qpolynomial_from_qpolynomial(qp
);
2596 } else if (tok
->type
== ISL_TOKEN_NAN
) {
2597 isl_qpolynomial
*qp
;
2598 isl_token_free(tok
);
2599 qp
= isl_qpolynomial_nan_on_domain(isl_map_get_space(map
));
2600 pwqp
= isl_pw_qpolynomial_from_qpolynomial(qp
);
2601 } else if (tok
->type
== ISL_TOKEN_IDENT
) {
2603 int pos
= vars_pos(v
, tok
->u
.s
, -1);
2605 isl_qpolynomial
*qp
;
2607 isl_token_free(tok
);
2611 vars_drop(v
, v
->n
- n
);
2612 isl_stream_error(s
, tok
, "unknown identifier");
2613 isl_token_free(tok
);
2616 isl_token_free(tok
);
2617 pow
= optional_power(s
);
2618 qp
= isl_qpolynomial_var_pow_on_domain(isl_map_get_space(map
), pos
, pow
);
2619 pwqp
= isl_pw_qpolynomial_from_qpolynomial(qp
);
2620 } else if (is_start_of_div(tok
)) {
2624 isl_stream_push_token(s
, tok
);
2625 pwaff
= accept_div(s
, isl_map_get_space(map
), v
);
2626 pow
= optional_power(s
);
2627 pwqp
= isl_pw_qpolynomial_from_pw_aff(pwaff
);
2628 pwqp
= isl_pw_qpolynomial_pow(pwqp
, pow
);
2629 } else if (tok
->type
== '-') {
2630 isl_token_free(tok
);
2631 pwqp
= read_factor(s
, map
, v
);
2632 pwqp
= isl_pw_qpolynomial_neg(pwqp
);
2634 isl_stream_error(s
, tok
, "unexpected isl_token");
2635 isl_stream_push_token(s
, tok
);
2639 if (isl_stream_eat_if_available(s
, '*') ||
2640 isl_stream_next_token_is(s
, ISL_TOKEN_IDENT
)) {
2641 isl_pw_qpolynomial
*pwqp2
;
2643 pwqp2
= read_factor(s
, map
, v
);
2644 pwqp
= isl_pw_qpolynomial_mul(pwqp
, pwqp2
);
2649 isl_pw_qpolynomial_free(pwqp
);
2653 static __isl_give isl_pw_qpolynomial
*read_term(__isl_keep isl_stream
*s
,
2654 __isl_keep isl_map
*map
, struct vars
*v
)
2656 struct isl_token
*tok
;
2657 isl_pw_qpolynomial
*pwqp
;
2659 pwqp
= read_factor(s
, map
, v
);
2662 tok
= next_token(s
);
2666 if (tok
->type
== '+') {
2667 isl_pw_qpolynomial
*pwqp2
;
2669 isl_token_free(tok
);
2670 pwqp2
= read_factor(s
, map
, v
);
2671 pwqp
= isl_pw_qpolynomial_add(pwqp
, pwqp2
);
2672 } else if (tok
->type
== '-') {
2673 isl_pw_qpolynomial
*pwqp2
;
2675 isl_token_free(tok
);
2676 pwqp2
= read_factor(s
, map
, v
);
2677 pwqp
= isl_pw_qpolynomial_sub(pwqp
, pwqp2
);
2679 isl_stream_push_token(s
, tok
);
2687 static __isl_give isl_map
*read_optional_formula(__isl_keep isl_stream
*s
,
2688 __isl_take isl_map
*map
, struct vars
*v
, int rational
)
2690 struct isl_token
*tok
;
2692 tok
= isl_stream_next_token(s
);
2694 isl_stream_error(s
, NULL
, "unexpected EOF");
2697 if (tok
->type
== ':' ||
2698 (tok
->type
== ISL_TOKEN_OR
&& !strcmp(tok
->u
.s
, "|"))) {
2699 isl_token_free(tok
);
2700 map
= read_formula(s
, v
, map
, rational
);
2702 isl_stream_push_token(s
, tok
);
2710 static struct isl_obj
obj_read_poly(__isl_keep isl_stream
*s
,
2711 __isl_take isl_map
*map
, struct vars
*v
, int n
)
2713 struct isl_obj obj
= { isl_obj_pw_qpolynomial
, NULL
};
2714 isl_pw_qpolynomial
*pwqp
;
2715 struct isl_set
*set
;
2717 pwqp
= read_term(s
, map
, v
);
2718 map
= read_optional_formula(s
, map
, v
, 0);
2719 set
= isl_map_range(map
);
2721 pwqp
= isl_pw_qpolynomial_intersect_domain(pwqp
, set
);
2723 vars_drop(v
, v
->n
- n
);
2729 static struct isl_obj
obj_read_poly_or_fold(__isl_keep isl_stream
*s
,
2730 __isl_take isl_set
*set
, struct vars
*v
, int n
)
2733 struct isl_obj obj
= { isl_obj_pw_qpolynomial_fold
, NULL
};
2734 isl_pw_qpolynomial
*pwqp
;
2735 isl_pw_qpolynomial_fold
*pwf
= NULL
;
2738 max
= isl_stream_eat_if_available(s
, ISL_TOKEN_MAX
);
2739 min
= !max
&& isl_stream_eat_if_available(s
, ISL_TOKEN_MIN
);
2741 return obj_read_poly(s
, set
, v
, n
);
2742 fold
= max
? isl_fold_max
: isl_fold_min
;
2744 if (isl_stream_eat(s
, '('))
2747 pwqp
= read_term(s
, set
, v
);
2748 pwf
= isl_pw_qpolynomial_fold_from_pw_qpolynomial(fold
, pwqp
);
2750 while (isl_stream_eat_if_available(s
, ',')) {
2751 isl_pw_qpolynomial_fold
*pwf_i
;
2752 pwqp
= read_term(s
, set
, v
);
2753 pwf_i
= isl_pw_qpolynomial_fold_from_pw_qpolynomial(fold
, pwqp
);
2754 pwf
= isl_pw_qpolynomial_fold_fold(pwf
, pwf_i
);
2757 if (isl_stream_eat(s
, ')'))
2760 set
= read_optional_formula(s
, set
, v
, 0);
2761 pwf
= isl_pw_qpolynomial_fold_intersect_domain(pwf
, set
);
2763 vars_drop(v
, v
->n
- n
);
2769 isl_pw_qpolynomial_fold_free(pwf
);
2770 obj
.type
= isl_obj_none
;
2774 static int is_rational(__isl_keep isl_stream
*s
)
2776 struct isl_token
*tok
;
2778 tok
= isl_stream_next_token(s
);
2781 if (tok
->type
== ISL_TOKEN_RAT
&& isl_stream_next_token_is(s
, ':')) {
2782 isl_token_free(tok
);
2783 isl_stream_eat(s
, ':');
2787 isl_stream_push_token(s
, tok
);
2792 static struct isl_obj
obj_read_body(__isl_keep isl_stream
*s
,
2793 __isl_take isl_map
*map
, struct vars
*v
)
2795 struct isl_token
*tok
;
2796 struct isl_obj obj
= { isl_obj_set
, NULL
};
2800 rational
= is_rational(s
);
2802 map
= isl_map_set_rational(map
);
2804 if (isl_stream_next_token_is(s
, ':')) {
2805 obj
.type
= isl_obj_set
;
2806 obj
.v
= read_optional_formula(s
, map
, v
, rational
);
2810 if (!next_is_tuple(s
))
2811 return obj_read_poly_or_fold(s
, map
, v
, n
);
2813 map
= read_map_tuple(s
, map
, isl_dim_in
, v
, 0);
2816 tok
= isl_stream_next_token(s
);
2819 if (tok
->type
== ISL_TOKEN_TO
) {
2820 obj
.type
= isl_obj_map
;
2821 isl_token_free(tok
);
2822 if (!next_is_tuple(s
)) {
2823 isl_set
*set
= isl_map_domain(map
);
2824 return obj_read_poly_or_fold(s
, set
, v
, n
);
2826 map
= read_map_tuple(s
, map
, isl_dim_out
, v
, 0);
2830 map
= isl_map_domain(map
);
2831 isl_stream_push_token(s
, tok
);
2834 map
= read_optional_formula(s
, map
, v
, rational
);
2836 vars_drop(v
, v
->n
- n
);
2842 obj
.type
= isl_obj_none
;
2846 static struct isl_obj
to_union(isl_ctx
*ctx
, struct isl_obj obj
)
2848 if (obj
.type
== isl_obj_map
) {
2849 obj
.v
= isl_union_map_from_map(obj
.v
);
2850 obj
.type
= isl_obj_union_map
;
2851 } else if (obj
.type
== isl_obj_set
) {
2852 obj
.v
= isl_union_set_from_set(obj
.v
);
2853 obj
.type
= isl_obj_union_set
;
2854 } else if (obj
.type
== isl_obj_pw_qpolynomial
) {
2855 obj
.v
= isl_union_pw_qpolynomial_from_pw_qpolynomial(obj
.v
);
2856 obj
.type
= isl_obj_union_pw_qpolynomial
;
2857 } else if (obj
.type
== isl_obj_pw_qpolynomial_fold
) {
2858 obj
.v
= isl_union_pw_qpolynomial_fold_from_pw_qpolynomial_fold(obj
.v
);
2859 obj
.type
= isl_obj_union_pw_qpolynomial_fold
;
2861 isl_assert(ctx
, 0, goto error
);
2864 obj
.type
->free(obj
.v
);
2865 obj
.type
= isl_obj_none
;
2869 static struct isl_obj
obj_add(__isl_keep isl_stream
*s
,
2870 struct isl_obj obj1
, struct isl_obj obj2
)
2872 if (obj2
.type
== isl_obj_none
|| !obj2
.v
)
2874 if (obj1
.type
== isl_obj_set
&& obj2
.type
== isl_obj_union_set
)
2875 obj1
= to_union(s
->ctx
, obj1
);
2876 if (obj1
.type
== isl_obj_union_set
&& obj2
.type
== isl_obj_set
)
2877 obj2
= to_union(s
->ctx
, obj2
);
2878 if (obj1
.type
== isl_obj_map
&& obj2
.type
== isl_obj_union_map
)
2879 obj1
= to_union(s
->ctx
, obj1
);
2880 if (obj1
.type
== isl_obj_union_map
&& obj2
.type
== isl_obj_map
)
2881 obj2
= to_union(s
->ctx
, obj2
);
2882 if (obj1
.type
== isl_obj_pw_qpolynomial
&&
2883 obj2
.type
== isl_obj_union_pw_qpolynomial
)
2884 obj1
= to_union(s
->ctx
, obj1
);
2885 if (obj1
.type
== isl_obj_union_pw_qpolynomial
&&
2886 obj2
.type
== isl_obj_pw_qpolynomial
)
2887 obj2
= to_union(s
->ctx
, obj2
);
2888 if (obj1
.type
== isl_obj_pw_qpolynomial_fold
&&
2889 obj2
.type
== isl_obj_union_pw_qpolynomial_fold
)
2890 obj1
= to_union(s
->ctx
, obj1
);
2891 if (obj1
.type
== isl_obj_union_pw_qpolynomial_fold
&&
2892 obj2
.type
== isl_obj_pw_qpolynomial_fold
)
2893 obj2
= to_union(s
->ctx
, obj2
);
2894 if (obj1
.type
!= obj2
.type
) {
2895 isl_stream_error(s
, NULL
,
2896 "attempt to combine incompatible objects");
2899 if (!obj1
.type
->add
)
2900 isl_die(s
->ctx
, isl_error_internal
,
2901 "combination not supported on object type", goto error
);
2902 if (obj1
.type
== isl_obj_map
&& !isl_map_has_equal_space(obj1
.v
, obj2
.v
)) {
2903 obj1
= to_union(s
->ctx
, obj1
);
2904 obj2
= to_union(s
->ctx
, obj2
);
2906 if (obj1
.type
== isl_obj_set
&& !isl_set_has_equal_space(obj1
.v
, obj2
.v
)) {
2907 obj1
= to_union(s
->ctx
, obj1
);
2908 obj2
= to_union(s
->ctx
, obj2
);
2910 if (obj1
.type
== isl_obj_pw_qpolynomial
&&
2911 !isl_pw_qpolynomial_has_equal_space(obj1
.v
, obj2
.v
)) {
2912 obj1
= to_union(s
->ctx
, obj1
);
2913 obj2
= to_union(s
->ctx
, obj2
);
2915 if (obj1
.type
== isl_obj_pw_qpolynomial_fold
&&
2916 !isl_pw_qpolynomial_fold_has_equal_space(obj1
.v
, obj2
.v
)) {
2917 obj1
= to_union(s
->ctx
, obj1
);
2918 obj2
= to_union(s
->ctx
, obj2
);
2920 obj1
.v
= obj1
.type
->add(obj1
.v
, obj2
.v
);
2923 obj1
.type
->free(obj1
.v
);
2924 obj2
.type
->free(obj2
.v
);
2925 obj1
.type
= isl_obj_none
;
2930 /* Are the first two tokens on "s", "domain" (either as a string
2931 * or as an identifier) followed by ":"?
2933 static int next_is_domain_colon(__isl_keep isl_stream
*s
)
2935 struct isl_token
*tok
;
2939 tok
= isl_stream_next_token(s
);
2942 if (tok
->type
!= ISL_TOKEN_IDENT
&& tok
->type
!= ISL_TOKEN_STRING
) {
2943 isl_stream_push_token(s
, tok
);
2947 name
= isl_token_get_str(s
->ctx
, tok
);
2948 res
= !strcmp(name
, "domain") && isl_stream_next_token_is(s
, ':');
2951 isl_stream_push_token(s
, tok
);
2956 /* Do the first tokens on "s" look like a schedule?
2958 * The root of a schedule is always a domain node, so the first thing
2959 * we expect in the stream is a domain key, i.e., "domain" followed
2960 * by ":". If the schedule was printed in YAML flow style, then
2961 * we additionally expect a "{" to open the outer mapping.
2963 static int next_is_schedule(__isl_keep isl_stream
*s
)
2965 struct isl_token
*tok
;
2968 tok
= isl_stream_next_token(s
);
2971 if (tok
->type
!= '{') {
2972 isl_stream_push_token(s
, tok
);
2973 return next_is_domain_colon(s
);
2976 is_schedule
= next_is_domain_colon(s
);
2977 isl_stream_push_token(s
, tok
);
2982 /* Read an isl_schedule from "s" and store it in an isl_obj.
2984 static struct isl_obj
schedule_read(__isl_keep isl_stream
*s
)
2988 obj
.type
= isl_obj_schedule
;
2989 obj
.v
= isl_stream_read_schedule(s
);
2994 /* Read a disjunction of object bodies from "s".
2995 * That is, read the inside of the braces, but not the braces themselves.
2996 * "v" contains a description of the identifiers parsed so far.
2997 * "map" contains information about the parameters.
2999 static struct isl_obj
obj_read_disjuncts(__isl_keep isl_stream
*s
,
3000 struct vars
*v
, __isl_keep isl_map
*map
)
3002 struct isl_obj obj
= { isl_obj_set
, NULL
};
3004 if (isl_stream_next_token_is(s
, '}')) {
3005 obj
.type
= isl_obj_union_set
;
3006 obj
.v
= isl_union_set_empty(isl_map_get_space(map
));
3012 o
= obj_read_body(s
, isl_map_copy(map
), v
);
3016 obj
= obj_add(s
, obj
, o
);
3017 if (obj
.type
== isl_obj_none
|| !obj
.v
)
3019 if (!isl_stream_eat_if_available(s
, ';'))
3021 if (isl_stream_next_token_is(s
, '}'))
3028 static struct isl_obj
obj_read(__isl_keep isl_stream
*s
)
3030 isl_map
*map
= NULL
;
3031 struct isl_token
*tok
;
3032 struct vars
*v
= NULL
;
3033 struct isl_obj obj
= { isl_obj_set
, NULL
};
3035 if (next_is_schedule(s
))
3036 return schedule_read(s
);
3038 tok
= next_token(s
);
3040 isl_stream_error(s
, NULL
, "unexpected EOF");
3043 if (tok
->type
== ISL_TOKEN_VALUE
) {
3044 struct isl_token
*tok2
;
3045 struct isl_map
*map
;
3047 tok2
= isl_stream_next_token(s
);
3048 if (!tok2
|| tok2
->type
!= ISL_TOKEN_VALUE
||
3049 isl_int_is_neg(tok2
->u
.v
)) {
3051 isl_stream_push_token(s
, tok2
);
3052 obj
.type
= isl_obj_val
;
3053 obj
.v
= isl_val_int_from_isl_int(s
->ctx
, tok
->u
.v
);
3054 isl_token_free(tok
);
3057 isl_stream_push_token(s
, tok2
);
3058 isl_stream_push_token(s
, tok
);
3059 map
= map_read_polylib(s
);
3062 if (isl_map_may_be_set(map
))
3063 obj
.v
= isl_map_range(map
);
3065 obj
.type
= isl_obj_map
;
3070 v
= vars_new(s
->ctx
);
3072 isl_stream_push_token(s
, tok
);
3075 map
= isl_map_universe(isl_space_params_alloc(s
->ctx
, 0));
3076 if (tok
->type
== '[') {
3077 isl_stream_push_token(s
, tok
);
3078 map
= read_map_tuple(s
, map
, isl_dim_param
, v
, 0);
3081 tok
= isl_stream_next_token(s
);
3082 if (!tok
|| tok
->type
!= ISL_TOKEN_TO
) {
3083 isl_stream_error(s
, tok
, "expecting '->'");
3085 isl_stream_push_token(s
, tok
);
3088 isl_token_free(tok
);
3089 tok
= isl_stream_next_token(s
);
3091 if (!tok
|| tok
->type
!= '{') {
3092 isl_stream_error(s
, tok
, "expecting '{'");
3094 isl_stream_push_token(s
, tok
);
3097 isl_token_free(tok
);
3099 tok
= isl_stream_next_token(s
);
3102 else if (tok
->type
== ISL_TOKEN_IDENT
&& !strcmp(tok
->u
.s
, "Sym")) {
3103 isl_token_free(tok
);
3104 if (isl_stream_eat(s
, '='))
3106 map
= read_map_tuple(s
, map
, isl_dim_param
, v
, 1);
3110 isl_stream_push_token(s
, tok
);
3112 obj
= obj_read_disjuncts(s
, v
, map
);
3113 if (obj
.type
== isl_obj_none
|| !obj
.v
)
3116 tok
= isl_stream_next_token(s
);
3117 if (tok
&& tok
->type
== '}') {
3118 isl_token_free(tok
);
3120 isl_stream_error(s
, tok
, "unexpected isl_token");
3122 isl_token_free(tok
);
3132 obj
.type
->free(obj
.v
);
3139 struct isl_obj
isl_stream_read_obj(__isl_keep isl_stream
*s
)
3144 __isl_give isl_map
*isl_stream_read_map(__isl_keep isl_stream
*s
)
3150 isl_assert(s
->ctx
, obj
.type
== isl_obj_map
||
3151 obj
.type
== isl_obj_set
, goto error
);
3153 if (obj
.type
== isl_obj_set
)
3154 obj
.v
= isl_map_from_range(obj
.v
);
3158 obj
.type
->free(obj
.v
);
3162 __isl_give isl_set
*isl_stream_read_set(__isl_keep isl_stream
*s
)
3168 if (obj
.type
== isl_obj_map
&& isl_map_may_be_set(obj
.v
)) {
3169 obj
.v
= isl_map_range(obj
.v
);
3170 obj
.type
= isl_obj_set
;
3172 isl_assert(s
->ctx
, obj
.type
== isl_obj_set
, goto error
);
3177 obj
.type
->free(obj
.v
);
3181 __isl_give isl_union_map
*isl_stream_read_union_map(__isl_keep isl_stream
*s
)
3186 if (obj
.type
== isl_obj_map
) {
3187 obj
.type
= isl_obj_union_map
;
3188 obj
.v
= isl_union_map_from_map(obj
.v
);
3190 if (obj
.type
== isl_obj_set
) {
3191 obj
.type
= isl_obj_union_set
;
3192 obj
.v
= isl_union_set_from_set(obj
.v
);
3194 if (obj
.v
&& obj
.type
== isl_obj_union_set
&&
3195 isl_union_set_is_empty(obj
.v
))
3196 obj
.type
= isl_obj_union_map
;
3197 if (obj
.v
&& obj
.type
!= isl_obj_union_map
)
3198 isl_die(s
->ctx
, isl_error_invalid
, "invalid input", goto error
);
3202 obj
.type
->free(obj
.v
);
3206 /* Extract an isl_union_set from "obj".
3207 * This only works if the object was detected as either a set
3208 * (in which case it is converted to a union set) or a union set.
3210 static __isl_give isl_union_set
*extract_union_set(isl_ctx
*ctx
,
3213 if (obj
.type
== isl_obj_set
) {
3214 obj
.type
= isl_obj_union_set
;
3215 obj
.v
= isl_union_set_from_set(obj
.v
);
3218 isl_assert(ctx
, obj
.type
== isl_obj_union_set
, goto error
);
3222 obj
.type
->free(obj
.v
);
3226 /* Read an isl_union_set from "s".
3227 * First read a generic object and then try and extract
3228 * an isl_union_set from that.
3230 __isl_give isl_union_set
*isl_stream_read_union_set(__isl_keep isl_stream
*s
)
3235 return extract_union_set(s
->ctx
, obj
);
3238 static __isl_give isl_basic_map
*isl_stream_read_basic_map(
3239 __isl_keep isl_stream
*s
)
3242 struct isl_map
*map
;
3243 struct isl_basic_map
*bmap
;
3246 if (obj
.v
&& (obj
.type
!= isl_obj_map
&& obj
.type
!= isl_obj_set
))
3247 isl_die(s
->ctx
, isl_error_invalid
, "not a (basic) set or map",
3254 isl_die(s
->ctx
, isl_error_invalid
,
3255 "set or map description involves "
3256 "more than one disjunct", goto error
);
3259 bmap
= isl_basic_map_empty(isl_map_get_space(map
));
3261 bmap
= isl_basic_map_copy(map
->p
[0]);
3267 obj
.type
->free(obj
.v
);
3271 /* Read an isl_basic_set object from "s".
3273 __isl_give isl_basic_set
*isl_stream_read_basic_set(__isl_keep isl_stream
*s
)
3275 isl_basic_map
*bmap
;
3276 bmap
= isl_stream_read_basic_map(s
);
3279 if (!isl_basic_map_may_be_set(bmap
))
3280 isl_die(s
->ctx
, isl_error_invalid
,
3281 "input is not a set", goto error
);
3282 return isl_basic_map_range(bmap
);
3284 isl_basic_map_free(bmap
);
3288 __isl_give isl_basic_map
*isl_basic_map_read_from_file(isl_ctx
*ctx
,
3291 struct isl_basic_map
*bmap
;
3292 isl_stream
*s
= isl_stream_new_file(ctx
, input
);
3295 bmap
= isl_stream_read_basic_map(s
);
3300 __isl_give isl_basic_set
*isl_basic_set_read_from_file(isl_ctx
*ctx
,
3303 isl_basic_set
*bset
;
3304 isl_stream
*s
= isl_stream_new_file(ctx
, input
);
3307 bset
= isl_stream_read_basic_set(s
);
3313 #define TYPE_BASE basic_map
3314 #include "isl_read_from_str_templ.c"
3317 #define TYPE_BASE basic_set
3318 #include "isl_read_from_str_templ.c"
3320 __isl_give isl_map
*isl_map_read_from_file(struct isl_ctx
*ctx
,
3323 struct isl_map
*map
;
3324 isl_stream
*s
= isl_stream_new_file(ctx
, input
);
3327 map
= isl_stream_read_map(s
);
3333 #define TYPE_BASE map
3334 #include "isl_read_from_str_templ.c"
3336 __isl_give isl_set
*isl_set_read_from_file(struct isl_ctx
*ctx
,
3340 isl_stream
*s
= isl_stream_new_file(ctx
, input
);
3343 set
= isl_stream_read_set(s
);
3349 #define TYPE_BASE set
3350 #include "isl_read_from_str_templ.c"
3352 __isl_give isl_union_map
*isl_union_map_read_from_file(isl_ctx
*ctx
,
3355 isl_union_map
*umap
;
3356 isl_stream
*s
= isl_stream_new_file(ctx
, input
);
3359 umap
= isl_stream_read_union_map(s
);
3365 #define TYPE_BASE union_map
3366 #include "isl_read_from_str_templ.c"
3368 __isl_give isl_union_set
*isl_union_set_read_from_file(isl_ctx
*ctx
,
3371 isl_union_set
*uset
;
3372 isl_stream
*s
= isl_stream_new_file(ctx
, input
);
3375 uset
= isl_stream_read_union_set(s
);
3381 #define TYPE_BASE union_set
3382 #include "isl_read_from_str_templ.c"
3384 static __isl_give isl_vec
*isl_vec_read_polylib(__isl_keep isl_stream
*s
)
3386 struct isl_vec
*vec
= NULL
;
3387 struct isl_token
*tok
;
3391 tok
= isl_stream_next_token(s
);
3392 if (!tok
|| tok
->type
!= ISL_TOKEN_VALUE
) {
3393 isl_stream_error(s
, tok
, "expecting vector length");
3397 size
= isl_int_get_si(tok
->u
.v
);
3398 isl_token_free(tok
);
3400 vec
= isl_vec_alloc(s
->ctx
, size
);
3402 for (j
= 0; j
< size
; ++j
) {
3403 tok
= next_signed_value(s
, "expecting constant value");
3406 isl_int_set(vec
->el
[j
], tok
->u
.v
);
3407 isl_token_free(tok
);
3412 isl_token_free(tok
);
3417 static __isl_give isl_vec
*vec_read(__isl_keep isl_stream
*s
)
3419 return isl_vec_read_polylib(s
);
3422 __isl_give isl_vec
*isl_vec_read_from_file(isl_ctx
*ctx
, FILE *input
)
3425 isl_stream
*s
= isl_stream_new_file(ctx
, input
);
3433 __isl_give isl_pw_qpolynomial
*isl_stream_read_pw_qpolynomial(
3434 __isl_keep isl_stream
*s
)
3440 isl_assert(s
->ctx
, obj
.type
== isl_obj_pw_qpolynomial
,
3445 obj
.type
->free(obj
.v
);
3450 #define TYPE_BASE pw_qpolynomial
3451 #include "isl_read_from_str_templ.c"
3453 __isl_give isl_pw_qpolynomial
*isl_pw_qpolynomial_read_from_file(isl_ctx
*ctx
,
3456 isl_pw_qpolynomial
*pwqp
;
3457 isl_stream
*s
= isl_stream_new_file(ctx
, input
);
3460 pwqp
= isl_stream_read_pw_qpolynomial(s
);
3465 /* Read an isl_pw_qpolynomial_fold from "s".
3466 * First read a generic object and
3467 * then check that it is an isl_pw_qpolynomial_fold.
3469 __isl_give isl_pw_qpolynomial_fold
*isl_stream_read_pw_qpolynomial_fold(
3470 __isl_keep isl_stream
*s
)
3475 if (obj
.v
&& obj
.type
!= isl_obj_pw_qpolynomial_fold
)
3476 isl_die(s
->ctx
, isl_error_invalid
, "invalid input", goto error
);
3480 obj
.type
->free(obj
.v
);
3485 #define TYPE_BASE pw_qpolynomial_fold
3486 #include "isl_read_from_str_templ.c"
3488 /* Is the next token an identifier not in "v"?
3490 static int next_is_fresh_ident(__isl_keep isl_stream
*s
, struct vars
*v
)
3494 struct isl_token
*tok
;
3496 tok
= isl_stream_next_token(s
);
3499 fresh
= tok
->type
== ISL_TOKEN_IDENT
&& vars_pos(v
, tok
->u
.s
, -1) >= n
;
3500 isl_stream_push_token(s
, tok
);
3502 vars_drop(v
, v
->n
- n
);
3507 /* First read the domain of the affine expression, which may be
3508 * a parameter space or a set.
3509 * The tricky part is that we don't know if the domain is a set or not,
3510 * so when we are trying to read the domain, we may actually be reading
3511 * the affine expression itself (defined on a parameter domains)
3512 * If the tuple we are reading is named, we assume it's the domain.
3513 * Also, if inside the tuple, the first thing we find is a nested tuple
3514 * or a new identifier, we again assume it's the domain.
3515 * Finally, if the tuple is empty, then it must be the domain
3516 * since it does not contain an affine expression.
3517 * Otherwise, we assume we are reading an affine expression.
3519 static __isl_give isl_set
*read_aff_domain(__isl_keep isl_stream
*s
,
3520 __isl_take isl_set
*dom
, struct vars
*v
)
3522 struct isl_token
*tok
, *tok2
;
3525 tok
= isl_stream_next_token(s
);
3526 if (tok
&& (tok
->type
== ISL_TOKEN_IDENT
|| tok
->is_keyword
)) {
3527 isl_stream_push_token(s
, tok
);
3528 return read_map_tuple(s
, dom
, isl_dim_set
, v
, 0);
3530 if (!tok
|| tok
->type
!= '[') {
3531 isl_stream_error(s
, tok
, "expecting '['");
3534 tok2
= isl_stream_next_token(s
);
3535 is_empty
= tok2
&& tok2
->type
== ']';
3537 isl_stream_push_token(s
, tok2
);
3538 if (is_empty
|| next_is_tuple(s
) || next_is_fresh_ident(s
, v
)) {
3539 isl_stream_push_token(s
, tok
);
3540 dom
= read_map_tuple(s
, dom
, isl_dim_set
, v
, 0);
3542 isl_stream_push_token(s
, tok
);
3547 isl_stream_push_token(s
, tok
);
3552 /* Read an affine expression from "s".
3554 __isl_give isl_aff
*isl_stream_read_aff(__isl_keep isl_stream
*s
)
3560 ma
= isl_stream_read_multi_aff(s
);
3561 dim
= isl_multi_aff_dim(ma
, isl_dim_out
);
3565 isl_die(s
->ctx
, isl_error_invalid
,
3566 "expecting single affine expression",
3569 aff
= isl_multi_aff_get_aff(ma
, 0);
3570 isl_multi_aff_free(ma
);
3573 isl_multi_aff_free(ma
);
3577 /* Read a piecewise affine expression from "s" with domain (space) "dom".
3579 static __isl_give isl_pw_aff
*read_pw_aff_with_dom(__isl_keep isl_stream
*s
,
3580 __isl_take isl_set
*dom
, struct vars
*v
)
3582 isl_pw_aff
*pwaff
= NULL
;
3584 if (!isl_set_is_params(dom
) && isl_stream_eat(s
, ISL_TOKEN_TO
))
3587 if (isl_stream_eat(s
, '['))
3590 pwaff
= accept_affine(s
, isl_set_get_space(dom
), v
);
3592 if (isl_stream_eat(s
, ']'))
3595 dom
= read_optional_formula(s
, dom
, v
, 0);
3596 pwaff
= isl_pw_aff_intersect_domain(pwaff
, dom
);
3601 isl_pw_aff_free(pwaff
);
3605 /* Read an affine expression, together with optional constraints
3606 * on the domain from "s". "dom" represents the initial constraints
3607 * on the parameter domain.
3608 * "v" contains a description of the identifiers parsed so far.
3610 static __isl_give isl_pw_aff
*read_conditional_aff(__isl_keep isl_stream
*s
,
3611 __isl_take isl_set
*dom
, struct vars
*v
)
3618 aff_dom
= read_aff_domain(s
, dom
, v
);
3619 pa
= read_pw_aff_with_dom(s
, aff_dom
, v
);
3620 vars_drop(v
, v
->n
- n
);
3627 #include "isl_stream_read_pw_with_params_templ.c"
3630 #define TYPE_BASE aff
3631 #include "isl_read_from_str_templ.c"
3634 #define TYPE_BASE pw_aff
3635 #include "isl_stream_read_with_params_templ.c"
3636 #include "isl_read_from_str_templ.c"
3638 /* Given that "pa" is the element at position "pos" of a tuple
3639 * returned by read_tuple, check that it does not involve any
3640 * output/set dimensions (appearing at the "n" positions starting at "first"),
3641 * remove those from the domain and replace the domain space
3642 * with "domain_space".
3644 * In particular, the result of read_tuple is of the form
3645 * [input, output] -> [output], with anonymous domain.
3646 * The function read_tuple accepts tuples where some output or
3647 * set dimensions are defined in terms of other output or set dimensions
3648 * since this function is also used to read maps. As a special case,
3649 * read_tuple also accepts dimensions that are defined in terms of themselves
3650 * (i.e., that are not defined).
3651 * These cases are not allowed here.
3653 static __isl_give isl_pw_aff
*separate_tuple_entry(__isl_take isl_pw_aff
*pa
,
3654 int pos
, unsigned first
, unsigned n
, __isl_take isl_space
*domain_space
)
3658 involves
= isl_pw_aff_involves_dims(pa
, isl_dim_in
, first
, pos
+ 1);
3660 pa
= isl_pw_aff_free(pa
);
3661 } else if (involves
) {
3662 isl_die(isl_pw_aff_get_ctx(pa
), isl_error_invalid
,
3663 "not an affine expression",
3664 pa
= isl_pw_aff_free(pa
));
3666 pa
= isl_pw_aff_drop_dims(pa
, isl_dim_in
, first
, n
);
3667 pa
= isl_pw_aff_reset_domain_space(pa
, domain_space
);
3672 /* Set entry "pos" of "mpa" to the corresponding entry in "tuple",
3673 * as obtained from read_tuple().
3674 * The "n" output dimensions also appear among the input dimensions
3675 * at position "first".
3677 * The entry is not allowed to depend on any (other) output dimensions.
3679 static __isl_give isl_multi_pw_aff
*isl_multi_pw_aff_set_tuple_entry(
3680 __isl_take isl_multi_pw_aff
*mpa
, __isl_take isl_pw_aff
*tuple_el
,
3681 int pos
, unsigned first
, unsigned n
)
3686 space
= isl_multi_pw_aff_get_domain_space(mpa
);
3687 pa
= separate_tuple_entry(tuple_el
, pos
, first
, n
, space
);
3688 return isl_multi_pw_aff_set_pw_aff(mpa
, pos
, pa
);
3694 #include <isl_multi_from_tuple_templ.c>
3696 /* Read a tuple of piecewise affine expressions,
3697 * including optional constraints on the domain from "s".
3698 * "dom" represents the initial constraints on the domain.
3700 * The input format is similar to that of a map, except that any conditions
3701 * on the domains should be specified inside the tuple since each
3702 * piecewise affine expression may have a different domain.
3703 * However, additional, shared conditions can also be specified.
3704 * This is especially useful for setting the explicit domain
3705 * of a zero-dimensional isl_multi_pw_aff.
3707 * The isl_multi_pw_aff may live in either a set or a map space.
3708 * First read the first tuple and check if it is followed by a "->".
3709 * If so, convert the tuple into the domain of the isl_multi_pw_aff and
3710 * read in the next tuple. This tuple (or the first tuple if it was
3711 * not followed by a "->") is then converted into an isl_multi_pw_aff
3712 * through a call to isl_multi_pw_aff_from_tuple.
3713 * The domain of the result is intersected with the domain.
3715 * Note that the last tuple may introduce new identifiers,
3716 * but these cannot be referenced in the description of the domain.
3718 static __isl_give isl_multi_pw_aff
*read_conditional_multi_pw_aff(
3719 __isl_keep isl_stream
*s
, __isl_take isl_set
*dom
, struct vars
*v
)
3721 isl_multi_pw_aff
*tuple
;
3722 isl_multi_pw_aff
*mpa
;
3727 tuple
= read_tuple(s
, v
, 0, 0);
3730 if (isl_stream_eat_if_available(s
, ISL_TOKEN_TO
)) {
3731 isl_map
*map
= map_from_tuple(tuple
, dom
, isl_dim_in
, v
, 0);
3732 dom
= isl_map_domain(map
);
3734 tuple
= read_tuple(s
, v
, 0, 0);
3738 mpa
= isl_multi_pw_aff_from_tuple(isl_set_get_space(dom
), tuple
);
3740 dom
= isl_set_free(dom
);
3742 vars_drop(v
, v
->n
- n_dom
);
3743 dom
= read_optional_formula(s
, dom
, v
, 0);
3745 vars_drop(v
, v
->n
- n
);
3747 mpa
= isl_multi_pw_aff_intersect_domain(mpa
, dom
);
3755 /* Read a tuple of affine expressions, together with optional constraints
3756 * on the domain from "s". "dom" represents the initial constraints
3759 * Read a tuple of piecewise affine expressions with optional constraints and
3760 * convert the result to an isl_pw_multi_aff on the shared domain.
3762 static __isl_give isl_pw_multi_aff
*read_conditional_multi_aff(
3763 __isl_keep isl_stream
*s
, __isl_take isl_set
*dom
, struct vars
*v
)
3765 isl_multi_pw_aff
*mpa
;
3767 mpa
= read_conditional_multi_pw_aff(s
, dom
, v
);
3768 return isl_pw_multi_aff_from_multi_pw_aff(mpa
);
3771 /* Read an isl_union_pw_multi_aff from "s" with parameter domain "dom".
3772 * "v" contains a description of the identifiers parsed so far.
3774 * In particular, read a sequence
3775 * of zero or more tuples of affine expressions with optional conditions and
3778 static __isl_give isl_union_pw_multi_aff
*
3779 isl_stream_read_with_params_union_pw_multi_aff(__isl_keep isl_stream
*s
,
3780 __isl_keep isl_set
*dom
, struct vars
*v
)
3782 isl_union_pw_multi_aff
*upma
;
3784 upma
= isl_union_pw_multi_aff_empty(isl_set_get_space(dom
));
3787 isl_pw_multi_aff
*pma
;
3788 isl_union_pw_multi_aff
*upma2
;
3790 if (isl_stream_next_token_is(s
, '}'))
3793 pma
= read_conditional_multi_aff(s
, isl_set_copy(dom
), v
);
3794 upma2
= isl_union_pw_multi_aff_from_pw_multi_aff(pma
);
3795 upma
= isl_union_pw_multi_aff_union_add(upma
, upma2
);
3798 } while (isl_stream_eat_if_available(s
, ';'));
3804 #define BASE multi_aff
3805 #include "isl_stream_read_pw_with_params_templ.c"
3808 #define TYPE_BASE pw_multi_aff
3809 #include "isl_stream_read_with_params_templ.c"
3810 #include "isl_read_from_str_templ.c"
3813 #define TYPE_BASE union_pw_multi_aff
3814 #include "isl_stream_read_with_params_templ.c"
3815 #include "isl_read_from_str_templ.c"
3820 #include <isl_multi_read_no_explicit_domain_templ.c>
3825 #include <isl_multi_read_no_explicit_domain_templ.c>
3827 /* Set entry "pos" of "ma" to the corresponding entry in "tuple",
3828 * as obtained from read_tuple().
3829 * The "n" output dimensions also appear among the input dimensions
3830 * at position "first".
3832 * The entry is not allowed to depend on any (other) output dimensions.
3834 static __isl_give isl_multi_aff
*isl_multi_aff_set_tuple_entry(
3835 __isl_take isl_multi_aff
*ma
, __isl_take isl_pw_aff
*tuple_el
,
3836 int pos
, unsigned first
, unsigned n
)
3842 space
= isl_multi_aff_get_domain_space(ma
);
3843 pa
= separate_tuple_entry(tuple_el
, pos
, first
, n
, space
);
3844 aff
= isl_pw_aff_as_aff(pa
);
3845 return isl_multi_aff_set_aff(ma
, pos
, aff
);
3851 #include <isl_multi_from_tuple_templ.c>
3853 /* Read a multi-affine expression from "s".
3854 * If the multi-affine expression has a domain, then the tuple
3855 * representing this domain cannot involve any affine expressions.
3856 * The tuple representing the actual expressions needs to consist
3857 * of only affine expressions.
3859 __isl_give isl_multi_aff
*isl_stream_read_multi_aff(__isl_keep isl_stream
*s
)
3862 isl_multi_pw_aff
*tuple
= NULL
;
3863 isl_space
*dom_space
= NULL
;
3864 isl_multi_aff
*ma
= NULL
;
3866 v
= vars_new(s
->ctx
);
3870 dom_space
= read_params(s
, v
);
3873 if (isl_stream_eat(s
, '{'))
3876 tuple
= read_tuple(s
, v
, 0, 0);
3879 if (isl_stream_eat_if_available(s
, ISL_TOKEN_TO
)) {
3883 has_expr
= tuple_has_expr(tuple
);
3887 isl_die(s
->ctx
, isl_error_invalid
,
3888 "expecting universe domain", goto error
);
3889 space
= isl_space_range(isl_multi_pw_aff_get_space(tuple
));
3890 dom_space
= isl_space_align_params(space
, dom_space
);
3891 isl_multi_pw_aff_free(tuple
);
3892 tuple
= read_tuple(s
, v
, 0, 0);
3897 if (isl_stream_eat(s
, '}'))
3900 ma
= isl_multi_aff_from_tuple(dom_space
, tuple
);
3905 isl_multi_pw_aff_free(tuple
);
3907 isl_space_free(dom_space
);
3908 isl_multi_aff_free(ma
);
3913 #define TYPE_BASE multi_aff
3914 #include "isl_read_from_str_templ.c"
3916 /* Read an isl_multi_pw_aff from "s" with parameter domain "dom"..
3917 * "v" contains a description of the identifiers parsed so far.
3919 static __isl_give isl_multi_pw_aff
*isl_stream_read_with_params_multi_pw_aff(
3920 __isl_keep isl_stream
*s
, __isl_keep isl_set
*dom
, struct vars
*v
)
3922 return read_conditional_multi_pw_aff(s
, isl_set_copy(dom
), v
);
3926 #define TYPE_BASE multi_pw_aff
3927 #include "isl_stream_read_with_params_templ.c"
3928 #include "isl_read_from_str_templ.c"
3930 /* Return an empty isl_union_pw_aff with parameter domain "dom".
3932 static __isl_give isl_union_pw_aff
*empty_union_pw_aff_with_dom(
3933 __isl_take isl_set
*dom
)
3937 space
= isl_set_get_space(dom
);
3939 return isl_union_pw_aff_empty_space(space
);
3942 /* Read the body of an isl_union_pw_aff from "s" with parameter domain "dom".
3944 static __isl_give isl_union_pw_aff
*read_union_pw_aff_with_dom(
3945 __isl_keep isl_stream
*s
, __isl_take isl_set
*dom
, struct vars
*v
)
3948 isl_union_pw_aff
*upa
= NULL
;
3952 if (isl_stream_next_token_is(s
, '}'))
3953 return empty_union_pw_aff_with_dom(dom
);
3956 aff_dom
= read_aff_domain(s
, isl_set_copy(dom
), v
);
3957 pa
= read_pw_aff_with_dom(s
, aff_dom
, v
);
3958 vars_drop(v
, v
->n
- n
);
3960 upa
= isl_union_pw_aff_from_pw_aff(pa
);
3962 while (isl_stream_eat_if_available(s
, ';')) {
3964 isl_union_pw_aff
*upa_i
;
3967 aff_dom
= read_aff_domain(s
, isl_set_copy(dom
), v
);
3968 pa_i
= read_pw_aff_with_dom(s
, aff_dom
, v
);
3969 vars_drop(v
, v
->n
- n
);
3971 upa_i
= isl_union_pw_aff_from_pw_aff(pa_i
);
3972 upa
= isl_union_pw_aff_union_add(upa
, upa_i
);
3979 /* Read an isl_union_pw_aff from "s" with parameter domain "dom".
3980 * "v" contains a description of the identifiers parsed so far.
3982 static __isl_give isl_union_pw_aff
*isl_stream_read_with_params_union_pw_aff(
3983 __isl_keep isl_stream
*s
, __isl_keep isl_set
*dom
, struct vars
*v
)
3985 return read_union_pw_aff_with_dom(s
, isl_set_copy(dom
), v
);
3989 #define TYPE_BASE union_pw_aff
3990 #include "isl_stream_read_with_params_templ.c"
3991 #include "isl_read_from_str_templ.c"
3993 /* This function is called for each element in a tuple inside
3994 * isl_stream_read_multi_union_pw_aff.
3996 * Read a '{', the union piecewise affine expression body and a '}' and
3997 * add the isl_union_pw_aff to *list.
3999 static __isl_give isl_space
*read_union_pw_aff_el(__isl_keep isl_stream
*s
,
4000 struct vars
*v
, __isl_take isl_space
*space
, int rational
, void *user
)
4003 isl_union_pw_aff
*upa
;
4004 isl_union_pw_aff_list
**list
= (isl_union_pw_aff_list
**) user
;
4006 dom
= isl_set_universe(isl_space_params(isl_space_copy(space
)));
4007 if (isl_stream_eat(s
, '{'))
4009 upa
= read_union_pw_aff_with_dom(s
, dom
, v
);
4010 *list
= isl_union_pw_aff_list_add(*list
, upa
);
4011 if (isl_stream_eat(s
, '}'))
4012 return isl_space_free(space
);
4014 return isl_space_free(space
);
4018 return isl_space_free(space
);
4021 /* Do the next tokens in "s" correspond to an empty tuple?
4022 * In particular, does the stream start with a '[', followed by a ']',
4023 * not followed by a "->"?
4025 static int next_is_empty_tuple(__isl_keep isl_stream
*s
)
4027 struct isl_token
*tok
, *tok2
, *tok3
;
4028 int is_empty_tuple
= 0;
4030 tok
= isl_stream_next_token(s
);
4033 if (tok
->type
!= '[') {
4034 isl_stream_push_token(s
, tok
);
4038 tok2
= isl_stream_next_token(s
);
4039 if (tok2
&& tok2
->type
== ']') {
4040 tok3
= isl_stream_next_token(s
);
4041 is_empty_tuple
= !tok
|| tok
->type
!= ISL_TOKEN_TO
;
4043 isl_stream_push_token(s
, tok3
);
4046 isl_stream_push_token(s
, tok2
);
4047 isl_stream_push_token(s
, tok
);
4049 return is_empty_tuple
;
4052 /* Do the next tokens in "s" correspond to a tuple of parameters?
4053 * In particular, does the stream start with a '[' that is not
4054 * followed by a '{' or a nested tuple?
4056 static int next_is_param_tuple(__isl_keep isl_stream
*s
)
4058 struct isl_token
*tok
, *tok2
;
4061 tok
= isl_stream_next_token(s
);
4064 if (tok
->type
!= '[' || next_is_tuple(s
)) {
4065 isl_stream_push_token(s
, tok
);
4069 tok2
= isl_stream_next_token(s
);
4070 is_tuple
= tok2
&& tok2
->type
!= '{';
4072 isl_stream_push_token(s
, tok2
);
4073 isl_stream_push_token(s
, tok
);
4078 /* Read the core of a body of an isl_multi_union_pw_aff from "s",
4079 * i.e., everything except the parameter specification and
4080 * without shared domain constraints.
4081 * "v" contains a description of the identifiers parsed so far.
4082 * The parameters, if any, are specified by "space".
4084 * The body is of the form
4086 * [{ [..] : ... ; [..] : ... }, { [..] : ... ; [..] : ... }]
4088 * Read the tuple, collecting the individual isl_union_pw_aff
4089 * elements in a list and construct the result from the tuple space and
4092 static __isl_give isl_multi_union_pw_aff
*read_multi_union_pw_aff_body_core(
4093 __isl_keep isl_stream
*s
, struct vars
*v
, __isl_take isl_space
*space
)
4095 isl_union_pw_aff_list
*list
;
4096 isl_multi_union_pw_aff
*mupa
;
4098 list
= isl_union_pw_aff_list_alloc(s
->ctx
, 0);
4099 space
= read_tuple_space(s
, v
, space
, 1, 0,
4100 &read_union_pw_aff_el
, &list
);
4101 mupa
= isl_multi_union_pw_aff_from_union_pw_aff_list(space
, list
);
4106 /* Read the body of an isl_union_set from "s",
4107 * i.e., everything except the parameter specification.
4108 * "v" contains a description of the identifiers parsed so far.
4109 * The parameters, if any, are specified by "space".
4111 * First read a generic disjunction of object bodies and then try and extract
4112 * an isl_union_set from that.
4114 static __isl_give isl_union_set
*read_union_set_body(__isl_keep isl_stream
*s
,
4115 struct vars
*v
, __isl_take isl_space
*space
)
4117 struct isl_obj obj
= { isl_obj_set
, NULL
};
4120 map
= isl_set_universe(space
);
4121 if (isl_stream_eat(s
, '{') < 0)
4123 obj
= obj_read_disjuncts(s
, v
, map
);
4124 if (isl_stream_eat(s
, '}') < 0)
4128 return extract_union_set(s
->ctx
, obj
);
4130 obj
.type
->free(obj
.v
);
4135 /* Read the body of an isl_multi_union_pw_aff from "s",
4136 * i.e., everything except the parameter specification.
4137 * "v" contains a description of the identifiers parsed so far.
4138 * The parameters, if any, are specified by "space".
4140 * In particular, handle the special case with shared domain constraints.
4141 * These are specified as
4145 * and are especially useful for setting the explicit domain
4146 * of a zero-dimensional isl_multi_union_pw_aff.
4147 * The core isl_multi_union_pw_aff body ([...]) is read by
4148 * read_multi_union_pw_aff_body_core.
4150 static __isl_give isl_multi_union_pw_aff
*read_multi_union_pw_aff_body(
4151 __isl_keep isl_stream
*s
, struct vars
*v
, __isl_take isl_space
*space
)
4153 isl_multi_union_pw_aff
*mupa
;
4155 if (!isl_stream_next_token_is(s
, '('))
4156 return read_multi_union_pw_aff_body_core(s
, v
, space
);
4158 if (isl_stream_eat(s
, '(') < 0)
4160 mupa
= read_multi_union_pw_aff_body_core(s
, v
, isl_space_copy(space
));
4161 if (isl_stream_eat_if_available(s
, ':')) {
4164 dom
= read_union_set_body(s
, v
, space
);
4165 mupa
= isl_multi_union_pw_aff_intersect_domain(mupa
, dom
);
4167 isl_space_free(space
);
4169 if (isl_stream_eat(s
, ')') < 0)
4170 return isl_multi_union_pw_aff_free(mupa
);
4174 isl_space_free(space
);
4178 /* Read an isl_multi_union_pw_aff from "s".
4180 * The input has the form
4182 * [{ [..] : ... ; [..] : ... }, { [..] : ... ; [..] : ... }]
4186 * [..] -> [{ [..] : ... ; [..] : ... }, { [..] : ... ; [..] : ... }]
4188 * Additionally, a shared domain may be specified as
4194 * [..] -> ([..] : ...)
4196 * The first case is handled by the caller, the second case
4197 * is handled by read_multi_union_pw_aff_body.
4199 * We first check for the special case of an empty tuple "[]".
4200 * Then we check if there are any parameters.
4201 * Finally, read the tuple and construct the result.
4203 static __isl_give isl_multi_union_pw_aff
*read_multi_union_pw_aff_core(
4204 __isl_keep isl_stream
*s
)
4207 isl_set
*dom
= NULL
;
4209 isl_multi_union_pw_aff
*mupa
= NULL
;
4211 if (next_is_empty_tuple(s
)) {
4212 if (isl_stream_eat(s
, '['))
4214 if (isl_stream_eat(s
, ']'))
4216 space
= isl_space_set_alloc(s
->ctx
, 0, 0);
4217 return isl_multi_union_pw_aff_zero(space
);
4220 v
= vars_new(s
->ctx
);
4224 dom
= isl_set_universe(isl_space_params_alloc(s
->ctx
, 0));
4225 if (next_is_param_tuple(s
)) {
4226 dom
= read_map_tuple(s
, dom
, isl_dim_param
, v
, 0);
4227 if (isl_stream_eat(s
, ISL_TOKEN_TO
))
4230 space
= isl_set_get_space(dom
);
4232 mupa
= read_multi_union_pw_aff_body(s
, v
, space
);
4240 isl_multi_union_pw_aff_free(mupa
);
4244 /* Read an isl_multi_union_pw_aff from "s".
4246 * In particular, handle the special case with shared domain constraints.
4247 * These are specified as
4251 * and are especially useful for setting the explicit domain
4252 * of a zero-dimensional isl_multi_union_pw_aff.
4253 * The core isl_multi_union_pw_aff ([...]) is read by
4254 * read_multi_union_pw_aff_core.
4256 __isl_give isl_multi_union_pw_aff
*isl_stream_read_multi_union_pw_aff(
4257 __isl_keep isl_stream
*s
)
4259 isl_multi_union_pw_aff
*mupa
;
4261 if (!isl_stream_next_token_is(s
, '('))
4262 return read_multi_union_pw_aff_core(s
);
4264 if (isl_stream_eat(s
, '(') < 0)
4266 mupa
= read_multi_union_pw_aff_core(s
);
4267 if (isl_stream_eat_if_available(s
, ':')) {
4270 dom
= isl_stream_read_union_set(s
);
4271 mupa
= isl_multi_union_pw_aff_intersect_domain(mupa
, dom
);
4273 if (isl_stream_eat(s
, ')') < 0)
4274 return isl_multi_union_pw_aff_free(mupa
);
4279 #define TYPE_BASE multi_union_pw_aff
4280 #include "isl_read_from_str_templ.c"
4282 __isl_give isl_union_pw_qpolynomial
*isl_stream_read_union_pw_qpolynomial(
4283 __isl_keep isl_stream
*s
)
4288 if (obj
.type
== isl_obj_pw_qpolynomial
) {
4289 obj
.type
= isl_obj_union_pw_qpolynomial
;
4290 obj
.v
= isl_union_pw_qpolynomial_from_pw_qpolynomial(obj
.v
);
4293 isl_assert(s
->ctx
, obj
.type
== isl_obj_union_pw_qpolynomial
,
4298 obj
.type
->free(obj
.v
);
4303 #define TYPE_BASE union_pw_qpolynomial
4304 #include "isl_read_from_str_templ.c"