isl_input.c: identity_tuple_el: extract out identity_tuple_el_on_space
[isl.git] / isl_input.c
blob94768a0e244e8a1578db1bf5a01acf88dde6b6c4
1 /*
2 * Copyright 2008-2009 Katholieke Universiteit Leuven
3 * Copyright 2010 INRIA Saclay
4 * Copyright 2012-2013 Ecole Normale Superieure
6 * Use of this software is governed by the MIT license
8 * Written by Sven Verdoolaege, K.U.Leuven, Departement
9 * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
10 * and INRIA Saclay - Ile-de-France, Parc Club Orsay Universite,
11 * ZAC des vignes, 4 rue Jacques Monod, 91893 Orsay, France
12 * and Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France
15 #include <ctype.h>
16 #include <stdio.h>
17 #include <string.h>
18 #include <isl_ctx_private.h>
19 #include <isl_map_private.h>
20 #include <isl_id_private.h>
21 #include <isl/set.h>
22 #include <isl_seq.h>
23 #include <isl_stream_private.h>
24 #include <isl/obj.h>
25 #include "isl_polynomial_private.h"
26 #include <isl/union_set.h>
27 #include <isl/union_map.h>
28 #include <isl_mat_private.h>
29 #include <isl_aff_private.h>
30 #include <isl_vec_private.h>
31 #include <isl/list.h>
32 #include <isl_val_private.h>
34 struct variable {
35 char *name;
36 int pos;
37 struct variable *next;
40 struct vars {
41 struct isl_ctx *ctx;
42 int n;
43 struct variable *v;
46 static struct vars *vars_new(struct isl_ctx *ctx)
48 struct vars *v;
49 v = isl_alloc_type(ctx, struct vars);
50 if (!v)
51 return NULL;
52 v->ctx = ctx;
53 v->n = 0;
54 v->v = NULL;
55 return v;
58 static void variable_free(struct variable *var)
60 while (var) {
61 struct variable *next = var->next;
62 free(var->name);
63 free(var);
64 var = next;
68 static void vars_free(struct vars *v)
70 if (!v)
71 return;
72 variable_free(v->v);
73 free(v);
76 static void vars_drop(struct vars *v, int n)
78 struct variable *var;
80 if (!v || !v->v)
81 return;
83 v->n -= n;
85 var = v->v;
86 while (--n >= 0) {
87 struct variable *next = var->next;
88 free(var->name);
89 free(var);
90 var = next;
92 v->v = var;
95 static struct variable *variable_new(struct vars *v, const char *name, int len,
96 int pos)
98 struct variable *var;
99 var = isl_calloc_type(v->ctx, struct variable);
100 if (!var)
101 goto error;
102 var->name = strdup(name);
103 var->name[len] = '\0';
104 var->pos = pos;
105 var->next = v->v;
106 return var;
107 error:
108 variable_free(v->v);
109 return NULL;
112 static int vars_pos(struct vars *v, const char *s, int len)
114 int pos;
115 struct variable *q;
117 if (len == -1)
118 len = strlen(s);
119 for (q = v->v; q; q = q->next) {
120 if (strncmp(q->name, s, len) == 0 && q->name[len] == '\0')
121 break;
123 if (q)
124 pos = q->pos;
125 else {
126 pos = v->n;
127 v->v = variable_new(v, s, len, v->n);
128 if (!v->v)
129 return -1;
130 v->n++;
132 return pos;
135 static int vars_add_anon(struct vars *v)
137 v->v = variable_new(v, "", 0, v->n);
139 if (!v->v)
140 return -1;
141 v->n++;
143 return 0;
146 /* Obtain next token, with some preprocessing.
147 * In particular, evaluate expressions of the form x^y,
148 * with x and y values.
150 static struct isl_token *next_token(__isl_keep isl_stream *s)
152 struct isl_token *tok, *tok2;
154 tok = isl_stream_next_token(s);
155 if (!tok || tok->type != ISL_TOKEN_VALUE)
156 return tok;
157 if (!isl_stream_eat_if_available(s, '^'))
158 return tok;
159 tok2 = isl_stream_next_token(s);
160 if (!tok2 || tok2->type != ISL_TOKEN_VALUE) {
161 isl_stream_error(s, tok2, "expecting constant value");
162 goto error;
165 isl_int_pow_ui(tok->u.v, tok->u.v, isl_int_get_ui(tok2->u.v));
167 isl_token_free(tok2);
168 return tok;
169 error:
170 isl_token_free(tok);
171 isl_token_free(tok2);
172 return NULL;
175 /* Read an isl_val from "s".
177 * The following token sequences are recognized
179 * "infty" -> infty
180 * "-" "infty" -> -infty
181 * "NaN" -> NaN
182 * n "/" d -> n/d
183 * v -> v
185 * where n, d and v are integer constants.
187 __isl_give isl_val *isl_stream_read_val(__isl_keep isl_stream *s)
189 struct isl_token *tok = NULL;
190 struct isl_token *tok2 = NULL;
191 isl_val *val;
193 tok = next_token(s);
194 if (!tok) {
195 isl_stream_error(s, NULL, "unexpected EOF");
196 goto error;
198 if (tok->type == ISL_TOKEN_INFTY) {
199 isl_token_free(tok);
200 return isl_val_infty(s->ctx);
202 if (tok->type == '-' &&
203 isl_stream_eat_if_available(s, ISL_TOKEN_INFTY)) {
204 isl_token_free(tok);
205 return isl_val_neginfty(s->ctx);
207 if (tok->type == ISL_TOKEN_NAN) {
208 isl_token_free(tok);
209 return isl_val_nan(s->ctx);
211 if (tok->type != ISL_TOKEN_VALUE) {
212 isl_stream_error(s, tok, "expecting value");
213 goto error;
216 if (isl_stream_eat_if_available(s, '/')) {
217 tok2 = next_token(s);
218 if (!tok2) {
219 isl_stream_error(s, NULL, "unexpected EOF");
220 goto error;
222 if (tok2->type != ISL_TOKEN_VALUE) {
223 isl_stream_error(s, tok2, "expecting value");
224 goto error;
226 val = isl_val_rat_from_isl_int(s->ctx, tok->u.v, tok2->u.v);
227 val = isl_val_normalize(val);
228 } else {
229 val = isl_val_int_from_isl_int(s->ctx, tok->u.v);
232 isl_token_free(tok);
233 isl_token_free(tok2);
234 return val;
235 error:
236 isl_token_free(tok);
237 isl_token_free(tok2);
238 return NULL;
241 /* Read an isl_val from "str".
243 struct isl_val *isl_val_read_from_str(struct isl_ctx *ctx,
244 const char *str)
246 isl_val *val;
247 isl_stream *s = isl_stream_new_str(ctx, str);
248 if (!s)
249 return NULL;
250 val = isl_stream_read_val(s);
251 isl_stream_free(s);
252 return val;
255 static int accept_cst_factor(__isl_keep isl_stream *s, isl_int *f)
257 struct isl_token *tok;
259 tok = next_token(s);
260 if (!tok || tok->type != ISL_TOKEN_VALUE) {
261 isl_stream_error(s, tok, "expecting constant value");
262 goto error;
265 isl_int_mul(*f, *f, tok->u.v);
267 isl_token_free(tok);
269 if (isl_stream_eat_if_available(s, '*'))
270 return accept_cst_factor(s, f);
272 return 0;
273 error:
274 isl_token_free(tok);
275 return -1;
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;
289 isl_pw_aff *q;
291 tok = next_token(s);
292 if (!tok || tok->type != ISL_TOKEN_VALUE) {
293 isl_stream_error(s, tok, "expecting constant value");
294 goto error;
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);
304 isl_token_free(tok);
305 return aff;
306 error:
307 isl_pw_aff_free(aff);
308 isl_token_free(tok);
309 return NULL;
312 static __isl_give isl_pw_aff *accept_affine(__isl_keep isl_stream *s,
313 __isl_take isl_space *space, struct vars *v);
314 static __isl_give isl_pw_aff_list *accept_affine_list(__isl_keep isl_stream *s,
315 __isl_take isl_space *dim, struct vars *v);
317 static __isl_give isl_pw_aff *accept_minmax(__isl_keep isl_stream *s,
318 __isl_take isl_space *dim, struct vars *v)
320 struct isl_token *tok;
321 isl_pw_aff_list *list = NULL;
322 int min;
324 tok = isl_stream_next_token(s);
325 if (!tok)
326 goto error;
327 min = tok->type == ISL_TOKEN_MIN;
328 isl_token_free(tok);
330 if (isl_stream_eat(s, '('))
331 goto error;
333 list = accept_affine_list(s, isl_space_copy(dim), v);
334 if (!list)
335 goto error;
337 if (isl_stream_eat(s, ')'))
338 goto error;
340 isl_space_free(dim);
341 return min ? isl_pw_aff_list_min(list) : isl_pw_aff_list_max(list);
342 error:
343 isl_space_free(dim);
344 isl_pw_aff_list_free(list);
345 return NULL;
348 /* Is "tok" the start of an integer division?
350 static int is_start_of_div(struct isl_token *tok)
352 if (!tok)
353 return 0;
354 if (tok->type == '[')
355 return 1;
356 if (tok->type == ISL_TOKEN_FLOOR)
357 return 1;
358 if (tok->type == ISL_TOKEN_CEIL)
359 return 1;
360 if (tok->type == ISL_TOKEN_FLOORD)
361 return 1;
362 if (tok->type == ISL_TOKEN_CEILD)
363 return 1;
364 return 0;
367 /* Read an integer division from "s" and return it as an isl_pw_aff.
369 * The integer division can be of the form
371 * [<affine expression>]
372 * floor(<affine expression>)
373 * ceil(<affine expression>)
374 * floord(<affine expression>,<denominator>)
375 * ceild(<affine expression>,<denominator>)
377 static __isl_give isl_pw_aff *accept_div(__isl_keep isl_stream *s,
378 __isl_take isl_space *dim, struct vars *v)
380 struct isl_token *tok;
381 int f = 0;
382 int c = 0;
383 int extra = 0;
384 isl_pw_aff *pwaff = NULL;
386 if (isl_stream_eat_if_available(s, ISL_TOKEN_FLOORD))
387 extra = f = 1;
388 else if (isl_stream_eat_if_available(s, ISL_TOKEN_CEILD))
389 extra = c = 1;
390 else if (isl_stream_eat_if_available(s, ISL_TOKEN_FLOOR))
391 f = 1;
392 else if (isl_stream_eat_if_available(s, ISL_TOKEN_CEIL))
393 c = 1;
394 if (f || c) {
395 if (isl_stream_eat(s, '('))
396 goto error;
397 } else {
398 if (isl_stream_eat(s, '['))
399 goto error;
402 pwaff = accept_affine(s, isl_space_copy(dim), v);
404 if (extra) {
405 if (isl_stream_eat(s, ','))
406 goto error;
408 tok = next_token(s);
409 if (!tok)
410 goto error;
411 if (tok->type != ISL_TOKEN_VALUE) {
412 isl_stream_error(s, tok, "expected denominator");
413 isl_stream_push_token(s, tok);
414 goto error;
416 pwaff = isl_pw_aff_scale_down(pwaff, tok->u.v);
417 isl_token_free(tok);
420 if (c)
421 pwaff = isl_pw_aff_ceil(pwaff);
422 else
423 pwaff = isl_pw_aff_floor(pwaff);
425 if (f || c) {
426 if (isl_stream_eat(s, ')'))
427 goto error;
428 } else {
429 if (isl_stream_eat(s, ']'))
430 goto error;
433 isl_space_free(dim);
434 return pwaff;
435 error:
436 isl_space_free(dim);
437 isl_pw_aff_free(pwaff);
438 return NULL;
441 static __isl_give isl_pw_aff *accept_affine_factor(__isl_keep isl_stream *s,
442 __isl_take isl_space *dim, struct vars *v)
444 struct isl_token *tok = NULL;
445 isl_pw_aff *res = NULL;
447 tok = next_token(s);
448 if (!tok) {
449 isl_stream_error(s, NULL, "unexpected EOF");
450 goto error;
453 if (tok->type == ISL_TOKEN_AFF) {
454 res = isl_pw_aff_copy(tok->u.pwaff);
455 isl_token_free(tok);
456 } else if (tok->type == ISL_TOKEN_IDENT) {
457 int n = v->n;
458 int pos = vars_pos(v, tok->u.s, -1);
459 isl_aff *aff;
461 if (pos < 0)
462 goto error;
463 if (pos >= n) {
464 vars_drop(v, v->n - n);
465 isl_stream_error(s, tok, "unknown identifier");
466 goto error;
469 aff = isl_aff_zero_on_domain(isl_local_space_from_space(isl_space_copy(dim)));
470 if (!aff)
471 goto error;
472 isl_int_set_si(aff->v->el[2 + pos], 1);
473 res = isl_pw_aff_from_aff(aff);
474 isl_token_free(tok);
475 } else if (tok->type == ISL_TOKEN_VALUE) {
476 if (isl_stream_eat_if_available(s, '*')) {
477 res = accept_affine_factor(s, isl_space_copy(dim), v);
478 res = isl_pw_aff_scale(res, tok->u.v);
479 } else {
480 isl_local_space *ls;
481 isl_aff *aff;
482 ls = isl_local_space_from_space(isl_space_copy(dim));
483 aff = isl_aff_zero_on_domain(ls);
484 aff = isl_aff_add_constant(aff, tok->u.v);
485 res = isl_pw_aff_from_aff(aff);
487 isl_token_free(tok);
488 } else if (tok->type == '(') {
489 isl_token_free(tok);
490 tok = NULL;
491 res = accept_affine(s, isl_space_copy(dim), v);
492 if (!res)
493 goto error;
494 if (isl_stream_eat(s, ')'))
495 goto error;
496 } else if (is_start_of_div(tok)) {
497 isl_stream_push_token(s, tok);
498 tok = NULL;
499 res = accept_div(s, isl_space_copy(dim), v);
500 } else if (tok->type == ISL_TOKEN_MIN || tok->type == ISL_TOKEN_MAX) {
501 isl_stream_push_token(s, tok);
502 tok = NULL;
503 res = accept_minmax(s, isl_space_copy(dim), v);
504 } else {
505 isl_stream_error(s, tok, "expecting factor");
506 goto error;
508 if (isl_stream_eat_if_available(s, '%') ||
509 isl_stream_eat_if_available(s, ISL_TOKEN_MOD)) {
510 isl_space_free(dim);
511 return affine_mod(s, v, res);
513 if (isl_stream_eat_if_available(s, '*')) {
514 isl_int f;
515 isl_int_init(f);
516 isl_int_set_si(f, 1);
517 if (accept_cst_factor(s, &f) < 0) {
518 isl_int_clear(f);
519 goto error2;
521 res = isl_pw_aff_scale(res, f);
522 isl_int_clear(f);
524 if (isl_stream_eat_if_available(s, '/')) {
525 isl_int f;
526 isl_int_init(f);
527 isl_int_set_si(f, 1);
528 if (accept_cst_factor(s, &f) < 0) {
529 isl_int_clear(f);
530 goto error2;
532 res = isl_pw_aff_scale_down(res, f);
533 isl_int_clear(f);
536 isl_space_free(dim);
537 return res;
538 error:
539 isl_token_free(tok);
540 error2:
541 isl_pw_aff_free(res);
542 isl_space_free(dim);
543 return NULL;
546 static __isl_give isl_pw_aff *add_cst(__isl_take isl_pw_aff *pwaff, isl_int v)
548 isl_aff *aff;
549 isl_space *space;
551 space = isl_pw_aff_get_domain_space(pwaff);
552 aff = isl_aff_zero_on_domain(isl_local_space_from_space(space));
553 aff = isl_aff_add_constant(aff, v);
555 return isl_pw_aff_add(pwaff, isl_pw_aff_from_aff(aff));
558 /* Return a piecewise affine expression defined on the specified domain
559 * that represents NaN.
561 static __isl_give isl_pw_aff *nan_on_domain(__isl_keep isl_space *space)
563 isl_local_space *ls;
565 ls = isl_local_space_from_space(isl_space_copy(space));
566 return isl_pw_aff_nan_on_domain(ls);
569 static __isl_give isl_pw_aff *accept_affine(__isl_keep isl_stream *s,
570 __isl_take isl_space *space, struct vars *v)
572 struct isl_token *tok = NULL;
573 isl_local_space *ls;
574 isl_pw_aff *res;
575 int sign = 1;
577 ls = isl_local_space_from_space(isl_space_copy(space));
578 res = isl_pw_aff_from_aff(isl_aff_zero_on_domain(ls));
579 if (!res)
580 goto error;
582 for (;;) {
583 tok = next_token(s);
584 if (!tok) {
585 isl_stream_error(s, NULL, "unexpected EOF");
586 goto error;
588 if (tok->type == '-') {
589 sign = -sign;
590 isl_token_free(tok);
591 continue;
593 if (tok->type == '(' || is_start_of_div(tok) ||
594 tok->type == ISL_TOKEN_MIN || tok->type == ISL_TOKEN_MAX ||
595 tok->type == ISL_TOKEN_IDENT ||
596 tok->type == ISL_TOKEN_AFF) {
597 isl_pw_aff *term;
598 isl_stream_push_token(s, tok);
599 tok = NULL;
600 term = accept_affine_factor(s,
601 isl_space_copy(space), v);
602 if (sign < 0)
603 res = isl_pw_aff_sub(res, term);
604 else
605 res = isl_pw_aff_add(res, term);
606 if (!res)
607 goto error;
608 sign = 1;
609 } else if (tok->type == ISL_TOKEN_VALUE) {
610 if (sign < 0)
611 isl_int_neg(tok->u.v, tok->u.v);
612 if (isl_stream_eat_if_available(s, '*') ||
613 isl_stream_next_token_is(s, ISL_TOKEN_IDENT)) {
614 isl_pw_aff *term;
615 term = accept_affine_factor(s,
616 isl_space_copy(space), v);
617 term = isl_pw_aff_scale(term, tok->u.v);
618 res = isl_pw_aff_add(res, term);
619 if (!res)
620 goto error;
621 } else {
622 res = add_cst(res, tok->u.v);
624 sign = 1;
625 } else if (tok->type == ISL_TOKEN_NAN) {
626 res = isl_pw_aff_add(res, nan_on_domain(space));
627 } else {
628 isl_stream_error(s, tok, "unexpected isl_token");
629 isl_stream_push_token(s, tok);
630 isl_pw_aff_free(res);
631 isl_space_free(space);
632 return NULL;
634 isl_token_free(tok);
636 tok = next_token(s);
637 if (tok && tok->type == '-') {
638 sign = -sign;
639 isl_token_free(tok);
640 } else if (tok && tok->type == '+') {
641 /* nothing */
642 isl_token_free(tok);
643 } else if (tok && tok->type == ISL_TOKEN_VALUE &&
644 isl_int_is_neg(tok->u.v)) {
645 isl_stream_push_token(s, tok);
646 } else {
647 if (tok)
648 isl_stream_push_token(s, tok);
649 break;
653 isl_space_free(space);
654 return res;
655 error:
656 isl_space_free(space);
657 isl_token_free(tok);
658 isl_pw_aff_free(res);
659 return NULL;
662 /* Is "type" the type of a comparison operator between lists
663 * of affine expressions?
665 static int is_list_comparator_type(int type)
667 switch (type) {
668 case ISL_TOKEN_LEX_LT:
669 case ISL_TOKEN_LEX_GT:
670 case ISL_TOKEN_LEX_LE:
671 case ISL_TOKEN_LEX_GE:
672 return 1;
673 default:
674 return 0;
678 static int is_comparator(struct isl_token *tok)
680 if (!tok)
681 return 0;
682 if (is_list_comparator_type(tok->type))
683 return 1;
685 switch (tok->type) {
686 case ISL_TOKEN_LT:
687 case ISL_TOKEN_GT:
688 case ISL_TOKEN_LE:
689 case ISL_TOKEN_GE:
690 case ISL_TOKEN_NE:
691 case '=':
692 return 1;
693 default:
694 return 0;
698 static __isl_give isl_map *read_formula(__isl_keep isl_stream *s,
699 struct vars *v, __isl_take isl_map *map, int rational);
700 static __isl_give isl_pw_aff *accept_extended_affine(__isl_keep isl_stream *s,
701 __isl_take isl_space *dim, struct vars *v, int rational);
703 /* Accept a ternary operator, given the first argument.
705 static __isl_give isl_pw_aff *accept_ternary(__isl_keep isl_stream *s,
706 __isl_take isl_map *cond, struct vars *v, int rational)
708 isl_space *space;
709 isl_pw_aff *pwaff1 = NULL, *pwaff2 = NULL, *pa_cond;
711 if (!cond)
712 return NULL;
714 if (isl_stream_eat(s, '?'))
715 goto error;
717 space = isl_space_wrap(isl_map_get_space(cond));
718 pwaff1 = accept_extended_affine(s, space, v, rational);
719 if (!pwaff1)
720 goto error;
722 if (isl_stream_eat(s, ':'))
723 goto error;
725 space = isl_pw_aff_get_domain_space(pwaff1);
726 pwaff2 = accept_extended_affine(s, space, v, rational);
727 if (!pwaff2)
728 goto error;
730 pa_cond = isl_set_indicator_function(isl_map_wrap(cond));
731 return isl_pw_aff_cond(pa_cond, pwaff1, pwaff2);
732 error:
733 isl_map_free(cond);
734 isl_pw_aff_free(pwaff1);
735 isl_pw_aff_free(pwaff2);
736 return NULL;
739 /* Set *line and *col to those of the next token, if any.
741 static void set_current_line_col(__isl_keep isl_stream *s, int *line, int *col)
743 struct isl_token *tok;
745 tok = isl_stream_next_token(s);
746 if (!tok)
747 return;
749 *line = tok->line;
750 *col = tok->col;
751 isl_stream_push_token(s, tok);
754 /* Push a token encapsulating "pa" onto "s", with the given
755 * line and column.
757 static isl_stat push_aff(__isl_keep isl_stream *s, int line, int col,
758 __isl_take isl_pw_aff *pa)
760 struct isl_token *tok;
762 tok = isl_token_new(s->ctx, line, col, 0);
763 if (!tok)
764 goto error;
765 tok->type = ISL_TOKEN_AFF;
766 tok->u.pwaff = pa;
767 isl_stream_push_token(s, tok);
769 return isl_stat_ok;
770 error:
771 isl_pw_aff_free(pa);
772 return isl_stat_error;
775 /* Is the next token a comparison operator?
777 static int next_is_comparator(__isl_keep isl_stream *s)
779 int is_comp;
780 struct isl_token *tok;
782 tok = isl_stream_next_token(s);
783 if (!tok)
784 return 0;
786 is_comp = is_comparator(tok);
787 isl_stream_push_token(s, tok);
789 return is_comp;
792 /* Accept an affine expression that may involve ternary operators.
793 * We first read an affine expression.
794 * If it is not followed by a comparison operator, we simply return it.
795 * Otherwise, we assume the affine expression is part of the first
796 * argument of a ternary operator and try to parse that.
798 static __isl_give isl_pw_aff *accept_extended_affine(__isl_keep isl_stream *s,
799 __isl_take isl_space *dim, struct vars *v, int rational)
801 isl_space *space;
802 isl_map *cond;
803 isl_pw_aff *pwaff;
804 int line = -1, col = -1;
806 set_current_line_col(s, &line, &col);
808 pwaff = accept_affine(s, dim, v);
809 if (rational)
810 pwaff = isl_pw_aff_set_rational(pwaff);
811 if (!pwaff)
812 return NULL;
813 if (!next_is_comparator(s))
814 return pwaff;
816 space = isl_pw_aff_get_domain_space(pwaff);
817 cond = isl_map_universe(isl_space_unwrap(space));
819 if (push_aff(s, line, col, pwaff) < 0)
820 cond = isl_map_free(cond);
821 if (!cond)
822 return NULL;
824 cond = read_formula(s, v, cond, rational);
826 return accept_ternary(s, cond, v, rational);
829 static __isl_give isl_map *read_var_def(__isl_keep isl_stream *s,
830 __isl_take isl_map *map, enum isl_dim_type type, struct vars *v,
831 int rational)
833 isl_pw_aff *def;
834 isl_size pos;
835 isl_map *def_map;
837 if (type == isl_dim_param)
838 pos = isl_map_dim(map, isl_dim_param);
839 else {
840 pos = isl_map_dim(map, isl_dim_in);
841 if (type == isl_dim_out) {
842 isl_size n_out = isl_map_dim(map, isl_dim_out);
843 if (pos < 0 || n_out < 0)
844 return isl_map_free(map);
845 pos += n_out;
847 type = isl_dim_in;
849 if (pos < 0)
850 return isl_map_free(map);
851 --pos;
853 def = accept_extended_affine(s, isl_space_wrap(isl_map_get_space(map)),
854 v, rational);
855 def_map = isl_map_from_pw_aff(def);
856 def_map = isl_map_equate(def_map, type, pos, isl_dim_out, 0);
857 def_map = isl_set_unwrap(isl_map_domain(def_map));
859 map = isl_map_intersect(map, def_map);
861 return map;
864 static __isl_give isl_pw_aff_list *accept_affine_list(__isl_keep isl_stream *s,
865 __isl_take isl_space *dim, struct vars *v)
867 isl_pw_aff *pwaff;
868 isl_pw_aff_list *list;
869 struct isl_token *tok = NULL;
871 pwaff = accept_affine(s, isl_space_copy(dim), v);
872 list = isl_pw_aff_list_from_pw_aff(pwaff);
873 if (!list)
874 goto error;
876 for (;;) {
877 tok = isl_stream_next_token(s);
878 if (!tok) {
879 isl_stream_error(s, NULL, "unexpected EOF");
880 goto error;
882 if (tok->type != ',') {
883 isl_stream_push_token(s, tok);
884 break;
886 isl_token_free(tok);
888 pwaff = accept_affine(s, isl_space_copy(dim), v);
889 list = isl_pw_aff_list_concat(list,
890 isl_pw_aff_list_from_pw_aff(pwaff));
891 if (!list)
892 goto error;
895 isl_space_free(dim);
896 return list;
897 error:
898 isl_space_free(dim);
899 isl_pw_aff_list_free(list);
900 return NULL;
903 static __isl_give isl_map *read_defined_var_list(__isl_keep isl_stream *s,
904 struct vars *v, __isl_take isl_map *map, int rational)
906 struct isl_token *tok;
908 while ((tok = isl_stream_next_token(s)) != NULL) {
909 int p;
910 int n = v->n;
912 if (tok->type != ISL_TOKEN_IDENT)
913 break;
915 p = vars_pos(v, tok->u.s, -1);
916 if (p < 0)
917 goto error;
918 if (p < n) {
919 isl_stream_error(s, tok, "expecting unique identifier");
920 goto error;
923 map = isl_map_add_dims(map, isl_dim_out, 1);
925 isl_token_free(tok);
926 tok = isl_stream_next_token(s);
927 if (tok && tok->type == '=') {
928 isl_token_free(tok);
929 map = read_var_def(s, map, isl_dim_out, v, rational);
930 tok = isl_stream_next_token(s);
933 if (!tok || tok->type != ',')
934 break;
936 isl_token_free(tok);
938 if (tok)
939 isl_stream_push_token(s, tok);
941 return map;
942 error:
943 isl_token_free(tok);
944 isl_map_free(map);
945 return NULL;
948 static int next_is_tuple(__isl_keep isl_stream *s)
950 struct isl_token *tok;
951 int is_tuple;
953 tok = isl_stream_next_token(s);
954 if (!tok)
955 return 0;
956 if (tok->type == '[') {
957 isl_stream_push_token(s, tok);
958 return 1;
960 if (tok->type != ISL_TOKEN_IDENT && !tok->is_keyword) {
961 isl_stream_push_token(s, tok);
962 return 0;
965 is_tuple = isl_stream_next_token_is(s, '[');
967 isl_stream_push_token(s, tok);
969 return is_tuple;
972 /* Is the next token one that necessarily forms the start of a condition?
974 static int next_is_condition_start(__isl_keep isl_stream *s)
976 return isl_stream_next_token_is(s, ISL_TOKEN_EXISTS) ||
977 isl_stream_next_token_is(s, ISL_TOKEN_NOT) ||
978 isl_stream_next_token_is(s, ISL_TOKEN_TRUE) ||
979 isl_stream_next_token_is(s, ISL_TOKEN_FALSE) ||
980 isl_stream_next_token_is(s, ISL_TOKEN_MAP);
983 /* Is "pa" an expression in term of earlier dimensions?
984 * The alternative is that the dimension is defined to be equal to itself,
985 * meaning that it has a universe domain and an expression that depends
986 * on itself. "i" is the position of the expression in a sequence
987 * of "n" expressions. The final dimensions of "pa" correspond to
988 * these "n" expressions.
990 static isl_bool pw_aff_is_expr(__isl_keep isl_pw_aff *pa, int i, int n)
992 isl_aff *aff;
994 if (!pa)
995 return isl_bool_error;
996 if (pa->n != 1)
997 return isl_bool_true;
998 if (!isl_set_plain_is_universe(pa->p[0].set))
999 return isl_bool_true;
1001 aff = pa->p[0].aff;
1002 if (isl_int_is_zero(aff->v->el[aff->v->size - n + i]))
1003 return isl_bool_true;
1004 return isl_bool_false;
1007 /* Does the tuple contain any dimensions that are defined
1008 * in terms of earlier dimensions?
1010 static isl_bool tuple_has_expr(__isl_keep isl_multi_pw_aff *tuple)
1012 int i;
1013 isl_size n;
1014 isl_bool has_expr = isl_bool_false;
1015 isl_pw_aff *pa;
1017 n = isl_multi_pw_aff_dim(tuple, isl_dim_out);
1018 if (n < 0)
1019 return isl_bool_error;
1020 for (i = 0; i < n; ++i) {
1021 pa = isl_multi_pw_aff_get_pw_aff(tuple, i);
1022 has_expr = pw_aff_is_expr(pa, i, n);
1023 isl_pw_aff_free(pa);
1024 if (has_expr < 0 || has_expr)
1025 break;
1028 return has_expr;
1031 /* Set the name of dimension "pos" in "space" to "name".
1032 * During printing, we add primes if the same name appears more than once
1033 * to distinguish the occurrences. Here, we remove those primes from "name"
1034 * before setting the name of the dimension.
1036 static __isl_give isl_space *space_set_dim_name(__isl_take isl_space *space,
1037 int pos, char *name)
1039 char *prime;
1041 if (!name)
1042 return space;
1044 prime = strchr(name, '\'');
1045 if (prime)
1046 *prime = '\0';
1047 space = isl_space_set_dim_name(space, isl_dim_out, pos, name);
1048 if (prime)
1049 *prime = '\'';
1051 return space;
1054 /* Construct an isl_pw_aff defined on a "space" (with v->n variables)
1055 * that is equal to the last of those variables.
1057 static __isl_give isl_pw_aff *identity_tuple_el_on_space(
1058 __isl_take isl_space *space, struct vars *v)
1060 isl_aff *aff;
1062 aff = isl_aff_zero_on_domain(isl_local_space_from_space(space));
1063 aff = isl_aff_add_coefficient_si(aff, isl_dim_in, v->n - 1, 1);
1064 return isl_pw_aff_from_aff(aff);
1067 /* Given that the (piecewise) affine expression "pa"
1068 * has just been parsed, followed by a colon,
1069 * continue parsing as part of a piecewise affine expression.
1071 * In particular, parse the conditions on "pa" and include them in the domain.
1073 static __isl_give isl_pw_aff *update_piecewise_affine_colon(
1074 __isl_take isl_pw_aff *pa, __isl_keep isl_stream *s,
1075 struct vars *v, int rational)
1077 isl_space *dom_space;
1078 isl_map *map;
1080 dom_space = isl_pw_aff_get_domain_space(pa);
1081 map = isl_map_universe(isl_space_from_domain(dom_space));
1082 map = read_formula(s, v, map, rational);
1083 pa = isl_pw_aff_intersect_domain(pa, isl_map_domain(map));
1085 return pa;
1088 /* Accept a piecewise affine expression.
1090 * At the outer level, the piecewise affine expression may be of the form
1092 * aff1 : condition1; aff2 : conditions2; ...
1094 * or simply
1096 * aff
1098 * each of the affine expressions may in turn include ternary operators.
1100 * There may be parentheses around some subexpression of "aff1"
1101 * around "aff1" itself, around "aff1 : condition1" and/or
1102 * around the entire piecewise affine expression.
1103 * We therefore remove the opening parenthesis (if any) from the stream
1104 * in case the closing parenthesis follows the colon, but if the closing
1105 * parenthesis is the first thing in the stream after the parsed affine
1106 * expression, we push the parsed expression onto the stream and parse
1107 * again in case the parentheses enclose some subexpression of "aff1".
1109 static __isl_give isl_pw_aff *accept_piecewise_affine(__isl_keep isl_stream *s,
1110 __isl_take isl_space *space, struct vars *v, int rational)
1112 isl_pw_aff *res;
1113 isl_space *res_space;
1115 res_space = isl_space_from_domain(isl_space_copy(space));
1116 res_space = isl_space_add_dims(res_space, isl_dim_out, 1);
1117 res = isl_pw_aff_empty(res_space);
1118 do {
1119 isl_pw_aff *pa;
1120 int seen_paren;
1121 int line = -1, col = -1;
1123 set_current_line_col(s, &line, &col);
1124 seen_paren = isl_stream_eat_if_available(s, '(');
1125 if (seen_paren)
1126 pa = accept_piecewise_affine(s, isl_space_copy(space),
1127 v, rational);
1128 else
1129 pa = accept_extended_affine(s, isl_space_copy(space),
1130 v, rational);
1131 if (seen_paren && isl_stream_eat_if_available(s, ')')) {
1132 seen_paren = 0;
1133 if (push_aff(s, line, col, pa) < 0)
1134 goto error;
1135 pa = accept_extended_affine(s, isl_space_copy(space),
1136 v, rational);
1138 if (isl_stream_eat_if_available(s, ':'))
1139 pa = update_piecewise_affine_colon(pa, s, v, rational);
1141 res = isl_pw_aff_union_add(res, pa);
1143 if (seen_paren && isl_stream_eat(s, ')'))
1144 goto error;
1145 } while (isl_stream_eat_if_available(s, ';'));
1147 isl_space_free(space);
1149 return res;
1150 error:
1151 isl_space_free(space);
1152 return isl_pw_aff_free(res);
1155 /* Read an affine expression from "s" for use in read_tuple.
1157 * accept_extended_affine requires a wrapped space as input.
1158 * read_tuple on the other hand expects each isl_pw_aff
1159 * to have an anonymous space. We therefore adjust the space
1160 * of the isl_pw_aff before returning it.
1162 static __isl_give isl_pw_aff *read_tuple_var_def(__isl_keep isl_stream *s,
1163 struct vars *v, int rational)
1165 isl_space *space;
1166 isl_pw_aff *def;
1168 space = isl_space_wrap(isl_space_alloc(s->ctx, 0, v->n, 0));
1170 def = accept_piecewise_affine(s, space, v, rational);
1171 def = isl_pw_aff_domain_factor_domain(def);
1173 return def;
1176 /* Read a list of tuple elements by calling "read_el" on each of them and
1177 * return a space with the same number of set dimensions derived from
1178 * the parameter space "space" and possibly updated by "read_el".
1179 * The elements in the list are separated by either "," or "][".
1180 * If "comma" is set then only "," is allowed.
1182 static __isl_give isl_space *read_tuple_list(__isl_keep isl_stream *s,
1183 struct vars *v, __isl_take isl_space *space, int rational, int comma,
1184 __isl_give isl_space *(*read_el)(__isl_keep isl_stream *s,
1185 struct vars *v, __isl_take isl_space *space, int rational,
1186 void *user),
1187 void *user)
1189 if (!space)
1190 return NULL;
1192 space = isl_space_set_from_params(space);
1194 if (isl_stream_next_token_is(s, ']'))
1195 return space;
1197 for (;;) {
1198 struct isl_token *tok;
1200 space = isl_space_add_dims(space, isl_dim_set, 1);
1202 space = read_el(s, v, space, rational, user);
1203 if (!space)
1204 return NULL;
1206 tok = isl_stream_next_token(s);
1207 if (!comma && tok && tok->type == ']' &&
1208 isl_stream_next_token_is(s, '[')) {
1209 isl_token_free(tok);
1210 tok = isl_stream_next_token(s);
1211 } else if (!tok || tok->type != ',') {
1212 if (tok)
1213 isl_stream_push_token(s, tok);
1214 break;
1217 isl_token_free(tok);
1220 return space;
1223 /* Read a tuple space from "s" derived from the parameter space "space".
1224 * Call "read_el" on each element in the tuples.
1226 static __isl_give isl_space *read_tuple_space(__isl_keep isl_stream *s,
1227 struct vars *v, __isl_take isl_space *space, int rational, int comma,
1228 __isl_give isl_space *(*read_el)(__isl_keep isl_stream *s,
1229 struct vars *v, __isl_take isl_space *space, int rational,
1230 void *user),
1231 void *user)
1233 struct isl_token *tok;
1234 char *name = NULL;
1235 isl_space *res = NULL;
1237 tok = isl_stream_next_token(s);
1238 if (!tok)
1239 goto error;
1240 if (tok->type == ISL_TOKEN_IDENT || tok->is_keyword) {
1241 name = strdup(tok->u.s);
1242 isl_token_free(tok);
1243 if (!name)
1244 goto error;
1245 } else
1246 isl_stream_push_token(s, tok);
1247 if (isl_stream_eat(s, '['))
1248 goto error;
1249 if (next_is_tuple(s)) {
1250 isl_space *out;
1251 res = read_tuple_space(s, v, isl_space_copy(space),
1252 rational, comma, read_el, user);
1253 if (isl_stream_eat(s, ISL_TOKEN_TO))
1254 goto error;
1255 out = read_tuple_space(s, v, isl_space_copy(space),
1256 rational, comma, read_el, user);
1257 res = isl_space_product(res, out);
1258 } else
1259 res = read_tuple_list(s, v, isl_space_copy(space),
1260 rational, comma, read_el, user);
1261 if (isl_stream_eat(s, ']'))
1262 goto error;
1264 if (name) {
1265 res = isl_space_set_tuple_name(res, isl_dim_set, name);
1266 free(name);
1269 isl_space_free(space);
1270 return res;
1271 error:
1272 free(name);
1273 isl_space_free(res);
1274 isl_space_free(space);
1275 return NULL;
1278 /* Construct an isl_pw_aff defined on a space with v->n variables
1279 * that is equal to the last of those variables.
1281 static __isl_give isl_pw_aff *identity_tuple_el(struct vars *v)
1283 isl_space *space;
1285 space = isl_space_set_alloc(v->ctx, 0, v->n);
1286 return identity_tuple_el_on_space(space, v);
1289 /* This function is called for each element in a tuple inside read_tuple.
1290 * Add a new variable to "v" and construct a corresponding isl_pw_aff defined
1291 * over a space containing all variables in "v" defined so far.
1292 * The isl_pw_aff expresses the new variable in terms of earlier variables
1293 * if a definition is provided. Otherwise, it is represented as being
1294 * equal to itself.
1295 * Add the isl_pw_aff to *list.
1296 * If the new variable was named, then adjust "space" accordingly and
1297 * return the updated space.
1299 static __isl_give isl_space *read_tuple_pw_aff_el(__isl_keep isl_stream *s,
1300 struct vars *v, __isl_take isl_space *space, int rational, void *user)
1302 isl_pw_aff_list **list = (isl_pw_aff_list **) user;
1303 isl_pw_aff *pa;
1304 struct isl_token *tok;
1305 int new_name = 0;
1307 tok = next_token(s);
1308 if (!tok) {
1309 isl_stream_error(s, NULL, "unexpected EOF");
1310 return isl_space_free(space);
1313 if (tok->type == ISL_TOKEN_IDENT) {
1314 int n = v->n;
1315 int p = vars_pos(v, tok->u.s, -1);
1316 if (p < 0)
1317 goto error;
1318 new_name = p >= n;
1321 if (tok->type == '*') {
1322 if (vars_add_anon(v) < 0)
1323 goto error;
1324 isl_token_free(tok);
1325 pa = identity_tuple_el(v);
1326 } else if (new_name) {
1327 isl_size pos = isl_space_dim(space, isl_dim_out);
1328 if (pos < 0)
1329 goto error;
1330 pos -= 1;
1331 space = space_set_dim_name(space, pos, v->v->name);
1332 isl_token_free(tok);
1333 if (isl_stream_eat_if_available(s, '='))
1334 pa = read_tuple_var_def(s, v, rational);
1335 else
1336 pa = identity_tuple_el(v);
1337 } else {
1338 isl_stream_push_token(s, tok);
1339 tok = NULL;
1340 if (vars_add_anon(v) < 0)
1341 goto error;
1342 pa = read_tuple_var_def(s, v, rational);
1345 *list = isl_pw_aff_list_add(*list, pa);
1346 if (!*list)
1347 return isl_space_free(space);
1349 return space;
1350 error:
1351 isl_token_free(tok);
1352 return isl_space_free(space);
1355 /* Read a tuple and represent it as an isl_multi_pw_aff.
1356 * The range space of the isl_multi_pw_aff is the space of the tuple.
1357 * The domain space is an anonymous space
1358 * with a dimension for each variable in the set of variables in "v",
1359 * including the variables in the range.
1360 * If a given dimension is not defined in terms of earlier dimensions in
1361 * the input, then the corresponding isl_pw_aff is set equal to one time
1362 * the variable corresponding to the dimension being defined.
1364 * The elements in the tuple are collected in a list by read_tuple_pw_aff_el.
1365 * Each element in this list is defined over a space representing
1366 * the variables defined so far. We need to adjust the earlier
1367 * elements to have as many variables in the domain as the final
1368 * element in the list.
1370 static __isl_give isl_multi_pw_aff *read_tuple(__isl_keep isl_stream *s,
1371 struct vars *v, int rational, int comma)
1373 int i;
1374 isl_size n;
1375 isl_space *space;
1376 isl_pw_aff_list *list;
1378 space = isl_space_params_alloc(v->ctx, 0);
1379 list = isl_pw_aff_list_alloc(s->ctx, 0);
1380 space = read_tuple_space(s, v, space, rational, comma,
1381 &read_tuple_pw_aff_el, &list);
1382 n = isl_space_dim(space, isl_dim_set);
1383 if (n < 0)
1384 space = isl_space_free(space);
1385 for (i = 0; i + 1 < n; ++i) {
1386 isl_pw_aff *pa;
1388 pa = isl_pw_aff_list_get_pw_aff(list, i);
1389 pa = isl_pw_aff_add_dims(pa, isl_dim_in, n - (i + 1));
1390 list = isl_pw_aff_list_set_pw_aff(list, i, pa);
1393 space = isl_space_from_range(space);
1394 space = isl_space_add_dims(space, isl_dim_in, v->n);
1395 return isl_multi_pw_aff_from_pw_aff_list(space, list);
1398 /* Add the tuple represented by the isl_multi_pw_aff "tuple" to "map".
1399 * We first create the appropriate space in "map" based on the range
1400 * space of this isl_multi_pw_aff. Then, we add equalities based
1401 * on the affine expressions. These live in an anonymous space,
1402 * however, so we first need to reset the space to that of "map".
1404 static __isl_give isl_map *map_from_tuple(__isl_take isl_multi_pw_aff *tuple,
1405 __isl_take isl_map *map, enum isl_dim_type type, struct vars *v,
1406 int rational)
1408 int i;
1409 isl_size n;
1410 isl_ctx *ctx;
1411 isl_space *space = NULL;
1413 n = isl_multi_pw_aff_dim(tuple, isl_dim_out);
1414 if (!map || n < 0)
1415 goto error;
1416 ctx = isl_multi_pw_aff_get_ctx(tuple);
1417 space = isl_space_range(isl_multi_pw_aff_get_space(tuple));
1418 if (!space)
1419 goto error;
1421 if (type == isl_dim_param) {
1422 if (isl_space_has_tuple_name(space, isl_dim_set) ||
1423 isl_space_is_wrapping(space)) {
1424 isl_die(ctx, isl_error_invalid,
1425 "parameter tuples cannot be named or nested",
1426 goto error);
1428 map = isl_map_add_dims(map, type, n);
1429 for (i = 0; i < n; ++i) {
1430 isl_id *id;
1431 if (!isl_space_has_dim_name(space, isl_dim_set, i))
1432 isl_die(ctx, isl_error_invalid,
1433 "parameters must be named",
1434 goto error);
1435 id = isl_space_get_dim_id(space, isl_dim_set, i);
1436 map = isl_map_set_dim_id(map, isl_dim_param, i, id);
1438 } else if (type == isl_dim_in) {
1439 isl_set *set;
1441 set = isl_set_universe(isl_space_copy(space));
1442 if (rational)
1443 set = isl_set_set_rational(set);
1444 set = isl_set_intersect_params(set, isl_map_params(map));
1445 map = isl_map_from_domain(set);
1446 } else {
1447 isl_set *set;
1449 set = isl_set_universe(isl_space_copy(space));
1450 if (rational)
1451 set = isl_set_set_rational(set);
1452 map = isl_map_from_domain_and_range(isl_map_domain(map), set);
1455 for (i = 0; i < n; ++i) {
1456 isl_pw_aff *pa;
1457 isl_space *space;
1458 isl_aff *aff;
1459 isl_set *set;
1460 isl_map *map_i;
1462 pa = isl_multi_pw_aff_get_pw_aff(tuple, i);
1463 space = isl_pw_aff_get_domain_space(pa);
1464 aff = isl_aff_zero_on_domain(isl_local_space_from_space(space));
1465 aff = isl_aff_add_coefficient_si(aff,
1466 isl_dim_in, v->n - n + i, -1);
1467 pa = isl_pw_aff_add(pa, isl_pw_aff_from_aff(aff));
1468 if (rational)
1469 pa = isl_pw_aff_set_rational(pa);
1470 set = isl_pw_aff_zero_set(pa);
1471 map_i = isl_map_from_range(set);
1472 map_i = isl_map_reset_space(map_i, isl_map_get_space(map));
1473 map = isl_map_intersect(map, map_i);
1476 isl_space_free(space);
1477 isl_multi_pw_aff_free(tuple);
1478 return map;
1479 error:
1480 isl_space_free(space);
1481 isl_multi_pw_aff_free(tuple);
1482 isl_map_free(map);
1483 return NULL;
1486 /* Read a tuple from "s" and add it to "map".
1487 * The tuple is initially represented as an isl_multi_pw_aff and
1488 * then added to "map".
1490 static __isl_give isl_map *read_map_tuple(__isl_keep isl_stream *s,
1491 __isl_take isl_map *map, enum isl_dim_type type, struct vars *v,
1492 int rational, int comma)
1494 isl_multi_pw_aff *tuple;
1496 tuple = read_tuple(s, v, rational, comma);
1497 if (!tuple)
1498 return isl_map_free(map);
1500 return map_from_tuple(tuple, map, type, v, rational);
1503 /* Given two equal-length lists of piecewise affine expression with the space
1504 * of "set" as domain, construct a set in the same space that expresses
1505 * that "left" and "right" satisfy the comparison "type".
1507 * A space is constructed of the same dimension as the number of elements
1508 * in the two lists. The comparison is then expressed in a map from
1509 * this space to itself and wrapped into a set. Finally the two lists
1510 * of piecewise affine expressions are plugged into this set.
1512 * Let S be the space of "set" and T the constructed space.
1513 * The lists are first changed into two isl_multi_pw_affs in S -> T and
1514 * then combined into an isl_multi_pw_aff in S -> [T -> T],
1515 * while the comparison is first expressed in T -> T, then [T -> T]
1516 * and finally in S.
1518 static __isl_give isl_set *list_cmp(__isl_keep isl_set *set, int type,
1519 __isl_take isl_pw_aff_list *left, __isl_take isl_pw_aff_list *right)
1521 isl_space *space;
1522 isl_size n;
1523 isl_multi_pw_aff *mpa1, *mpa2;
1525 n = isl_pw_aff_list_n_pw_aff(left);
1526 if (!set || n < 0 || !right)
1527 goto error;
1529 space = isl_set_get_space(set);
1530 space = isl_space_from_domain(space);
1531 space = isl_space_add_dims(space, isl_dim_out, n);
1532 mpa1 = isl_multi_pw_aff_from_pw_aff_list(isl_space_copy(space), left);
1533 mpa2 = isl_multi_pw_aff_from_pw_aff_list(isl_space_copy(space), right);
1534 mpa1 = isl_multi_pw_aff_range_product(mpa1, mpa2);
1536 space = isl_space_range(space);
1537 switch (type) {
1538 case ISL_TOKEN_LEX_LT:
1539 set = isl_map_wrap(isl_map_lex_lt(space));
1540 break;
1541 case ISL_TOKEN_LEX_GT:
1542 set = isl_map_wrap(isl_map_lex_gt(space));
1543 break;
1544 case ISL_TOKEN_LEX_LE:
1545 set = isl_map_wrap(isl_map_lex_le(space));
1546 break;
1547 case ISL_TOKEN_LEX_GE:
1548 set = isl_map_wrap(isl_map_lex_ge(space));
1549 break;
1550 default:
1551 isl_multi_pw_aff_free(mpa1);
1552 isl_space_free(space);
1553 isl_die(isl_set_get_ctx(set), isl_error_internal,
1554 "unhandled list comparison type", return NULL);
1556 set = isl_set_preimage_multi_pw_aff(set, mpa1);
1557 return set;
1558 error:
1559 isl_pw_aff_list_free(left);
1560 isl_pw_aff_list_free(right);
1561 return NULL;
1564 /* Construct constraints of the form
1566 * a op b
1568 * where a is an element in "left", op is an operator of type "type" and
1569 * b is an element in "right", add the constraints to "set" and return
1570 * the result.
1571 * "rational" is set if the constraints should be treated as
1572 * a rational constraints.
1574 * If "type" is the type of a comparison operator between lists
1575 * of affine expressions, then a single (compound) constraint
1576 * is constructed by list_cmp instead.
1578 static __isl_give isl_set *construct_constraints(
1579 __isl_take isl_set *set, int type,
1580 __isl_keep isl_pw_aff_list *left, __isl_keep isl_pw_aff_list *right,
1581 int rational)
1583 isl_set *cond;
1585 left = isl_pw_aff_list_copy(left);
1586 right = isl_pw_aff_list_copy(right);
1587 if (rational) {
1588 left = isl_pw_aff_list_set_rational(left);
1589 right = isl_pw_aff_list_set_rational(right);
1591 if (is_list_comparator_type(type))
1592 cond = list_cmp(set, type, left, right);
1593 else if (type == ISL_TOKEN_LE)
1594 cond = isl_pw_aff_list_le_set(left, right);
1595 else if (type == ISL_TOKEN_GE)
1596 cond = isl_pw_aff_list_ge_set(left, right);
1597 else if (type == ISL_TOKEN_LT)
1598 cond = isl_pw_aff_list_lt_set(left, right);
1599 else if (type == ISL_TOKEN_GT)
1600 cond = isl_pw_aff_list_gt_set(left, right);
1601 else if (type == ISL_TOKEN_NE)
1602 cond = isl_pw_aff_list_ne_set(left, right);
1603 else
1604 cond = isl_pw_aff_list_eq_set(left, right);
1606 return isl_set_intersect(set, cond);
1609 /* Read a constraint from "s", add it to "map" and return the result.
1610 * "v" contains a description of the identifiers parsed so far.
1611 * "rational" is set if the constraint should be treated as
1612 * a rational constraint.
1613 * The constraint read from "s" may be applied to multiple pairs
1614 * of affine expressions and may be chained.
1615 * In particular, a list of affine expressions is read, followed
1616 * by a comparison operator and another list of affine expressions.
1617 * The comparison operator is then applied to each pair of elements
1618 * in the two lists and the results are added to "map".
1619 * However, if the operator expects two lists of affine expressions,
1620 * then it is applied directly to those lists and the two lists
1621 * are required to have the same length.
1622 * If the next token is another comparison operator, then another
1623 * list of affine expressions is read and the process repeats.
1625 * The processing is performed on a wrapped copy of "map" because
1626 * an affine expression cannot have a binary relation as domain.
1628 static __isl_give isl_map *add_constraint(__isl_keep isl_stream *s,
1629 struct vars *v, __isl_take isl_map *map, int rational)
1631 struct isl_token *tok;
1632 int type;
1633 isl_pw_aff_list *list1 = NULL, *list2 = NULL;
1634 isl_size n1, n2;
1635 isl_set *set;
1637 set = isl_map_wrap(map);
1638 list1 = accept_affine_list(s, isl_set_get_space(set), v);
1639 if (!list1)
1640 goto error;
1641 tok = isl_stream_next_token(s);
1642 if (!is_comparator(tok)) {
1643 isl_stream_error(s, tok, "missing operator");
1644 if (tok)
1645 isl_stream_push_token(s, tok);
1646 goto error;
1648 type = tok->type;
1649 isl_token_free(tok);
1650 for (;;) {
1651 list2 = accept_affine_list(s, isl_set_get_space(set), v);
1652 n1 = isl_pw_aff_list_n_pw_aff(list1);
1653 n2 = isl_pw_aff_list_n_pw_aff(list2);
1654 if (n1 < 0 || n2 < 0)
1655 goto error;
1656 if (is_list_comparator_type(type) && n1 != n2) {
1657 isl_stream_error(s, NULL,
1658 "list arguments not of same size");
1659 goto error;
1662 set = construct_constraints(set, type, list1, list2, rational);
1663 isl_pw_aff_list_free(list1);
1664 list1 = list2;
1666 if (!next_is_comparator(s))
1667 break;
1668 tok = isl_stream_next_token(s);
1669 type = tok->type;
1670 isl_token_free(tok);
1672 isl_pw_aff_list_free(list1);
1674 return isl_set_unwrap(set);
1675 error:
1676 isl_pw_aff_list_free(list1);
1677 isl_pw_aff_list_free(list2);
1678 isl_set_free(set);
1679 return NULL;
1682 static __isl_give isl_map *read_exists(__isl_keep isl_stream *s,
1683 struct vars *v, __isl_take isl_map *map, int rational)
1685 int n = v->n;
1686 int seen_paren = isl_stream_eat_if_available(s, '(');
1688 map = isl_map_from_domain(isl_map_wrap(map));
1689 map = read_defined_var_list(s, v, map, rational);
1691 if (isl_stream_eat(s, ':'))
1692 goto error;
1694 map = read_formula(s, v, map, rational);
1695 map = isl_set_unwrap(isl_map_domain(map));
1697 vars_drop(v, v->n - n);
1698 if (seen_paren && isl_stream_eat(s, ')'))
1699 goto error;
1701 return map;
1702 error:
1703 isl_map_free(map);
1704 return NULL;
1707 /* Parse an expression between parentheses and push the result
1708 * back on the stream.
1710 * The parsed expression may be either an affine expression
1711 * or a condition. The first type is pushed onto the stream
1712 * as an isl_pw_aff, while the second is pushed as an isl_map.
1714 * If the initial token indicates the start of a condition,
1715 * we parse it as such.
1716 * Otherwise, we first parse an affine expression and push
1717 * that onto the stream. If the affine expression covers the
1718 * entire expression between parentheses, we return.
1719 * Otherwise, we assume that the affine expression is the
1720 * start of a condition and continue parsing.
1722 static int resolve_paren_expr(__isl_keep isl_stream *s,
1723 struct vars *v, __isl_take isl_map *map, int rational)
1725 struct isl_token *tok, *tok2;
1726 int has_paren;
1727 int line, col;
1728 isl_pw_aff *pwaff;
1730 tok = isl_stream_next_token(s);
1731 if (!tok || tok->type != '(')
1732 goto error;
1734 if (isl_stream_next_token_is(s, '('))
1735 if (resolve_paren_expr(s, v, isl_map_copy(map), rational))
1736 goto error;
1738 if (next_is_condition_start(s)) {
1739 map = read_formula(s, v, map, rational);
1740 if (isl_stream_eat(s, ')'))
1741 goto error;
1742 tok->type = ISL_TOKEN_MAP;
1743 tok->u.map = map;
1744 isl_stream_push_token(s, tok);
1745 return 0;
1748 tok2 = isl_stream_next_token(s);
1749 if (!tok2)
1750 goto error;
1751 line = tok2->line;
1752 col = tok2->col;
1753 isl_stream_push_token(s, tok2);
1755 pwaff = accept_affine(s, isl_space_wrap(isl_map_get_space(map)), v);
1756 if (!pwaff)
1757 goto error;
1759 has_paren = isl_stream_eat_if_available(s, ')');
1761 if (push_aff(s, line, col, pwaff) < 0)
1762 goto error;
1764 if (has_paren) {
1765 isl_token_free(tok);
1766 isl_map_free(map);
1767 return 0;
1770 map = read_formula(s, v, map, rational);
1771 if (isl_stream_eat(s, ')'))
1772 goto error;
1774 tok->type = ISL_TOKEN_MAP;
1775 tok->u.map = map;
1776 isl_stream_push_token(s, tok);
1778 return 0;
1779 error:
1780 isl_token_free(tok);
1781 isl_map_free(map);
1782 return -1;
1785 static __isl_give isl_map *read_conjunct(__isl_keep isl_stream *s,
1786 struct vars *v, __isl_take isl_map *map, int rational)
1788 if (isl_stream_next_token_is(s, '('))
1789 if (resolve_paren_expr(s, v, isl_map_copy(map), rational))
1790 goto error;
1792 if (isl_stream_next_token_is(s, ISL_TOKEN_MAP)) {
1793 struct isl_token *tok;
1794 tok = isl_stream_next_token(s);
1795 if (!tok)
1796 goto error;
1797 isl_map_free(map);
1798 map = isl_map_copy(tok->u.map);
1799 isl_token_free(tok);
1800 return map;
1803 if (isl_stream_eat_if_available(s, ISL_TOKEN_EXISTS))
1804 return read_exists(s, v, map, rational);
1806 if (isl_stream_eat_if_available(s, ISL_TOKEN_TRUE))
1807 return map;
1809 if (isl_stream_eat_if_available(s, ISL_TOKEN_FALSE)) {
1810 isl_space *dim = isl_map_get_space(map);
1811 isl_map_free(map);
1812 return isl_map_empty(dim);
1815 return add_constraint(s, v, map, rational);
1816 error:
1817 isl_map_free(map);
1818 return NULL;
1821 static __isl_give isl_map *read_conjuncts(__isl_keep isl_stream *s,
1822 struct vars *v, __isl_take isl_map *map, int rational)
1824 isl_map *res;
1825 int negate;
1827 negate = isl_stream_eat_if_available(s, ISL_TOKEN_NOT);
1828 res = read_conjunct(s, v, isl_map_copy(map), rational);
1829 if (negate)
1830 res = isl_map_subtract(isl_map_copy(map), res);
1832 while (res && isl_stream_eat_if_available(s, ISL_TOKEN_AND)) {
1833 isl_map *res_i;
1835 negate = isl_stream_eat_if_available(s, ISL_TOKEN_NOT);
1836 res_i = read_conjunct(s, v, isl_map_copy(map), rational);
1837 if (negate)
1838 res = isl_map_subtract(res, res_i);
1839 else
1840 res = isl_map_intersect(res, res_i);
1843 isl_map_free(map);
1844 return res;
1847 static struct isl_map *read_disjuncts(__isl_keep isl_stream *s,
1848 struct vars *v, __isl_take isl_map *map, int rational)
1850 isl_map *res;
1852 if (isl_stream_next_token_is(s, '}'))
1853 return map;
1855 res = read_conjuncts(s, v, isl_map_copy(map), rational);
1856 while (isl_stream_eat_if_available(s, ISL_TOKEN_OR)) {
1857 isl_map *res_i;
1859 res_i = read_conjuncts(s, v, isl_map_copy(map), rational);
1860 res = isl_map_union(res, res_i);
1863 isl_map_free(map);
1864 return res;
1867 /* Read a first order formula from "s", add the corresponding
1868 * constraints to "map" and return the result.
1870 * In particular, read a formula of the form
1874 * or
1876 * a implies b
1878 * where a and b are disjunctions.
1880 * In the first case, map is replaced by
1882 * map \cap { [..] : a }
1884 * In the second case, it is replaced by
1886 * (map \setminus { [..] : a}) \cup (map \cap { [..] : b })
1888 static __isl_give isl_map *read_formula(__isl_keep isl_stream *s,
1889 struct vars *v, __isl_take isl_map *map, int rational)
1891 isl_map *res;
1893 res = read_disjuncts(s, v, isl_map_copy(map), rational);
1895 if (isl_stream_eat_if_available(s, ISL_TOKEN_IMPLIES)) {
1896 isl_map *res2;
1898 res = isl_map_subtract(isl_map_copy(map), res);
1899 res2 = read_disjuncts(s, v, map, rational);
1900 res = isl_map_union(res, res2);
1901 } else
1902 isl_map_free(map);
1904 return res;
1907 static isl_size polylib_pos_to_isl_pos(__isl_keep isl_basic_map *bmap, int pos)
1909 isl_size n_out, n_in, n_param, n_div;
1911 n_param = isl_basic_map_dim(bmap, isl_dim_param);
1912 n_in = isl_basic_map_dim(bmap, isl_dim_in);
1913 n_out = isl_basic_map_dim(bmap, isl_dim_out);
1914 n_div = isl_basic_map_dim(bmap, isl_dim_div);
1915 if (n_param < 0 || n_in < 0 || n_out < 0 || n_div < 0)
1916 return isl_size_error;
1918 if (pos < n_out)
1919 return 1 + n_param + n_in + pos;
1920 pos -= n_out;
1922 if (pos < n_in)
1923 return 1 + n_param + pos;
1924 pos -= n_in;
1926 if (pos < n_div)
1927 return 1 + n_param + n_in + n_out + pos;
1928 pos -= n_div;
1930 if (pos < n_param)
1931 return 1 + pos;
1933 return 0;
1936 static __isl_give isl_basic_map *basic_map_read_polylib_constraint(
1937 __isl_keep isl_stream *s, __isl_take isl_basic_map *bmap)
1939 int j;
1940 struct isl_token *tok;
1941 int type;
1942 int k;
1943 isl_int *c;
1944 isl_size total;
1946 if (!bmap)
1947 return NULL;
1949 tok = isl_stream_next_token(s);
1950 if (!tok || tok->type != ISL_TOKEN_VALUE) {
1951 isl_stream_error(s, tok, "expecting coefficient");
1952 if (tok)
1953 isl_stream_push_token(s, tok);
1954 goto error;
1956 if (!tok->on_new_line) {
1957 isl_stream_error(s, tok, "coefficient should appear on new line");
1958 isl_stream_push_token(s, tok);
1959 goto error;
1962 type = isl_int_get_si(tok->u.v);
1963 isl_token_free(tok);
1965 isl_assert(s->ctx, type == 0 || type == 1, goto error);
1966 if (type == 0) {
1967 k = isl_basic_map_alloc_equality(bmap);
1968 c = bmap->eq[k];
1969 } else {
1970 k = isl_basic_map_alloc_inequality(bmap);
1971 c = bmap->ineq[k];
1973 if (k < 0)
1974 goto error;
1976 total = isl_basic_map_dim(bmap, isl_dim_all);
1977 if (total < 0)
1978 return isl_basic_map_free(bmap);
1979 for (j = 0; j < 1 + total; ++j) {
1980 isl_size pos;
1981 tok = isl_stream_next_token(s);
1982 if (!tok || tok->type != ISL_TOKEN_VALUE) {
1983 isl_stream_error(s, tok, "expecting coefficient");
1984 if (tok)
1985 isl_stream_push_token(s, tok);
1986 goto error;
1988 if (tok->on_new_line) {
1989 isl_stream_error(s, tok,
1990 "coefficient should not appear on new line");
1991 isl_stream_push_token(s, tok);
1992 goto error;
1994 pos = polylib_pos_to_isl_pos(bmap, j);
1995 if (pos >= 0)
1996 isl_int_set(c[pos], tok->u.v);
1997 isl_token_free(tok);
1998 if (pos < 0)
1999 return isl_basic_map_free(bmap);
2002 return bmap;
2003 error:
2004 isl_basic_map_free(bmap);
2005 return NULL;
2008 static __isl_give isl_basic_map *basic_map_read_polylib(
2009 __isl_keep isl_stream *s)
2011 int i;
2012 struct isl_token *tok;
2013 struct isl_token *tok2;
2014 int n_row, n_col;
2015 int on_new_line;
2016 unsigned in = 0, out, local = 0;
2017 struct isl_basic_map *bmap = NULL;
2018 int nparam = 0;
2020 tok = isl_stream_next_token(s);
2021 if (!tok) {
2022 isl_stream_error(s, NULL, "unexpected EOF");
2023 return NULL;
2025 tok2 = isl_stream_next_token(s);
2026 if (!tok2) {
2027 isl_token_free(tok);
2028 isl_stream_error(s, NULL, "unexpected EOF");
2029 return NULL;
2031 if (tok->type != ISL_TOKEN_VALUE || tok2->type != ISL_TOKEN_VALUE) {
2032 isl_stream_push_token(s, tok2);
2033 isl_stream_push_token(s, tok);
2034 isl_stream_error(s, NULL,
2035 "expecting constraint matrix dimensions");
2036 return NULL;
2038 n_row = isl_int_get_si(tok->u.v);
2039 n_col = isl_int_get_si(tok2->u.v);
2040 on_new_line = tok2->on_new_line;
2041 isl_token_free(tok2);
2042 isl_token_free(tok);
2043 isl_assert(s->ctx, !on_new_line, return NULL);
2044 isl_assert(s->ctx, n_row >= 0, return NULL);
2045 isl_assert(s->ctx, n_col >= 2 + nparam, return NULL);
2046 tok = isl_stream_next_token_on_same_line(s);
2047 if (tok) {
2048 if (tok->type != ISL_TOKEN_VALUE) {
2049 isl_stream_error(s, tok,
2050 "expecting number of output dimensions");
2051 isl_stream_push_token(s, tok);
2052 goto error;
2054 out = isl_int_get_si(tok->u.v);
2055 isl_token_free(tok);
2057 tok = isl_stream_next_token_on_same_line(s);
2058 if (!tok || tok->type != ISL_TOKEN_VALUE) {
2059 isl_stream_error(s, tok,
2060 "expecting number of input dimensions");
2061 if (tok)
2062 isl_stream_push_token(s, tok);
2063 goto error;
2065 in = isl_int_get_si(tok->u.v);
2066 isl_token_free(tok);
2068 tok = isl_stream_next_token_on_same_line(s);
2069 if (!tok || tok->type != ISL_TOKEN_VALUE) {
2070 isl_stream_error(s, tok,
2071 "expecting number of existentials");
2072 if (tok)
2073 isl_stream_push_token(s, tok);
2074 goto error;
2076 local = isl_int_get_si(tok->u.v);
2077 isl_token_free(tok);
2079 tok = isl_stream_next_token_on_same_line(s);
2080 if (!tok || tok->type != ISL_TOKEN_VALUE) {
2081 isl_stream_error(s, tok,
2082 "expecting number of parameters");
2083 if (tok)
2084 isl_stream_push_token(s, tok);
2085 goto error;
2087 nparam = isl_int_get_si(tok->u.v);
2088 isl_token_free(tok);
2089 if (n_col != 1 + out + in + local + nparam + 1) {
2090 isl_stream_error(s, NULL,
2091 "dimensions don't match");
2092 goto error;
2094 } else
2095 out = n_col - 2 - nparam;
2096 bmap = isl_basic_map_alloc(s->ctx, nparam, in, out, local, n_row, n_row);
2097 if (!bmap)
2098 return NULL;
2100 for (i = 0; i < local; ++i) {
2101 int k = isl_basic_map_alloc_div(bmap);
2102 if (k < 0)
2103 goto error;
2104 isl_seq_clr(bmap->div[k], 1 + 1 + nparam + in + out + local);
2107 for (i = 0; i < n_row; ++i)
2108 bmap = basic_map_read_polylib_constraint(s, bmap);
2110 tok = isl_stream_next_token_on_same_line(s);
2111 if (tok) {
2112 isl_stream_error(s, tok, "unexpected extra token on line");
2113 isl_stream_push_token(s, tok);
2114 goto error;
2117 bmap = isl_basic_map_simplify(bmap);
2118 bmap = isl_basic_map_finalize(bmap);
2119 return bmap;
2120 error:
2121 isl_basic_map_free(bmap);
2122 return NULL;
2125 static struct isl_map *map_read_polylib(__isl_keep isl_stream *s)
2127 struct isl_token *tok;
2128 struct isl_token *tok2;
2129 int i, n;
2130 struct isl_map *map;
2132 tok = isl_stream_next_token(s);
2133 if (!tok) {
2134 isl_stream_error(s, NULL, "unexpected EOF");
2135 return NULL;
2137 tok2 = isl_stream_next_token_on_same_line(s);
2138 if (tok2 && tok2->type == ISL_TOKEN_VALUE) {
2139 isl_stream_push_token(s, tok2);
2140 isl_stream_push_token(s, tok);
2141 return isl_map_from_basic_map(basic_map_read_polylib(s));
2143 if (tok2) {
2144 isl_stream_error(s, tok2, "unexpected token");
2145 isl_stream_push_token(s, tok2);
2146 isl_stream_push_token(s, tok);
2147 return NULL;
2149 n = isl_int_get_si(tok->u.v);
2150 isl_token_free(tok);
2152 isl_assert(s->ctx, n >= 1, return NULL);
2154 map = isl_map_from_basic_map(basic_map_read_polylib(s));
2156 for (i = 1; map && i < n; ++i)
2157 map = isl_map_union(map,
2158 isl_map_from_basic_map(basic_map_read_polylib(s)));
2160 return map;
2163 static int optional_power(__isl_keep isl_stream *s)
2165 int pow;
2166 struct isl_token *tok;
2168 tok = isl_stream_next_token(s);
2169 if (!tok)
2170 return 1;
2171 if (tok->type != '^') {
2172 isl_stream_push_token(s, tok);
2173 return 1;
2175 isl_token_free(tok);
2176 tok = isl_stream_next_token(s);
2177 if (!tok || tok->type != ISL_TOKEN_VALUE) {
2178 isl_stream_error(s, tok, "expecting exponent");
2179 if (tok)
2180 isl_stream_push_token(s, tok);
2181 return 1;
2183 pow = isl_int_get_si(tok->u.v);
2184 isl_token_free(tok);
2185 return pow;
2188 static __isl_give isl_pw_qpolynomial *read_term(__isl_keep isl_stream *s,
2189 __isl_keep isl_map *map, struct vars *v);
2191 static __isl_give isl_pw_qpolynomial *read_factor(__isl_keep isl_stream *s,
2192 __isl_keep isl_map *map, struct vars *v)
2194 isl_pw_qpolynomial *pwqp;
2195 struct isl_token *tok;
2197 tok = next_token(s);
2198 if (!tok) {
2199 isl_stream_error(s, NULL, "unexpected EOF");
2200 return NULL;
2202 if (tok->type == '(') {
2203 int pow;
2205 isl_token_free(tok);
2206 pwqp = read_term(s, map, v);
2207 if (!pwqp)
2208 return NULL;
2209 if (isl_stream_eat(s, ')'))
2210 goto error;
2211 pow = optional_power(s);
2212 pwqp = isl_pw_qpolynomial_pow(pwqp, pow);
2213 } else if (tok->type == ISL_TOKEN_VALUE) {
2214 struct isl_token *tok2;
2215 isl_qpolynomial *qp;
2217 tok2 = isl_stream_next_token(s);
2218 if (tok2 && tok2->type == '/') {
2219 isl_token_free(tok2);
2220 tok2 = next_token(s);
2221 if (!tok2 || tok2->type != ISL_TOKEN_VALUE) {
2222 isl_stream_error(s, tok2, "expected denominator");
2223 isl_token_free(tok);
2224 isl_token_free(tok2);
2225 return NULL;
2227 qp = isl_qpolynomial_rat_cst_on_domain(isl_map_get_space(map),
2228 tok->u.v, tok2->u.v);
2229 isl_token_free(tok2);
2230 } else {
2231 isl_stream_push_token(s, tok2);
2232 qp = isl_qpolynomial_cst_on_domain(isl_map_get_space(map),
2233 tok->u.v);
2235 isl_token_free(tok);
2236 pwqp = isl_pw_qpolynomial_from_qpolynomial(qp);
2237 } else if (tok->type == ISL_TOKEN_INFTY) {
2238 isl_qpolynomial *qp;
2239 isl_token_free(tok);
2240 qp = isl_qpolynomial_infty_on_domain(isl_map_get_space(map));
2241 pwqp = isl_pw_qpolynomial_from_qpolynomial(qp);
2242 } else if (tok->type == ISL_TOKEN_NAN) {
2243 isl_qpolynomial *qp;
2244 isl_token_free(tok);
2245 qp = isl_qpolynomial_nan_on_domain(isl_map_get_space(map));
2246 pwqp = isl_pw_qpolynomial_from_qpolynomial(qp);
2247 } else if (tok->type == ISL_TOKEN_IDENT) {
2248 int n = v->n;
2249 int pos = vars_pos(v, tok->u.s, -1);
2250 int pow;
2251 isl_qpolynomial *qp;
2252 if (pos < 0) {
2253 isl_token_free(tok);
2254 return NULL;
2256 if (pos >= n) {
2257 vars_drop(v, v->n - n);
2258 isl_stream_error(s, tok, "unknown identifier");
2259 isl_token_free(tok);
2260 return NULL;
2262 isl_token_free(tok);
2263 pow = optional_power(s);
2264 qp = isl_qpolynomial_var_pow_on_domain(isl_map_get_space(map), pos, pow);
2265 pwqp = isl_pw_qpolynomial_from_qpolynomial(qp);
2266 } else if (is_start_of_div(tok)) {
2267 isl_pw_aff *pwaff;
2268 int pow;
2270 isl_stream_push_token(s, tok);
2271 pwaff = accept_div(s, isl_map_get_space(map), v);
2272 pow = optional_power(s);
2273 pwqp = isl_pw_qpolynomial_from_pw_aff(pwaff);
2274 pwqp = isl_pw_qpolynomial_pow(pwqp, pow);
2275 } else if (tok->type == '-') {
2276 isl_token_free(tok);
2277 pwqp = read_factor(s, map, v);
2278 pwqp = isl_pw_qpolynomial_neg(pwqp);
2279 } else {
2280 isl_stream_error(s, tok, "unexpected isl_token");
2281 isl_stream_push_token(s, tok);
2282 return NULL;
2285 if (isl_stream_eat_if_available(s, '*') ||
2286 isl_stream_next_token_is(s, ISL_TOKEN_IDENT)) {
2287 isl_pw_qpolynomial *pwqp2;
2289 pwqp2 = read_factor(s, map, v);
2290 pwqp = isl_pw_qpolynomial_mul(pwqp, pwqp2);
2293 return pwqp;
2294 error:
2295 isl_pw_qpolynomial_free(pwqp);
2296 return NULL;
2299 static __isl_give isl_pw_qpolynomial *read_term(__isl_keep isl_stream *s,
2300 __isl_keep isl_map *map, struct vars *v)
2302 struct isl_token *tok;
2303 isl_pw_qpolynomial *pwqp;
2305 pwqp = read_factor(s, map, v);
2307 for (;;) {
2308 tok = next_token(s);
2309 if (!tok)
2310 return pwqp;
2312 if (tok->type == '+') {
2313 isl_pw_qpolynomial *pwqp2;
2315 isl_token_free(tok);
2316 pwqp2 = read_factor(s, map, v);
2317 pwqp = isl_pw_qpolynomial_add(pwqp, pwqp2);
2318 } else if (tok->type == '-') {
2319 isl_pw_qpolynomial *pwqp2;
2321 isl_token_free(tok);
2322 pwqp2 = read_factor(s, map, v);
2323 pwqp = isl_pw_qpolynomial_sub(pwqp, pwqp2);
2324 } else if (tok->type == ISL_TOKEN_VALUE &&
2325 isl_int_is_neg(tok->u.v)) {
2326 isl_pw_qpolynomial *pwqp2;
2328 isl_stream_push_token(s, tok);
2329 pwqp2 = read_factor(s, map, v);
2330 pwqp = isl_pw_qpolynomial_add(pwqp, pwqp2);
2331 } else {
2332 isl_stream_push_token(s, tok);
2333 break;
2337 return pwqp;
2340 static __isl_give isl_map *read_optional_formula(__isl_keep isl_stream *s,
2341 __isl_take isl_map *map, struct vars *v, int rational)
2343 struct isl_token *tok;
2345 tok = isl_stream_next_token(s);
2346 if (!tok) {
2347 isl_stream_error(s, NULL, "unexpected EOF");
2348 goto error;
2350 if (tok->type == ':' ||
2351 (tok->type == ISL_TOKEN_OR && !strcmp(tok->u.s, "|"))) {
2352 isl_token_free(tok);
2353 map = read_formula(s, v, map, rational);
2354 } else
2355 isl_stream_push_token(s, tok);
2357 return map;
2358 error:
2359 isl_map_free(map);
2360 return NULL;
2363 static struct isl_obj obj_read_poly(__isl_keep isl_stream *s,
2364 __isl_take isl_map *map, struct vars *v, int n)
2366 struct isl_obj obj = { isl_obj_pw_qpolynomial, NULL };
2367 isl_pw_qpolynomial *pwqp;
2368 struct isl_set *set;
2370 pwqp = read_term(s, map, v);
2371 map = read_optional_formula(s, map, v, 0);
2372 set = isl_map_range(map);
2374 pwqp = isl_pw_qpolynomial_intersect_domain(pwqp, set);
2376 vars_drop(v, v->n - n);
2378 obj.v = pwqp;
2379 return obj;
2382 static struct isl_obj obj_read_poly_or_fold(__isl_keep isl_stream *s,
2383 __isl_take isl_set *set, struct vars *v, int n)
2385 struct isl_obj obj = { isl_obj_pw_qpolynomial_fold, NULL };
2386 isl_pw_qpolynomial *pwqp;
2387 isl_pw_qpolynomial_fold *pwf = NULL;
2389 if (!isl_stream_eat_if_available(s, ISL_TOKEN_MAX))
2390 return obj_read_poly(s, set, v, n);
2392 if (isl_stream_eat(s, '('))
2393 goto error;
2395 pwqp = read_term(s, set, v);
2396 pwf = isl_pw_qpolynomial_fold_from_pw_qpolynomial(isl_fold_max, pwqp);
2398 while (isl_stream_eat_if_available(s, ',')) {
2399 isl_pw_qpolynomial_fold *pwf_i;
2400 pwqp = read_term(s, set, v);
2401 pwf_i = isl_pw_qpolynomial_fold_from_pw_qpolynomial(isl_fold_max,
2402 pwqp);
2403 pwf = isl_pw_qpolynomial_fold_fold(pwf, pwf_i);
2406 if (isl_stream_eat(s, ')'))
2407 goto error;
2409 set = read_optional_formula(s, set, v, 0);
2410 pwf = isl_pw_qpolynomial_fold_intersect_domain(pwf, set);
2412 vars_drop(v, v->n - n);
2414 obj.v = pwf;
2415 return obj;
2416 error:
2417 isl_set_free(set);
2418 isl_pw_qpolynomial_fold_free(pwf);
2419 obj.type = isl_obj_none;
2420 return obj;
2423 static int is_rational(__isl_keep isl_stream *s)
2425 struct isl_token *tok;
2427 tok = isl_stream_next_token(s);
2428 if (!tok)
2429 return 0;
2430 if (tok->type == ISL_TOKEN_RAT && isl_stream_next_token_is(s, ':')) {
2431 isl_token_free(tok);
2432 isl_stream_eat(s, ':');
2433 return 1;
2436 isl_stream_push_token(s, tok);
2438 return 0;
2441 static struct isl_obj obj_read_body(__isl_keep isl_stream *s,
2442 __isl_take isl_map *map, struct vars *v)
2444 struct isl_token *tok;
2445 struct isl_obj obj = { isl_obj_set, NULL };
2446 int n = v->n;
2447 int rational;
2449 rational = is_rational(s);
2450 if (rational)
2451 map = isl_map_set_rational(map);
2453 if (isl_stream_next_token_is(s, ':')) {
2454 obj.type = isl_obj_set;
2455 obj.v = read_optional_formula(s, map, v, rational);
2456 return obj;
2459 if (!next_is_tuple(s))
2460 return obj_read_poly_or_fold(s, map, v, n);
2462 map = read_map_tuple(s, map, isl_dim_in, v, rational, 0);
2463 if (!map)
2464 goto error;
2465 tok = isl_stream_next_token(s);
2466 if (!tok)
2467 goto error;
2468 if (tok->type == ISL_TOKEN_TO) {
2469 obj.type = isl_obj_map;
2470 isl_token_free(tok);
2471 if (!next_is_tuple(s)) {
2472 isl_set *set = isl_map_domain(map);
2473 return obj_read_poly_or_fold(s, set, v, n);
2475 map = read_map_tuple(s, map, isl_dim_out, v, rational, 0);
2476 if (!map)
2477 goto error;
2478 } else {
2479 map = isl_map_domain(map);
2480 isl_stream_push_token(s, tok);
2483 map = read_optional_formula(s, map, v, rational);
2485 vars_drop(v, v->n - n);
2487 obj.v = map;
2488 return obj;
2489 error:
2490 isl_map_free(map);
2491 obj.type = isl_obj_none;
2492 return obj;
2495 static struct isl_obj to_union(isl_ctx *ctx, struct isl_obj obj)
2497 if (obj.type == isl_obj_map) {
2498 obj.v = isl_union_map_from_map(obj.v);
2499 obj.type = isl_obj_union_map;
2500 } else if (obj.type == isl_obj_set) {
2501 obj.v = isl_union_set_from_set(obj.v);
2502 obj.type = isl_obj_union_set;
2503 } else if (obj.type == isl_obj_pw_qpolynomial) {
2504 obj.v = isl_union_pw_qpolynomial_from_pw_qpolynomial(obj.v);
2505 obj.type = isl_obj_union_pw_qpolynomial;
2506 } else if (obj.type == isl_obj_pw_qpolynomial_fold) {
2507 obj.v = isl_union_pw_qpolynomial_fold_from_pw_qpolynomial_fold(obj.v);
2508 obj.type = isl_obj_union_pw_qpolynomial_fold;
2509 } else
2510 isl_assert(ctx, 0, goto error);
2511 return obj;
2512 error:
2513 obj.type->free(obj.v);
2514 obj.type = isl_obj_none;
2515 return obj;
2518 static struct isl_obj obj_add(__isl_keep isl_stream *s,
2519 struct isl_obj obj1, struct isl_obj obj2)
2521 if (obj2.type == isl_obj_none || !obj2.v)
2522 goto error;
2523 if (obj1.type == isl_obj_set && obj2.type == isl_obj_union_set)
2524 obj1 = to_union(s->ctx, obj1);
2525 if (obj1.type == isl_obj_union_set && obj2.type == isl_obj_set)
2526 obj2 = to_union(s->ctx, obj2);
2527 if (obj1.type == isl_obj_map && obj2.type == isl_obj_union_map)
2528 obj1 = to_union(s->ctx, obj1);
2529 if (obj1.type == isl_obj_union_map && obj2.type == isl_obj_map)
2530 obj2 = to_union(s->ctx, obj2);
2531 if (obj1.type == isl_obj_pw_qpolynomial &&
2532 obj2.type == isl_obj_union_pw_qpolynomial)
2533 obj1 = to_union(s->ctx, obj1);
2534 if (obj1.type == isl_obj_union_pw_qpolynomial &&
2535 obj2.type == isl_obj_pw_qpolynomial)
2536 obj2 = to_union(s->ctx, obj2);
2537 if (obj1.type == isl_obj_pw_qpolynomial_fold &&
2538 obj2.type == isl_obj_union_pw_qpolynomial_fold)
2539 obj1 = to_union(s->ctx, obj1);
2540 if (obj1.type == isl_obj_union_pw_qpolynomial_fold &&
2541 obj2.type == isl_obj_pw_qpolynomial_fold)
2542 obj2 = to_union(s->ctx, obj2);
2543 if (obj1.type != obj2.type) {
2544 isl_stream_error(s, NULL,
2545 "attempt to combine incompatible objects");
2546 goto error;
2548 if (!obj1.type->add)
2549 isl_die(s->ctx, isl_error_internal,
2550 "combination not supported on object type", goto error);
2551 if (obj1.type == isl_obj_map && !isl_map_has_equal_space(obj1.v, obj2.v)) {
2552 obj1 = to_union(s->ctx, obj1);
2553 obj2 = to_union(s->ctx, obj2);
2555 if (obj1.type == isl_obj_set && !isl_set_has_equal_space(obj1.v, obj2.v)) {
2556 obj1 = to_union(s->ctx, obj1);
2557 obj2 = to_union(s->ctx, obj2);
2559 if (obj1.type == isl_obj_pw_qpolynomial &&
2560 !isl_pw_qpolynomial_has_equal_space(obj1.v, obj2.v)) {
2561 obj1 = to_union(s->ctx, obj1);
2562 obj2 = to_union(s->ctx, obj2);
2564 if (obj1.type == isl_obj_pw_qpolynomial_fold &&
2565 !isl_pw_qpolynomial_fold_has_equal_space(obj1.v, obj2.v)) {
2566 obj1 = to_union(s->ctx, obj1);
2567 obj2 = to_union(s->ctx, obj2);
2569 obj1.v = obj1.type->add(obj1.v, obj2.v);
2570 return obj1;
2571 error:
2572 obj1.type->free(obj1.v);
2573 obj2.type->free(obj2.v);
2574 obj1.type = isl_obj_none;
2575 obj1.v = NULL;
2576 return obj1;
2579 /* Are the first two tokens on "s", "domain" (either as a string
2580 * or as an identifier) followed by ":"?
2582 static int next_is_domain_colon(__isl_keep isl_stream *s)
2584 struct isl_token *tok;
2585 char *name;
2586 int res;
2588 tok = isl_stream_next_token(s);
2589 if (!tok)
2590 return 0;
2591 if (tok->type != ISL_TOKEN_IDENT && tok->type != ISL_TOKEN_STRING) {
2592 isl_stream_push_token(s, tok);
2593 return 0;
2596 name = isl_token_get_str(s->ctx, tok);
2597 res = !strcmp(name, "domain") && isl_stream_next_token_is(s, ':');
2598 free(name);
2600 isl_stream_push_token(s, tok);
2602 return res;
2605 /* Do the first tokens on "s" look like a schedule?
2607 * The root of a schedule is always a domain node, so the first thing
2608 * we expect in the stream is a domain key, i.e., "domain" followed
2609 * by ":". If the schedule was printed in YAML flow style, then
2610 * we additionally expect a "{" to open the outer mapping.
2612 static int next_is_schedule(__isl_keep isl_stream *s)
2614 struct isl_token *tok;
2615 int is_schedule;
2617 tok = isl_stream_next_token(s);
2618 if (!tok)
2619 return 0;
2620 if (tok->type != '{') {
2621 isl_stream_push_token(s, tok);
2622 return next_is_domain_colon(s);
2625 is_schedule = next_is_domain_colon(s);
2626 isl_stream_push_token(s, tok);
2628 return is_schedule;
2631 /* Read an isl_schedule from "s" and store it in an isl_obj.
2633 static struct isl_obj schedule_read(__isl_keep isl_stream *s)
2635 struct isl_obj obj;
2637 obj.type = isl_obj_schedule;
2638 obj.v = isl_stream_read_schedule(s);
2640 return obj;
2643 /* Read a disjunction of object bodies from "s".
2644 * That is, read the inside of the braces, but not the braces themselves.
2645 * "v" contains a description of the identifiers parsed so far.
2646 * "map" contains information about the parameters.
2648 static struct isl_obj obj_read_disjuncts(__isl_keep isl_stream *s,
2649 struct vars *v, __isl_keep isl_map *map)
2651 struct isl_obj obj = { isl_obj_set, NULL };
2653 if (isl_stream_next_token_is(s, '}')) {
2654 obj.type = isl_obj_union_set;
2655 obj.v = isl_union_set_empty(isl_map_get_space(map));
2656 return obj;
2659 for (;;) {
2660 struct isl_obj o;
2661 o = obj_read_body(s, isl_map_copy(map), v);
2662 if (!obj.v)
2663 obj = o;
2664 else
2665 obj = obj_add(s, obj, o);
2666 if (obj.type == isl_obj_none || !obj.v)
2667 return obj;
2668 if (!isl_stream_eat_if_available(s, ';'))
2669 break;
2670 if (isl_stream_next_token_is(s, '}'))
2671 break;
2674 return obj;
2677 static struct isl_obj obj_read(__isl_keep isl_stream *s)
2679 isl_map *map = NULL;
2680 struct isl_token *tok;
2681 struct vars *v = NULL;
2682 struct isl_obj obj = { isl_obj_set, NULL };
2684 if (next_is_schedule(s))
2685 return schedule_read(s);
2687 tok = next_token(s);
2688 if (!tok) {
2689 isl_stream_error(s, NULL, "unexpected EOF");
2690 goto error;
2692 if (tok->type == ISL_TOKEN_VALUE) {
2693 struct isl_token *tok2;
2694 struct isl_map *map;
2696 tok2 = isl_stream_next_token(s);
2697 if (!tok2 || tok2->type != ISL_TOKEN_VALUE ||
2698 isl_int_is_neg(tok2->u.v)) {
2699 if (tok2)
2700 isl_stream_push_token(s, tok2);
2701 obj.type = isl_obj_val;
2702 obj.v = isl_val_int_from_isl_int(s->ctx, tok->u.v);
2703 isl_token_free(tok);
2704 return obj;
2706 isl_stream_push_token(s, tok2);
2707 isl_stream_push_token(s, tok);
2708 map = map_read_polylib(s);
2709 if (!map)
2710 goto error;
2711 if (isl_map_may_be_set(map))
2712 obj.v = isl_map_range(map);
2713 else {
2714 obj.type = isl_obj_map;
2715 obj.v = map;
2717 return obj;
2719 v = vars_new(s->ctx);
2720 if (!v) {
2721 isl_stream_push_token(s, tok);
2722 goto error;
2724 map = isl_map_universe(isl_space_params_alloc(s->ctx, 0));
2725 if (tok->type == '[') {
2726 isl_stream_push_token(s, tok);
2727 map = read_map_tuple(s, map, isl_dim_param, v, 0, 0);
2728 if (!map)
2729 goto error;
2730 tok = isl_stream_next_token(s);
2731 if (!tok || tok->type != ISL_TOKEN_TO) {
2732 isl_stream_error(s, tok, "expecting '->'");
2733 if (tok)
2734 isl_stream_push_token(s, tok);
2735 goto error;
2737 isl_token_free(tok);
2738 tok = isl_stream_next_token(s);
2740 if (!tok || tok->type != '{') {
2741 isl_stream_error(s, tok, "expecting '{'");
2742 if (tok)
2743 isl_stream_push_token(s, tok);
2744 goto error;
2746 isl_token_free(tok);
2748 tok = isl_stream_next_token(s);
2749 if (!tok)
2751 else if (tok->type == ISL_TOKEN_IDENT && !strcmp(tok->u.s, "Sym")) {
2752 isl_token_free(tok);
2753 if (isl_stream_eat(s, '='))
2754 goto error;
2755 map = read_map_tuple(s, map, isl_dim_param, v, 0, 1);
2756 if (!map)
2757 goto error;
2758 } else
2759 isl_stream_push_token(s, tok);
2761 obj = obj_read_disjuncts(s, v, map);
2762 if (obj.type == isl_obj_none || !obj.v)
2763 goto error;
2765 tok = isl_stream_next_token(s);
2766 if (tok && tok->type == '}') {
2767 isl_token_free(tok);
2768 } else {
2769 isl_stream_error(s, tok, "unexpected isl_token");
2770 if (tok)
2771 isl_token_free(tok);
2772 goto error;
2775 vars_free(v);
2776 isl_map_free(map);
2778 return obj;
2779 error:
2780 isl_map_free(map);
2781 obj.type->free(obj.v);
2782 if (v)
2783 vars_free(v);
2784 obj.v = NULL;
2785 return obj;
2788 struct isl_obj isl_stream_read_obj(__isl_keep isl_stream *s)
2790 return obj_read(s);
2793 __isl_give isl_map *isl_stream_read_map(__isl_keep isl_stream *s)
2795 struct isl_obj obj;
2797 obj = obj_read(s);
2798 if (obj.v)
2799 isl_assert(s->ctx, obj.type == isl_obj_map ||
2800 obj.type == isl_obj_set, goto error);
2802 if (obj.type == isl_obj_set)
2803 obj.v = isl_map_from_range(obj.v);
2805 return obj.v;
2806 error:
2807 obj.type->free(obj.v);
2808 return NULL;
2811 __isl_give isl_set *isl_stream_read_set(__isl_keep isl_stream *s)
2813 struct isl_obj obj;
2815 obj = obj_read(s);
2816 if (obj.v) {
2817 if (obj.type == isl_obj_map && isl_map_may_be_set(obj.v)) {
2818 obj.v = isl_map_range(obj.v);
2819 obj.type = isl_obj_set;
2821 isl_assert(s->ctx, obj.type == isl_obj_set, goto error);
2824 return obj.v;
2825 error:
2826 obj.type->free(obj.v);
2827 return NULL;
2830 __isl_give isl_union_map *isl_stream_read_union_map(__isl_keep isl_stream *s)
2832 struct isl_obj obj;
2834 obj = obj_read(s);
2835 if (obj.type == isl_obj_map) {
2836 obj.type = isl_obj_union_map;
2837 obj.v = isl_union_map_from_map(obj.v);
2839 if (obj.type == isl_obj_set) {
2840 obj.type = isl_obj_union_set;
2841 obj.v = isl_union_set_from_set(obj.v);
2843 if (obj.v && obj.type == isl_obj_union_set &&
2844 isl_union_set_is_empty(obj.v))
2845 obj.type = isl_obj_union_map;
2846 if (obj.v && obj.type != isl_obj_union_map)
2847 isl_die(s->ctx, isl_error_invalid, "invalid input", goto error);
2849 return obj.v;
2850 error:
2851 obj.type->free(obj.v);
2852 return NULL;
2855 /* Extract an isl_union_set from "obj".
2856 * This only works if the object was detected as either a set
2857 * (in which case it is converted to a union set) or a union set.
2859 static __isl_give isl_union_set *extract_union_set(isl_ctx *ctx,
2860 struct isl_obj obj)
2862 if (obj.type == isl_obj_set) {
2863 obj.type = isl_obj_union_set;
2864 obj.v = isl_union_set_from_set(obj.v);
2866 if (obj.v)
2867 isl_assert(ctx, obj.type == isl_obj_union_set, goto error);
2869 return obj.v;
2870 error:
2871 obj.type->free(obj.v);
2872 return NULL;
2875 /* Read an isl_union_set from "s".
2876 * First read a generic object and then try and extract
2877 * an isl_union_set from that.
2879 __isl_give isl_union_set *isl_stream_read_union_set(__isl_keep isl_stream *s)
2881 struct isl_obj obj;
2883 obj = obj_read(s);
2884 return extract_union_set(s->ctx, obj);
2887 static __isl_give isl_basic_map *basic_map_read(__isl_keep isl_stream *s)
2889 struct isl_obj obj;
2890 struct isl_map *map;
2891 struct isl_basic_map *bmap;
2893 obj = obj_read(s);
2894 if (obj.v && (obj.type != isl_obj_map && obj.type != isl_obj_set))
2895 isl_die(s->ctx, isl_error_invalid, "not a (basic) set or map",
2896 goto error);
2897 map = obj.v;
2898 if (!map)
2899 return NULL;
2901 if (map->n > 1)
2902 isl_die(s->ctx, isl_error_invalid,
2903 "set or map description involves "
2904 "more than one disjunct", goto error);
2906 if (map->n == 0)
2907 bmap = isl_basic_map_empty(isl_map_get_space(map));
2908 else
2909 bmap = isl_basic_map_copy(map->p[0]);
2911 isl_map_free(map);
2913 return bmap;
2914 error:
2915 obj.type->free(obj.v);
2916 return NULL;
2919 static __isl_give isl_basic_set *basic_set_read(__isl_keep isl_stream *s)
2921 isl_basic_map *bmap;
2922 bmap = basic_map_read(s);
2923 if (!bmap)
2924 return NULL;
2925 if (!isl_basic_map_may_be_set(bmap))
2926 isl_die(s->ctx, isl_error_invalid,
2927 "input is not a set", goto error);
2928 return isl_basic_map_range(bmap);
2929 error:
2930 isl_basic_map_free(bmap);
2931 return NULL;
2934 __isl_give isl_basic_map *isl_basic_map_read_from_file(isl_ctx *ctx,
2935 FILE *input)
2937 struct isl_basic_map *bmap;
2938 isl_stream *s = isl_stream_new_file(ctx, input);
2939 if (!s)
2940 return NULL;
2941 bmap = basic_map_read(s);
2942 isl_stream_free(s);
2943 return bmap;
2946 __isl_give isl_basic_set *isl_basic_set_read_from_file(isl_ctx *ctx,
2947 FILE *input)
2949 isl_basic_set *bset;
2950 isl_stream *s = isl_stream_new_file(ctx, input);
2951 if (!s)
2952 return NULL;
2953 bset = basic_set_read(s);
2954 isl_stream_free(s);
2955 return bset;
2958 struct isl_basic_map *isl_basic_map_read_from_str(struct isl_ctx *ctx,
2959 const char *str)
2961 struct isl_basic_map *bmap;
2962 isl_stream *s = isl_stream_new_str(ctx, str);
2963 if (!s)
2964 return NULL;
2965 bmap = basic_map_read(s);
2966 isl_stream_free(s);
2967 return bmap;
2970 struct isl_basic_set *isl_basic_set_read_from_str(struct isl_ctx *ctx,
2971 const char *str)
2973 isl_basic_set *bset;
2974 isl_stream *s = isl_stream_new_str(ctx, str);
2975 if (!s)
2976 return NULL;
2977 bset = basic_set_read(s);
2978 isl_stream_free(s);
2979 return bset;
2982 __isl_give isl_map *isl_map_read_from_file(struct isl_ctx *ctx,
2983 FILE *input)
2985 struct isl_map *map;
2986 isl_stream *s = isl_stream_new_file(ctx, input);
2987 if (!s)
2988 return NULL;
2989 map = isl_stream_read_map(s);
2990 isl_stream_free(s);
2991 return map;
2994 __isl_give isl_map *isl_map_read_from_str(struct isl_ctx *ctx,
2995 const char *str)
2997 struct isl_map *map;
2998 isl_stream *s = isl_stream_new_str(ctx, str);
2999 if (!s)
3000 return NULL;
3001 map = isl_stream_read_map(s);
3002 isl_stream_free(s);
3003 return map;
3006 __isl_give isl_set *isl_set_read_from_file(struct isl_ctx *ctx,
3007 FILE *input)
3009 isl_set *set;
3010 isl_stream *s = isl_stream_new_file(ctx, input);
3011 if (!s)
3012 return NULL;
3013 set = isl_stream_read_set(s);
3014 isl_stream_free(s);
3015 return set;
3018 struct isl_set *isl_set_read_from_str(struct isl_ctx *ctx,
3019 const char *str)
3021 isl_set *set;
3022 isl_stream *s = isl_stream_new_str(ctx, str);
3023 if (!s)
3024 return NULL;
3025 set = isl_stream_read_set(s);
3026 isl_stream_free(s);
3027 return set;
3030 __isl_give isl_union_map *isl_union_map_read_from_file(isl_ctx *ctx,
3031 FILE *input)
3033 isl_union_map *umap;
3034 isl_stream *s = isl_stream_new_file(ctx, input);
3035 if (!s)
3036 return NULL;
3037 umap = isl_stream_read_union_map(s);
3038 isl_stream_free(s);
3039 return umap;
3042 __isl_give isl_union_map *isl_union_map_read_from_str(struct isl_ctx *ctx,
3043 const char *str)
3045 isl_union_map *umap;
3046 isl_stream *s = isl_stream_new_str(ctx, str);
3047 if (!s)
3048 return NULL;
3049 umap = isl_stream_read_union_map(s);
3050 isl_stream_free(s);
3051 return umap;
3054 __isl_give isl_union_set *isl_union_set_read_from_file(isl_ctx *ctx,
3055 FILE *input)
3057 isl_union_set *uset;
3058 isl_stream *s = isl_stream_new_file(ctx, input);
3059 if (!s)
3060 return NULL;
3061 uset = isl_stream_read_union_set(s);
3062 isl_stream_free(s);
3063 return uset;
3066 __isl_give isl_union_set *isl_union_set_read_from_str(struct isl_ctx *ctx,
3067 const char *str)
3069 isl_union_set *uset;
3070 isl_stream *s = isl_stream_new_str(ctx, str);
3071 if (!s)
3072 return NULL;
3073 uset = isl_stream_read_union_set(s);
3074 isl_stream_free(s);
3075 return uset;
3078 static __isl_give isl_vec *isl_vec_read_polylib(__isl_keep isl_stream *s)
3080 struct isl_vec *vec = NULL;
3081 struct isl_token *tok;
3082 unsigned size;
3083 int j;
3085 tok = isl_stream_next_token(s);
3086 if (!tok || tok->type != ISL_TOKEN_VALUE) {
3087 isl_stream_error(s, tok, "expecting vector length");
3088 goto error;
3091 size = isl_int_get_si(tok->u.v);
3092 isl_token_free(tok);
3094 vec = isl_vec_alloc(s->ctx, size);
3096 for (j = 0; j < size; ++j) {
3097 tok = isl_stream_next_token(s);
3098 if (!tok || tok->type != ISL_TOKEN_VALUE) {
3099 isl_stream_error(s, tok, "expecting constant value");
3100 goto error;
3102 isl_int_set(vec->el[j], tok->u.v);
3103 isl_token_free(tok);
3106 return vec;
3107 error:
3108 isl_token_free(tok);
3109 isl_vec_free(vec);
3110 return NULL;
3113 static __isl_give isl_vec *vec_read(__isl_keep isl_stream *s)
3115 return isl_vec_read_polylib(s);
3118 __isl_give isl_vec *isl_vec_read_from_file(isl_ctx *ctx, FILE *input)
3120 isl_vec *v;
3121 isl_stream *s = isl_stream_new_file(ctx, input);
3122 if (!s)
3123 return NULL;
3124 v = vec_read(s);
3125 isl_stream_free(s);
3126 return v;
3129 __isl_give isl_pw_qpolynomial *isl_stream_read_pw_qpolynomial(
3130 __isl_keep isl_stream *s)
3132 struct isl_obj obj;
3134 obj = obj_read(s);
3135 if (obj.v)
3136 isl_assert(s->ctx, obj.type == isl_obj_pw_qpolynomial,
3137 goto error);
3139 return obj.v;
3140 error:
3141 obj.type->free(obj.v);
3142 return NULL;
3145 __isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_read_from_str(isl_ctx *ctx,
3146 const char *str)
3148 isl_pw_qpolynomial *pwqp;
3149 isl_stream *s = isl_stream_new_str(ctx, str);
3150 if (!s)
3151 return NULL;
3152 pwqp = isl_stream_read_pw_qpolynomial(s);
3153 isl_stream_free(s);
3154 return pwqp;
3157 __isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_read_from_file(isl_ctx *ctx,
3158 FILE *input)
3160 isl_pw_qpolynomial *pwqp;
3161 isl_stream *s = isl_stream_new_file(ctx, input);
3162 if (!s)
3163 return NULL;
3164 pwqp = isl_stream_read_pw_qpolynomial(s);
3165 isl_stream_free(s);
3166 return pwqp;
3169 /* Is the next token an identifer not in "v"?
3171 static int next_is_fresh_ident(__isl_keep isl_stream *s, struct vars *v)
3173 int n = v->n;
3174 int fresh;
3175 struct isl_token *tok;
3177 tok = isl_stream_next_token(s);
3178 if (!tok)
3179 return 0;
3180 fresh = tok->type == ISL_TOKEN_IDENT && vars_pos(v, tok->u.s, -1) >= n;
3181 isl_stream_push_token(s, tok);
3183 vars_drop(v, v->n - n);
3185 return fresh;
3188 /* First read the domain of the affine expression, which may be
3189 * a parameter space or a set.
3190 * The tricky part is that we don't know if the domain is a set or not,
3191 * so when we are trying to read the domain, we may actually be reading
3192 * the affine expression itself (defined on a parameter domains)
3193 * If the tuple we are reading is named, we assume it's the domain.
3194 * Also, if inside the tuple, the first thing we find is a nested tuple
3195 * or a new identifier, we again assume it's the domain.
3196 * Finally, if the tuple is empty, then it must be the domain
3197 * since it does not contain an affine expression.
3198 * Otherwise, we assume we are reading an affine expression.
3200 static __isl_give isl_set *read_aff_domain(__isl_keep isl_stream *s,
3201 __isl_take isl_set *dom, struct vars *v)
3203 struct isl_token *tok, *tok2;
3204 int is_empty;
3206 tok = isl_stream_next_token(s);
3207 if (tok && (tok->type == ISL_TOKEN_IDENT || tok->is_keyword)) {
3208 isl_stream_push_token(s, tok);
3209 return read_map_tuple(s, dom, isl_dim_set, v, 0, 0);
3211 if (!tok || tok->type != '[') {
3212 isl_stream_error(s, tok, "expecting '['");
3213 goto error;
3215 tok2 = isl_stream_next_token(s);
3216 is_empty = tok2 && tok2->type == ']';
3217 if (tok2)
3218 isl_stream_push_token(s, tok2);
3219 if (is_empty || next_is_tuple(s) || next_is_fresh_ident(s, v)) {
3220 isl_stream_push_token(s, tok);
3221 dom = read_map_tuple(s, dom, isl_dim_set, v, 0, 0);
3222 } else
3223 isl_stream_push_token(s, tok);
3225 return dom;
3226 error:
3227 if (tok)
3228 isl_stream_push_token(s, tok);
3229 isl_set_free(dom);
3230 return NULL;
3233 /* Read an affine expression from "s".
3235 __isl_give isl_aff *isl_stream_read_aff(__isl_keep isl_stream *s)
3237 isl_aff *aff;
3238 isl_multi_aff *ma;
3239 isl_size dim;
3241 ma = isl_stream_read_multi_aff(s);
3242 dim = isl_multi_aff_dim(ma, isl_dim_out);
3243 if (dim < 0)
3244 goto error;
3245 if (dim != 1)
3246 isl_die(s->ctx, isl_error_invalid,
3247 "expecting single affine expression",
3248 goto error);
3250 aff = isl_multi_aff_get_aff(ma, 0);
3251 isl_multi_aff_free(ma);
3252 return aff;
3253 error:
3254 isl_multi_aff_free(ma);
3255 return NULL;
3258 /* Read a piecewise affine expression from "s" with domain (space) "dom".
3260 static __isl_give isl_pw_aff *read_pw_aff_with_dom(__isl_keep isl_stream *s,
3261 __isl_take isl_set *dom, struct vars *v)
3263 isl_pw_aff *pwaff = NULL;
3265 if (!isl_set_is_params(dom) && isl_stream_eat(s, ISL_TOKEN_TO))
3266 goto error;
3268 if (isl_stream_eat(s, '['))
3269 goto error;
3271 pwaff = accept_affine(s, isl_set_get_space(dom), v);
3273 if (isl_stream_eat(s, ']'))
3274 goto error;
3276 dom = read_optional_formula(s, dom, v, 0);
3277 pwaff = isl_pw_aff_intersect_domain(pwaff, dom);
3279 return pwaff;
3280 error:
3281 isl_set_free(dom);
3282 isl_pw_aff_free(pwaff);
3283 return NULL;
3286 __isl_give isl_pw_aff *isl_stream_read_pw_aff(__isl_keep isl_stream *s)
3288 struct vars *v;
3289 isl_set *dom = NULL;
3290 isl_set *aff_dom;
3291 isl_pw_aff *pa = NULL;
3292 int n;
3294 v = vars_new(s->ctx);
3295 if (!v)
3296 return NULL;
3298 dom = isl_set_universe(isl_space_params_alloc(s->ctx, 0));
3299 if (next_is_tuple(s)) {
3300 dom = read_map_tuple(s, dom, isl_dim_param, v, 1, 0);
3301 if (isl_stream_eat(s, ISL_TOKEN_TO))
3302 goto error;
3304 if (isl_stream_eat(s, '{'))
3305 goto error;
3307 n = v->n;
3308 aff_dom = read_aff_domain(s, isl_set_copy(dom), v);
3309 pa = read_pw_aff_with_dom(s, aff_dom, v);
3310 vars_drop(v, v->n - n);
3312 while (isl_stream_eat_if_available(s, ';')) {
3313 isl_pw_aff *pa_i;
3315 n = v->n;
3316 aff_dom = read_aff_domain(s, isl_set_copy(dom), v);
3317 pa_i = read_pw_aff_with_dom(s, aff_dom, v);
3318 vars_drop(v, v->n - n);
3320 pa = isl_pw_aff_union_add(pa, pa_i);
3323 if (isl_stream_eat(s, '}'))
3324 goto error;
3326 vars_free(v);
3327 isl_set_free(dom);
3328 return pa;
3329 error:
3330 vars_free(v);
3331 isl_set_free(dom);
3332 isl_pw_aff_free(pa);
3333 return NULL;
3336 __isl_give isl_aff *isl_aff_read_from_str(isl_ctx *ctx, const char *str)
3338 isl_aff *aff;
3339 isl_stream *s = isl_stream_new_str(ctx, str);
3340 if (!s)
3341 return NULL;
3342 aff = isl_stream_read_aff(s);
3343 isl_stream_free(s);
3344 return aff;
3347 __isl_give isl_pw_aff *isl_pw_aff_read_from_str(isl_ctx *ctx, const char *str)
3349 isl_pw_aff *pa;
3350 isl_stream *s = isl_stream_new_str(ctx, str);
3351 if (!s)
3352 return NULL;
3353 pa = isl_stream_read_pw_aff(s);
3354 isl_stream_free(s);
3355 return pa;
3358 /* Extract an isl_multi_pw_aff with domain space "dom_space"
3359 * from a tuple "tuple" read by read_tuple.
3361 * Note that the function read_tuple accepts tuples where some output or
3362 * set dimensions are defined in terms of other output or set dimensions
3363 * since this function is also used to read maps. As a special case,
3364 * read_tuple also accept dimensions that are defined in terms of themselves
3365 * (i.e., that are not defined).
3366 * These cases are not allowed when extracting an isl_multi_pw_aff so check
3367 * that the definitions of the output/set dimensions do not involve any
3368 * output/set dimensions.
3369 * Finally, drop the output dimensions from the domain of the result
3370 * of read_tuple (which is of the form [input, output] -> [output],
3371 * with anonymous domain) and reset the space.
3373 static __isl_give isl_multi_pw_aff *extract_mpa_from_tuple(
3374 __isl_take isl_space *dom_space, __isl_keep isl_multi_pw_aff *tuple)
3376 int i;
3377 isl_size dim, n;
3378 isl_space *space;
3379 isl_multi_pw_aff *mpa;
3381 n = isl_multi_pw_aff_dim(tuple, isl_dim_out);
3382 dim = isl_space_dim(dom_space, isl_dim_all);
3383 if (n < 0 || dim < 0)
3384 dom_space = isl_space_free(dom_space);
3385 space = isl_space_range(isl_multi_pw_aff_get_space(tuple));
3386 space = isl_space_align_params(space, isl_space_copy(dom_space));
3387 if (!isl_space_is_params(dom_space))
3388 space = isl_space_map_from_domain_and_range(
3389 isl_space_copy(dom_space), space);
3390 isl_space_free(dom_space);
3391 mpa = isl_multi_pw_aff_alloc(space);
3393 for (i = 0; i < n; ++i) {
3394 isl_pw_aff *pa;
3395 pa = isl_multi_pw_aff_get_pw_aff(tuple, i);
3396 if (!pa)
3397 return isl_multi_pw_aff_free(mpa);
3398 if (isl_pw_aff_involves_dims(pa, isl_dim_in, dim, i + 1)) {
3399 isl_ctx *ctx = isl_pw_aff_get_ctx(pa);
3400 isl_pw_aff_free(pa);
3401 isl_die(ctx, isl_error_invalid,
3402 "not an affine expression",
3403 return isl_multi_pw_aff_free(mpa));
3405 pa = isl_pw_aff_drop_dims(pa, isl_dim_in, dim, n);
3406 space = isl_multi_pw_aff_get_domain_space(mpa);
3407 pa = isl_pw_aff_reset_domain_space(pa, space);
3408 mpa = isl_multi_pw_aff_set_pw_aff(mpa, i, pa);
3411 return mpa;
3414 /* Read a tuple of affine expressions, together with optional constraints
3415 * on the domain from "s". "dom" represents the initial constraints
3416 * on the domain.
3418 * The isl_multi_aff may live in either a set or a map space.
3419 * First read the first tuple and check if it is followed by a "->".
3420 * If so, convert the tuple into the domain of the isl_multi_pw_aff and
3421 * read in the next tuple. This tuple (or the first tuple if it was
3422 * not followed by a "->") is then converted into an isl_multi_pw_aff
3423 * through a call to extract_mpa_from_tuple.
3424 * The result is converted to an isl_pw_multi_aff and
3425 * its domain is intersected with the domain.
3427 static __isl_give isl_pw_multi_aff *read_conditional_multi_aff(
3428 __isl_keep isl_stream *s, __isl_take isl_set *dom, struct vars *v)
3430 isl_multi_pw_aff *tuple;
3431 isl_multi_pw_aff *mpa;
3432 isl_pw_multi_aff *pma;
3433 int n = v->n;
3435 tuple = read_tuple(s, v, 0, 0);
3436 if (!tuple)
3437 goto error;
3438 if (isl_stream_eat_if_available(s, ISL_TOKEN_TO)) {
3439 isl_map *map = map_from_tuple(tuple, dom, isl_dim_in, v, 0);
3440 dom = isl_map_domain(map);
3441 tuple = read_tuple(s, v, 0, 0);
3442 if (!tuple)
3443 goto error;
3446 dom = read_optional_formula(s, dom, v, 0);
3448 vars_drop(v, v->n - n);
3450 mpa = extract_mpa_from_tuple(isl_set_get_space(dom), tuple);
3451 isl_multi_pw_aff_free(tuple);
3452 pma = isl_pw_multi_aff_from_multi_pw_aff(mpa);
3453 pma = isl_pw_multi_aff_intersect_domain(pma, dom);
3455 return pma;
3456 error:
3457 isl_set_free(dom);
3458 return NULL;
3461 /* Read an isl_pw_multi_aff from "s".
3463 * In particular, first read the parameters and then read a sequence
3464 * of one or more tuples of affine expressions with optional conditions and
3465 * add them up.
3467 __isl_give isl_pw_multi_aff *isl_stream_read_pw_multi_aff(
3468 __isl_keep isl_stream *s)
3470 struct vars *v;
3471 isl_set *dom;
3472 isl_pw_multi_aff *pma = NULL;
3474 v = vars_new(s->ctx);
3475 if (!v)
3476 return NULL;
3478 dom = isl_set_universe(isl_space_params_alloc(s->ctx, 0));
3479 if (next_is_tuple(s)) {
3480 dom = read_map_tuple(s, dom, isl_dim_param, v, 1, 0);
3481 if (isl_stream_eat(s, ISL_TOKEN_TO))
3482 goto error;
3484 if (isl_stream_eat(s, '{'))
3485 goto error;
3487 pma = read_conditional_multi_aff(s, isl_set_copy(dom), v);
3489 while (isl_stream_eat_if_available(s, ';')) {
3490 isl_pw_multi_aff *pma2;
3492 pma2 = read_conditional_multi_aff(s, isl_set_copy(dom), v);
3493 pma = isl_pw_multi_aff_union_add(pma, pma2);
3494 if (!pma)
3495 goto error;
3498 if (isl_stream_eat(s, '}'))
3499 goto error;
3501 isl_set_free(dom);
3502 vars_free(v);
3503 return pma;
3504 error:
3505 isl_pw_multi_aff_free(pma);
3506 isl_set_free(dom);
3507 vars_free(v);
3508 return NULL;
3511 __isl_give isl_pw_multi_aff *isl_pw_multi_aff_read_from_str(isl_ctx *ctx,
3512 const char *str)
3514 isl_pw_multi_aff *pma;
3515 isl_stream *s = isl_stream_new_str(ctx, str);
3516 if (!s)
3517 return NULL;
3518 pma = isl_stream_read_pw_multi_aff(s);
3519 isl_stream_free(s);
3520 return pma;
3523 /* Read an isl_union_pw_multi_aff from "s".
3524 * We currently read a generic object and if it turns out to be a set or
3525 * a map, we convert that to an isl_union_pw_multi_aff.
3526 * It would be more efficient if we were to construct
3527 * the isl_union_pw_multi_aff directly.
3529 __isl_give isl_union_pw_multi_aff *isl_stream_read_union_pw_multi_aff(
3530 __isl_keep isl_stream *s)
3532 struct isl_obj obj;
3534 obj = obj_read(s);
3535 if (!obj.v)
3536 return NULL;
3538 if (obj.type == isl_obj_map || obj.type == isl_obj_set)
3539 obj = to_union(s->ctx, obj);
3540 if (obj.type == isl_obj_union_map)
3541 return isl_union_pw_multi_aff_from_union_map(obj.v);
3542 if (obj.type == isl_obj_union_set)
3543 return isl_union_pw_multi_aff_from_union_set(obj.v);
3545 obj.type->free(obj.v);
3546 isl_die(s->ctx, isl_error_invalid, "unexpected object type",
3547 return NULL);
3550 /* Read an isl_union_pw_multi_aff from "str".
3552 __isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_read_from_str(
3553 isl_ctx *ctx, const char *str)
3555 isl_union_pw_multi_aff *upma;
3556 isl_stream *s = isl_stream_new_str(ctx, str);
3557 if (!s)
3558 return NULL;
3559 upma = isl_stream_read_union_pw_multi_aff(s);
3560 isl_stream_free(s);
3561 return upma;
3564 /* Assuming "pa" represents a single affine expression defined on a universe
3565 * domain, extract this affine expression.
3567 static __isl_give isl_aff *aff_from_pw_aff(__isl_take isl_pw_aff *pa)
3569 isl_aff *aff;
3571 if (!pa)
3572 return NULL;
3573 if (pa->n != 1)
3574 isl_die(isl_pw_aff_get_ctx(pa), isl_error_invalid,
3575 "expecting single affine expression",
3576 goto error);
3577 if (!isl_set_plain_is_universe(pa->p[0].set))
3578 isl_die(isl_pw_aff_get_ctx(pa), isl_error_invalid,
3579 "expecting universe domain",
3580 goto error);
3582 aff = isl_aff_copy(pa->p[0].aff);
3583 isl_pw_aff_free(pa);
3584 return aff;
3585 error:
3586 isl_pw_aff_free(pa);
3587 return NULL;
3590 #undef BASE
3591 #define BASE val
3593 #include <isl_multi_read_no_explicit_domain_templ.c>
3595 #undef BASE
3596 #define BASE id
3598 #include <isl_multi_read_no_explicit_domain_templ.c>
3600 /* Read a multi-affine expression from "s".
3601 * If the multi-affine expression has a domain, then the tuple
3602 * representing this domain cannot involve any affine expressions.
3603 * The tuple representing the actual expressions needs to consist
3604 * of only affine expressions. Moreover, these expressions can
3605 * only depend on parameters and input dimensions and not on other
3606 * output dimensions.
3608 __isl_give isl_multi_aff *isl_stream_read_multi_aff(__isl_keep isl_stream *s)
3610 struct vars *v;
3611 isl_set *dom = NULL;
3612 isl_multi_pw_aff *tuple = NULL;
3613 int i;
3614 isl_size dim, n;
3615 isl_space *space, *dom_space;
3616 isl_multi_aff *ma = NULL;
3618 v = vars_new(s->ctx);
3619 if (!v)
3620 return NULL;
3622 dom = isl_set_universe(isl_space_params_alloc(s->ctx, 0));
3623 if (next_is_tuple(s)) {
3624 dom = read_map_tuple(s, dom, isl_dim_param, v, 1, 0);
3625 if (isl_stream_eat(s, ISL_TOKEN_TO))
3626 goto error;
3628 if (!isl_set_plain_is_universe(dom))
3629 isl_die(s->ctx, isl_error_invalid,
3630 "expecting universe parameter domain", goto error);
3631 if (isl_stream_eat(s, '{'))
3632 goto error;
3634 tuple = read_tuple(s, v, 0, 0);
3635 if (!tuple)
3636 goto error;
3637 if (isl_stream_eat_if_available(s, ISL_TOKEN_TO)) {
3638 isl_set *set;
3639 isl_space *space;
3640 isl_bool has_expr;
3642 has_expr = tuple_has_expr(tuple);
3643 if (has_expr < 0)
3644 goto error;
3645 if (has_expr)
3646 isl_die(s->ctx, isl_error_invalid,
3647 "expecting universe domain", goto error);
3648 space = isl_space_range(isl_multi_pw_aff_get_space(tuple));
3649 set = isl_set_universe(space);
3650 dom = isl_set_intersect_params(set, dom);
3651 isl_multi_pw_aff_free(tuple);
3652 tuple = read_tuple(s, v, 0, 0);
3653 if (!tuple)
3654 goto error;
3657 if (isl_stream_eat(s, '}'))
3658 goto error;
3660 n = isl_multi_pw_aff_dim(tuple, isl_dim_out);
3661 dim = isl_set_dim(dom, isl_dim_all);
3662 if (n < 0 || dim < 0)
3663 goto error;
3664 dom_space = isl_set_get_space(dom);
3665 space = isl_space_range(isl_multi_pw_aff_get_space(tuple));
3666 space = isl_space_align_params(space, isl_space_copy(dom_space));
3667 if (!isl_space_is_params(dom_space))
3668 space = isl_space_map_from_domain_and_range(
3669 isl_space_copy(dom_space), space);
3670 isl_space_free(dom_space);
3671 ma = isl_multi_aff_alloc(space);
3673 for (i = 0; i < n; ++i) {
3674 isl_pw_aff *pa;
3675 isl_aff *aff;
3676 pa = isl_multi_pw_aff_get_pw_aff(tuple, i);
3677 aff = aff_from_pw_aff(pa);
3678 if (!aff)
3679 goto error;
3680 if (isl_aff_involves_dims(aff, isl_dim_in, dim, i + 1)) {
3681 isl_aff_free(aff);
3682 isl_die(s->ctx, isl_error_invalid,
3683 "not an affine expression", goto error);
3685 aff = isl_aff_drop_dims(aff, isl_dim_in, dim, n);
3686 space = isl_multi_aff_get_domain_space(ma);
3687 aff = isl_aff_reset_domain_space(aff, space);
3688 ma = isl_multi_aff_set_aff(ma, i, aff);
3691 isl_multi_pw_aff_free(tuple);
3692 vars_free(v);
3693 isl_set_free(dom);
3694 return ma;
3695 error:
3696 isl_multi_pw_aff_free(tuple);
3697 vars_free(v);
3698 isl_set_free(dom);
3699 isl_multi_aff_free(ma);
3700 return NULL;
3703 __isl_give isl_multi_aff *isl_multi_aff_read_from_str(isl_ctx *ctx,
3704 const char *str)
3706 isl_multi_aff *maff;
3707 isl_stream *s = isl_stream_new_str(ctx, str);
3708 if (!s)
3709 return NULL;
3710 maff = isl_stream_read_multi_aff(s);
3711 isl_stream_free(s);
3712 return maff;
3715 /* Read an isl_multi_pw_aff from "s".
3717 * The input format is similar to that of map, except that any conditions
3718 * on the domains should be specified inside the tuple since each
3719 * piecewise affine expression may have a different domain.
3720 * However, additional, shared conditions can also be specified.
3721 * This is especially useful for setting the explicit domain
3722 * of a zero-dimensional isl_multi_pw_aff.
3724 * Since we do not know in advance if the isl_multi_pw_aff lives
3725 * in a set or a map space, we first read the first tuple and check
3726 * if it is followed by a "->". If so, we convert the tuple into
3727 * the domain of the isl_multi_pw_aff and read in the next tuple.
3728 * This tuple (or the first tuple if it was not followed by a "->")
3729 * is then converted into the isl_multi_pw_aff through a call
3730 * to extract_mpa_from_tuple and the domain of the result
3731 * is intersected with the domain.
3733 __isl_give isl_multi_pw_aff *isl_stream_read_multi_pw_aff(
3734 __isl_keep isl_stream *s)
3736 struct vars *v;
3737 isl_set *dom = NULL;
3738 isl_multi_pw_aff *tuple = NULL;
3739 isl_multi_pw_aff *mpa = NULL;
3741 v = vars_new(s->ctx);
3742 if (!v)
3743 return NULL;
3745 dom = isl_set_universe(isl_space_params_alloc(s->ctx, 0));
3746 if (next_is_tuple(s)) {
3747 dom = read_map_tuple(s, dom, isl_dim_param, v, 1, 0);
3748 if (isl_stream_eat(s, ISL_TOKEN_TO))
3749 goto error;
3751 if (isl_stream_eat(s, '{'))
3752 goto error;
3754 tuple = read_tuple(s, v, 0, 0);
3755 if (!tuple)
3756 goto error;
3757 if (isl_stream_eat_if_available(s, ISL_TOKEN_TO)) {
3758 isl_map *map = map_from_tuple(tuple, dom, isl_dim_in, v, 0);
3759 dom = isl_map_domain(map);
3760 tuple = read_tuple(s, v, 0, 0);
3761 if (!tuple)
3762 goto error;
3765 if (isl_stream_eat_if_available(s, ':'))
3766 dom = read_formula(s, v, dom, 0);
3768 if (isl_stream_eat(s, '}'))
3769 goto error;
3771 mpa = extract_mpa_from_tuple(isl_set_get_space(dom), tuple);
3773 isl_multi_pw_aff_free(tuple);
3774 vars_free(v);
3775 mpa = isl_multi_pw_aff_intersect_domain(mpa, dom);
3776 return mpa;
3777 error:
3778 isl_multi_pw_aff_free(tuple);
3779 vars_free(v);
3780 isl_set_free(dom);
3781 isl_multi_pw_aff_free(mpa);
3782 return NULL;
3785 /* Read an isl_multi_pw_aff from "str".
3787 __isl_give isl_multi_pw_aff *isl_multi_pw_aff_read_from_str(isl_ctx *ctx,
3788 const char *str)
3790 isl_multi_pw_aff *mpa;
3791 isl_stream *s = isl_stream_new_str(ctx, str);
3792 if (!s)
3793 return NULL;
3794 mpa = isl_stream_read_multi_pw_aff(s);
3795 isl_stream_free(s);
3796 return mpa;
3799 /* Read the body of an isl_union_pw_aff from "s" with parameter domain "dom".
3801 static __isl_give isl_union_pw_aff *read_union_pw_aff_with_dom(
3802 __isl_keep isl_stream *s, __isl_take isl_set *dom, struct vars *v)
3804 isl_pw_aff *pa;
3805 isl_union_pw_aff *upa = NULL;
3806 isl_set *aff_dom;
3807 int n;
3809 n = v->n;
3810 aff_dom = read_aff_domain(s, isl_set_copy(dom), v);
3811 pa = read_pw_aff_with_dom(s, aff_dom, v);
3812 vars_drop(v, v->n - n);
3814 upa = isl_union_pw_aff_from_pw_aff(pa);
3816 while (isl_stream_eat_if_available(s, ';')) {
3817 isl_pw_aff *pa_i;
3818 isl_union_pw_aff *upa_i;
3820 n = v->n;
3821 aff_dom = read_aff_domain(s, isl_set_copy(dom), v);
3822 pa_i = read_pw_aff_with_dom(s, aff_dom, v);
3823 vars_drop(v, v->n - n);
3825 upa_i = isl_union_pw_aff_from_pw_aff(pa_i);
3826 upa = isl_union_pw_aff_union_add(upa, upa_i);
3829 isl_set_free(dom);
3830 return upa;
3833 /* Read an isl_union_pw_aff from "s".
3835 * First check if there are any paramters, then read in the opening brace
3836 * and use read_union_pw_aff_with_dom to read in the body of
3837 * the isl_union_pw_aff. Finally, read the closing brace.
3839 __isl_give isl_union_pw_aff *isl_stream_read_union_pw_aff(
3840 __isl_keep isl_stream *s)
3842 struct vars *v;
3843 isl_set *dom;
3844 isl_union_pw_aff *upa = NULL;
3846 v = vars_new(s->ctx);
3847 if (!v)
3848 return NULL;
3850 dom = isl_set_universe(isl_space_params_alloc(s->ctx, 0));
3851 if (next_is_tuple(s)) {
3852 dom = read_map_tuple(s, dom, isl_dim_param, v, 1, 0);
3853 if (isl_stream_eat(s, ISL_TOKEN_TO))
3854 goto error;
3856 if (isl_stream_eat(s, '{'))
3857 goto error;
3859 upa = read_union_pw_aff_with_dom(s, isl_set_copy(dom), v);
3861 if (isl_stream_eat(s, '}'))
3862 goto error;
3864 vars_free(v);
3865 isl_set_free(dom);
3866 return upa;
3867 error:
3868 vars_free(v);
3869 isl_set_free(dom);
3870 isl_union_pw_aff_free(upa);
3871 return NULL;
3874 /* Read an isl_union_pw_aff from "str".
3876 __isl_give isl_union_pw_aff *isl_union_pw_aff_read_from_str(isl_ctx *ctx,
3877 const char *str)
3879 isl_union_pw_aff *upa;
3880 isl_stream *s = isl_stream_new_str(ctx, str);
3881 if (!s)
3882 return NULL;
3883 upa = isl_stream_read_union_pw_aff(s);
3884 isl_stream_free(s);
3885 return upa;
3888 /* This function is called for each element in a tuple inside
3889 * isl_stream_read_multi_union_pw_aff.
3891 * Read a '{', the union piecewise affine expression body and a '}' and
3892 * add the isl_union_pw_aff to *list.
3894 static __isl_give isl_space *read_union_pw_aff_el(__isl_keep isl_stream *s,
3895 struct vars *v, __isl_take isl_space *space, int rational, void *user)
3897 isl_set *dom;
3898 isl_union_pw_aff *upa;
3899 isl_union_pw_aff_list **list = (isl_union_pw_aff_list **) user;
3901 dom = isl_set_universe(isl_space_params(isl_space_copy(space)));
3902 if (isl_stream_eat(s, '{'))
3903 goto error;
3904 upa = read_union_pw_aff_with_dom(s, dom, v);
3905 *list = isl_union_pw_aff_list_add(*list, upa);
3906 if (isl_stream_eat(s, '}'))
3907 return isl_space_free(space);
3908 if (!*list)
3909 return isl_space_free(space);
3910 return space;
3911 error:
3912 isl_set_free(dom);
3913 return isl_space_free(space);
3916 /* Do the next tokens in "s" correspond to an empty tuple?
3917 * In particular, does the stream start with a '[', followed by a ']',
3918 * not followed by a "->"?
3920 static int next_is_empty_tuple(__isl_keep isl_stream *s)
3922 struct isl_token *tok, *tok2, *tok3;
3923 int is_empty_tuple = 0;
3925 tok = isl_stream_next_token(s);
3926 if (!tok)
3927 return 0;
3928 if (tok->type != '[') {
3929 isl_stream_push_token(s, tok);
3930 return 0;
3933 tok2 = isl_stream_next_token(s);
3934 if (tok2 && tok2->type == ']') {
3935 tok3 = isl_stream_next_token(s);
3936 is_empty_tuple = !tok || tok->type != ISL_TOKEN_TO;
3937 if (tok3)
3938 isl_stream_push_token(s, tok3);
3940 if (tok2)
3941 isl_stream_push_token(s, tok2);
3942 isl_stream_push_token(s, tok);
3944 return is_empty_tuple;
3947 /* Do the next tokens in "s" correspond to a tuple of parameters?
3948 * In particular, does the stream start with a '[' that is not
3949 * followed by a '{' or a nested tuple?
3951 static int next_is_param_tuple(__isl_keep isl_stream *s)
3953 struct isl_token *tok, *tok2;
3954 int is_tuple;
3956 tok = isl_stream_next_token(s);
3957 if (!tok)
3958 return 0;
3959 if (tok->type != '[' || next_is_tuple(s)) {
3960 isl_stream_push_token(s, tok);
3961 return 0;
3964 tok2 = isl_stream_next_token(s);
3965 is_tuple = tok2 && tok2->type != '{';
3966 if (tok2)
3967 isl_stream_push_token(s, tok2);
3968 isl_stream_push_token(s, tok);
3970 return is_tuple;
3973 /* Read the core of a body of an isl_multi_union_pw_aff from "s",
3974 * i.e., everything except the parameter specification and
3975 * without shared domain constraints.
3976 * "v" contains a description of the identifiers parsed so far.
3977 * The parameters, if any, are specified by "space".
3979 * The body is of the form
3981 * [{ [..] : ... ; [..] : ... }, { [..] : ... ; [..] : ... }]
3983 * Read the tuple, collecting the individual isl_union_pw_aff
3984 * elements in a list and construct the result from the tuple space and
3985 * the list.
3987 static __isl_give isl_multi_union_pw_aff *read_multi_union_pw_aff_body_core(
3988 __isl_keep isl_stream *s, struct vars *v, __isl_take isl_space *space)
3990 isl_union_pw_aff_list *list;
3991 isl_multi_union_pw_aff *mupa;
3993 list = isl_union_pw_aff_list_alloc(s->ctx, 0);
3994 space = read_tuple_space(s, v, space, 1, 0,
3995 &read_union_pw_aff_el, &list);
3996 mupa = isl_multi_union_pw_aff_from_union_pw_aff_list(space, list);
3998 return mupa;
4001 /* Read the body of an isl_union_set from "s",
4002 * i.e., everything except the parameter specification.
4003 * "v" contains a description of the identifiers parsed so far.
4004 * The parameters, if any, are specified by "space".
4006 * First read a generic disjunction of object bodies and then try and extract
4007 * an isl_union_set from that.
4009 static __isl_give isl_union_set *read_union_set_body(__isl_keep isl_stream *s,
4010 struct vars *v, __isl_take isl_space *space)
4012 struct isl_obj obj = { isl_obj_set, NULL };
4013 isl_map *map;
4015 map = isl_set_universe(space);
4016 if (isl_stream_eat(s, '{') < 0)
4017 goto error;
4018 obj = obj_read_disjuncts(s, v, map);
4019 if (isl_stream_eat(s, '}') < 0)
4020 goto error;
4021 isl_map_free(map);
4023 return extract_union_set(s->ctx, obj);
4024 error:
4025 obj.type->free(obj.v);
4026 isl_map_free(map);
4027 return NULL;
4030 /* Read the body of an isl_multi_union_pw_aff from "s",
4031 * i.e., everything except the parameter specification.
4032 * "v" contains a description of the identifiers parsed so far.
4033 * The parameters, if any, are specified by "space".
4035 * In particular, handle the special case with shared domain constraints.
4036 * These are specified as
4038 * ([...] : ...)
4040 * and are especially useful for setting the explicit domain
4041 * of a zero-dimensional isl_multi_union_pw_aff.
4042 * The core isl_multi_union_pw_aff body ([...]) is read by
4043 * read_multi_union_pw_aff_body_core.
4045 static __isl_give isl_multi_union_pw_aff *read_multi_union_pw_aff_body(
4046 __isl_keep isl_stream *s, struct vars *v, __isl_take isl_space *space)
4048 isl_multi_union_pw_aff *mupa;
4050 if (!isl_stream_next_token_is(s, '('))
4051 return read_multi_union_pw_aff_body_core(s, v, space);
4053 if (isl_stream_eat(s, '(') < 0)
4054 goto error;
4055 mupa = read_multi_union_pw_aff_body_core(s, v, isl_space_copy(space));
4056 if (isl_stream_eat_if_available(s, ':')) {
4057 isl_union_set *dom;
4059 dom = read_union_set_body(s, v, space);
4060 mupa = isl_multi_union_pw_aff_intersect_domain(mupa, dom);
4061 } else {
4062 isl_space_free(space);
4064 if (isl_stream_eat(s, ')') < 0)
4065 return isl_multi_union_pw_aff_free(mupa);
4067 return mupa;
4068 error:
4069 isl_space_free(space);
4070 return NULL;
4073 /* Read an isl_multi_union_pw_aff from "s".
4075 * The input has the form
4077 * [{ [..] : ... ; [..] : ... }, { [..] : ... ; [..] : ... }]
4079 * or
4081 * [..] -> [{ [..] : ... ; [..] : ... }, { [..] : ... ; [..] : ... }]
4083 * Additionally, a shared domain may be specified as
4085 * ([..] : ...)
4087 * or
4089 * [..] -> ([..] : ...)
4091 * The first case is handled by the caller, the second case
4092 * is handled by read_multi_union_pw_aff_body.
4094 * We first check for the special case of an empty tuple "[]".
4095 * Then we check if there are any parameters.
4096 * Finally, read the tuple and construct the result.
4098 static __isl_give isl_multi_union_pw_aff *read_multi_union_pw_aff_core(
4099 __isl_keep isl_stream *s)
4101 struct vars *v;
4102 isl_set *dom = NULL;
4103 isl_space *space;
4104 isl_multi_union_pw_aff *mupa = NULL;
4106 if (next_is_empty_tuple(s)) {
4107 if (isl_stream_eat(s, '['))
4108 return NULL;
4109 if (isl_stream_eat(s, ']'))
4110 return NULL;
4111 space = isl_space_set_alloc(s->ctx, 0, 0);
4112 return isl_multi_union_pw_aff_zero(space);
4115 v = vars_new(s->ctx);
4116 if (!v)
4117 return NULL;
4119 dom = isl_set_universe(isl_space_params_alloc(s->ctx, 0));
4120 if (next_is_param_tuple(s)) {
4121 dom = read_map_tuple(s, dom, isl_dim_param, v, 1, 0);
4122 if (isl_stream_eat(s, ISL_TOKEN_TO))
4123 goto error;
4125 space = isl_set_get_space(dom);
4126 isl_set_free(dom);
4127 mupa = read_multi_union_pw_aff_body(s, v, space);
4129 vars_free(v);
4131 return mupa;
4132 error:
4133 vars_free(v);
4134 isl_set_free(dom);
4135 isl_multi_union_pw_aff_free(mupa);
4136 return NULL;
4139 /* Read an isl_multi_union_pw_aff from "s".
4141 * In particular, handle the special case with shared domain constraints.
4142 * These are specified as
4144 * ([...] : ...)
4146 * and are especially useful for setting the explicit domain
4147 * of a zero-dimensional isl_multi_union_pw_aff.
4148 * The core isl_multi_union_pw_aff ([...]) is read by
4149 * read_multi_union_pw_aff_core.
4151 __isl_give isl_multi_union_pw_aff *isl_stream_read_multi_union_pw_aff(
4152 __isl_keep isl_stream *s)
4154 isl_multi_union_pw_aff *mupa;
4156 if (!isl_stream_next_token_is(s, '('))
4157 return read_multi_union_pw_aff_core(s);
4159 if (isl_stream_eat(s, '(') < 0)
4160 return NULL;
4161 mupa = read_multi_union_pw_aff_core(s);
4162 if (isl_stream_eat_if_available(s, ':')) {
4163 isl_union_set *dom;
4165 dom = isl_stream_read_union_set(s);
4166 mupa = isl_multi_union_pw_aff_intersect_domain(mupa, dom);
4168 if (isl_stream_eat(s, ')') < 0)
4169 return isl_multi_union_pw_aff_free(mupa);
4170 return mupa;
4173 /* Read an isl_multi_union_pw_aff from "str".
4175 __isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_read_from_str(
4176 isl_ctx *ctx, const char *str)
4178 isl_multi_union_pw_aff *mupa;
4179 isl_stream *s = isl_stream_new_str(ctx, str);
4180 if (!s)
4181 return NULL;
4182 mupa = isl_stream_read_multi_union_pw_aff(s);
4183 isl_stream_free(s);
4184 return mupa;
4187 __isl_give isl_union_pw_qpolynomial *isl_stream_read_union_pw_qpolynomial(
4188 __isl_keep isl_stream *s)
4190 struct isl_obj obj;
4192 obj = obj_read(s);
4193 if (obj.type == isl_obj_pw_qpolynomial) {
4194 obj.type = isl_obj_union_pw_qpolynomial;
4195 obj.v = isl_union_pw_qpolynomial_from_pw_qpolynomial(obj.v);
4197 if (obj.v)
4198 isl_assert(s->ctx, obj.type == isl_obj_union_pw_qpolynomial,
4199 goto error);
4201 return obj.v;
4202 error:
4203 obj.type->free(obj.v);
4204 return NULL;
4207 __isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_read_from_str(
4208 isl_ctx *ctx, const char *str)
4210 isl_union_pw_qpolynomial *upwqp;
4211 isl_stream *s = isl_stream_new_str(ctx, str);
4212 if (!s)
4213 return NULL;
4214 upwqp = isl_stream_read_union_pw_qpolynomial(s);
4215 isl_stream_free(s);
4216 return upwqp;