isl_input.c add_equalities: gauss and finalize result after adding equalities
[platform/upstream/isl.git] / isl_input.c
1 /*
2  * Copyright 2008-2009 Katholieke Universiteit Leuven
3  * Copyright 2010      INRIA Saclay
4  *
5  * Use of this software is governed by the GNU LGPLv2.1 license
6  *
7  * Written by Sven Verdoolaege, K.U.Leuven, Departement
8  * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
9  * and INRIA Saclay - Ile-de-France, Parc Club Orsay Universite,
10  * ZAC des vignes, 4 rue Jacques Monod, 91893 Orsay, France 
11  */
12
13 #include <ctype.h>
14 #include <stdio.h>
15 #include <string.h>
16 #include <strings.h>
17 #include <isl_set.h>
18 #include <isl_seq.h>
19 #include <isl_div.h>
20 #include "isl_stream.h"
21 #include "isl_map_private.h"
22 #include "isl_obj.h"
23 #include "isl_polynomial_private.h"
24 #include <isl_union_map.h>
25 #include <isl_mat_private.h>
26
27 struct variable {
28         char                    *name;
29         int                      pos;
30         struct variable         *next;
31 };
32
33 struct vars {
34         struct isl_ctx  *ctx;
35         int              n;
36         struct variable *v;
37 };
38
39 static struct vars *vars_new(struct isl_ctx *ctx)
40 {
41         struct vars *v;
42         v = isl_alloc_type(ctx, struct vars);
43         if (!v)
44                 return NULL;
45         v->ctx = ctx;
46         v->n = 0;
47         v->v = NULL;
48         return v;
49 }
50
51 static void variable_free(struct variable *var)
52 {
53         while (var) {
54                 struct variable *next = var->next;
55                 free(var->name);
56                 free(var);
57                 var = next;
58         }
59 }
60
61 static void vars_free(struct vars *v)
62 {
63         if (!v)
64                 return;
65         variable_free(v->v);
66         free(v);
67 }
68
69 static void vars_drop(struct vars *v, int n)
70 {
71         struct variable *var;
72
73         if (!v || !v->v)
74                 return;
75
76         v->n -= n;
77
78         var = v->v;
79         while (--n >= 0) {
80                 struct variable *next = var->next;
81                 free(var->name);
82                 free(var);
83                 var = next;
84         }
85         v->v = var;
86 }
87
88 static struct variable *variable_new(struct vars *v, const char *name, int len,
89                                 int pos)
90 {
91         struct variable *var;
92         var = isl_alloc_type(v->ctx, struct variable);
93         if (!var)
94                 goto error;
95         var->name = strdup(name);
96         var->name[len] = '\0';
97         var->pos = pos;
98         var->next = v->v;
99         return var;
100 error:
101         variable_free(v->v);
102         return NULL;
103 }
104
105 static int vars_pos(struct vars *v, const char *s, int len)
106 {
107         int pos;
108         struct variable *q;
109
110         if (len == -1)
111                 len = strlen(s);
112         for (q = v->v; q; q = q->next) {
113                 if (strncmp(q->name, s, len) == 0 && q->name[len] == '\0')
114                         break;
115         }
116         if (q)
117                 pos = q->pos;
118         else {
119                 pos = v->n;
120                 v->v = variable_new(v, s, len, v->n);
121                 if (!v->v)
122                         return -1;
123                 v->n++;
124         }
125         return pos;
126 }
127
128 static __isl_give isl_dim *set_name(__isl_take isl_dim *dim,
129         enum isl_dim_type type, unsigned pos, char *name)
130 {
131         char *prime;
132
133         if (!dim)
134                 return NULL;
135         if (!name)
136                 return dim;
137
138         prime = strchr(name, '\'');
139         if (prime)
140                 *prime = '\0';
141         dim = isl_dim_set_name(dim, type, pos, name);
142         if (prime)
143                 *prime = '\'';
144
145         return dim;
146 }
147
148 static int accept_cst_factor(struct isl_stream *s, isl_int *f)
149 {
150         struct isl_token *tok;
151
152         tok = isl_stream_next_token(s);
153         if (!tok || tok->type != ISL_TOKEN_VALUE) {
154                 isl_stream_error(s, tok, "expecting constant value");
155                 goto error;
156         }
157
158         isl_int_mul(*f, *f, tok->u.v);
159
160         isl_token_free(tok);
161
162         if (isl_stream_eat_if_available(s, '*'))
163                 return accept_cst_factor(s, f);
164
165         return 0;
166 error:
167         isl_token_free(tok);
168         return -1;
169 }
170
171 static struct isl_vec *accept_affine(struct isl_stream *s, struct vars *v);
172
173 static __isl_give isl_vec *accept_affine_factor(struct isl_stream *s,
174         struct vars *v)
175 {
176         struct isl_token *tok = NULL;
177         isl_vec *aff = NULL;
178
179         tok = isl_stream_next_token(s);
180         if (!tok) {
181                 isl_stream_error(s, NULL, "unexpected EOF");
182                 goto error;
183         }
184         if (tok->type == ISL_TOKEN_IDENT) {
185                 int n = v->n;
186                 int pos = vars_pos(v, tok->u.s, -1);
187                 if (pos < 0)
188                         goto error;
189                 if (pos >= n) {
190                         isl_stream_error(s, tok, "unknown identifier");
191                         goto error;
192                 }
193
194                 aff = isl_vec_alloc(v->ctx, 1 + v->n);
195                 if (!aff)
196                         goto error;
197                 isl_seq_clr(aff->el, aff->size);
198                 isl_int_set_si(aff->el[1 + pos], 1);
199                 isl_token_free(tok);
200         } else if (tok->type == ISL_TOKEN_VALUE) {
201                 if (isl_stream_eat_if_available(s, '*')) {
202                         aff = accept_affine_factor(s, v);
203                         aff = isl_vec_scale(aff, tok->u.v);
204                 } else {
205                         aff = isl_vec_alloc(v->ctx, 1 + v->n);
206                         if (!aff)
207                                 goto error;
208                         isl_seq_clr(aff->el, aff->size);
209                         isl_int_set(aff->el[0], tok->u.v);
210                 }
211                 isl_token_free(tok);
212         } else if (tok->type == '(') {
213                 isl_token_free(tok);
214                 tok = NULL;
215                 aff = accept_affine(s, v);
216                 if (!aff)
217                         goto error;
218                 if (isl_stream_eat(s, ')'))
219                         goto error;
220         } else {
221                 isl_stream_error(s, tok, "expecting factor");
222                 goto error;
223         }
224         if (isl_stream_eat_if_available(s, '*')) {
225                 isl_int f;
226                 isl_int_init(f);
227                 isl_int_set_si(f, 1);
228                 if (accept_cst_factor(s, &f) < 0) {
229                         isl_int_clear(f);
230                         goto error;
231                 }
232                 aff = isl_vec_scale(aff, f);
233                 isl_int_clear(f);
234         }
235
236         return aff;
237 error:
238         isl_token_free(tok);
239         isl_vec_free(aff);
240         return NULL;
241 }
242
243 static struct isl_vec *accept_affine(struct isl_stream *s, struct vars *v)
244 {
245         struct isl_token *tok = NULL;
246         struct isl_vec *aff;
247         int sign = 1;
248
249         aff = isl_vec_alloc(v->ctx, 1 + v->n);
250         if (!aff)
251                 return NULL;
252         isl_seq_clr(aff->el, aff->size);
253
254         for (;;) {
255                 tok = isl_stream_next_token(s);
256                 if (!tok) {
257                         isl_stream_error(s, NULL, "unexpected EOF");
258                         goto error;
259                 }
260                 if (tok->type == '-') {
261                         sign = -sign;
262                         isl_token_free(tok);
263                         continue;
264                 }
265                 if (tok->type == '(' || tok->type == ISL_TOKEN_IDENT) {
266                         isl_vec *aff2;
267                         isl_stream_push_token(s, tok);
268                         tok = NULL;
269                         aff2 = accept_affine_factor(s, v);
270                         if (sign < 0)
271                                 aff2 = isl_vec_scale(aff2, s->ctx->negone);
272                         aff = isl_vec_add(aff, aff2);
273                         if (!aff)
274                                 goto error;
275                         sign = 1;
276                 } else if (tok->type == ISL_TOKEN_VALUE) {
277                         if (sign < 0)
278                                 isl_int_neg(tok->u.v, tok->u.v);
279                         if (isl_stream_eat_if_available(s, '*') ||
280                             isl_stream_next_token_is(s, ISL_TOKEN_IDENT)) {
281                                 isl_vec *aff2;
282                                 aff2 = accept_affine_factor(s, v);
283                                 aff2 = isl_vec_scale(aff2, tok->u.v);
284                                 aff = isl_vec_add(aff, aff2);
285                                 if (!aff)
286                                         goto error;
287                         } else {
288                                 isl_int_add(aff->el[0], aff->el[0], tok->u.v);
289                         }
290                         sign = 1;
291                 }
292                 isl_token_free(tok);
293
294                 tok = isl_stream_next_token(s);
295                 if (tok && tok->type == '-') {
296                         sign = -sign;
297                         isl_token_free(tok);
298                 } else if (tok && tok->type == '+') {
299                         /* nothing */
300                         isl_token_free(tok);
301                 } else if (tok && tok->type == ISL_TOKEN_VALUE &&
302                            isl_int_is_neg(tok->u.v)) {
303                         isl_stream_push_token(s, tok);
304                 } else {
305                         if (tok)
306                                 isl_stream_push_token(s, tok);
307                         break;
308                 }
309         }
310
311         return aff;
312 error:
313         isl_token_free(tok);
314         isl_vec_free(aff);
315         return NULL;
316 }
317
318 static __isl_give isl_mat *read_var_def(struct isl_stream *s,
319         __isl_take isl_mat *eq, enum isl_dim_type type, struct vars *v)
320 {
321         struct isl_vec *vec;
322
323         vec = accept_affine(s, v);
324         if (!vec)
325                 goto error;
326         v->v = variable_new(v, "", 0, v->n);
327         if (!v->v)
328                 goto error;
329         v->n++;
330         eq = isl_mat_add_rows(eq, 1);
331         if (eq) {
332                 isl_seq_cpy(eq->row[eq->n_row - 1], vec->el, vec->size);
333                 isl_int_set_si(eq->row[eq->n_row - 1][vec->size], -1);
334         }
335         isl_vec_free(vec);
336
337         return eq;
338 error:
339         isl_mat_free(eq);
340         return NULL;
341 }
342
343 static __isl_give isl_dim *read_var_list(struct isl_stream *s,
344         __isl_take isl_dim *dim, enum isl_dim_type type, struct vars *v,
345         __isl_keep isl_mat **eq)
346 {
347         int i = 0;
348         struct isl_token *tok;
349
350         while ((tok = isl_stream_next_token(s)) != NULL) {
351                 int new_name = 0;
352
353                 if (tok->type == ISL_TOKEN_IDENT) {
354                         int n = v->n;
355                         int p = vars_pos(v, tok->u.s, -1);
356                         if (p < 0)
357                                 goto error;
358                         new_name = p >= n;
359                 }
360
361                 if (new_name) {
362                         dim = isl_dim_add(dim, type, 1);
363                         if (eq)
364                                 *eq = isl_mat_add_zero_cols(*eq, 1);
365                         dim = set_name(dim, type, i, v->v->name);
366                         isl_token_free(tok);
367                 } else if (tok->type == ISL_TOKEN_IDENT ||
368                            tok->type == ISL_TOKEN_VALUE ||
369                            tok->type == '-') {
370                         if (type == isl_dim_param) {
371                                 isl_stream_error(s, tok,
372                                                 "expecting unique identifier");
373                                 goto error;
374                         }
375                         isl_stream_push_token(s, tok);
376                         tok = NULL;
377                         dim = isl_dim_add(dim, type, 1);
378                         *eq = isl_mat_add_zero_cols(*eq, 1);
379                         *eq = read_var_def(s, *eq, type, v);
380                 } else
381                         break;
382
383                 tok = isl_stream_next_token(s);
384                 if (!tok || tok->type != ',')
385                         break;
386
387                 isl_token_free(tok);
388                 i++;
389         }
390         if (tok)
391                 isl_stream_push_token(s, tok);
392
393         return dim;
394 error:
395         isl_token_free(tok);
396         isl_dim_free(dim);
397         return NULL;
398 }
399
400 static __isl_give isl_mat *accept_affine_list(struct isl_stream *s,
401         struct vars *v)
402 {
403         struct isl_vec *vec;
404         struct isl_mat *mat;
405         struct isl_token *tok = NULL;
406
407         vec = accept_affine(s, v);
408         mat = isl_mat_from_row_vec(vec);
409         if (!mat)
410                 return NULL;
411
412         for (;;) {
413                 tok = isl_stream_next_token(s);
414                 if (!tok) {
415                         isl_stream_error(s, NULL, "unexpected EOF");
416                         goto error;
417                 }
418                 if (tok->type != ',') {
419                         isl_stream_push_token(s, tok);
420                         break;
421                 }
422                 isl_token_free(tok);
423
424                 vec = accept_affine(s, v);
425                 mat = isl_mat_vec_concat(mat, vec);
426                 if (!mat)
427                         return NULL;
428         }
429
430         return mat;
431 error:
432         isl_mat_free(mat);
433         return NULL;
434 }
435
436 static struct isl_basic_map *add_div_definition(struct isl_stream *s,
437         struct vars *v, struct isl_basic_map *bmap, int k)
438 {
439         struct isl_token *tok;
440         int seen_paren = 0;
441         struct isl_vec *aff;
442
443         if (isl_stream_eat(s, '['))
444                 goto error;
445
446         tok = isl_stream_next_token(s);
447         if (!tok)
448                 goto error;
449         if (tok->type == '(') {
450                 seen_paren = 1;
451                 isl_token_free(tok);
452         } else
453                 isl_stream_push_token(s, tok);
454
455         aff = accept_affine(s, v);
456         if (!aff)
457                 goto error;
458
459         isl_seq_cpy(bmap->div[k] + 1, aff->el, aff->size);
460
461         isl_vec_free(aff);
462
463         if (seen_paren && isl_stream_eat(s, ')'))
464                 goto error;
465         if (isl_stream_eat(s, '/'))
466                 goto error;
467
468         tok = isl_stream_next_token(s);
469         if (!tok)
470                 goto error;
471         if (tok->type != ISL_TOKEN_VALUE) {
472                 isl_stream_error(s, tok, "expected denominator");
473                 isl_stream_push_token(s, tok);
474                 goto error;
475         }
476         isl_int_set(bmap->div[k][0], tok->u.v);
477         isl_token_free(tok);
478
479         if (isl_stream_eat(s, ']'))
480                 goto error;
481
482         if (isl_basic_map_add_div_constraints(bmap, k) < 0)
483                 goto error;
484
485         return bmap;
486 error:
487         isl_basic_map_free(bmap);
488         return NULL;
489 }
490
491 static struct isl_basic_map *read_defined_var_list(struct isl_stream *s,
492         struct vars *v, struct isl_basic_map *bmap)
493 {
494         struct isl_token *tok;
495
496         while ((tok = isl_stream_next_token(s)) != NULL) {
497                 int k;
498                 int p;
499                 int n = v->n;
500                 unsigned total = isl_basic_map_total_dim(bmap);
501
502                 if (tok->type != ISL_TOKEN_IDENT)
503                         break;
504
505                 p = vars_pos(v, tok->u.s, -1);
506                 if (p < 0)
507                         goto error;
508                 if (p < n) {
509                         isl_stream_error(s, tok, "expecting unique identifier");
510                         goto error;
511                 }
512
513                 bmap = isl_basic_map_cow(bmap);
514                 bmap = isl_basic_map_extend_dim(bmap, isl_dim_copy(bmap->dim),
515                                                 1, 0, 2);
516
517                 if ((k = isl_basic_map_alloc_div(bmap)) < 0)
518                         goto error;
519                 isl_seq_clr(bmap->div[k], 1 + 1 + total);
520
521                 isl_token_free(tok);
522                 tok = isl_stream_next_token(s);
523                 if (tok && tok->type == '=') {
524                         isl_token_free(tok);
525                         bmap = add_div_definition(s, v, bmap, k);
526                         tok = isl_stream_next_token(s);
527                 }
528
529                 if (!tok || tok->type != ',')
530                         break;
531
532                 isl_token_free(tok);
533         }
534         if (tok)
535                 isl_stream_push_token(s, tok);
536
537         return bmap;
538 error:
539         isl_token_free(tok);
540         isl_basic_map_free(bmap);
541         return NULL;
542 }
543
544 static int next_is_tuple(struct isl_stream *s)
545 {
546         struct isl_token *tok;
547         int is_tuple;
548
549         tok = isl_stream_next_token(s);
550         if (!tok)
551                 return 0;
552         if (tok->type == '[') {
553                 isl_stream_push_token(s, tok);
554                 return 1;
555         }
556         if (tok->type != ISL_TOKEN_IDENT) {
557                 isl_stream_push_token(s, tok);
558                 return 0;
559         }
560
561         is_tuple = isl_stream_next_token_is(s, '[');
562
563         isl_stream_push_token(s, tok);
564
565         return is_tuple;
566 }
567
568 static __isl_give isl_dim *read_tuple(struct isl_stream *s,
569         __isl_take isl_dim *dim, enum isl_dim_type type, struct vars *v,
570         __isl_keep isl_mat **eq);
571
572 static __isl_give isl_dim *read_nested_tuple(struct isl_stream *s,
573         __isl_take isl_dim *dim, struct vars *v, __isl_keep isl_mat **eq)
574 {
575         dim = read_tuple(s, dim, isl_dim_in, v, eq);
576         if (isl_stream_eat(s, ISL_TOKEN_TO))
577                 goto error;
578         dim = read_tuple(s, dim, isl_dim_out, v, eq);
579         dim = isl_dim_wrap(dim);
580         return dim;
581 error:
582         isl_dim_free(dim);
583         return NULL;
584 }
585
586 static __isl_give isl_dim *read_tuple(struct isl_stream *s,
587         __isl_take isl_dim *dim, enum isl_dim_type type, struct vars *v,
588         __isl_keep isl_mat **eq)
589 {
590         struct isl_token *tok;
591         char *name = NULL;
592
593         tok = isl_stream_next_token(s);
594         if (tok && tok->type == ISL_TOKEN_IDENT) {
595                 name = strdup(tok->u.s);
596                 if (!name)
597                         goto error;
598                 isl_token_free(tok);
599                 tok = isl_stream_next_token(s);
600         }
601         if (!tok || tok->type != '[') {
602                 isl_stream_error(s, tok, "expecting '['");
603                 goto error;
604         }
605         isl_token_free(tok);
606         if (type != isl_dim_param && next_is_tuple(s)) {
607                 isl_dim *nested = isl_dim_copy(dim);
608                 nested = isl_dim_drop(nested, isl_dim_in, 0,
609                                         isl_dim_size(nested, isl_dim_in));
610                 nested = isl_dim_drop(nested, isl_dim_out, 0,
611                                         isl_dim_size(nested, isl_dim_out));
612                 nested = read_nested_tuple(s, nested, v, eq);
613                 if (type == isl_dim_in) {
614                         isl_dim_free(dim);
615                         dim = isl_dim_reverse(nested);
616                 } else {
617                         dim = isl_dim_join(dim, nested);
618                 }
619         } else
620                 dim = read_var_list(s, dim, type, v, eq);
621         tok = isl_stream_next_token(s);
622         if (!tok || tok->type != ']') {
623                 isl_stream_error(s, tok, "expecting ']'");
624                 goto error;
625         }
626         isl_token_free(tok);
627
628         if (name) {
629                 dim = isl_dim_set_tuple_name(dim, type, name);
630                 free(name);
631         }
632
633         return dim;
634 error:
635         if (tok)
636                 isl_token_free(tok);
637         isl_dim_free(dim);
638         return NULL;
639 }
640
641 static struct isl_basic_map *add_constraints(struct isl_stream *s,
642         struct vars *v, struct isl_basic_map *bmap);
643
644 static struct isl_basic_map *add_exists(struct isl_stream *s,
645         struct vars *v, struct isl_basic_map *bmap)
646 {
647         struct isl_token *tok;
648         int n = v->n;
649         int extra;
650         int seen_paren = 0;
651         int i;
652         unsigned total;
653
654         tok = isl_stream_next_token(s);
655         if (!tok)
656                 goto error;
657         if (tok->type == '(') {
658                 seen_paren = 1;
659                 isl_token_free(tok);
660         } else
661                 isl_stream_push_token(s, tok);
662
663         bmap = read_defined_var_list(s, v, bmap);
664         if (!bmap)
665                 goto error;
666
667         if (isl_stream_eat(s, ':'))
668                 goto error;
669         bmap = add_constraints(s, v, bmap);
670         if (seen_paren && isl_stream_eat(s, ')'))
671                 goto error;
672         return bmap;
673 error:
674         isl_basic_map_free(bmap);
675         return NULL;
676 }
677
678 static __isl_give isl_basic_map *construct_constraint(
679         __isl_take isl_basic_map *bmap, enum isl_token_type type,
680         isl_int *left, isl_int *right)
681 {
682         int k;
683         unsigned len;
684         struct isl_ctx *ctx;
685
686         if (!bmap)
687                 return NULL;
688         len = 1 + isl_basic_map_total_dim(bmap);
689         ctx = bmap->ctx;
690
691         k = isl_basic_map_alloc_inequality(bmap);
692         if (k < 0)
693                 goto error;
694         if (type == ISL_TOKEN_LE)
695                 isl_seq_combine(bmap->ineq[k], ctx->negone, left,
696                                                ctx->one, right,
697                                                len);
698         else if (type == ISL_TOKEN_GE)
699                 isl_seq_combine(bmap->ineq[k], ctx->one, left,
700                                                ctx->negone, right,
701                                                len);
702         else if (type == ISL_TOKEN_LT) {
703                 isl_seq_combine(bmap->ineq[k], ctx->negone, left,
704                                                ctx->one, right,
705                                                len);
706                 isl_int_sub_ui(bmap->ineq[k][0], bmap->ineq[k][0], 1);
707         } else if (type == ISL_TOKEN_GT) {
708                 isl_seq_combine(bmap->ineq[k], ctx->one, left,
709                                                ctx->negone, right,
710                                                len);
711                 isl_int_sub_ui(bmap->ineq[k][0], bmap->ineq[k][0], 1);
712         } else {
713                 isl_seq_combine(bmap->ineq[k], ctx->one, left,
714                                                ctx->negone, right,
715                                                len);
716                 isl_basic_map_inequality_to_equality(bmap, k);
717         }
718
719         return bmap;
720 error:
721         isl_basic_map_free(bmap);
722         return NULL;
723 }
724
725 static int is_comparator(struct isl_token *tok)
726 {
727         if (!tok)
728                 return 0;
729
730         switch (tok->type) {
731         case ISL_TOKEN_LT:
732         case ISL_TOKEN_GT:
733         case ISL_TOKEN_LE:
734         case ISL_TOKEN_GE:
735         case '=':
736                 return 1;
737         default:
738                 return 0;
739         }
740 }
741
742 static struct isl_basic_map *add_constraint(struct isl_stream *s,
743         struct vars *v, struct isl_basic_map *bmap)
744 {
745         int i, j;
746         unsigned total = isl_basic_map_total_dim(bmap);
747         struct isl_token *tok = NULL;
748         struct isl_mat *aff1 = NULL, *aff2 = NULL;
749
750         tok = isl_stream_next_token(s);
751         if (!tok)
752                 goto error;
753         if (tok->type == ISL_TOKEN_EXISTS) {
754                 isl_token_free(tok);
755                 return add_exists(s, v, bmap);
756         }
757         isl_stream_push_token(s, tok);
758         tok = NULL;
759
760         bmap = isl_basic_map_cow(bmap);
761
762         aff1 = accept_affine_list(s, v);
763         if (!aff1)
764                 goto error;
765         tok = isl_stream_next_token(s);
766         if (!is_comparator(tok)) {
767                 isl_stream_error(s, tok, "missing operator");
768                 if (tok)
769                         isl_stream_push_token(s, tok);
770                 tok = NULL;
771                 goto error;
772         }
773         isl_assert(aff1->ctx, aff1->n_col == 1 + total, goto error);
774         for (;;) {
775                 aff2 = accept_affine_list(s, v);
776                 if (!aff2)
777                         goto error;
778                 isl_assert(aff2->ctx, aff2->n_col == 1 + total, goto error);
779
780                 bmap = isl_basic_map_extend_constraints(bmap, 0,
781                                                 aff1->n_row * aff2->n_row);
782                 for (i = 0; i < aff1->n_row; ++i)
783                         for (j = 0; j < aff2->n_row; ++j)
784                                 bmap = construct_constraint(bmap, tok->type,
785                                                     aff1->row[i], aff2->row[j]);
786                 isl_token_free(tok);
787                 isl_mat_free(aff1);
788                 aff1 = aff2;
789
790                 tok = isl_stream_next_token(s);
791                 if (!is_comparator(tok)) {
792                         if (tok)
793                                 isl_stream_push_token(s, tok);
794                         break;
795                 }
796         }
797         isl_mat_free(aff1);
798
799         return bmap;
800 error:
801         if (tok)
802                 isl_token_free(tok);
803         isl_mat_free(aff1);
804         isl_mat_free(aff2);
805         isl_basic_map_free(bmap);
806         return NULL;
807 }
808
809 static struct isl_basic_map *add_constraints(struct isl_stream *s,
810         struct vars *v, struct isl_basic_map *bmap)
811 {
812         struct isl_token *tok;
813
814         for (;;) {
815                 bmap = add_constraint(s, v, bmap);
816                 if (!bmap)
817                         return NULL;
818                 tok = isl_stream_next_token(s);
819                 if (!tok) {
820                         isl_stream_error(s, NULL, "unexpected EOF");
821                         goto error;
822                 }
823                 if (tok->type != ISL_TOKEN_AND)
824                         break;
825                 isl_token_free(tok);
826         }
827         isl_stream_push_token(s, tok);
828
829         return bmap;
830 error:
831         if (tok)
832                 isl_token_free(tok);
833         isl_basic_map_free(bmap);
834         return NULL;
835 }
836
837 static struct isl_basic_map *read_disjunct(struct isl_stream *s,
838         struct vars *v, __isl_take isl_dim *dim)
839 {
840         int seen_paren = 0;
841         struct isl_token *tok;
842         struct isl_basic_map *bmap;
843
844         bmap = isl_basic_map_alloc_dim(dim, 0, 0, 0);
845         if (!bmap)
846                 return NULL;
847
848         tok = isl_stream_next_token(s);
849         if (!tok)
850                 goto error;
851         if (tok->type == '(') {
852                 seen_paren = 1;
853                 isl_token_free(tok);
854         } else
855                 isl_stream_push_token(s, tok);
856
857         bmap = add_constraints(s, v, bmap);
858         bmap = isl_basic_map_simplify(bmap);
859         bmap = isl_basic_map_finalize(bmap);
860
861         if (seen_paren && isl_stream_eat(s, ')'))
862                 goto error;
863
864         return bmap;
865 error:
866         isl_basic_map_free(bmap);
867         return NULL;
868 }
869
870 static struct isl_map *read_disjuncts(struct isl_stream *s,
871         struct vars *v, __isl_take isl_dim *dim)
872 {
873         struct isl_token *tok;
874         struct isl_map *map;
875
876         tok = isl_stream_next_token(s);
877         if (!tok) {
878                 isl_stream_error(s, NULL, "unexpected EOF");
879                 goto error;
880         }
881         if (tok->type == '}') {
882                 isl_stream_push_token(s, tok);
883                 return isl_map_universe(dim);
884         }
885         isl_stream_push_token(s, tok);
886
887         map = isl_map_empty(isl_dim_copy(dim));
888         for (;;) {
889                 struct isl_basic_map *bmap;
890                 int n = v->n;
891
892                 bmap = read_disjunct(s, v, isl_dim_copy(dim));
893                 map = isl_map_union(map, isl_map_from_basic_map(bmap));
894
895                 vars_drop(v, v->n - n);
896
897                 tok = isl_stream_next_token(s);
898                 if (!tok || tok->type != ISL_TOKEN_OR)
899                         break;
900                 isl_token_free(tok);
901         }
902         if (tok)
903                 isl_stream_push_token(s, tok);
904
905         isl_dim_free(dim);
906         return map;
907 error:
908         isl_dim_free(dim);
909         return NULL;
910 }
911
912 static int polylib_pos_to_isl_pos(__isl_keep isl_basic_map *bmap, int pos)
913 {
914         if (pos < isl_basic_map_dim(bmap, isl_dim_out))
915                 return 1 + isl_basic_map_dim(bmap, isl_dim_param) +
916                            isl_basic_map_dim(bmap, isl_dim_in) + pos;
917         pos -= isl_basic_map_dim(bmap, isl_dim_out);
918
919         if (pos < isl_basic_map_dim(bmap, isl_dim_in))
920                 return 1 + isl_basic_map_dim(bmap, isl_dim_param) + pos;
921         pos -= isl_basic_map_dim(bmap, isl_dim_in);
922
923         if (pos < isl_basic_map_dim(bmap, isl_dim_div))
924                 return 1 + isl_basic_map_dim(bmap, isl_dim_param) +
925                            isl_basic_map_dim(bmap, isl_dim_in) +
926                            isl_basic_map_dim(bmap, isl_dim_out) + pos;
927         pos -= isl_basic_map_dim(bmap, isl_dim_div);
928
929         if (pos < isl_basic_map_dim(bmap, isl_dim_param))
930                 return 1 + pos;
931
932         return 0;
933 }
934
935 static __isl_give isl_basic_map *basic_map_read_polylib_constraint(
936         struct isl_stream *s, __isl_take isl_basic_map *bmap)
937 {
938         int j;
939         struct isl_token *tok;
940         int type;
941         int k;
942         isl_int *c;
943         unsigned nparam;
944         unsigned dim;
945
946         if (!bmap)
947                 return NULL;
948
949         nparam = isl_basic_map_dim(bmap, isl_dim_param);
950         dim = isl_basic_map_dim(bmap, isl_dim_out);
951
952         tok = isl_stream_next_token(s);
953         if (!tok || tok->type != ISL_TOKEN_VALUE) {
954                 isl_stream_error(s, tok, "expecting coefficient");
955                 if (tok)
956                         isl_stream_push_token(s, tok);
957                 goto error;
958         }
959         if (!tok->on_new_line) {
960                 isl_stream_error(s, tok, "coefficient should appear on new line");
961                 isl_stream_push_token(s, tok);
962                 goto error;
963         }
964
965         type = isl_int_get_si(tok->u.v);
966         isl_token_free(tok);
967
968         isl_assert(s->ctx, type == 0 || type == 1, goto error);
969         if (type == 0) {
970                 k = isl_basic_map_alloc_equality(bmap);
971                 c = bmap->eq[k];
972         } else {
973                 k = isl_basic_map_alloc_inequality(bmap);
974                 c = bmap->ineq[k];
975         }
976         if (k < 0)
977                 goto error;
978
979         for (j = 0; j < 1 + isl_basic_map_total_dim(bmap); ++j) {
980                 int pos;
981                 tok = isl_stream_next_token(s);
982                 if (!tok || tok->type != ISL_TOKEN_VALUE) {
983                         isl_stream_error(s, tok, "expecting coefficient");
984                         if (tok)
985                                 isl_stream_push_token(s, tok);
986                         goto error;
987                 }
988                 if (tok->on_new_line) {
989                         isl_stream_error(s, tok,
990                                 "coefficient should not appear on new line");
991                         isl_stream_push_token(s, tok);
992                         goto error;
993                 }
994                 pos = polylib_pos_to_isl_pos(bmap, j);
995                 isl_int_set(c[pos], tok->u.v);
996                 isl_token_free(tok);
997         }
998
999         return bmap;
1000 error:
1001         isl_basic_map_free(bmap);
1002         return NULL;
1003 }
1004
1005 static __isl_give isl_basic_map *basic_map_read_polylib(struct isl_stream *s,
1006         int nparam)
1007 {
1008         int i;
1009         struct isl_token *tok;
1010         struct isl_token *tok2;
1011         int n_row, n_col;
1012         int on_new_line;
1013         unsigned in = 0, out, local = 0;
1014         struct isl_basic_map *bmap = NULL;
1015
1016         if (nparam < 0)
1017                 nparam = 0;
1018
1019         tok = isl_stream_next_token(s);
1020         if (!tok) {
1021                 isl_stream_error(s, NULL, "unexpected EOF");
1022                 return NULL;
1023         }
1024         tok2 = isl_stream_next_token(s);
1025         if (!tok2) {
1026                 isl_token_free(tok);
1027                 isl_stream_error(s, NULL, "unexpected EOF");
1028                 return NULL;
1029         }
1030         n_row = isl_int_get_si(tok->u.v);
1031         n_col = isl_int_get_si(tok2->u.v);
1032         on_new_line = tok2->on_new_line;
1033         isl_token_free(tok2);
1034         isl_token_free(tok);
1035         isl_assert(s->ctx, !on_new_line, return NULL);
1036         isl_assert(s->ctx, n_row >= 0, return NULL);
1037         isl_assert(s->ctx, n_col >= 2 + nparam, return NULL);
1038         tok = isl_stream_next_token_on_same_line(s);
1039         if (tok) {
1040                 if (tok->type != ISL_TOKEN_VALUE) {
1041                         isl_stream_error(s, tok,
1042                                     "expecting number of output dimensions");
1043                         isl_stream_push_token(s, tok);
1044                         goto error;
1045                 }
1046                 out = isl_int_get_si(tok->u.v);
1047                 isl_token_free(tok);
1048
1049                 tok = isl_stream_next_token_on_same_line(s);
1050                 if (!tok || tok->type != ISL_TOKEN_VALUE) {
1051                         isl_stream_error(s, tok,
1052                                     "expecting number of input dimensions");
1053                         if (tok)
1054                                 isl_stream_push_token(s, tok);
1055                         goto error;
1056                 }
1057                 in = isl_int_get_si(tok->u.v);
1058                 isl_token_free(tok);
1059
1060                 tok = isl_stream_next_token_on_same_line(s);
1061                 if (!tok || tok->type != ISL_TOKEN_VALUE) {
1062                         isl_stream_error(s, tok,
1063                                     "expecting number of existentials");
1064                         if (tok)
1065                                 isl_stream_push_token(s, tok);
1066                         goto error;
1067                 }
1068                 local = isl_int_get_si(tok->u.v);
1069                 isl_token_free(tok);
1070
1071                 tok = isl_stream_next_token_on_same_line(s);
1072                 if (!tok || tok->type != ISL_TOKEN_VALUE) {
1073                         isl_stream_error(s, tok,
1074                                     "expecting number of parameters");
1075                         if (tok)
1076                                 isl_stream_push_token(s, tok);
1077                         goto error;
1078                 }
1079                 nparam = isl_int_get_si(tok->u.v);
1080                 isl_token_free(tok);
1081                 if (n_col != 1 + out + in + local + nparam + 1) {
1082                         isl_stream_error(s, NULL,
1083                                     "dimensions don't match");
1084                         goto error;
1085                 }
1086         } else
1087                 out = n_col - 2 - nparam;
1088         bmap = isl_basic_map_alloc(s->ctx, nparam, in, out, local, n_row, n_row);
1089         if (!bmap)
1090                 return NULL;
1091
1092         for (i = 0; i < local; ++i) {
1093                 int k = isl_basic_map_alloc_div(bmap);
1094                 if (k < 0)
1095                         goto error;
1096         }
1097
1098         for (i = 0; i < n_row; ++i)
1099                 bmap = basic_map_read_polylib_constraint(s, bmap);
1100
1101         tok = isl_stream_next_token_on_same_line(s);
1102         if (tok) {
1103                 isl_stream_error(s, tok, "unexpected extra token on line");
1104                 isl_stream_push_token(s, tok);
1105                 goto error;
1106         }
1107
1108         bmap = isl_basic_map_simplify(bmap);
1109         bmap = isl_basic_map_finalize(bmap);
1110         return bmap;
1111 error:
1112         isl_basic_map_free(bmap);
1113         return NULL;
1114 }
1115
1116 static struct isl_map *map_read_polylib(struct isl_stream *s, int nparam)
1117 {
1118         struct isl_token *tok;
1119         struct isl_token *tok2;
1120         int i, n;
1121         struct isl_map *map;
1122
1123         tok = isl_stream_next_token(s);
1124         if (!tok) {
1125                 isl_stream_error(s, NULL, "unexpected EOF");
1126                 return NULL;
1127         }
1128         tok2 = isl_stream_next_token_on_same_line(s);
1129         if (tok2) {
1130                 isl_stream_push_token(s, tok2);
1131                 isl_stream_push_token(s, tok);
1132                 return isl_map_from_basic_map(basic_map_read_polylib(s, nparam));
1133         }
1134         n = isl_int_get_si(tok->u.v);
1135         isl_token_free(tok);
1136
1137         isl_assert(s->ctx, n >= 1, return NULL);
1138
1139         map = isl_map_from_basic_map(basic_map_read_polylib(s, nparam));
1140
1141         for (i = 1; i < n; ++i)
1142                 map = isl_map_union(map,
1143                         isl_map_from_basic_map(basic_map_read_polylib(s, nparam)));
1144
1145         return map;
1146 }
1147
1148 static int optional_power(struct isl_stream *s)
1149 {
1150         int pow;
1151         struct isl_token *tok;
1152
1153         tok = isl_stream_next_token(s);
1154         if (!tok)
1155                 return 1;
1156         if (tok->type != '^') {
1157                 isl_stream_push_token(s, tok);
1158                 return 1;
1159         }
1160         isl_token_free(tok);
1161         tok = isl_stream_next_token(s);
1162         if (!tok || tok->type != ISL_TOKEN_VALUE) {
1163                 isl_stream_error(s, tok, "expecting exponent");
1164                 if (tok)
1165                         isl_stream_push_token(s, tok);
1166                 return 1;
1167         }
1168         pow = isl_int_get_si(tok->u.v);
1169         isl_token_free(tok);
1170         return pow;
1171 }
1172
1173 static __isl_give isl_div *read_div(struct isl_stream *s,
1174         __isl_keep isl_basic_map *bmap, struct vars *v)
1175 {
1176         unsigned total = isl_basic_map_total_dim(bmap);
1177         int k;
1178
1179         bmap = isl_basic_map_copy(bmap);
1180         bmap = isl_basic_map_cow(bmap);
1181         bmap = isl_basic_map_extend_dim(bmap, isl_dim_copy(bmap->dim),
1182                                         1, 0, 2);
1183
1184         if ((k = isl_basic_map_alloc_div(bmap)) < 0)
1185                 goto error;
1186         isl_seq_clr(bmap->div[k], 1 + 1 + total);
1187         bmap = add_div_definition(s, v, bmap, k);
1188
1189         return isl_basic_map_div(bmap, k);
1190 error:
1191         isl_basic_map_free(bmap);
1192         return NULL;
1193 }
1194
1195 static __isl_give isl_qpolynomial *read_term(struct isl_stream *s,
1196         __isl_keep isl_basic_map *bmap, struct vars *v);
1197
1198 static __isl_give isl_qpolynomial *read_factor(struct isl_stream *s,
1199         __isl_keep isl_basic_map *bmap, struct vars *v)
1200 {
1201         struct isl_qpolynomial *qp;
1202         struct isl_token *tok;
1203
1204         tok = isl_stream_next_token(s);
1205         if (!tok) {
1206                 isl_stream_error(s, NULL, "unexpected EOF");
1207                 return NULL;
1208         }
1209         if (tok->type == '(') {
1210                 isl_token_free(tok);
1211                 qp = read_term(s, bmap, v);
1212                 if (!qp)
1213                         return NULL;
1214                 if (isl_stream_eat(s, ')'))
1215                         goto error;
1216         } else if (tok->type == ISL_TOKEN_VALUE) {
1217                 struct isl_token *tok2;
1218                 tok2 = isl_stream_next_token(s);
1219                 if (tok2 && tok2->type == '/') {
1220                         isl_token_free(tok2);
1221                         tok2 = isl_stream_next_token(s);
1222                         if (!tok2 || tok2->type != ISL_TOKEN_VALUE) {
1223                                 isl_stream_error(s, tok2, "expected denominator");
1224                                 isl_token_free(tok);
1225                                 isl_token_free(tok2);
1226                                 return NULL;
1227                         }
1228                         qp = isl_qpolynomial_rat_cst(isl_basic_map_get_dim(bmap),
1229                                                     tok->u.v, tok2->u.v);
1230                         isl_token_free(tok2);
1231                 } else {
1232                         isl_stream_push_token(s, tok2);
1233                         qp = isl_qpolynomial_cst(isl_basic_map_get_dim(bmap),
1234                                                 tok->u.v);
1235                 }
1236                 isl_token_free(tok);
1237         } else if (tok->type == ISL_TOKEN_INFTY) {
1238                 isl_token_free(tok);
1239                 qp = isl_qpolynomial_infty(isl_basic_map_get_dim(bmap));
1240         } else if (tok->type == ISL_TOKEN_NAN) {
1241                 isl_token_free(tok);
1242                 qp = isl_qpolynomial_nan(isl_basic_map_get_dim(bmap));
1243         } else if (tok->type == ISL_TOKEN_IDENT) {
1244                 int n = v->n;
1245                 int pos = vars_pos(v, tok->u.s, -1);
1246                 int pow;
1247                 if (pos < 0) {
1248                         isl_token_free(tok);
1249                         return NULL;
1250                 }
1251                 if (pos >= n) {
1252                         isl_stream_error(s, tok, "unknown identifier");
1253                         isl_token_free(tok);
1254                         return NULL;
1255                 }
1256                 isl_token_free(tok);
1257                 pow = optional_power(s);
1258                 qp = isl_qpolynomial_pow(isl_basic_map_get_dim(bmap), pos, pow);
1259         } else if (tok->type == '[') {
1260                 isl_div *div;
1261                 int pow;
1262
1263                 isl_stream_push_token(s, tok);
1264                 div = read_div(s, bmap, v);
1265                 pow = optional_power(s);
1266                 qp = isl_qpolynomial_div_pow(div, pow);
1267         } else if (tok->type == '-') {
1268                 struct isl_qpolynomial *qp2;
1269
1270                 isl_token_free(tok);
1271                 qp = isl_qpolynomial_cst(isl_basic_map_get_dim(bmap),
1272                                             s->ctx->negone);
1273                 qp2 = read_factor(s, bmap, v);
1274                 qp = isl_qpolynomial_mul(qp, qp2);
1275         } else {
1276                 isl_stream_error(s, tok, "unexpected isl_token");
1277                 isl_stream_push_token(s, tok);
1278                 return NULL;
1279         }
1280
1281         if (isl_stream_eat_if_available(s, '*') ||
1282             isl_stream_next_token_is(s, ISL_TOKEN_IDENT)) {
1283                 struct isl_qpolynomial *qp2;
1284
1285                 qp2 = read_factor(s, bmap, v);
1286                 qp = isl_qpolynomial_mul(qp, qp2);
1287         }
1288
1289         return qp;
1290 error:
1291         isl_qpolynomial_free(qp);
1292         return NULL;
1293 }
1294
1295 static __isl_give isl_qpolynomial *read_term(struct isl_stream *s,
1296         __isl_keep isl_basic_map *bmap, struct vars *v)
1297 {
1298         struct isl_token *tok;
1299         struct isl_qpolynomial *qp;
1300
1301         qp = read_factor(s, bmap, v);
1302
1303         for (;;) {
1304                 tok = isl_stream_next_token(s);
1305                 if (!tok)
1306                         return qp;
1307
1308                 if (tok->type == '+') {
1309                         struct isl_qpolynomial *qp2;
1310
1311                         isl_token_free(tok);
1312                         qp2 = read_factor(s, bmap, v);
1313                         qp = isl_qpolynomial_add(qp, qp2);
1314                 } else if (tok->type == '-') {
1315                         struct isl_qpolynomial *qp2;
1316
1317                         isl_token_free(tok);
1318                         qp2 = read_factor(s, bmap, v);
1319                         qp = isl_qpolynomial_sub(qp, qp2);
1320                 } else if (tok->type == ISL_TOKEN_VALUE &&
1321                             isl_int_is_neg(tok->u.v)) {
1322                         struct isl_qpolynomial *qp2;
1323
1324                         isl_stream_push_token(s, tok);
1325                         qp2 = read_factor(s, bmap, v);
1326                         qp = isl_qpolynomial_add(qp, qp2);
1327                 } else {
1328                         isl_stream_push_token(s, tok);
1329                         break;
1330                 }
1331         }
1332
1333         return qp;
1334 }
1335
1336 static __isl_give isl_map *read_optional_disjuncts(struct isl_stream *s,
1337         __isl_take isl_basic_map *bmap, struct vars *v)
1338 {
1339         struct isl_token *tok;
1340         struct isl_map *map;
1341
1342         tok = isl_stream_next_token(s);
1343         if (!tok) {
1344                 isl_stream_error(s, NULL, "unexpected EOF");
1345                 goto error;
1346         }
1347         map = isl_map_from_basic_map(isl_basic_map_copy(bmap));
1348         if (tok->type == ':') {
1349                 isl_token_free(tok);
1350                 map = isl_map_intersect(map,
1351                             read_disjuncts(s, v, isl_basic_map_get_dim(bmap)));
1352         } else
1353                 isl_stream_push_token(s, tok);
1354
1355         isl_basic_map_free(bmap);
1356
1357         return map;
1358 error:
1359         isl_basic_map_free(bmap);
1360         return NULL;
1361 }
1362
1363 static struct isl_obj obj_read_poly(struct isl_stream *s,
1364         __isl_take isl_basic_map *bmap, struct vars *v, int n)
1365 {
1366         struct isl_obj obj = { isl_obj_pw_qpolynomial, NULL };
1367         struct isl_pw_qpolynomial *pwqp;
1368         struct isl_qpolynomial *qp;
1369         struct isl_map *map;
1370         struct isl_set *set;
1371
1372         qp = read_term(s, bmap, v);
1373         map = read_optional_disjuncts(s, bmap, v);
1374         set = isl_map_range(map);
1375
1376         pwqp = isl_pw_qpolynomial_alloc(set, qp);
1377
1378         vars_drop(v, v->n - n);
1379
1380         obj.v = pwqp;
1381         return obj;
1382 }
1383
1384 static struct isl_obj obj_read_poly_or_fold(struct isl_stream *s,
1385         __isl_take isl_basic_map *bmap, struct vars *v, int n)
1386 {
1387         struct isl_obj obj = { isl_obj_pw_qpolynomial_fold, NULL };
1388         struct isl_obj obj_p;
1389         isl_qpolynomial *qp;
1390         isl_qpolynomial_fold *fold = NULL;
1391         isl_pw_qpolynomial_fold *pwf;
1392         isl_map *map;
1393         isl_set *set;
1394
1395         if (!isl_stream_eat_if_available(s, ISL_TOKEN_MAX))
1396                 return obj_read_poly(s, bmap, v, n);
1397
1398         if (isl_stream_eat(s, '('))
1399                 goto error;
1400
1401         qp = read_term(s, bmap, v);
1402         fold = isl_qpolynomial_fold_alloc(isl_fold_max, qp);
1403
1404         while (isl_stream_eat_if_available(s, ',')) {
1405                 isl_qpolynomial_fold *fold_i;
1406                 qp = read_term(s, bmap, v);
1407                 fold_i = isl_qpolynomial_fold_alloc(isl_fold_max, qp);
1408                 fold = isl_qpolynomial_fold_fold(fold, fold_i);
1409         }
1410
1411         if (isl_stream_eat(s, ')'))
1412                 goto error;
1413
1414         map = read_optional_disjuncts(s, bmap, v);
1415         set = isl_map_range(map);
1416         pwf = isl_pw_qpolynomial_fold_alloc(isl_fold_max, set, fold);
1417
1418         vars_drop(v, v->n - n);
1419
1420         obj.v = pwf;
1421         return obj;
1422 error:
1423         isl_basic_map_free(bmap);
1424         isl_qpolynomial_fold_free(fold);
1425         obj.type = isl_obj_none;
1426         return obj;
1427 }
1428
1429 static __isl_give isl_basic_map *add_equalities(__isl_take isl_basic_map *bmap,
1430         isl_mat *eq)
1431 {
1432         int i, k;
1433         unsigned total = 1 + isl_basic_map_total_dim(bmap);
1434
1435         if (!bmap || !eq)
1436                 goto error;
1437
1438         bmap = isl_basic_map_extend_constraints(bmap, eq->n_row, 0);
1439
1440         for (i = 0; i < eq->n_row; ++i) {
1441                 k = isl_basic_map_alloc_equality(bmap);
1442                 if (k < 0)
1443                         goto error;
1444                 isl_seq_cpy(bmap->eq[k], eq->row[i], eq->n_col);
1445                 isl_seq_clr(bmap->eq[k] + eq->n_col, total - eq->n_col);
1446         }
1447
1448         isl_mat_free(eq);
1449         bmap = isl_basic_map_gauss(bmap, NULL);
1450         bmap = isl_basic_map_finalize(bmap);
1451         return bmap;
1452 error:
1453         isl_mat_free(eq);
1454         isl_basic_map_free(bmap);
1455         return NULL;
1456 }
1457
1458 static struct isl_obj obj_read_body(struct isl_stream *s,
1459         __isl_take isl_dim *dim, struct vars *v)
1460 {
1461         struct isl_map *map = NULL;
1462         struct isl_token *tok;
1463         struct isl_obj obj = { isl_obj_set, NULL };
1464         int n = v->n;
1465         isl_mat *eq = NULL;
1466         isl_basic_map *bmap;
1467
1468         if (!next_is_tuple(s)) {
1469                 bmap = isl_basic_map_alloc_dim(dim, 0, 0, 0);
1470                 return obj_read_poly_or_fold(s, bmap, v, n);
1471         }
1472
1473         eq = isl_mat_alloc(s->ctx, 0, 1 + n);
1474
1475         dim = read_tuple(s, dim, isl_dim_in, v, &eq);
1476         if (!dim)
1477                 goto error;
1478         tok = isl_stream_next_token(s);
1479         if (tok && tok->type == ISL_TOKEN_TO) {
1480                 obj.type = isl_obj_map;
1481                 isl_token_free(tok);
1482                 if (!next_is_tuple(s)) {
1483                         bmap = isl_basic_map_alloc_dim(dim, 0, 0, 0);
1484                         bmap = add_equalities(bmap, eq);
1485                         bmap = isl_basic_map_reverse(bmap);
1486                         return obj_read_poly_or_fold(s, bmap, v, n);
1487                 }
1488                 dim = read_tuple(s, dim, isl_dim_out, v, &eq);
1489                 if (!dim)
1490                         goto error;
1491         } else {
1492                 dim = isl_dim_reverse(dim);
1493                 if (tok)
1494                         isl_stream_push_token(s, tok);
1495         }
1496
1497         bmap = isl_basic_map_alloc_dim(dim, 0, 0, 0);
1498         bmap = add_equalities(bmap, eq);
1499
1500         map = read_optional_disjuncts(s, bmap, v);
1501
1502         vars_drop(v, v->n - n);
1503
1504         obj.v = map;
1505         return obj;
1506 error:
1507         isl_mat_free(eq);
1508         isl_dim_free(dim);
1509         obj.type = isl_obj_none;
1510         return obj;
1511 }
1512
1513 static struct isl_obj to_union(isl_ctx *ctx, struct isl_obj obj)
1514 {
1515         if (obj.type == isl_obj_map) {
1516                 obj.v = isl_union_map_from_map(obj.v);
1517                 obj.type = isl_obj_union_map;
1518         } else if (obj.type == isl_obj_set) {
1519                 obj.v = isl_union_set_from_set(obj.v);
1520                 obj.type = isl_obj_union_set;
1521         } else if (obj.type == isl_obj_pw_qpolynomial) {
1522                 obj.v = isl_union_pw_qpolynomial_from_pw_qpolynomial(obj.v);
1523                 obj.type = isl_obj_union_pw_qpolynomial;
1524         } else if (obj.type == isl_obj_pw_qpolynomial_fold) {
1525                 obj.v = isl_union_pw_qpolynomial_fold_from_pw_qpolynomial_fold(obj.v);
1526                 obj.type = isl_obj_union_pw_qpolynomial_fold;
1527         } else
1528                 isl_assert(ctx, 0, goto error);
1529         return obj;
1530 error:
1531         obj.type->free(obj.v);
1532         obj.type = isl_obj_none;
1533         return obj;
1534 }
1535
1536 static struct isl_obj obj_add(struct isl_ctx *ctx,
1537         struct isl_obj obj1, struct isl_obj obj2)
1538 {
1539         if (obj1.type == isl_obj_set && obj2.type == isl_obj_union_set)
1540                 obj1 = to_union(ctx, obj1);
1541         if (obj1.type == isl_obj_union_set && obj2.type == isl_obj_set)
1542                 obj2 = to_union(ctx, obj2);
1543         if (obj1.type == isl_obj_map && obj2.type == isl_obj_union_map)
1544                 obj1 = to_union(ctx, obj1);
1545         if (obj1.type == isl_obj_union_map && obj2.type == isl_obj_map)
1546                 obj2 = to_union(ctx, obj2);
1547         if (obj1.type == isl_obj_pw_qpolynomial &&
1548             obj2.type == isl_obj_union_pw_qpolynomial)
1549                 obj1 = to_union(ctx, obj1);
1550         if (obj1.type == isl_obj_union_pw_qpolynomial &&
1551             obj2.type == isl_obj_pw_qpolynomial)
1552                 obj2 = to_union(ctx, obj2);
1553         if (obj1.type == isl_obj_pw_qpolynomial_fold &&
1554             obj2.type == isl_obj_union_pw_qpolynomial_fold)
1555                 obj1 = to_union(ctx, obj1);
1556         if (obj1.type == isl_obj_union_pw_qpolynomial_fold &&
1557             obj2.type == isl_obj_pw_qpolynomial_fold)
1558                 obj2 = to_union(ctx, obj2);
1559         isl_assert(ctx, obj1.type == obj2.type, goto error);
1560         if (obj1.type == isl_obj_map && !isl_map_has_equal_dim(obj1.v, obj2.v)) {
1561                 obj1 = to_union(ctx, obj1);
1562                 obj2 = to_union(ctx, obj2);
1563         }
1564         if (obj1.type == isl_obj_set && !isl_set_has_equal_dim(obj1.v, obj2.v)) {
1565                 obj1 = to_union(ctx, obj1);
1566                 obj2 = to_union(ctx, obj2);
1567         }
1568         if (obj1.type == isl_obj_pw_qpolynomial &&
1569             !isl_pw_qpolynomial_has_equal_dim(obj1.v, obj2.v)) {
1570                 obj1 = to_union(ctx, obj1);
1571                 obj2 = to_union(ctx, obj2);
1572         }
1573         if (obj1.type == isl_obj_pw_qpolynomial_fold &&
1574             !isl_pw_qpolynomial_fold_has_equal_dim(obj1.v, obj2.v)) {
1575                 obj1 = to_union(ctx, obj1);
1576                 obj2 = to_union(ctx, obj2);
1577         }
1578         obj1.v = obj1.type->add(obj1.v, obj2.v);
1579         return obj1;
1580 error:
1581         obj1.type->free(obj1.v);
1582         obj2.type->free(obj2.v);
1583         obj1.type = isl_obj_none;
1584         obj1.v = NULL;
1585         return obj1;
1586 }
1587
1588 static struct isl_obj obj_read(struct isl_stream *s, int nparam)
1589 {
1590         isl_dim *dim = NULL;
1591         struct isl_token *tok;
1592         struct vars *v = NULL;
1593         struct isl_obj obj = { isl_obj_set, NULL };
1594
1595         tok = isl_stream_next_token(s);
1596         if (!tok) {
1597                 isl_stream_error(s, NULL, "unexpected EOF");
1598                 goto error;
1599         }
1600         if (tok->type == ISL_TOKEN_VALUE) {
1601                 struct isl_map *map;
1602                 isl_stream_push_token(s, tok);
1603                 map = map_read_polylib(s, nparam);
1604                 if (!map)
1605                         goto error;
1606                 if (isl_map_dim(map, isl_dim_in) > 0)
1607                         obj.type = isl_obj_map;
1608                 obj.v = map;
1609                 return obj;
1610         }
1611         v = vars_new(s->ctx);
1612         if (!v) {
1613                 isl_stream_push_token(s, tok);
1614                 goto error;
1615         }
1616         dim = isl_dim_alloc(s->ctx, 0, 0, 0);
1617         if (tok->type == '[') {
1618                 isl_stream_push_token(s, tok);
1619                 dim = read_tuple(s, dim, isl_dim_param, v, NULL);
1620                 if (!dim)
1621                         goto error;
1622                 if (nparam >= 0)
1623                         isl_assert(s->ctx, nparam == v->n, goto error);
1624                 tok = isl_stream_next_token(s);
1625                 if (!tok || tok->type != ISL_TOKEN_TO) {
1626                         isl_stream_error(s, tok, "expecting '->'");
1627                         if (tok)
1628                                 isl_stream_push_token(s, tok);
1629                         goto error;
1630                 }
1631                 isl_token_free(tok);
1632                 tok = isl_stream_next_token(s);
1633         } else if (nparam > 0)
1634                 dim = isl_dim_add(dim, isl_dim_param, nparam);
1635         if (!tok || tok->type != '{') {
1636                 isl_stream_error(s, tok, "expecting '{'");
1637                 if (tok)
1638                         isl_stream_push_token(s, tok);
1639                 goto error;
1640         }
1641         isl_token_free(tok);
1642
1643         tok = isl_stream_next_token(s);
1644         if (!tok)
1645                 ;
1646         else if (tok->type == ISL_TOKEN_IDENT && !strcmp(tok->u.s, "Sym")) {
1647                 isl_token_free(tok);
1648                 if (isl_stream_eat(s, '='))
1649                         goto error;
1650                 dim = read_tuple(s, dim, isl_dim_param, v, NULL);
1651                 if (!dim)
1652                         goto error;
1653                 if (nparam >= 0)
1654                         isl_assert(s->ctx, nparam == v->n, goto error);
1655         } else if (tok->type == '}') {
1656                 obj.type = isl_obj_union_set;
1657                 obj.v = isl_union_set_empty(isl_dim_copy(dim));
1658                 isl_token_free(tok);
1659                 goto done;
1660         } else
1661                 isl_stream_push_token(s, tok);
1662
1663         for (;;) {
1664                 struct isl_obj o;
1665                 tok = NULL;
1666                 o = obj_read_body(s, isl_dim_copy(dim), v);
1667                 if (o.type == isl_obj_none)
1668                         break;
1669                 if (!obj.v)
1670                         obj = o;
1671                 else {
1672                         obj = obj_add(s->ctx, obj, o);
1673                         if (obj.type == isl_obj_none)
1674                                 break;
1675                 }
1676                 tok = isl_stream_next_token(s);
1677                 if (!tok || tok->type != ';')
1678                         break;
1679                 isl_token_free(tok);
1680         }
1681
1682         if (tok && tok->type == '}') {
1683                 isl_token_free(tok);
1684         } else {
1685                 isl_stream_error(s, tok, "unexpected isl_token");
1686                 if (tok)
1687                         isl_token_free(tok);
1688                 goto error;
1689         }
1690 done:
1691         vars_free(v);
1692         isl_dim_free(dim);
1693
1694         return obj;
1695 error:
1696         isl_dim_free(dim);
1697         obj.type->free(obj.v);
1698         if (v)
1699                 vars_free(v);
1700         obj.v = NULL;
1701         return obj;
1702 }
1703
1704 struct isl_obj isl_stream_read_obj(struct isl_stream *s)
1705 {
1706         return obj_read(s, -1);
1707 }
1708
1709 __isl_give isl_map *isl_stream_read_map(struct isl_stream *s, int nparam)
1710 {
1711         struct isl_obj obj;
1712         struct isl_map *map;
1713
1714         obj = obj_read(s, nparam);
1715         if (obj.v)
1716                 isl_assert(s->ctx, obj.type == isl_obj_map ||
1717                                    obj.type == isl_obj_set, goto error);
1718
1719         return obj.v;
1720 error:
1721         obj.type->free(obj.v);
1722         return NULL;
1723 }
1724
1725 __isl_give isl_set *isl_stream_read_set(struct isl_stream *s, int nparam)
1726 {
1727         struct isl_obj obj;
1728         struct isl_set *set;
1729
1730         obj = obj_read(s, nparam);
1731         if (obj.v)
1732                 isl_assert(s->ctx, obj.type == isl_obj_set, goto error);
1733
1734         return obj.v;
1735 error:
1736         obj.type->free(obj.v);
1737         return NULL;
1738 }
1739
1740 static struct isl_basic_map *basic_map_read(struct isl_stream *s, int nparam)
1741 {
1742         struct isl_obj obj;
1743         struct isl_map *map;
1744         struct isl_basic_map *bmap;
1745
1746         obj = obj_read(s, nparam);
1747         map = obj.v;
1748         if (!map)
1749                 return NULL;
1750
1751         isl_assert(map->ctx, map->n <= 1, goto error);
1752
1753         if (map->n == 0)
1754                 bmap = isl_basic_map_empty_like_map(map);
1755         else
1756                 bmap = isl_basic_map_copy(map->p[0]);
1757
1758         isl_map_free(map);
1759
1760         return bmap;
1761 error:
1762         isl_map_free(map);
1763         return NULL;
1764 }
1765
1766 __isl_give isl_basic_map *isl_basic_map_read_from_file(isl_ctx *ctx,
1767                 FILE *input, int nparam)
1768 {
1769         struct isl_basic_map *bmap;
1770         struct isl_stream *s = isl_stream_new_file(ctx, input);
1771         if (!s)
1772                 return NULL;
1773         bmap = basic_map_read(s, nparam);
1774         isl_stream_free(s);
1775         return bmap;
1776 }
1777
1778 __isl_give isl_basic_set *isl_basic_set_read_from_file(isl_ctx *ctx,
1779                 FILE *input, int nparam)
1780 {
1781         struct isl_basic_map *bmap;
1782         bmap = isl_basic_map_read_from_file(ctx, input, nparam);
1783         if (!bmap)
1784                 return NULL;
1785         isl_assert(ctx, isl_basic_map_n_in(bmap) == 0, goto error);
1786         return (struct isl_basic_set *)bmap;
1787 error:
1788         isl_basic_map_free(bmap);
1789         return NULL;
1790 }
1791
1792 struct isl_basic_map *isl_basic_map_read_from_str(struct isl_ctx *ctx,
1793                 const char *str, int nparam)
1794 {
1795         struct isl_basic_map *bmap;
1796         struct isl_stream *s = isl_stream_new_str(ctx, str);
1797         if (!s)
1798                 return NULL;
1799         bmap = basic_map_read(s, nparam);
1800         isl_stream_free(s);
1801         return bmap;
1802 }
1803
1804 struct isl_basic_set *isl_basic_set_read_from_str(struct isl_ctx *ctx,
1805                 const char *str, int nparam)
1806 {
1807         struct isl_basic_map *bmap;
1808         bmap = isl_basic_map_read_from_str(ctx, str, nparam);
1809         if (!bmap)
1810                 return NULL;
1811         isl_assert(ctx, isl_basic_map_n_in(bmap) == 0, goto error);
1812         return (struct isl_basic_set *)bmap;
1813 error:
1814         isl_basic_map_free(bmap);
1815         return NULL;
1816 }
1817
1818 __isl_give isl_map *isl_map_read_from_file(struct isl_ctx *ctx,
1819                 FILE *input, int nparam)
1820 {
1821         struct isl_map *map;
1822         struct isl_stream *s = isl_stream_new_file(ctx, input);
1823         if (!s)
1824                 return NULL;
1825         map = isl_stream_read_map(s, nparam);
1826         isl_stream_free(s);
1827         return map;
1828 }
1829
1830 __isl_give isl_map *isl_map_read_from_str(struct isl_ctx *ctx,
1831                 const char *str, int nparam)
1832 {
1833         struct isl_map *map;
1834         struct isl_stream *s = isl_stream_new_str(ctx, str);
1835         if (!s)
1836                 return NULL;
1837         map = isl_stream_read_map(s, nparam);
1838         isl_stream_free(s);
1839         return map;
1840 }
1841
1842 __isl_give isl_set *isl_set_read_from_file(struct isl_ctx *ctx,
1843                 FILE *input, int nparam)
1844 {
1845         struct isl_map *map;
1846         map = isl_map_read_from_file(ctx, input, nparam);
1847         if (!map)
1848                 return NULL;
1849         isl_assert(ctx, isl_map_n_in(map) == 0, goto error);
1850         return (struct isl_set *)map;
1851 error:
1852         isl_map_free(map);
1853         return NULL;
1854 }
1855
1856 struct isl_set *isl_set_read_from_str(struct isl_ctx *ctx,
1857                 const char *str, int nparam)
1858 {
1859         struct isl_map *map;
1860         map = isl_map_read_from_str(ctx, str, nparam);
1861         if (!map)
1862                 return NULL;
1863         isl_assert(ctx, isl_map_n_in(map) == 0, goto error);
1864         return (struct isl_set *)map;
1865 error:
1866         isl_map_free(map);
1867         return NULL;
1868 }
1869
1870 static char *next_line(FILE *input, char *line, unsigned len)
1871 {
1872         char *p;
1873
1874         do {
1875                 if (!(p = fgets(line, len, input)))
1876                         return NULL;
1877                 while (isspace(*p) && *p != '\n')
1878                         ++p;
1879         } while (*p == '#' || *p == '\n');
1880
1881         return p;
1882 }
1883
1884 static struct isl_vec *isl_vec_read_from_file_polylib(struct isl_ctx *ctx,
1885                 FILE *input)
1886 {
1887         struct isl_vec *vec = NULL;
1888         char line[1024];
1889         char val[1024];
1890         char *p;
1891         unsigned size;
1892         int j;
1893         int n;
1894         int offset;
1895
1896         isl_assert(ctx, next_line(input, line, sizeof(line)), return NULL);
1897         isl_assert(ctx, sscanf(line, "%u", &size) == 1, return NULL);
1898
1899         vec = isl_vec_alloc(ctx, size);
1900
1901         p = next_line(input, line, sizeof(line));
1902         isl_assert(ctx, p, goto error);
1903
1904         for (j = 0; j < size; ++j) {
1905                 n = sscanf(p, "%s%n", val, &offset);
1906                 isl_assert(ctx, n != 0, goto error);
1907                 isl_int_read(vec->el[j], val);
1908                 p += offset;
1909         }
1910
1911         return vec;
1912 error:
1913         isl_vec_free(vec);
1914         return NULL;
1915 }
1916
1917 struct isl_vec *isl_vec_read_from_file(struct isl_ctx *ctx,
1918                 FILE *input, unsigned input_format)
1919 {
1920         if (input_format == ISL_FORMAT_POLYLIB)
1921                 return isl_vec_read_from_file_polylib(ctx, input);
1922         else
1923                 isl_assert(ctx, 0, return NULL);
1924 }
1925
1926 __isl_give isl_pw_qpolynomial *isl_stream_read_pw_qpolynomial(
1927         struct isl_stream *s)
1928 {
1929         struct isl_obj obj;
1930         struct isl_pw_qpolynomial *pwqp;
1931
1932         obj = obj_read(s, -1);
1933         if (obj.v)
1934                 isl_assert(s->ctx, obj.type == isl_obj_pw_qpolynomial,
1935                            goto error);
1936
1937         return obj.v;
1938 error:
1939         obj.type->free(obj.v);
1940         return NULL;
1941 }
1942
1943 __isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_read_from_str(isl_ctx *ctx,
1944                 const char *str)
1945 {
1946         isl_pw_qpolynomial *pwqp;
1947         struct isl_stream *s = isl_stream_new_str(ctx, str);
1948         if (!s)
1949                 return NULL;
1950         pwqp = isl_stream_read_pw_qpolynomial(s);
1951         isl_stream_free(s);
1952         return pwqp;
1953 }