1 1.1 mrg /* 2 1.1 mrg * Copyright 2008-2009 Katholieke Universiteit Leuven 3 1.1 mrg * Copyright 2010 INRIA Saclay 4 1.1 mrg * Copyright 2012-2013 Ecole Normale Superieure 5 1.1 mrg * Copyright 2019,2022 Cerebras Systems 6 1.1 mrg * 7 1.1 mrg * Use of this software is governed by the MIT license 8 1.1 mrg * 9 1.1 mrg * Written by Sven Verdoolaege, K.U.Leuven, Departement 10 1.1 mrg * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium 11 1.1 mrg * and INRIA Saclay - Ile-de-France, Parc Club Orsay Universite, 12 1.1 mrg * ZAC des vignes, 4 rue Jacques Monod, 91893 Orsay, France 13 1.1 mrg * and Ecole Normale Superieure, 45 rue dUlm, 75230 Paris, France 14 1.1 mrg * and Cerebras Systems, 175 S San Antonio Rd, Los Altos, CA, USA 15 1.1 mrg */ 16 1.1 mrg 17 1.1 mrg #include <ctype.h> 18 1.1 mrg #include <stdio.h> 19 1.1 mrg #include <string.h> 20 1.1 mrg #include <isl_ctx_private.h> 21 1.1 mrg #include <isl_map_private.h> 22 1.1 mrg #include <isl_id_private.h> 23 1.1 mrg #include <isl/set.h> 24 1.1 mrg #include <isl_seq.h> 25 1.1 mrg #include <isl_stream_private.h> 26 1.1 mrg #include <isl/obj.h> 27 1.1 mrg #include "isl_polynomial_private.h" 28 1.1 mrg #include <isl/union_set.h> 29 1.1 mrg #include <isl/union_map.h> 30 1.1 mrg #include <isl_mat_private.h> 31 1.1 mrg #include <isl_aff_private.h> 32 1.1 mrg #include <isl_vec_private.h> 33 1.1 mrg #include <isl/list.h> 34 1.1 mrg #include <isl_val_private.h> 35 1.1 mrg 36 1.1 mrg struct variable { 37 1.1 mrg char *name; 38 1.1 mrg int pos; 39 1.1 mrg struct variable *next; 40 1.1 mrg }; 41 1.1 mrg 42 1.1 mrg struct vars { 43 1.1 mrg struct isl_ctx *ctx; 44 1.1 mrg int n; 45 1.1 mrg struct variable *v; 46 1.1 mrg }; 47 1.1 mrg 48 1.1 mrg static struct vars *vars_new(struct isl_ctx *ctx) 49 1.1 mrg { 50 1.1 mrg struct vars *v; 51 1.1 mrg v = isl_alloc_type(ctx, struct vars); 52 1.1 mrg if (!v) 53 1.1 mrg return NULL; 54 1.1 mrg v->ctx = ctx; 55 1.1 mrg v->n = 0; 56 1.1 mrg v->v = NULL; 57 1.1 mrg return v; 58 1.1 mrg } 59 1.1 mrg 60 1.1 mrg static void variable_free(struct variable *var) 61 1.1 mrg { 62 1.1 mrg while (var) { 63 1.1 mrg struct variable *next = var->next; 64 1.1 mrg free(var->name); 65 1.1 mrg free(var); 66 1.1 mrg var = next; 67 1.1 mrg } 68 1.1 mrg } 69 1.1 mrg 70 1.1 mrg static void vars_free(struct vars *v) 71 1.1 mrg { 72 1.1 mrg if (!v) 73 1.1 mrg return; 74 1.1 mrg variable_free(v->v); 75 1.1 mrg free(v); 76 1.1 mrg } 77 1.1 mrg 78 1.1 mrg static void vars_drop(struct vars *v, int n) 79 1.1 mrg { 80 1.1 mrg struct variable *var; 81 1.1 mrg 82 1.1 mrg if (!v || !v->v) 83 1.1 mrg return; 84 1.1 mrg 85 1.1 mrg v->n -= n; 86 1.1 mrg 87 1.1 mrg var = v->v; 88 1.1 mrg while (--n >= 0) { 89 1.1 mrg struct variable *next = var->next; 90 1.1 mrg free(var->name); 91 1.1 mrg free(var); 92 1.1 mrg var = next; 93 1.1 mrg } 94 1.1 mrg v->v = var; 95 1.1 mrg } 96 1.1 mrg 97 1.1 mrg static struct variable *variable_new(struct vars *v, const char *name, int len, 98 1.1 mrg int pos) 99 1.1 mrg { 100 1.1 mrg struct variable *var; 101 1.1 mrg var = isl_calloc_type(v->ctx, struct variable); 102 1.1 mrg if (!var) 103 1.1 mrg goto error; 104 1.1 mrg var->name = strdup(name); 105 1.1 mrg var->name[len] = '\0'; 106 1.1 mrg var->pos = pos; 107 1.1 mrg var->next = v->v; 108 1.1 mrg return var; 109 1.1 mrg error: 110 1.1 mrg variable_free(v->v); 111 1.1 mrg return NULL; 112 1.1 mrg } 113 1.1 mrg 114 1.1 mrg static int vars_pos(struct vars *v, const char *s, int len) 115 1.1 mrg { 116 1.1 mrg int pos; 117 1.1 mrg struct variable *q; 118 1.1 mrg 119 1.1 mrg if (len == -1) 120 1.1 mrg len = strlen(s); 121 1.1 mrg for (q = v->v; q; q = q->next) { 122 1.1 mrg if (strncmp(q->name, s, len) == 0 && q->name[len] == '\0') 123 1.1 mrg break; 124 1.1 mrg } 125 1.1 mrg if (q) 126 1.1 mrg pos = q->pos; 127 1.1 mrg else { 128 1.1 mrg pos = v->n; 129 1.1 mrg v->v = variable_new(v, s, len, v->n); 130 1.1 mrg if (!v->v) 131 1.1 mrg return -1; 132 1.1 mrg v->n++; 133 1.1 mrg } 134 1.1 mrg return pos; 135 1.1 mrg } 136 1.1 mrg 137 1.1 mrg static int vars_add_anon(struct vars *v) 138 1.1 mrg { 139 1.1 mrg v->v = variable_new(v, "", 0, v->n); 140 1.1 mrg 141 1.1 mrg if (!v->v) 142 1.1 mrg return -1; 143 1.1 mrg v->n++; 144 1.1 mrg 145 1.1 mrg return 0; 146 1.1 mrg } 147 1.1 mrg 148 1.1 mrg /* Obtain next token, with some preprocessing. 149 1.1 mrg * In particular, evaluate expressions of the form x^y, 150 1.1 mrg * with x and y values. 151 1.1 mrg */ 152 1.1 mrg static struct isl_token *next_token(__isl_keep isl_stream *s) 153 1.1 mrg { 154 1.1 mrg struct isl_token *tok, *tok2; 155 1.1 mrg 156 1.1 mrg tok = isl_stream_next_token(s); 157 1.1 mrg if (!tok || tok->type != ISL_TOKEN_VALUE) 158 1.1 mrg return tok; 159 1.1 mrg if (!isl_stream_eat_if_available(s, '^')) 160 1.1 mrg return tok; 161 1.1 mrg tok2 = isl_stream_next_token(s); 162 1.1 mrg if (!tok2 || tok2->type != ISL_TOKEN_VALUE) { 163 1.1 mrg isl_stream_error(s, tok2, "expecting constant value"); 164 1.1 mrg goto error; 165 1.1 mrg } 166 1.1 mrg 167 1.1 mrg isl_int_pow_ui(tok->u.v, tok->u.v, isl_int_get_ui(tok2->u.v)); 168 1.1 mrg 169 1.1 mrg isl_token_free(tok2); 170 1.1 mrg return tok; 171 1.1 mrg error: 172 1.1 mrg isl_token_free(tok); 173 1.1 mrg isl_token_free(tok2); 174 1.1 mrg return NULL; 175 1.1 mrg } 176 1.1 mrg 177 1.1 mrg /* Read an isl_val from "s". 178 1.1 mrg * 179 1.1 mrg * The following token sequences are recognized 180 1.1 mrg * 181 1.1 mrg * "infty" -> infty 182 1.1 mrg * "-" "infty" -> -infty 183 1.1 mrg * "NaN" -> NaN 184 1.1 mrg * n "/" d -> n/d 185 1.1 mrg * "-" n "/" d -> -n/d 186 1.1 mrg * v -> v 187 1.1 mrg * "-" v -> -v 188 1.1 mrg * 189 1.1 mrg * where n, d and v are integer constants. 190 1.1 mrg */ 191 1.1 mrg __isl_give isl_val *isl_stream_read_val(__isl_keep isl_stream *s) 192 1.1 mrg { 193 1.1 mrg struct isl_token *tok = NULL; 194 1.1 mrg struct isl_token *tok2 = NULL; 195 1.1 mrg int sign = 1; 196 1.1 mrg isl_val *val; 197 1.1 mrg 198 1.1 mrg if (isl_stream_eat_if_available(s, '-')) 199 1.1 mrg sign = -1; 200 1.1 mrg tok = next_token(s); 201 1.1 mrg if (!tok) { 202 1.1 mrg isl_stream_error(s, NULL, "unexpected EOF"); 203 1.1 mrg goto error; 204 1.1 mrg } 205 1.1 mrg if (tok->type == ISL_TOKEN_INFTY) { 206 1.1 mrg isl_token_free(tok); 207 1.1 mrg if (sign > 0) 208 1.1 mrg return isl_val_infty(s->ctx); 209 1.1 mrg else 210 1.1 mrg return isl_val_neginfty(s->ctx); 211 1.1 mrg } 212 1.1 mrg if (sign > 0 && tok->type == ISL_TOKEN_NAN) { 213 1.1 mrg isl_token_free(tok); 214 1.1 mrg return isl_val_nan(s->ctx); 215 1.1 mrg } 216 1.1 mrg if (tok->type != ISL_TOKEN_VALUE) { 217 1.1 mrg isl_stream_error(s, tok, "expecting value"); 218 1.1 mrg goto error; 219 1.1 mrg } 220 1.1 mrg 221 1.1 mrg if (sign < 0) 222 1.1 mrg isl_int_neg(tok->u.v, tok->u.v); 223 1.1 mrg 224 1.1 mrg if (isl_stream_eat_if_available(s, '/')) { 225 1.1 mrg tok2 = next_token(s); 226 1.1 mrg if (!tok2) { 227 1.1 mrg isl_stream_error(s, NULL, "unexpected EOF"); 228 1.1 mrg goto error; 229 1.1 mrg } 230 1.1 mrg if (tok2->type != ISL_TOKEN_VALUE) { 231 1.1 mrg isl_stream_error(s, tok2, "expecting value"); 232 1.1 mrg goto error; 233 1.1 mrg } 234 1.1 mrg val = isl_val_rat_from_isl_int(s->ctx, tok->u.v, tok2->u.v); 235 1.1 mrg val = isl_val_normalize(val); 236 1.1 mrg } else { 237 1.1 mrg val = isl_val_int_from_isl_int(s->ctx, tok->u.v); 238 1.1 mrg } 239 1.1 mrg 240 1.1 mrg isl_token_free(tok); 241 1.1 mrg isl_token_free(tok2); 242 1.1 mrg return val; 243 1.1 mrg error: 244 1.1 mrg isl_token_free(tok); 245 1.1 mrg isl_token_free(tok2); 246 1.1 mrg return NULL; 247 1.1 mrg } 248 1.1 mrg 249 1.1 mrg #undef TYPE_BASE 250 1.1 mrg #define TYPE_BASE val 251 1.1 mrg #include "isl_read_from_str_templ.c" 252 1.1 mrg 253 1.1 mrg static isl_stat accept_cst_factor(__isl_keep isl_stream *s, isl_int *f) 254 1.1 mrg { 255 1.1 mrg struct isl_token *tok; 256 1.1 mrg 257 1.1 mrg if (isl_stream_eat_if_available(s, '-')) 258 1.1 mrg isl_int_neg(*f, *f); 259 1.1 mrg tok = next_token(s); 260 1.1 mrg if (!tok || tok->type != ISL_TOKEN_VALUE) { 261 1.1 mrg isl_stream_error(s, tok, "expecting constant value"); 262 1.1 mrg goto error; 263 1.1 mrg } 264 1.1 mrg 265 1.1 mrg isl_int_mul(*f, *f, tok->u.v); 266 1.1 mrg 267 1.1 mrg isl_token_free(tok); 268 1.1 mrg 269 1.1 mrg if (isl_stream_eat_if_available(s, '*')) 270 1.1 mrg return accept_cst_factor(s, f); 271 1.1 mrg 272 1.1 mrg return isl_stat_ok; 273 1.1 mrg error: 274 1.1 mrg isl_token_free(tok); 275 1.1 mrg return isl_stat_error; 276 1.1 mrg } 277 1.1 mrg 278 1.1 mrg /* Given an affine expression aff, return an affine expression 279 1.1 mrg * for aff % d, with d the next token on the stream, which is 280 1.1 mrg * assumed to be a constant. 281 1.1 mrg * 282 1.1 mrg * We introduce an integer division q = [aff/d] and the result 283 1.1 mrg * is set to aff - d q. 284 1.1 mrg */ 285 1.1 mrg static __isl_give isl_pw_aff *affine_mod(__isl_keep isl_stream *s, 286 1.1 mrg struct vars *v, __isl_take isl_pw_aff *aff) 287 1.1 mrg { 288 1.1 mrg struct isl_token *tok; 289 1.1 mrg isl_pw_aff *q; 290 1.1 mrg 291 1.1 mrg tok = next_token(s); 292 1.1 mrg if (!tok || tok->type != ISL_TOKEN_VALUE) { 293 1.1 mrg isl_stream_error(s, tok, "expecting constant value"); 294 1.1 mrg goto error; 295 1.1 mrg } 296 1.1 mrg 297 1.1 mrg q = isl_pw_aff_copy(aff); 298 1.1 mrg q = isl_pw_aff_scale_down(q, tok->u.v); 299 1.1 mrg q = isl_pw_aff_floor(q); 300 1.1 mrg q = isl_pw_aff_scale(q, tok->u.v); 301 1.1 mrg 302 1.1 mrg aff = isl_pw_aff_sub(aff, q); 303 1.1 mrg 304 1.1 mrg isl_token_free(tok); 305 1.1 mrg return aff; 306 1.1 mrg error: 307 1.1 mrg isl_pw_aff_free(aff); 308 1.1 mrg isl_token_free(tok); 309 1.1 mrg return NULL; 310 1.1 mrg } 311 1.1 mrg 312 1.1 mrg static __isl_give isl_pw_aff *accept_affine(__isl_keep isl_stream *s, 313 1.1 mrg __isl_take isl_space *space, struct vars *v); 314 1.1 mrg static __isl_give isl_pw_aff_list *accept_affine_list(__isl_keep isl_stream *s, 315 1.1 mrg __isl_take isl_space *space, struct vars *v); 316 1.1 mrg 317 1.1 mrg static __isl_give isl_pw_aff *accept_minmax(__isl_keep isl_stream *s, 318 1.1 mrg __isl_take isl_space *space, struct vars *v) 319 1.1 mrg { 320 1.1 mrg struct isl_token *tok; 321 1.1 mrg isl_pw_aff_list *list = NULL; 322 1.1 mrg int min; 323 1.1 mrg 324 1.1 mrg tok = isl_stream_next_token(s); 325 1.1 mrg if (!tok) 326 1.1 mrg goto error; 327 1.1 mrg min = tok->type == ISL_TOKEN_MIN; 328 1.1 mrg isl_token_free(tok); 329 1.1 mrg 330 1.1 mrg if (isl_stream_eat(s, '(')) 331 1.1 mrg goto error; 332 1.1 mrg 333 1.1 mrg list = accept_affine_list(s, isl_space_copy(space), v); 334 1.1 mrg if (!list) 335 1.1 mrg goto error; 336 1.1 mrg 337 1.1 mrg if (isl_stream_eat(s, ')')) 338 1.1 mrg goto error; 339 1.1 mrg 340 1.1 mrg isl_space_free(space); 341 1.1 mrg return min ? isl_pw_aff_list_min(list) : isl_pw_aff_list_max(list); 342 1.1 mrg error: 343 1.1 mrg isl_space_free(space); 344 1.1 mrg isl_pw_aff_list_free(list); 345 1.1 mrg return NULL; 346 1.1 mrg } 347 1.1 mrg 348 1.1 mrg /* Divide "pa" by an integer constant read from the stream. 349 1.1 mrg */ 350 1.1 mrg static __isl_give isl_pw_aff *pw_aff_div_by_cst(__isl_keep isl_stream *s, 351 1.1 mrg __isl_take isl_pw_aff *pa) 352 1.1 mrg { 353 1.1 mrg struct isl_token *tok; 354 1.1 mrg 355 1.1 mrg tok = next_token(s); 356 1.1 mrg if (!tok || tok->type != ISL_TOKEN_VALUE) { 357 1.1 mrg isl_stream_error(s, tok, "expecting denominator"); 358 1.1 mrg isl_token_free(tok); 359 1.1 mrg return isl_pw_aff_free(pa); 360 1.1 mrg } 361 1.1 mrg 362 1.1 mrg pa = isl_pw_aff_scale_down(pa, tok->u.v); 363 1.1 mrg 364 1.1 mrg isl_token_free(tok); 365 1.1 mrg 366 1.1 mrg return pa; 367 1.1 mrg } 368 1.1 mrg 369 1.1 mrg /* Return the (signed) value that is next on the stream, 370 1.1 mrg * using "next" to read the next token and printing "msg" in case of an error. 371 1.1 mrg */ 372 1.1 mrg static struct isl_token *next_signed_value_fn(__isl_keep isl_stream *s, 373 1.1 mrg struct isl_token *(*next)(__isl_keep isl_stream *s), char *msg) 374 1.1 mrg { 375 1.1 mrg struct isl_token *tok; 376 1.1 mrg int sign = 1; 377 1.1 mrg 378 1.1 mrg if (isl_stream_eat_if_available(s, '-')) 379 1.1 mrg sign = -1; 380 1.1 mrg tok = next(s); 381 1.1 mrg if (!tok || tok->type != ISL_TOKEN_VALUE) { 382 1.1 mrg isl_stream_error(s, tok, msg); 383 1.1 mrg isl_token_free(tok); 384 1.1 mrg return NULL; 385 1.1 mrg } 386 1.1 mrg if (sign < 0) 387 1.1 mrg isl_int_neg(tok->u.v, tok->u.v); 388 1.1 mrg return tok; 389 1.1 mrg } 390 1.1 mrg 391 1.1 mrg /* Return the (signed) value that is next on the stream, 392 1.1 mrg * printing "msg" in case of an error. 393 1.1 mrg */ 394 1.1 mrg static struct isl_token *next_signed_value(__isl_keep isl_stream *s, char *msg) 395 1.1 mrg { 396 1.1 mrg return next_signed_value_fn(s, &isl_stream_next_token, msg); 397 1.1 mrg } 398 1.1 mrg 399 1.1 mrg /* Return the (signed) value that is next on the stream, 400 1.1 mrg * provided it is on the same line, 401 1.1 mrg * printing "msg" in case of an error. 402 1.1 mrg */ 403 1.1 mrg static struct isl_token *next_signed_value_on_same_line( 404 1.1 mrg __isl_keep isl_stream *s, char *msg) 405 1.1 mrg { 406 1.1 mrg return next_signed_value_fn(s, 407 1.1 mrg &isl_stream_next_token_on_same_line, msg); 408 1.1 mrg } 409 1.1 mrg 410 1.1 mrg /* Is "tok" the start of an integer division? 411 1.1 mrg */ 412 1.1 mrg static int is_start_of_div(struct isl_token *tok) 413 1.1 mrg { 414 1.1 mrg if (!tok) 415 1.1 mrg return 0; 416 1.1 mrg if (tok->type == '[') 417 1.1 mrg return 1; 418 1.1 mrg if (tok->type == ISL_TOKEN_FLOOR) 419 1.1 mrg return 1; 420 1.1 mrg if (tok->type == ISL_TOKEN_CEIL) 421 1.1 mrg return 1; 422 1.1 mrg if (tok->type == ISL_TOKEN_FLOORD) 423 1.1 mrg return 1; 424 1.1 mrg if (tok->type == ISL_TOKEN_CEILD) 425 1.1 mrg return 1; 426 1.1 mrg return 0; 427 1.1 mrg } 428 1.1 mrg 429 1.1 mrg /* Read an integer division from "s" and return it as an isl_pw_aff. 430 1.1 mrg * 431 1.1 mrg * The integer division can be of the form 432 1.1 mrg * 433 1.1 mrg * [<affine expression>] 434 1.1 mrg * floor(<affine expression>) 435 1.1 mrg * ceil(<affine expression>) 436 1.1 mrg * floord(<affine expression>,<denominator>) 437 1.1 mrg * ceild(<affine expression>,<denominator>) 438 1.1 mrg */ 439 1.1 mrg static __isl_give isl_pw_aff *accept_div(__isl_keep isl_stream *s, 440 1.1 mrg __isl_take isl_space *space, struct vars *v) 441 1.1 mrg { 442 1.1 mrg int f = 0; 443 1.1 mrg int c = 0; 444 1.1 mrg int extra = 0; 445 1.1 mrg isl_pw_aff *pwaff = NULL; 446 1.1 mrg 447 1.1 mrg if (isl_stream_eat_if_available(s, ISL_TOKEN_FLOORD)) 448 1.1 mrg extra = f = 1; 449 1.1 mrg else if (isl_stream_eat_if_available(s, ISL_TOKEN_CEILD)) 450 1.1 mrg extra = c = 1; 451 1.1 mrg else if (isl_stream_eat_if_available(s, ISL_TOKEN_FLOOR)) 452 1.1 mrg f = 1; 453 1.1 mrg else if (isl_stream_eat_if_available(s, ISL_TOKEN_CEIL)) 454 1.1 mrg c = 1; 455 1.1 mrg if (f || c) { 456 1.1 mrg if (isl_stream_eat(s, '(')) 457 1.1 mrg goto error; 458 1.1 mrg } else { 459 1.1 mrg if (isl_stream_eat(s, '[')) 460 1.1 mrg goto error; 461 1.1 mrg } 462 1.1 mrg 463 1.1 mrg pwaff = accept_affine(s, isl_space_copy(space), v); 464 1.1 mrg 465 1.1 mrg if (extra) { 466 1.1 mrg if (isl_stream_eat(s, ',')) 467 1.1 mrg goto error; 468 1.1 mrg 469 1.1 mrg pwaff = pw_aff_div_by_cst(s, pwaff); 470 1.1 mrg } 471 1.1 mrg 472 1.1 mrg if (c) 473 1.1 mrg pwaff = isl_pw_aff_ceil(pwaff); 474 1.1 mrg else 475 1.1 mrg pwaff = isl_pw_aff_floor(pwaff); 476 1.1 mrg 477 1.1 mrg if (f || c) { 478 1.1 mrg if (isl_stream_eat(s, ')')) 479 1.1 mrg goto error; 480 1.1 mrg } else { 481 1.1 mrg if (isl_stream_eat(s, ']')) 482 1.1 mrg goto error; 483 1.1 mrg } 484 1.1 mrg 485 1.1 mrg isl_space_free(space); 486 1.1 mrg return pwaff; 487 1.1 mrg error: 488 1.1 mrg isl_space_free(space); 489 1.1 mrg isl_pw_aff_free(pwaff); 490 1.1 mrg return NULL; 491 1.1 mrg } 492 1.1 mrg 493 1.1 mrg static __isl_give isl_pw_aff *accept_affine_factor(__isl_keep isl_stream *s, 494 1.1 mrg __isl_take isl_space *space, struct vars *v) 495 1.1 mrg { 496 1.1 mrg struct isl_token *tok = NULL; 497 1.1 mrg isl_pw_aff *res = NULL; 498 1.1 mrg 499 1.1 mrg tok = next_token(s); 500 1.1 mrg if (!tok) { 501 1.1 mrg isl_stream_error(s, NULL, "unexpected EOF"); 502 1.1 mrg goto error; 503 1.1 mrg } 504 1.1 mrg 505 1.1 mrg if (tok->type == ISL_TOKEN_AFF) { 506 1.1 mrg res = isl_pw_aff_copy(tok->u.pwaff); 507 1.1 mrg isl_token_free(tok); 508 1.1 mrg } else if (tok->type == ISL_TOKEN_IDENT) { 509 1.1 mrg int n = v->n; 510 1.1 mrg int pos = vars_pos(v, tok->u.s, -1); 511 1.1 mrg isl_aff *aff; 512 1.1 mrg 513 1.1 mrg if (pos < 0) 514 1.1 mrg goto error; 515 1.1 mrg if (pos >= n) { 516 1.1 mrg vars_drop(v, v->n - n); 517 1.1 mrg isl_stream_error(s, tok, "unknown identifier"); 518 1.1 mrg goto error; 519 1.1 mrg } 520 1.1 mrg 521 1.1 mrg aff = isl_aff_zero_on_domain(isl_local_space_from_space(isl_space_copy(space))); 522 1.1 mrg if (!aff) 523 1.1 mrg goto error; 524 1.1 mrg aff->v = isl_vec_set_element_si(aff->v, 2 + pos, 1); 525 1.1 mrg if (!aff->v) 526 1.1 mrg aff = isl_aff_free(aff); 527 1.1 mrg res = isl_pw_aff_from_aff(aff); 528 1.1 mrg isl_token_free(tok); 529 1.1 mrg } else if (tok->type == ISL_TOKEN_VALUE) { 530 1.1 mrg if (isl_stream_eat_if_available(s, '*') || 531 1.1 mrg isl_stream_next_token_is(s, ISL_TOKEN_IDENT)) { 532 1.1 mrg if (isl_stream_eat_if_available(s, '-')) 533 1.1 mrg isl_int_neg(tok->u.v, tok->u.v); 534 1.1 mrg res = accept_affine_factor(s, isl_space_copy(space), v); 535 1.1 mrg res = isl_pw_aff_scale(res, tok->u.v); 536 1.1 mrg } else { 537 1.1 mrg isl_local_space *ls; 538 1.1 mrg isl_aff *aff; 539 1.1 mrg ls = isl_local_space_from_space(isl_space_copy(space)); 540 1.1 mrg aff = isl_aff_zero_on_domain(ls); 541 1.1 mrg aff = isl_aff_add_constant(aff, tok->u.v); 542 1.1 mrg res = isl_pw_aff_from_aff(aff); 543 1.1 mrg } 544 1.1 mrg isl_token_free(tok); 545 1.1 mrg } else if (tok->type == '(') { 546 1.1 mrg isl_token_free(tok); 547 1.1 mrg tok = NULL; 548 1.1 mrg res = accept_affine(s, isl_space_copy(space), v); 549 1.1 mrg if (!res) 550 1.1 mrg goto error; 551 1.1 mrg if (isl_stream_eat(s, ')')) 552 1.1 mrg goto error; 553 1.1 mrg } else if (is_start_of_div(tok)) { 554 1.1 mrg isl_stream_push_token(s, tok); 555 1.1 mrg tok = NULL; 556 1.1 mrg res = accept_div(s, isl_space_copy(space), v); 557 1.1 mrg } else if (tok->type == ISL_TOKEN_MIN || tok->type == ISL_TOKEN_MAX) { 558 1.1 mrg isl_stream_push_token(s, tok); 559 1.1 mrg tok = NULL; 560 1.1 mrg res = accept_minmax(s, isl_space_copy(space), v); 561 1.1 mrg } else { 562 1.1 mrg isl_stream_error(s, tok, "expecting factor"); 563 1.1 mrg goto error; 564 1.1 mrg } 565 1.1 mrg if (isl_stream_eat_if_available(s, '%') || 566 1.1 mrg isl_stream_eat_if_available(s, ISL_TOKEN_MOD)) { 567 1.1 mrg isl_space_free(space); 568 1.1 mrg return affine_mod(s, v, res); 569 1.1 mrg } 570 1.1 mrg if (isl_stream_eat_if_available(s, '*')) { 571 1.1 mrg isl_int f; 572 1.1 mrg isl_int_init(f); 573 1.1 mrg isl_int_set_si(f, 1); 574 1.1 mrg if (accept_cst_factor(s, &f) < 0) { 575 1.1 mrg isl_int_clear(f); 576 1.1 mrg goto error2; 577 1.1 mrg } 578 1.1 mrg res = isl_pw_aff_scale(res, f); 579 1.1 mrg isl_int_clear(f); 580 1.1 mrg } 581 1.1 mrg if (isl_stream_eat_if_available(s, '/')) 582 1.1 mrg res = pw_aff_div_by_cst(s, res); 583 1.1 mrg if (isl_stream_eat_if_available(s, ISL_TOKEN_INT_DIV)) 584 1.1 mrg res = isl_pw_aff_floor(pw_aff_div_by_cst(s, res)); 585 1.1 mrg 586 1.1 mrg isl_space_free(space); 587 1.1 mrg return res; 588 1.1 mrg error: 589 1.1 mrg isl_token_free(tok); 590 1.1 mrg error2: 591 1.1 mrg isl_pw_aff_free(res); 592 1.1 mrg isl_space_free(space); 593 1.1 mrg return NULL; 594 1.1 mrg } 595 1.1 mrg 596 1.1 mrg /* Return a piecewise affine expression defined on the specified domain 597 1.1 mrg * that represents NaN. 598 1.1 mrg */ 599 1.1 mrg static __isl_give isl_pw_aff *nan_on_domain(__isl_keep isl_space *space) 600 1.1 mrg { 601 1.1 mrg return isl_pw_aff_nan_on_domain_space(isl_space_copy(space)); 602 1.1 mrg } 603 1.1 mrg 604 1.1 mrg static __isl_give isl_pw_aff *accept_affine(__isl_keep isl_stream *s, 605 1.1 mrg __isl_take isl_space *space, struct vars *v) 606 1.1 mrg { 607 1.1 mrg struct isl_token *tok = NULL; 608 1.1 mrg isl_local_space *ls; 609 1.1 mrg isl_pw_aff *res; 610 1.1 mrg int op = 1; 611 1.1 mrg int sign = 1; 612 1.1 mrg 613 1.1 mrg ls = isl_local_space_from_space(isl_space_copy(space)); 614 1.1 mrg res = isl_pw_aff_from_aff(isl_aff_zero_on_domain(ls)); 615 1.1 mrg if (!res) 616 1.1 mrg goto error; 617 1.1 mrg 618 1.1 mrg for (;;) { 619 1.1 mrg tok = next_token(s); 620 1.1 mrg if (!tok) { 621 1.1 mrg isl_stream_error(s, NULL, "unexpected EOF"); 622 1.1 mrg goto error; 623 1.1 mrg } 624 1.1 mrg if (tok->type == '-') { 625 1.1 mrg sign = -sign; 626 1.1 mrg isl_token_free(tok); 627 1.1 mrg continue; 628 1.1 mrg } 629 1.1 mrg if (tok->type == '(' || is_start_of_div(tok) || 630 1.1 mrg tok->type == ISL_TOKEN_MIN || tok->type == ISL_TOKEN_MAX || 631 1.1 mrg tok->type == ISL_TOKEN_IDENT || 632 1.1 mrg tok->type == ISL_TOKEN_VALUE || 633 1.1 mrg tok->type == ISL_TOKEN_AFF) { 634 1.1 mrg isl_pw_aff *term; 635 1.1 mrg if (tok->type == ISL_TOKEN_VALUE && sign < 0) { 636 1.1 mrg isl_int_neg(tok->u.v, tok->u.v); 637 1.1 mrg sign = 1; 638 1.1 mrg } 639 1.1 mrg isl_stream_push_token(s, tok); 640 1.1 mrg tok = NULL; 641 1.1 mrg term = accept_affine_factor(s, 642 1.1 mrg isl_space_copy(space), v); 643 1.1 mrg if (op * sign < 0) 644 1.1 mrg res = isl_pw_aff_sub(res, term); 645 1.1 mrg else 646 1.1 mrg res = isl_pw_aff_add(res, term); 647 1.1 mrg if (!res) 648 1.1 mrg goto error; 649 1.1 mrg } else if (tok->type == ISL_TOKEN_NAN) { 650 1.1 mrg res = isl_pw_aff_add(res, nan_on_domain(space)); 651 1.1 mrg } else { 652 1.1 mrg isl_stream_error(s, tok, "unexpected isl_token"); 653 1.1 mrg isl_stream_push_token(s, tok); 654 1.1 mrg isl_pw_aff_free(res); 655 1.1 mrg isl_space_free(space); 656 1.1 mrg return NULL; 657 1.1 mrg } 658 1.1 mrg isl_token_free(tok); 659 1.1 mrg 660 1.1 mrg tok = next_token(s); 661 1.1 mrg sign = 1; 662 1.1 mrg if (tok && tok->type == '-') { 663 1.1 mrg op = -1; 664 1.1 mrg isl_token_free(tok); 665 1.1 mrg } else if (tok && tok->type == '+') { 666 1.1 mrg op = 1; 667 1.1 mrg isl_token_free(tok); 668 1.1 mrg } else { 669 1.1 mrg if (tok) 670 1.1 mrg isl_stream_push_token(s, tok); 671 1.1 mrg break; 672 1.1 mrg } 673 1.1 mrg } 674 1.1 mrg 675 1.1 mrg isl_space_free(space); 676 1.1 mrg return res; 677 1.1 mrg error: 678 1.1 mrg isl_space_free(space); 679 1.1 mrg isl_token_free(tok); 680 1.1 mrg isl_pw_aff_free(res); 681 1.1 mrg return NULL; 682 1.1 mrg } 683 1.1 mrg 684 1.1 mrg /* Is "type" the type of a comparison operator between lists 685 1.1 mrg * of affine expressions? 686 1.1 mrg */ 687 1.1 mrg static int is_list_comparator_type(int type) 688 1.1 mrg { 689 1.1 mrg switch (type) { 690 1.1 mrg case ISL_TOKEN_LEX_LT: 691 1.1 mrg case ISL_TOKEN_LEX_GT: 692 1.1 mrg case ISL_TOKEN_LEX_LE: 693 1.1 mrg case ISL_TOKEN_LEX_GE: 694 1.1 mrg return 1; 695 1.1 mrg default: 696 1.1 mrg return 0; 697 1.1 mrg } 698 1.1 mrg } 699 1.1 mrg 700 1.1 mrg static int is_comparator(struct isl_token *tok) 701 1.1 mrg { 702 1.1 mrg if (!tok) 703 1.1 mrg return 0; 704 1.1 mrg if (is_list_comparator_type(tok->type)) 705 1.1 mrg return 1; 706 1.1 mrg 707 1.1 mrg switch (tok->type) { 708 1.1 mrg case ISL_TOKEN_LT: 709 1.1 mrg case ISL_TOKEN_GT: 710 1.1 mrg case ISL_TOKEN_LE: 711 1.1 mrg case ISL_TOKEN_GE: 712 1.1 mrg case ISL_TOKEN_NE: 713 1.1 mrg case '=': 714 1.1 mrg return 1; 715 1.1 mrg default: 716 1.1 mrg return 0; 717 1.1 mrg } 718 1.1 mrg } 719 1.1 mrg 720 1.1 mrg static __isl_give isl_map *read_formula(__isl_keep isl_stream *s, 721 1.1 mrg struct vars *v, __isl_take isl_map *map, int rational); 722 1.1 mrg static __isl_give isl_pw_aff *accept_extended_affine(__isl_keep isl_stream *s, 723 1.1 mrg __isl_take isl_space *space, struct vars *v, int rational); 724 1.1 mrg 725 1.1 mrg /* Accept a ternary operator, given the first argument. 726 1.1 mrg */ 727 1.1 mrg static __isl_give isl_pw_aff *accept_ternary(__isl_keep isl_stream *s, 728 1.1 mrg __isl_take isl_map *cond, struct vars *v, int rational) 729 1.1 mrg { 730 1.1 mrg isl_space *space; 731 1.1 mrg isl_pw_aff *pwaff1 = NULL, *pwaff2 = NULL, *pa_cond; 732 1.1 mrg 733 1.1 mrg if (!cond) 734 1.1 mrg return NULL; 735 1.1 mrg 736 1.1 mrg if (isl_stream_eat(s, '?')) 737 1.1 mrg goto error; 738 1.1 mrg 739 1.1 mrg space = isl_space_wrap(isl_map_get_space(cond)); 740 1.1 mrg pwaff1 = accept_extended_affine(s, space, v, rational); 741 1.1 mrg if (!pwaff1) 742 1.1 mrg goto error; 743 1.1 mrg 744 1.1 mrg if (isl_stream_eat(s, ':')) 745 1.1 mrg goto error; 746 1.1 mrg 747 1.1 mrg space = isl_pw_aff_get_domain_space(pwaff1); 748 1.1 mrg pwaff2 = accept_extended_affine(s, space, v, rational); 749 1.1 mrg if (!pwaff2) 750 1.1 mrg goto error; 751 1.1 mrg 752 1.1 mrg pa_cond = isl_set_indicator_function(isl_map_wrap(cond)); 753 1.1 mrg return isl_pw_aff_cond(pa_cond, pwaff1, pwaff2); 754 1.1 mrg error: 755 1.1 mrg isl_map_free(cond); 756 1.1 mrg isl_pw_aff_free(pwaff1); 757 1.1 mrg isl_pw_aff_free(pwaff2); 758 1.1 mrg return NULL; 759 1.1 mrg } 760 1.1 mrg 761 1.1 mrg /* Set *line and *col to those of the next token, if any. 762 1.1 mrg */ 763 1.1 mrg static void set_current_line_col(__isl_keep isl_stream *s, int *line, int *col) 764 1.1 mrg { 765 1.1 mrg struct isl_token *tok; 766 1.1 mrg 767 1.1 mrg tok = isl_stream_next_token(s); 768 1.1 mrg if (!tok) 769 1.1 mrg return; 770 1.1 mrg 771 1.1 mrg *line = tok->line; 772 1.1 mrg *col = tok->col; 773 1.1 mrg isl_stream_push_token(s, tok); 774 1.1 mrg } 775 1.1 mrg 776 1.1 mrg /* Push a token encapsulating "pa" onto "s", with the given 777 1.1 mrg * line and column. 778 1.1 mrg */ 779 1.1 mrg static isl_stat push_aff(__isl_keep isl_stream *s, int line, int col, 780 1.1 mrg __isl_take isl_pw_aff *pa) 781 1.1 mrg { 782 1.1 mrg struct isl_token *tok; 783 1.1 mrg 784 1.1 mrg tok = isl_token_new(s->ctx, line, col, 0); 785 1.1 mrg if (!tok) 786 1.1 mrg goto error; 787 1.1 mrg tok->type = ISL_TOKEN_AFF; 788 1.1 mrg tok->u.pwaff = pa; 789 1.1 mrg isl_stream_push_token(s, tok); 790 1.1 mrg 791 1.1 mrg return isl_stat_ok; 792 1.1 mrg error: 793 1.1 mrg isl_pw_aff_free(pa); 794 1.1 mrg return isl_stat_error; 795 1.1 mrg } 796 1.1 mrg 797 1.1 mrg /* Is the next token a comparison operator? 798 1.1 mrg */ 799 1.1 mrg static int next_is_comparator(__isl_keep isl_stream *s) 800 1.1 mrg { 801 1.1 mrg int is_comp; 802 1.1 mrg struct isl_token *tok; 803 1.1 mrg 804 1.1 mrg tok = isl_stream_next_token(s); 805 1.1 mrg if (!tok) 806 1.1 mrg return 0; 807 1.1 mrg 808 1.1 mrg is_comp = is_comparator(tok); 809 1.1 mrg isl_stream_push_token(s, tok); 810 1.1 mrg 811 1.1 mrg return is_comp; 812 1.1 mrg } 813 1.1 mrg 814 1.1 mrg /* Accept an affine expression that may involve ternary operators. 815 1.1 mrg * We first read an affine expression. 816 1.1 mrg * If it is not followed by a comparison operator, we simply return it. 817 1.1 mrg * Otherwise, we assume the affine expression is part of the first 818 1.1 mrg * argument of a ternary operator and try to parse that. 819 1.1 mrg */ 820 1.1 mrg static __isl_give isl_pw_aff *accept_extended_affine(__isl_keep isl_stream *s, 821 1.1 mrg __isl_take isl_space *space, struct vars *v, int rational) 822 1.1 mrg { 823 1.1 mrg isl_map *cond; 824 1.1 mrg isl_pw_aff *pwaff; 825 1.1 mrg int line = -1, col = -1; 826 1.1 mrg 827 1.1 mrg set_current_line_col(s, &line, &col); 828 1.1 mrg 829 1.1 mrg pwaff = accept_affine(s, space, v); 830 1.1 mrg if (rational) 831 1.1 mrg pwaff = isl_pw_aff_set_rational(pwaff); 832 1.1 mrg if (!pwaff) 833 1.1 mrg return NULL; 834 1.1 mrg if (!next_is_comparator(s)) 835 1.1 mrg return pwaff; 836 1.1 mrg 837 1.1 mrg space = isl_pw_aff_get_domain_space(pwaff); 838 1.1 mrg cond = isl_map_universe(isl_space_unwrap(space)); 839 1.1 mrg 840 1.1 mrg if (push_aff(s, line, col, pwaff) < 0) 841 1.1 mrg cond = isl_map_free(cond); 842 1.1 mrg if (!cond) 843 1.1 mrg return NULL; 844 1.1 mrg 845 1.1 mrg cond = read_formula(s, v, cond, rational); 846 1.1 mrg 847 1.1 mrg return accept_ternary(s, cond, v, rational); 848 1.1 mrg } 849 1.1 mrg 850 1.1 mrg static __isl_give isl_map *read_var_def(__isl_keep isl_stream *s, 851 1.1 mrg __isl_take isl_map *map, enum isl_dim_type type, struct vars *v, 852 1.1 mrg int rational) 853 1.1 mrg { 854 1.1 mrg isl_pw_aff *def; 855 1.1 mrg isl_size pos; 856 1.1 mrg isl_map *def_map; 857 1.1 mrg 858 1.1 mrg if (type == isl_dim_param) 859 1.1 mrg pos = isl_map_dim(map, isl_dim_param); 860 1.1 mrg else { 861 1.1 mrg pos = isl_map_dim(map, isl_dim_in); 862 1.1 mrg if (type == isl_dim_out) { 863 1.1 mrg isl_size n_out = isl_map_dim(map, isl_dim_out); 864 1.1 mrg if (pos < 0 || n_out < 0) 865 1.1 mrg return isl_map_free(map); 866 1.1 mrg pos += n_out; 867 1.1 mrg } 868 1.1 mrg type = isl_dim_in; 869 1.1 mrg } 870 1.1 mrg if (pos < 0) 871 1.1 mrg return isl_map_free(map); 872 1.1 mrg --pos; 873 1.1 mrg 874 1.1 mrg def = accept_extended_affine(s, isl_space_wrap(isl_map_get_space(map)), 875 1.1 mrg v, rational); 876 1.1 mrg def_map = isl_map_from_pw_aff(def); 877 1.1 mrg def_map = isl_map_equate(def_map, type, pos, isl_dim_out, 0); 878 1.1 mrg def_map = isl_set_unwrap(isl_map_domain(def_map)); 879 1.1 mrg 880 1.1 mrg map = isl_map_intersect(map, def_map); 881 1.1 mrg 882 1.1 mrg return map; 883 1.1 mrg } 884 1.1 mrg 885 1.1 mrg static __isl_give isl_pw_aff_list *accept_affine_list(__isl_keep isl_stream *s, 886 1.1 mrg __isl_take isl_space *space, struct vars *v) 887 1.1 mrg { 888 1.1 mrg isl_pw_aff *pwaff; 889 1.1 mrg isl_pw_aff_list *list; 890 1.1 mrg struct isl_token *tok = NULL; 891 1.1 mrg 892 1.1 mrg pwaff = accept_affine(s, isl_space_copy(space), v); 893 1.1 mrg list = isl_pw_aff_list_from_pw_aff(pwaff); 894 1.1 mrg if (!list) 895 1.1 mrg goto error; 896 1.1 mrg 897 1.1 mrg for (;;) { 898 1.1 mrg tok = isl_stream_next_token(s); 899 1.1 mrg if (!tok) { 900 1.1 mrg isl_stream_error(s, NULL, "unexpected EOF"); 901 1.1 mrg goto error; 902 1.1 mrg } 903 1.1 mrg if (tok->type != ',') { 904 1.1 mrg isl_stream_push_token(s, tok); 905 1.1 mrg break; 906 1.1 mrg } 907 1.1 mrg isl_token_free(tok); 908 1.1 mrg 909 1.1 mrg pwaff = accept_affine(s, isl_space_copy(space), v); 910 1.1 mrg list = isl_pw_aff_list_concat(list, 911 1.1 mrg isl_pw_aff_list_from_pw_aff(pwaff)); 912 1.1 mrg if (!list) 913 1.1 mrg goto error; 914 1.1 mrg } 915 1.1 mrg 916 1.1 mrg isl_space_free(space); 917 1.1 mrg return list; 918 1.1 mrg error: 919 1.1 mrg isl_space_free(space); 920 1.1 mrg isl_pw_aff_list_free(list); 921 1.1 mrg return NULL; 922 1.1 mrg } 923 1.1 mrg 924 1.1 mrg static __isl_give isl_map *read_defined_var_list(__isl_keep isl_stream *s, 925 1.1 mrg struct vars *v, __isl_take isl_map *map, int rational) 926 1.1 mrg { 927 1.1 mrg struct isl_token *tok; 928 1.1 mrg 929 1.1 mrg while ((tok = isl_stream_next_token(s)) != NULL) { 930 1.1 mrg int p; 931 1.1 mrg int n = v->n; 932 1.1 mrg 933 1.1 mrg if (tok->type != ISL_TOKEN_IDENT) 934 1.1 mrg break; 935 1.1 mrg 936 1.1 mrg p = vars_pos(v, tok->u.s, -1); 937 1.1 mrg if (p < 0) 938 1.1 mrg goto error; 939 1.1 mrg if (p < n) { 940 1.1 mrg isl_stream_error(s, tok, "expecting unique identifier"); 941 1.1 mrg goto error; 942 1.1 mrg } 943 1.1 mrg 944 1.1 mrg map = isl_map_add_dims(map, isl_dim_out, 1); 945 1.1 mrg 946 1.1 mrg isl_token_free(tok); 947 1.1 mrg tok = isl_stream_next_token(s); 948 1.1 mrg if (tok && tok->type == '=') { 949 1.1 mrg isl_token_free(tok); 950 1.1 mrg map = read_var_def(s, map, isl_dim_out, v, rational); 951 1.1 mrg tok = isl_stream_next_token(s); 952 1.1 mrg } 953 1.1 mrg 954 1.1 mrg if (!tok || tok->type != ',') 955 1.1 mrg break; 956 1.1 mrg 957 1.1 mrg isl_token_free(tok); 958 1.1 mrg } 959 1.1 mrg if (tok) 960 1.1 mrg isl_stream_push_token(s, tok); 961 1.1 mrg 962 1.1 mrg return map; 963 1.1 mrg error: 964 1.1 mrg isl_token_free(tok); 965 1.1 mrg isl_map_free(map); 966 1.1 mrg return NULL; 967 1.1 mrg } 968 1.1 mrg 969 1.1 mrg static int next_is_tuple(__isl_keep isl_stream *s) 970 1.1 mrg { 971 1.1 mrg struct isl_token *tok; 972 1.1 mrg int is_tuple; 973 1.1 mrg 974 1.1 mrg tok = isl_stream_next_token(s); 975 1.1 mrg if (!tok) 976 1.1 mrg return 0; 977 1.1 mrg if (tok->type == '[') { 978 1.1 mrg isl_stream_push_token(s, tok); 979 1.1 mrg return 1; 980 1.1 mrg } 981 1.1 mrg if (tok->type != ISL_TOKEN_IDENT && !tok->is_keyword) { 982 1.1 mrg isl_stream_push_token(s, tok); 983 1.1 mrg return 0; 984 1.1 mrg } 985 1.1 mrg 986 1.1 mrg is_tuple = isl_stream_next_token_is(s, '['); 987 1.1 mrg 988 1.1 mrg isl_stream_push_token(s, tok); 989 1.1 mrg 990 1.1 mrg return is_tuple; 991 1.1 mrg } 992 1.1 mrg 993 1.1 mrg /* Does the next token mark the end of a tuple element? 994 1.1 mrg */ 995 1.1 mrg static int next_is_end_tuple_element(__isl_keep isl_stream *s) 996 1.1 mrg { 997 1.1 mrg return isl_stream_next_token_is(s, ',') || 998 1.1 mrg isl_stream_next_token_is(s, ']'); 999 1.1 mrg } 1000 1.1 mrg 1001 1.1 mrg /* Is the next token one that necessarily forms the start of a condition? 1002 1.1 mrg */ 1003 1.1 mrg static int next_is_condition_start(__isl_keep isl_stream *s) 1004 1.1 mrg { 1005 1.1 mrg return isl_stream_next_token_is(s, ISL_TOKEN_EXISTS) || 1006 1.1 mrg isl_stream_next_token_is(s, ISL_TOKEN_NOT) || 1007 1.1 mrg isl_stream_next_token_is(s, ISL_TOKEN_TRUE) || 1008 1.1 mrg isl_stream_next_token_is(s, ISL_TOKEN_FALSE) || 1009 1.1 mrg isl_stream_next_token_is(s, ISL_TOKEN_MAP); 1010 1.1 mrg } 1011 1.1 mrg 1012 1.1 mrg /* Is "pa" an expression in term of earlier dimensions? 1013 1.1 mrg * The alternative is that the dimension is defined to be equal to itself, 1014 1.1 mrg * meaning that it has a universe domain and an expression that depends 1015 1.1 mrg * on itself. "i" is the position of the expression in a sequence 1016 1.1 mrg * of "n" expressions. The final dimensions of "pa" correspond to 1017 1.1 mrg * these "n" expressions. 1018 1.1 mrg */ 1019 1.1 mrg static isl_bool pw_aff_is_expr(__isl_keep isl_pw_aff *pa, int i, int n) 1020 1.1 mrg { 1021 1.1 mrg isl_aff *aff; 1022 1.1 mrg 1023 1.1 mrg if (!pa) 1024 1.1 mrg return isl_bool_error; 1025 1.1 mrg if (pa->n != 1) 1026 1.1 mrg return isl_bool_true; 1027 1.1 mrg if (!isl_set_plain_is_universe(pa->p[0].set)) 1028 1.1 mrg return isl_bool_true; 1029 1.1 mrg 1030 1.1 mrg aff = pa->p[0].aff; 1031 1.1 mrg if (isl_int_is_zero(aff->v->el[aff->v->size - n + i])) 1032 1.1 mrg return isl_bool_true; 1033 1.1 mrg return isl_bool_false; 1034 1.1 mrg } 1035 1.1 mrg 1036 1.1 mrg /* Does the tuple contain any dimensions that are defined 1037 1.1 mrg * in terms of earlier dimensions? 1038 1.1 mrg */ 1039 1.1 mrg static isl_bool tuple_has_expr(__isl_keep isl_multi_pw_aff *tuple) 1040 1.1 mrg { 1041 1.1 mrg int i; 1042 1.1 mrg isl_size n; 1043 1.1 mrg isl_bool has_expr = isl_bool_false; 1044 1.1 mrg isl_pw_aff *pa; 1045 1.1 mrg 1046 1.1 mrg n = isl_multi_pw_aff_dim(tuple, isl_dim_out); 1047 1.1 mrg if (n < 0) 1048 1.1 mrg return isl_bool_error; 1049 1.1 mrg for (i = 0; i < n; ++i) { 1050 1.1 mrg pa = isl_multi_pw_aff_get_pw_aff(tuple, i); 1051 1.1 mrg has_expr = pw_aff_is_expr(pa, i, n); 1052 1.1 mrg isl_pw_aff_free(pa); 1053 1.1 mrg if (has_expr < 0 || has_expr) 1054 1.1 mrg break; 1055 1.1 mrg } 1056 1.1 mrg 1057 1.1 mrg return has_expr; 1058 1.1 mrg } 1059 1.1 mrg 1060 1.1 mrg /* Set the name of dimension "pos" in "space" to "name". 1061 1.1 mrg * During printing, we add primes if the same name appears more than once 1062 1.1 mrg * to distinguish the occurrences. Here, we remove those primes from "name" 1063 1.1 mrg * before setting the name of the dimension. 1064 1.1 mrg */ 1065 1.1 mrg static __isl_give isl_space *space_set_dim_name(__isl_take isl_space *space, 1066 1.1 mrg int pos, char *name) 1067 1.1 mrg { 1068 1.1 mrg char *prime; 1069 1.1 mrg 1070 1.1 mrg if (!name) 1071 1.1 mrg return space; 1072 1.1 mrg 1073 1.1 mrg prime = strchr(name, '\''); 1074 1.1 mrg if (prime) 1075 1.1 mrg *prime = '\0'; 1076 1.1 mrg space = isl_space_set_dim_name(space, isl_dim_out, pos, name); 1077 1.1 mrg if (prime) 1078 1.1 mrg *prime = '\''; 1079 1.1 mrg 1080 1.1 mrg return space; 1081 1.1 mrg } 1082 1.1 mrg 1083 1.1 mrg /* Set the name of the last (output) dimension of "space" to "name", 1084 1.1 mrg * ignoring any primes in "name". 1085 1.1 mrg */ 1086 1.1 mrg static __isl_give isl_space *space_set_last_dim_name( 1087 1.1 mrg __isl_take isl_space *space, char *name) 1088 1.1 mrg { 1089 1.1 mrg isl_size pos; 1090 1.1 mrg 1091 1.1 mrg pos = isl_space_dim(space, isl_dim_out); 1092 1.1 mrg if (pos < 0) 1093 1.1 mrg return isl_space_free(space); 1094 1.1 mrg return space_set_dim_name(space, pos - 1, name); 1095 1.1 mrg } 1096 1.1 mrg 1097 1.1 mrg /* Construct an isl_pw_aff defined on a "space" (with v->n variables) 1098 1.1 mrg * that is equal to the last of those variables. 1099 1.1 mrg */ 1100 1.1 mrg static __isl_give isl_pw_aff *identity_tuple_el_on_space( 1101 1.1 mrg __isl_take isl_space *space, struct vars *v) 1102 1.1 mrg { 1103 1.1 mrg isl_aff *aff; 1104 1.1 mrg 1105 1.1 mrg aff = isl_aff_zero_on_domain(isl_local_space_from_space(space)); 1106 1.1 mrg aff = isl_aff_add_coefficient_si(aff, isl_dim_in, v->n - 1, 1); 1107 1.1 mrg return isl_pw_aff_from_aff(aff); 1108 1.1 mrg } 1109 1.1 mrg 1110 1.1 mrg /* Construct an isl_pw_aff defined on the domain space of "pa" 1111 1.1 mrg * that is equal to the last variable in "v". 1112 1.1 mrg * 1113 1.1 mrg * That is, if D is the domain space of "pa", then construct 1114 1.1 mrg * 1115 1.1 mrg * D[..., i] -> i. 1116 1.1 mrg */ 1117 1.1 mrg static __isl_give isl_pw_aff *init_range(__isl_keep isl_pw_aff *pa, 1118 1.1 mrg struct vars *v) 1119 1.1 mrg { 1120 1.1 mrg isl_space *space; 1121 1.1 mrg 1122 1.1 mrg space = isl_pw_aff_get_domain_space(pa); 1123 1.1 mrg return identity_tuple_el_on_space(space, v); 1124 1.1 mrg } 1125 1.1 mrg 1126 1.1 mrg /* Impose the lower bound "lower" on the variable represented by "range_pa". 1127 1.1 mrg * 1128 1.1 mrg * In particular, "range_pa" is of the form 1129 1.1 mrg * 1130 1.1 mrg * D[..., i] -> i : C 1131 1.1 mrg * 1132 1.1 mrg * with D also the domains space of "lower' and "C" some constraints. 1133 1.1 mrg * 1134 1.1 mrg * Return the expression 1135 1.1 mrg * 1136 1.1 mrg * D[..., i] -> i : C and i >= lower 1137 1.1 mrg */ 1138 1.1 mrg static __isl_give isl_pw_aff *set_lower(__isl_take isl_pw_aff *range_pa, 1139 1.1 mrg __isl_take isl_pw_aff *lower) 1140 1.1 mrg { 1141 1.1 mrg isl_set *range; 1142 1.1 mrg 1143 1.1 mrg range = isl_pw_aff_ge_set(isl_pw_aff_copy(range_pa), lower); 1144 1.1 mrg return isl_pw_aff_intersect_domain(range_pa, range); 1145 1.1 mrg } 1146 1.1 mrg 1147 1.1 mrg /* Impose the upper bound "upper" on the variable represented by "range_pa". 1148 1.1 mrg * 1149 1.1 mrg * In particular, "range_pa" is of the form 1150 1.1 mrg * 1151 1.1 mrg * D[..., i] -> i : C 1152 1.1 mrg * 1153 1.1 mrg * with D also the domains space of "upper' and "C" some constraints. 1154 1.1 mrg * 1155 1.1 mrg * Return the expression 1156 1.1 mrg * 1157 1.1 mrg * D[..., i] -> i : C and i <= upper 1158 1.1 mrg */ 1159 1.1 mrg static __isl_give isl_pw_aff *set_upper(__isl_take isl_pw_aff *range_pa, 1160 1.1 mrg __isl_take isl_pw_aff *upper) 1161 1.1 mrg { 1162 1.1 mrg isl_set *range; 1163 1.1 mrg 1164 1.1 mrg range = isl_pw_aff_le_set(isl_pw_aff_copy(range_pa), upper); 1165 1.1 mrg return isl_pw_aff_intersect_domain(range_pa, range); 1166 1.1 mrg } 1167 1.1 mrg 1168 1.1 mrg /* Construct a piecewise affine expression corresponding 1169 1.1 mrg * to the last variable in "v" that is greater than or equal to "pa". 1170 1.1 mrg * 1171 1.1 mrg * In particular, if D is the domain space of "pa", 1172 1.1 mrg * then construct the expression 1173 1.1 mrg * 1174 1.1 mrg * D[..., i] -> i, 1175 1.1 mrg * 1176 1.1 mrg * impose lower bound "pa" and return 1177 1.1 mrg * 1178 1.1 mrg * D[..., i] -> i : i >= pa 1179 1.1 mrg */ 1180 1.1 mrg static __isl_give isl_pw_aff *construct_lower(__isl_take isl_pw_aff *pa, 1181 1.1 mrg struct vars *v) 1182 1.1 mrg { 1183 1.1 mrg return set_lower(init_range(pa, v), pa); 1184 1.1 mrg } 1185 1.1 mrg 1186 1.1 mrg /* Construct a piecewise affine expression corresponding 1187 1.1 mrg * to the last variable in "v" that is smaller than or equal to "pa". 1188 1.1 mrg * 1189 1.1 mrg * In particular, if D is the domain space of "pa", 1190 1.1 mrg * then construct the expression 1191 1.1 mrg * 1192 1.1 mrg * D[..., i] -> i, 1193 1.1 mrg * 1194 1.1 mrg * impose lower bound "pa" and return 1195 1.1 mrg * 1196 1.1 mrg * D[..., i] -> i : i <= pa 1197 1.1 mrg */ 1198 1.1 mrg static __isl_give isl_pw_aff *construct_upper(__isl_take isl_pw_aff *pa, 1199 1.1 mrg struct vars *v) 1200 1.1 mrg { 1201 1.1 mrg return set_upper(init_range(pa, v), pa); 1202 1.1 mrg } 1203 1.1 mrg 1204 1.1 mrg /* Construct a piecewise affine expression corresponding 1205 1.1 mrg * to the last variable in "v" that ranges between "pa" and "pa2". 1206 1.1 mrg * 1207 1.1 mrg * In particular, if D is the domain space of "pa" (and "pa2"), 1208 1.1 mrg * then construct the expression 1209 1.1 mrg * 1210 1.1 mrg * D[..., i] -> i, 1211 1.1 mrg * 1212 1.1 mrg * impose lower bound "pa" and upper bound "pa2" and return 1213 1.1 mrg * 1214 1.1 mrg * D[..., i] -> i : pa <= i <= pa2 1215 1.1 mrg */ 1216 1.1 mrg static __isl_give isl_pw_aff *construct_range(__isl_take isl_pw_aff *pa, 1217 1.1 mrg __isl_take isl_pw_aff *pa2, struct vars *v) 1218 1.1 mrg { 1219 1.1 mrg return set_upper(set_lower(init_range(pa, v), pa), pa2); 1220 1.1 mrg } 1221 1.1 mrg 1222 1.1 mrg static int resolve_paren_expr(__isl_keep isl_stream *s, 1223 1.1 mrg struct vars *v, __isl_take isl_map *map, int rational); 1224 1.1 mrg 1225 1.1 mrg /* Given that the (piecewise) affine expression "pa" 1226 1.1 mrg * has just been parsed, followed by a colon, 1227 1.1 mrg * continue parsing as part of a piecewise affine expression. 1228 1.1 mrg * 1229 1.1 mrg * In particular, check if the colon is followed by a condition. 1230 1.1 mrg * If so, parse the conditions(a) on "pa" and include them in the domain. 1231 1.1 mrg * Otherwise, if the colon is followed by another (piecewise) affine expression 1232 1.1 mrg * then consider the two expressions as endpoints of a range of values and 1233 1.1 mrg * return a piecewise affine expression that takes values in that range. 1234 1.1 mrg * Note that an affine expression followed by a comparison operator 1235 1.1 mrg * is considered to be part of a condition. 1236 1.1 mrg * If the colon is not followed by anything (inside the tuple element), 1237 1.1 mrg * then consider "pa" as a lower bound on a range of values without upper bound 1238 1.1 mrg * and return a piecewise affine expression that takes values in that range. 1239 1.1 mrg */ 1240 1.1 mrg static __isl_give isl_pw_aff *update_piecewise_affine_colon( 1241 1.1 mrg __isl_take isl_pw_aff *pa, __isl_keep isl_stream *s, 1242 1.1 mrg struct vars *v, int rational) 1243 1.1 mrg { 1244 1.1 mrg isl_space *dom_space; 1245 1.1 mrg isl_map *map; 1246 1.1 mrg 1247 1.1 mrg dom_space = isl_pw_aff_get_domain_space(pa); 1248 1.1 mrg map = isl_map_universe(isl_space_from_domain(dom_space)); 1249 1.1 mrg 1250 1.1 mrg if (isl_stream_next_token_is(s, '(')) 1251 1.1 mrg if (resolve_paren_expr(s, v, isl_map_copy(map), rational)) 1252 1.1 mrg goto error; 1253 1.1 mrg if (next_is_end_tuple_element(s)) { 1254 1.1 mrg isl_map_free(map); 1255 1.1 mrg return construct_lower(pa, v); 1256 1.1 mrg } 1257 1.1 mrg if (!next_is_condition_start(s)) { 1258 1.1 mrg int line = -1, col = -1; 1259 1.1 mrg isl_space *space; 1260 1.1 mrg isl_pw_aff *pa2; 1261 1.1 mrg 1262 1.1 mrg set_current_line_col(s, &line, &col); 1263 1.1 mrg space = isl_space_wrap(isl_map_get_space(map)); 1264 1.1 mrg pa2 = accept_affine(s, space, v); 1265 1.1 mrg if (rational) 1266 1.1 mrg pa2 = isl_pw_aff_set_rational(pa2); 1267 1.1 mrg if (!next_is_comparator(s)) { 1268 1.1 mrg isl_map_free(map); 1269 1.1 mrg pa2 = isl_pw_aff_domain_factor_domain(pa2); 1270 1.1 mrg return construct_range(pa, pa2, v); 1271 1.1 mrg } 1272 1.1 mrg if (push_aff(s, line, col, pa2) < 0) 1273 1.1 mrg goto error; 1274 1.1 mrg } 1275 1.1 mrg 1276 1.1 mrg map = read_formula(s, v, map, rational); 1277 1.1 mrg pa = isl_pw_aff_intersect_domain(pa, isl_map_domain(map)); 1278 1.1 mrg 1279 1.1 mrg return pa; 1280 1.1 mrg error: 1281 1.1 mrg isl_map_free(map); 1282 1.1 mrg isl_pw_aff_free(pa); 1283 1.1 mrg return NULL; 1284 1.1 mrg } 1285 1.1 mrg 1286 1.1 mrg /* Accept a piecewise affine expression. 1287 1.1 mrg * 1288 1.1 mrg * At the outer level, the piecewise affine expression may be of the form 1289 1.1 mrg * 1290 1.1 mrg * aff1 : condition1; aff2 : conditions2; ... 1291 1.1 mrg * 1292 1.1 mrg * or one of 1293 1.1 mrg * 1294 1.1 mrg * aff : 1295 1.1 mrg * aff1 : aff2 1296 1.1 mrg * : aff 1297 1.1 mrg * : 1298 1.1 mrg * 1299 1.1 mrg * or simply 1300 1.1 mrg * 1301 1.1 mrg * aff 1302 1.1 mrg * 1303 1.1 mrg * each of the affine expressions may in turn include ternary operators. 1304 1.1 mrg * 1305 1.1 mrg * If the first token is a colon, then the expression must be 1306 1.1 mrg * ":" or ": aff2", depending on whether anything follows the colon 1307 1.1 mrg * inside the tuple element. 1308 1.1 mrg * The first is considered to represent an arbitrary value. 1309 1.1 mrg * The second is considered to represent a range of values 1310 1.1 mrg * with the given upper bound and no lower bound. 1311 1.1 mrg * 1312 1.1 mrg * There may be parentheses around some subexpression of "aff1" 1313 1.1 mrg * around "aff1" itself, around "aff1 : condition1" and/or 1314 1.1 mrg * around the entire piecewise affine expression. 1315 1.1 mrg * We therefore remove the opening parenthesis (if any) from the stream 1316 1.1 mrg * in case the closing parenthesis follows the colon, but if the closing 1317 1.1 mrg * parenthesis is the first thing in the stream after the parsed affine 1318 1.1 mrg * expression, we push the parsed expression onto the stream and parse 1319 1.1 mrg * again in case the parentheses enclose some subexpression of "aff1". 1320 1.1 mrg */ 1321 1.1 mrg static __isl_give isl_pw_aff *accept_piecewise_affine(__isl_keep isl_stream *s, 1322 1.1 mrg __isl_take isl_space *space, struct vars *v, int rational) 1323 1.1 mrg { 1324 1.1 mrg isl_pw_aff *res; 1325 1.1 mrg isl_space *res_space; 1326 1.1 mrg 1327 1.1 mrg if (isl_stream_eat_if_available(s, ':')) { 1328 1.1 mrg if (next_is_end_tuple_element(s)) 1329 1.1 mrg return identity_tuple_el_on_space(space, v); 1330 1.1 mrg else 1331 1.1 mrg return construct_upper(accept_affine(s, space, v), v); 1332 1.1 mrg } 1333 1.1 mrg 1334 1.1 mrg res_space = isl_space_from_domain(isl_space_copy(space)); 1335 1.1 mrg res_space = isl_space_add_dims(res_space, isl_dim_out, 1); 1336 1.1 mrg res = isl_pw_aff_empty(res_space); 1337 1.1 mrg do { 1338 1.1 mrg isl_pw_aff *pa; 1339 1.1 mrg int seen_paren; 1340 1.1 mrg int line = -1, col = -1; 1341 1.1 mrg 1342 1.1 mrg set_current_line_col(s, &line, &col); 1343 1.1 mrg seen_paren = isl_stream_eat_if_available(s, '('); 1344 1.1 mrg if (seen_paren) 1345 1.1 mrg pa = accept_piecewise_affine(s, isl_space_copy(space), 1346 1.1 mrg v, rational); 1347 1.1 mrg else 1348 1.1 mrg pa = accept_extended_affine(s, isl_space_copy(space), 1349 1.1 mrg v, rational); 1350 1.1 mrg if (seen_paren && isl_stream_eat_if_available(s, ')')) { 1351 1.1 mrg seen_paren = 0; 1352 1.1 mrg if (push_aff(s, line, col, pa) < 0) 1353 1.1 mrg goto error; 1354 1.1 mrg pa = accept_extended_affine(s, isl_space_copy(space), 1355 1.1 mrg v, rational); 1356 1.1 mrg } 1357 1.1 mrg if (pa && isl_stream_eat_if_available(s, ':')) 1358 1.1 mrg pa = update_piecewise_affine_colon(pa, s, v, rational); 1359 1.1 mrg 1360 1.1 mrg res = isl_pw_aff_union_add(res, pa); 1361 1.1 mrg 1362 1.1 mrg if (!res || (seen_paren && isl_stream_eat(s, ')'))) 1363 1.1 mrg goto error; 1364 1.1 mrg } while (isl_stream_eat_if_available(s, ';')); 1365 1.1 mrg 1366 1.1 mrg isl_space_free(space); 1367 1.1 mrg 1368 1.1 mrg return res; 1369 1.1 mrg error: 1370 1.1 mrg isl_space_free(space); 1371 1.1 mrg return isl_pw_aff_free(res); 1372 1.1 mrg } 1373 1.1 mrg 1374 1.1 mrg /* Read an affine expression from "s" for use in read_tuple. 1375 1.1 mrg * 1376 1.1 mrg * accept_extended_affine requires a wrapped space as input. 1377 1.1 mrg * read_tuple on the other hand expects each isl_pw_aff 1378 1.1 mrg * to have an anonymous space. We therefore adjust the space 1379 1.1 mrg * of the isl_pw_aff before returning it. 1380 1.1 mrg */ 1381 1.1 mrg static __isl_give isl_pw_aff *read_tuple_var_def(__isl_keep isl_stream *s, 1382 1.1 mrg struct vars *v, int rational) 1383 1.1 mrg { 1384 1.1 mrg isl_space *space; 1385 1.1 mrg isl_pw_aff *def; 1386 1.1 mrg 1387 1.1 mrg space = isl_space_wrap(isl_space_alloc(s->ctx, 0, v->n, 0)); 1388 1.1 mrg 1389 1.1 mrg def = accept_piecewise_affine(s, space, v, rational); 1390 1.1 mrg def = isl_pw_aff_domain_factor_domain(def); 1391 1.1 mrg 1392 1.1 mrg return def; 1393 1.1 mrg } 1394 1.1 mrg 1395 1.1 mrg /* Read a list of tuple elements by calling "read_el" on each of them and 1396 1.1 mrg * return a space with the same number of set dimensions derived from 1397 1.1 mrg * the parameter space "space" and possibly updated by "read_el". 1398 1.1 mrg * The elements in the list are separated by either "," or "][". 1399 1.1 mrg * If "comma" is set then only "," is allowed. 1400 1.1 mrg */ 1401 1.1 mrg static __isl_give isl_space *read_tuple_list(__isl_keep isl_stream *s, 1402 1.1 mrg struct vars *v, __isl_take isl_space *space, int rational, int comma, 1403 1.1 mrg __isl_give isl_space *(*read_el)(__isl_keep isl_stream *s, 1404 1.1 mrg struct vars *v, __isl_take isl_space *space, int rational, 1405 1.1 mrg void *user), 1406 1.1 mrg void *user) 1407 1.1 mrg { 1408 1.1 mrg if (!space) 1409 1.1 mrg return NULL; 1410 1.1 mrg 1411 1.1 mrg space = isl_space_set_from_params(space); 1412 1.1 mrg 1413 1.1 mrg if (isl_stream_next_token_is(s, ']')) 1414 1.1 mrg return space; 1415 1.1 mrg 1416 1.1 mrg for (;;) { 1417 1.1 mrg struct isl_token *tok; 1418 1.1 mrg 1419 1.1 mrg space = isl_space_add_dims(space, isl_dim_set, 1); 1420 1.1 mrg 1421 1.1 mrg space = read_el(s, v, space, rational, user); 1422 1.1 mrg if (!space) 1423 1.1 mrg return NULL; 1424 1.1 mrg 1425 1.1 mrg tok = isl_stream_next_token(s); 1426 1.1 mrg if (!comma && tok && tok->type == ']' && 1427 1.1 mrg isl_stream_next_token_is(s, '[')) { 1428 1.1 mrg isl_token_free(tok); 1429 1.1 mrg tok = isl_stream_next_token(s); 1430 1.1 mrg } else if (!tok || tok->type != ',') { 1431 1.1 mrg if (tok) 1432 1.1 mrg isl_stream_push_token(s, tok); 1433 1.1 mrg break; 1434 1.1 mrg } 1435 1.1 mrg 1436 1.1 mrg isl_token_free(tok); 1437 1.1 mrg } 1438 1.1 mrg 1439 1.1 mrg return space; 1440 1.1 mrg } 1441 1.1 mrg 1442 1.1 mrg /* Read a tuple space from "s" derived from the parameter space "space". 1443 1.1 mrg * Call "read_el" on each element in the tuples. 1444 1.1 mrg */ 1445 1.1 mrg static __isl_give isl_space *read_tuple_space(__isl_keep isl_stream *s, 1446 1.1 mrg struct vars *v, __isl_take isl_space *space, int rational, int comma, 1447 1.1 mrg __isl_give isl_space *(*read_el)(__isl_keep isl_stream *s, 1448 1.1 mrg struct vars *v, __isl_take isl_space *space, int rational, 1449 1.1 mrg void *user), 1450 1.1 mrg void *user) 1451 1.1 mrg { 1452 1.1 mrg struct isl_token *tok; 1453 1.1 mrg char *name = NULL; 1454 1.1 mrg isl_space *res = NULL; 1455 1.1 mrg 1456 1.1 mrg tok = isl_stream_next_token(s); 1457 1.1 mrg if (!tok) 1458 1.1 mrg goto error; 1459 1.1 mrg if (tok->type == ISL_TOKEN_IDENT || tok->is_keyword) { 1460 1.1 mrg name = strdup(tok->u.s); 1461 1.1 mrg isl_token_free(tok); 1462 1.1 mrg if (!name) 1463 1.1 mrg goto error; 1464 1.1 mrg } else 1465 1.1 mrg isl_stream_push_token(s, tok); 1466 1.1 mrg if (isl_stream_eat(s, '[')) 1467 1.1 mrg goto error; 1468 1.1 mrg if (next_is_tuple(s)) { 1469 1.1 mrg isl_space *out; 1470 1.1 mrg res = read_tuple_space(s, v, isl_space_copy(space), 1471 1.1 mrg rational, comma, read_el, user); 1472 1.1 mrg if (isl_stream_eat(s, ISL_TOKEN_TO)) 1473 1.1 mrg goto error; 1474 1.1 mrg out = read_tuple_space(s, v, isl_space_copy(space), 1475 1.1 mrg rational, comma, read_el, user); 1476 1.1 mrg res = isl_space_product(res, out); 1477 1.1 mrg } else 1478 1.1 mrg res = read_tuple_list(s, v, isl_space_copy(space), 1479 1.1 mrg rational, comma, read_el, user); 1480 1.1 mrg if (!res || isl_stream_eat(s, ']')) 1481 1.1 mrg goto error; 1482 1.1 mrg 1483 1.1 mrg if (name) { 1484 1.1 mrg res = isl_space_set_tuple_name(res, isl_dim_set, name); 1485 1.1 mrg free(name); 1486 1.1 mrg } 1487 1.1 mrg 1488 1.1 mrg isl_space_free(space); 1489 1.1 mrg return res; 1490 1.1 mrg error: 1491 1.1 mrg free(name); 1492 1.1 mrg isl_space_free(res); 1493 1.1 mrg isl_space_free(space); 1494 1.1 mrg return NULL; 1495 1.1 mrg } 1496 1.1 mrg 1497 1.1 mrg /* Construct an isl_pw_aff defined on a space with v->n variables 1498 1.1 mrg * that is equal to the last of those variables. 1499 1.1 mrg */ 1500 1.1 mrg static __isl_give isl_pw_aff *identity_tuple_el(struct vars *v) 1501 1.1 mrg { 1502 1.1 mrg isl_space *space; 1503 1.1 mrg 1504 1.1 mrg space = isl_space_set_alloc(v->ctx, 0, v->n); 1505 1.1 mrg return identity_tuple_el_on_space(space, v); 1506 1.1 mrg } 1507 1.1 mrg 1508 1.1 mrg /* This function is called for each element in a tuple inside read_tuple. 1509 1.1 mrg * Add a new variable to "v" and construct a corresponding isl_pw_aff defined 1510 1.1 mrg * over a space containing all variables in "v" defined so far. 1511 1.1 mrg * The isl_pw_aff expresses the new variable in terms of earlier variables 1512 1.1 mrg * if a definition is provided. Otherwise, it is represented as being 1513 1.1 mrg * equal to itself. 1514 1.1 mrg * Add the isl_pw_aff to *list. 1515 1.1 mrg * If the new variable was named, then adjust "space" accordingly and 1516 1.1 mrg * return the updated space. 1517 1.1 mrg */ 1518 1.1 mrg static __isl_give isl_space *read_tuple_pw_aff_el(__isl_keep isl_stream *s, 1519 1.1 mrg struct vars *v, __isl_take isl_space *space, int rational, void *user) 1520 1.1 mrg { 1521 1.1 mrg isl_pw_aff_list **list = (isl_pw_aff_list **) user; 1522 1.1 mrg isl_pw_aff *pa; 1523 1.1 mrg struct isl_token *tok; 1524 1.1 mrg int new_name = 0; 1525 1.1 mrg 1526 1.1 mrg tok = next_token(s); 1527 1.1 mrg if (!tok) { 1528 1.1 mrg isl_stream_error(s, NULL, "unexpected EOF"); 1529 1.1 mrg return isl_space_free(space); 1530 1.1 mrg } 1531 1.1 mrg 1532 1.1 mrg if (tok->type == ISL_TOKEN_IDENT) { 1533 1.1 mrg int n = v->n; 1534 1.1 mrg int p = vars_pos(v, tok->u.s, -1); 1535 1.1 mrg if (p < 0) 1536 1.1 mrg goto error; 1537 1.1 mrg new_name = p >= n; 1538 1.1 mrg } 1539 1.1 mrg 1540 1.1 mrg if (tok->type == '*') { 1541 1.1 mrg if (vars_add_anon(v) < 0) 1542 1.1 mrg goto error; 1543 1.1 mrg isl_token_free(tok); 1544 1.1 mrg pa = identity_tuple_el(v); 1545 1.1 mrg } else if (new_name) { 1546 1.1 mrg space = space_set_last_dim_name(space, v->v->name); 1547 1.1 mrg isl_token_free(tok); 1548 1.1 mrg if (isl_stream_eat_if_available(s, '=')) 1549 1.1 mrg pa = read_tuple_var_def(s, v, rational); 1550 1.1 mrg else 1551 1.1 mrg pa = identity_tuple_el(v); 1552 1.1 mrg } else { 1553 1.1 mrg isl_stream_push_token(s, tok); 1554 1.1 mrg tok = NULL; 1555 1.1 mrg if (vars_add_anon(v) < 0) 1556 1.1 mrg goto error; 1557 1.1 mrg pa = read_tuple_var_def(s, v, rational); 1558 1.1 mrg } 1559 1.1 mrg 1560 1.1 mrg *list = isl_pw_aff_list_add(*list, pa); 1561 1.1 mrg if (!*list) 1562 1.1 mrg return isl_space_free(space); 1563 1.1 mrg 1564 1.1 mrg return space; 1565 1.1 mrg error: 1566 1.1 mrg isl_token_free(tok); 1567 1.1 mrg return isl_space_free(space); 1568 1.1 mrg } 1569 1.1 mrg 1570 1.1 mrg /* Read a tuple and represent it as an isl_multi_pw_aff. 1571 1.1 mrg * The range space of the isl_multi_pw_aff is the space of the tuple. 1572 1.1 mrg * The domain space is an anonymous space 1573 1.1 mrg * with a dimension for each variable in the set of variables in "v", 1574 1.1 mrg * including the variables in the range. 1575 1.1 mrg * If a given dimension is not defined in terms of earlier dimensions in 1576 1.1 mrg * the input, then the corresponding isl_pw_aff is set equal to one time 1577 1.1 mrg * the variable corresponding to the dimension being defined. 1578 1.1 mrg * 1579 1.1 mrg * The elements in the tuple are collected in a list by read_tuple_pw_aff_el. 1580 1.1 mrg * Each element in this list is defined over a space representing 1581 1.1 mrg * the variables defined so far. We need to adjust the earlier 1582 1.1 mrg * elements to have as many variables in the domain as the final 1583 1.1 mrg * element in the list. 1584 1.1 mrg */ 1585 1.1 mrg static __isl_give isl_multi_pw_aff *read_tuple(__isl_keep isl_stream *s, 1586 1.1 mrg struct vars *v, int rational, int comma) 1587 1.1 mrg { 1588 1.1 mrg int i; 1589 1.1 mrg isl_size n; 1590 1.1 mrg isl_space *space; 1591 1.1 mrg isl_pw_aff_list *list; 1592 1.1 mrg 1593 1.1 mrg space = isl_space_params_alloc(v->ctx, 0); 1594 1.1 mrg list = isl_pw_aff_list_alloc(s->ctx, 0); 1595 1.1 mrg space = read_tuple_space(s, v, space, rational, comma, 1596 1.1 mrg &read_tuple_pw_aff_el, &list); 1597 1.1 mrg n = isl_space_dim(space, isl_dim_set); 1598 1.1 mrg if (n < 0) 1599 1.1 mrg space = isl_space_free(space); 1600 1.1 mrg for (i = 0; i + 1 < n; ++i) { 1601 1.1 mrg isl_pw_aff *pa; 1602 1.1 mrg 1603 1.1 mrg pa = isl_pw_aff_list_get_pw_aff(list, i); 1604 1.1 mrg pa = isl_pw_aff_add_dims(pa, isl_dim_in, n - (i + 1)); 1605 1.1 mrg list = isl_pw_aff_list_set_pw_aff(list, i, pa); 1606 1.1 mrg } 1607 1.1 mrg 1608 1.1 mrg space = isl_space_from_range(space); 1609 1.1 mrg space = isl_space_add_dims(space, isl_dim_in, v->n); 1610 1.1 mrg return isl_multi_pw_aff_from_pw_aff_list(space, list); 1611 1.1 mrg } 1612 1.1 mrg 1613 1.1 mrg /* Add the tuple represented by the isl_multi_pw_aff "tuple" to "map". 1614 1.1 mrg * We first create the appropriate space in "map" based on the range 1615 1.1 mrg * space of this isl_multi_pw_aff. Then, we add equalities based 1616 1.1 mrg * on the affine expressions. These live in an anonymous space, 1617 1.1 mrg * however, so we first need to reset the space to that of "map". 1618 1.1 mrg */ 1619 1.1 mrg static __isl_give isl_map *map_from_tuple(__isl_take isl_multi_pw_aff *tuple, 1620 1.1 mrg __isl_take isl_map *map, enum isl_dim_type type, struct vars *v, 1621 1.1 mrg int rational) 1622 1.1 mrg { 1623 1.1 mrg int i; 1624 1.1 mrg isl_size n; 1625 1.1 mrg isl_ctx *ctx; 1626 1.1 mrg isl_space *space = NULL; 1627 1.1 mrg 1628 1.1 mrg n = isl_multi_pw_aff_dim(tuple, isl_dim_out); 1629 1.1 mrg if (!map || n < 0) 1630 1.1 mrg goto error; 1631 1.1 mrg ctx = isl_multi_pw_aff_get_ctx(tuple); 1632 1.1 mrg space = isl_space_range(isl_multi_pw_aff_get_space(tuple)); 1633 1.1 mrg if (!space) 1634 1.1 mrg goto error; 1635 1.1 mrg 1636 1.1 mrg if (type == isl_dim_param) { 1637 1.1 mrg if (isl_space_has_tuple_name(space, isl_dim_set) || 1638 1.1 mrg isl_space_is_wrapping(space)) { 1639 1.1 mrg isl_die(ctx, isl_error_invalid, 1640 1.1 mrg "parameter tuples cannot be named or nested", 1641 1.1 mrg goto error); 1642 1.1 mrg } 1643 1.1 mrg map = isl_map_add_dims(map, type, n); 1644 1.1 mrg for (i = 0; i < n; ++i) { 1645 1.1 mrg isl_id *id; 1646 1.1 mrg if (!isl_space_has_dim_name(space, isl_dim_set, i)) 1647 1.1 mrg isl_die(ctx, isl_error_invalid, 1648 1.1 mrg "parameters must be named", 1649 1.1 mrg goto error); 1650 1.1 mrg id = isl_space_get_dim_id(space, isl_dim_set, i); 1651 1.1 mrg map = isl_map_set_dim_id(map, isl_dim_param, i, id); 1652 1.1 mrg } 1653 1.1 mrg } else if (type == isl_dim_in) { 1654 1.1 mrg isl_set *set; 1655 1.1 mrg 1656 1.1 mrg set = isl_set_universe(isl_space_copy(space)); 1657 1.1 mrg if (rational) 1658 1.1 mrg set = isl_set_set_rational(set); 1659 1.1 mrg set = isl_set_intersect_params(set, isl_map_params(map)); 1660 1.1 mrg map = isl_map_from_domain(set); 1661 1.1 mrg } else { 1662 1.1 mrg isl_set *set; 1663 1.1 mrg 1664 1.1 mrg set = isl_set_universe(isl_space_copy(space)); 1665 1.1 mrg if (rational) 1666 1.1 mrg set = isl_set_set_rational(set); 1667 1.1 mrg map = isl_map_from_domain_and_range(isl_map_domain(map), set); 1668 1.1 mrg } 1669 1.1 mrg 1670 1.1 mrg for (i = 0; i < n; ++i) { 1671 1.1 mrg isl_pw_aff *pa; 1672 1.1 mrg isl_space *space; 1673 1.1 mrg isl_aff *aff; 1674 1.1 mrg isl_set *set; 1675 1.1 mrg isl_map *map_i; 1676 1.1 mrg 1677 1.1 mrg pa = isl_multi_pw_aff_get_pw_aff(tuple, i); 1678 1.1 mrg space = isl_pw_aff_get_domain_space(pa); 1679 1.1 mrg aff = isl_aff_zero_on_domain(isl_local_space_from_space(space)); 1680 1.1 mrg aff = isl_aff_add_coefficient_si(aff, 1681 1.1 mrg isl_dim_in, v->n - n + i, -1); 1682 1.1 mrg pa = isl_pw_aff_add(pa, isl_pw_aff_from_aff(aff)); 1683 1.1 mrg if (rational) 1684 1.1 mrg pa = isl_pw_aff_set_rational(pa); 1685 1.1 mrg set = isl_pw_aff_zero_set(pa); 1686 1.1 mrg map_i = isl_map_from_range(set); 1687 1.1 mrg map_i = isl_map_reset_space(map_i, isl_map_get_space(map)); 1688 1.1 mrg map = isl_map_intersect(map, map_i); 1689 1.1 mrg } 1690 1.1 mrg 1691 1.1 mrg isl_space_free(space); 1692 1.1 mrg isl_multi_pw_aff_free(tuple); 1693 1.1 mrg return map; 1694 1.1 mrg error: 1695 1.1 mrg isl_space_free(space); 1696 1.1 mrg isl_multi_pw_aff_free(tuple); 1697 1.1 mrg isl_map_free(map); 1698 1.1 mrg return NULL; 1699 1.1 mrg } 1700 1.1 mrg 1701 1.1 mrg /* Read a tuple from "s" and add it to "map". 1702 1.1 mrg * The tuple is initially represented as an isl_multi_pw_aff and 1703 1.1 mrg * then added to "map". 1704 1.1 mrg */ 1705 1.1 mrg static __isl_give isl_map *read_map_tuple(__isl_keep isl_stream *s, 1706 1.1 mrg __isl_take isl_map *map, enum isl_dim_type type, struct vars *v, 1707 1.1 mrg int comma) 1708 1.1 mrg { 1709 1.1 mrg isl_bool rational; 1710 1.1 mrg isl_multi_pw_aff *tuple; 1711 1.1 mrg 1712 1.1 mrg rational = isl_map_is_rational(map); 1713 1.1 mrg if (rational < 0) 1714 1.1 mrg return isl_map_free(map); 1715 1.1 mrg tuple = read_tuple(s, v, rational, comma); 1716 1.1 mrg if (!tuple) 1717 1.1 mrg return isl_map_free(map); 1718 1.1 mrg 1719 1.1 mrg return map_from_tuple(tuple, map, type, v, rational); 1720 1.1 mrg } 1721 1.1 mrg 1722 1.1 mrg /* Read the parameter domain of an expression from "s" (if any) and 1723 1.1 mrg * check that it does not involve any constraints. 1724 1.1 mrg * "v" contains a description of the identifiers parsed so far 1725 1.1 mrg * (of which there should not be any at this point) and is extended 1726 1.1 mrg * by this function. 1727 1.1 mrg */ 1728 1.1 mrg static __isl_give isl_set *read_universe_params(__isl_keep isl_stream *s, 1729 1.1 mrg struct vars *v) 1730 1.1 mrg { 1731 1.1 mrg isl_set *dom; 1732 1.1 mrg 1733 1.1 mrg dom = isl_set_universe(isl_space_params_alloc(s->ctx, 0)); 1734 1.1 mrg if (next_is_tuple(s)) { 1735 1.1 mrg dom = read_map_tuple(s, dom, isl_dim_param, v, 0); 1736 1.1 mrg if (isl_stream_eat(s, ISL_TOKEN_TO)) 1737 1.1 mrg return isl_set_free(dom); 1738 1.1 mrg } 1739 1.1 mrg if (!isl_set_plain_is_universe(dom)) 1740 1.1 mrg isl_die(s->ctx, isl_error_invalid, 1741 1.1 mrg "expecting universe parameter domain", 1742 1.1 mrg return isl_set_free(dom)); 1743 1.1 mrg 1744 1.1 mrg return dom; 1745 1.1 mrg } 1746 1.1 mrg 1747 1.1 mrg /* Read the parameter domain of an expression from "s" (if any), 1748 1.1 mrg * check that it does not involve any constraints and return its space. 1749 1.1 mrg * "v" contains a description of the identifiers parsed so far 1750 1.1 mrg * (of which there should not be any at this point) and is extended 1751 1.1 mrg * by this function. 1752 1.1 mrg */ 1753 1.1 mrg static __isl_give isl_space *read_params(__isl_keep isl_stream *s, 1754 1.1 mrg struct vars *v) 1755 1.1 mrg { 1756 1.1 mrg isl_space *space; 1757 1.1 mrg isl_set *set; 1758 1.1 mrg 1759 1.1 mrg set = read_universe_params(s, v); 1760 1.1 mrg space = isl_set_get_space(set); 1761 1.1 mrg isl_set_free(set); 1762 1.1 mrg 1763 1.1 mrg return space; 1764 1.1 mrg } 1765 1.1 mrg 1766 1.1 mrg /* This function is called for each element in a tuple inside read_space_tuples. 1767 1.1 mrg * Add a new variable to "v" and adjust "space" accordingly 1768 1.1 mrg * if the variable has a name. 1769 1.1 mrg */ 1770 1.1 mrg static __isl_give isl_space *read_tuple_id(__isl_keep isl_stream *s, 1771 1.1 mrg struct vars *v, __isl_take isl_space *space, int rational, void *user) 1772 1.1 mrg { 1773 1.1 mrg struct isl_token *tok; 1774 1.1 mrg 1775 1.1 mrg tok = next_token(s); 1776 1.1 mrg if (!tok) { 1777 1.1 mrg isl_stream_error(s, NULL, "unexpected EOF"); 1778 1.1 mrg return isl_space_free(space); 1779 1.1 mrg } 1780 1.1 mrg 1781 1.1 mrg if (tok->type == ISL_TOKEN_IDENT) { 1782 1.1 mrg int n = v->n; 1783 1.1 mrg int p = vars_pos(v, tok->u.s, -1); 1784 1.1 mrg if (p < 0) 1785 1.1 mrg goto error; 1786 1.1 mrg if (p < n) { 1787 1.1 mrg isl_stream_error(s, tok, "expecting fresh identifier"); 1788 1.1 mrg goto error; 1789 1.1 mrg } 1790 1.1 mrg space = space_set_last_dim_name(space, v->v->name); 1791 1.1 mrg } else if (tok->type == '*') { 1792 1.1 mrg if (vars_add_anon(v) < 0) 1793 1.1 mrg goto error; 1794 1.1 mrg } else { 1795 1.1 mrg isl_stream_error(s, tok, "expecting identifier or '*'"); 1796 1.1 mrg goto error; 1797 1.1 mrg } 1798 1.1 mrg 1799 1.1 mrg isl_token_free(tok); 1800 1.1 mrg return space; 1801 1.1 mrg error: 1802 1.1 mrg isl_token_free(tok); 1803 1.1 mrg return isl_space_free(space); 1804 1.1 mrg } 1805 1.1 mrg 1806 1.1 mrg /* Given a parameter space "params", extend it with one or two tuples 1807 1.1 mrg * read from "s". 1808 1.1 mrg * "v" contains a description of the identifiers parsed so far and is extended 1809 1.1 mrg * by this function. 1810 1.1 mrg */ 1811 1.1 mrg static __isl_give isl_space *read_space_tuples(__isl_keep isl_stream *s, 1812 1.1 mrg struct vars *v, __isl_take isl_space *params) 1813 1.1 mrg { 1814 1.1 mrg isl_space *space, *ran; 1815 1.1 mrg 1816 1.1 mrg space = read_tuple_space(s, v, isl_space_copy(params), 1, 1, 1817 1.1 mrg &read_tuple_id, NULL); 1818 1.1 mrg if (isl_stream_eat_if_available(s, ISL_TOKEN_TO)) { 1819 1.1 mrg ran = read_tuple_space(s, v, isl_space_copy(params), 1, 1, 1820 1.1 mrg &read_tuple_id, NULL); 1821 1.1 mrg space = isl_space_unwrap(isl_space_product(space, ran)); 1822 1.1 mrg } 1823 1.1 mrg isl_space_free(params); 1824 1.1 mrg 1825 1.1 mrg return space; 1826 1.1 mrg } 1827 1.1 mrg 1828 1.1 mrg /* Read an isl_space object from "s". 1829 1.1 mrg * 1830 1.1 mrg * First read the parameters (if any). 1831 1.1 mrg * 1832 1.1 mrg * Then check if the description is of the special form "{ : }", 1833 1.1 mrg * in which case it represents a parameter space. 1834 1.1 mrg * Otherwise, it has one or two tuples. 1835 1.1 mrg */ 1836 1.1 mrg __isl_give isl_space *isl_stream_read_space(__isl_keep isl_stream *s) 1837 1.1 mrg { 1838 1.1 mrg struct vars *v; 1839 1.1 mrg isl_space *space; 1840 1.1 mrg 1841 1.1 mrg v = vars_new(s->ctx); 1842 1.1 mrg if (!v) 1843 1.1 mrg return NULL; 1844 1.1 mrg space = read_params(s, v); 1845 1.1 mrg 1846 1.1 mrg if (isl_stream_eat(s, '{')) 1847 1.1 mrg goto error; 1848 1.1 mrg 1849 1.1 mrg if (!isl_stream_eat_if_available(s, ':')) 1850 1.1 mrg space = read_space_tuples(s, v, space); 1851 1.1 mrg 1852 1.1 mrg if (isl_stream_eat(s, '}')) 1853 1.1 mrg goto error; 1854 1.1 mrg 1855 1.1 mrg vars_free(v); 1856 1.1 mrg return space; 1857 1.1 mrg error: 1858 1.1 mrg vars_free(v); 1859 1.1 mrg isl_space_free(space); 1860 1.1 mrg return NULL; 1861 1.1 mrg } 1862 1.1 mrg 1863 1.1 mrg #undef TYPE_BASE 1864 1.1 mrg #define TYPE_BASE space 1865 1.1 mrg #include "isl_read_from_str_templ.c" 1866 1.1 mrg 1867 1.1 mrg /* Given two equal-length lists of piecewise affine expression with the space 1868 1.1 mrg * of "set" as domain, construct a set in the same space that expresses 1869 1.1 mrg * that "left" and "right" satisfy the comparison "type". 1870 1.1 mrg * 1871 1.1 mrg * A space is constructed of the same dimension as the number of elements 1872 1.1 mrg * in the two lists. The comparison is then expressed in a map from 1873 1.1 mrg * this space to itself and wrapped into a set. Finally the two lists 1874 1.1 mrg * of piecewise affine expressions are plugged into this set. 1875 1.1 mrg * 1876 1.1 mrg * Let S be the space of "set" and T the constructed space. 1877 1.1 mrg * The lists are first changed into two isl_multi_pw_affs in S -> T and 1878 1.1 mrg * then combined into an isl_multi_pw_aff in S -> [T -> T], 1879 1.1 mrg * while the comparison is first expressed in T -> T, then [T -> T] 1880 1.1 mrg * and finally in S. 1881 1.1 mrg */ 1882 1.1 mrg static __isl_give isl_set *list_cmp(__isl_keep isl_set *set, int type, 1883 1.1 mrg __isl_take isl_pw_aff_list *left, __isl_take isl_pw_aff_list *right) 1884 1.1 mrg { 1885 1.1 mrg isl_space *space; 1886 1.1 mrg isl_size n; 1887 1.1 mrg isl_multi_pw_aff *mpa1, *mpa2; 1888 1.1 mrg 1889 1.1 mrg n = isl_pw_aff_list_n_pw_aff(left); 1890 1.1 mrg if (!set || n < 0 || !right) 1891 1.1 mrg goto error; 1892 1.1 mrg 1893 1.1 mrg space = isl_set_get_space(set); 1894 1.1 mrg space = isl_space_from_domain(space); 1895 1.1 mrg space = isl_space_add_dims(space, isl_dim_out, n); 1896 1.1 mrg mpa1 = isl_multi_pw_aff_from_pw_aff_list(isl_space_copy(space), left); 1897 1.1 mrg mpa2 = isl_multi_pw_aff_from_pw_aff_list(isl_space_copy(space), right); 1898 1.1 mrg mpa1 = isl_multi_pw_aff_range_product(mpa1, mpa2); 1899 1.1 mrg 1900 1.1 mrg space = isl_space_range(space); 1901 1.1 mrg switch (type) { 1902 1.1 mrg case ISL_TOKEN_LEX_LT: 1903 1.1 mrg set = isl_map_wrap(isl_map_lex_lt(space)); 1904 1.1 mrg break; 1905 1.1 mrg case ISL_TOKEN_LEX_GT: 1906 1.1 mrg set = isl_map_wrap(isl_map_lex_gt(space)); 1907 1.1 mrg break; 1908 1.1 mrg case ISL_TOKEN_LEX_LE: 1909 1.1 mrg set = isl_map_wrap(isl_map_lex_le(space)); 1910 1.1 mrg break; 1911 1.1 mrg case ISL_TOKEN_LEX_GE: 1912 1.1 mrg set = isl_map_wrap(isl_map_lex_ge(space)); 1913 1.1 mrg break; 1914 1.1 mrg default: 1915 1.1 mrg isl_multi_pw_aff_free(mpa1); 1916 1.1 mrg isl_space_free(space); 1917 1.1 mrg isl_die(isl_set_get_ctx(set), isl_error_internal, 1918 1.1 mrg "unhandled list comparison type", return NULL); 1919 1.1 mrg } 1920 1.1 mrg set = isl_set_preimage_multi_pw_aff(set, mpa1); 1921 1.1 mrg return set; 1922 1.1 mrg error: 1923 1.1 mrg isl_pw_aff_list_free(left); 1924 1.1 mrg isl_pw_aff_list_free(right); 1925 1.1 mrg return NULL; 1926 1.1 mrg } 1927 1.1 mrg 1928 1.1 mrg /* Construct constraints of the form 1929 1.1 mrg * 1930 1.1 mrg * a op b 1931 1.1 mrg * 1932 1.1 mrg * where a is an element in "left", op is an operator of type "type" and 1933 1.1 mrg * b is an element in "right", add the constraints to "set" and return 1934 1.1 mrg * the result. 1935 1.1 mrg * "rational" is set if the constraints should be treated as 1936 1.1 mrg * a rational constraints. 1937 1.1 mrg * 1938 1.1 mrg * If "type" is the type of a comparison operator between lists 1939 1.1 mrg * of affine expressions, then a single (compound) constraint 1940 1.1 mrg * is constructed by list_cmp instead. 1941 1.1 mrg */ 1942 1.1 mrg static __isl_give isl_set *construct_constraints( 1943 1.1 mrg __isl_take isl_set *set, int type, 1944 1.1 mrg __isl_keep isl_pw_aff_list *left, __isl_keep isl_pw_aff_list *right, 1945 1.1 mrg int rational) 1946 1.1 mrg { 1947 1.1 mrg isl_set *cond; 1948 1.1 mrg 1949 1.1 mrg left = isl_pw_aff_list_copy(left); 1950 1.1 mrg right = isl_pw_aff_list_copy(right); 1951 1.1 mrg if (rational) { 1952 1.1 mrg left = isl_pw_aff_list_set_rational(left); 1953 1.1 mrg right = isl_pw_aff_list_set_rational(right); 1954 1.1 mrg } 1955 1.1 mrg if (is_list_comparator_type(type)) 1956 1.1 mrg cond = list_cmp(set, type, left, right); 1957 1.1 mrg else if (type == ISL_TOKEN_LE) 1958 1.1 mrg cond = isl_pw_aff_list_le_set(left, right); 1959 1.1 mrg else if (type == ISL_TOKEN_GE) 1960 1.1 mrg cond = isl_pw_aff_list_ge_set(left, right); 1961 1.1 mrg else if (type == ISL_TOKEN_LT) 1962 1.1 mrg cond = isl_pw_aff_list_lt_set(left, right); 1963 1.1 mrg else if (type == ISL_TOKEN_GT) 1964 1.1 mrg cond = isl_pw_aff_list_gt_set(left, right); 1965 1.1 mrg else if (type == ISL_TOKEN_NE) 1966 1.1 mrg cond = isl_pw_aff_list_ne_set(left, right); 1967 1.1 mrg else 1968 1.1 mrg cond = isl_pw_aff_list_eq_set(left, right); 1969 1.1 mrg 1970 1.1 mrg return isl_set_intersect(set, cond); 1971 1.1 mrg } 1972 1.1 mrg 1973 1.1 mrg /* Read a constraint from "s", add it to "map" and return the result. 1974 1.1 mrg * "v" contains a description of the identifiers parsed so far. 1975 1.1 mrg * "rational" is set if the constraint should be treated as 1976 1.1 mrg * a rational constraint. 1977 1.1 mrg * The constraint read from "s" may be applied to multiple pairs 1978 1.1 mrg * of affine expressions and may be chained. 1979 1.1 mrg * In particular, a list of affine expressions is read, followed 1980 1.1 mrg * by a comparison operator and another list of affine expressions. 1981 1.1 mrg * The comparison operator is then applied to each pair of elements 1982 1.1 mrg * in the two lists and the results are added to "map". 1983 1.1 mrg * However, if the operator expects two lists of affine expressions, 1984 1.1 mrg * then it is applied directly to those lists and the two lists 1985 1.1 mrg * are required to have the same length. 1986 1.1 mrg * If the next token is another comparison operator, then another 1987 1.1 mrg * list of affine expressions is read and the process repeats. 1988 1.1 mrg * 1989 1.1 mrg * The processing is performed on a wrapped copy of "map" because 1990 1.1 mrg * an affine expression cannot have a binary relation as domain. 1991 1.1 mrg */ 1992 1.1 mrg static __isl_give isl_map *add_constraint(__isl_keep isl_stream *s, 1993 1.1 mrg struct vars *v, __isl_take isl_map *map, int rational) 1994 1.1 mrg { 1995 1.1 mrg struct isl_token *tok; 1996 1.1 mrg int type; 1997 1.1 mrg isl_pw_aff_list *list1 = NULL, *list2 = NULL; 1998 1.1 mrg isl_size n1, n2; 1999 1.1 mrg isl_set *set; 2000 1.1 mrg 2001 1.1 mrg set = isl_map_wrap(map); 2002 1.1 mrg list1 = accept_affine_list(s, isl_set_get_space(set), v); 2003 1.1 mrg if (!list1) 2004 1.1 mrg goto error; 2005 1.1 mrg tok = isl_stream_next_token(s); 2006 1.1 mrg if (!is_comparator(tok)) { 2007 1.1 mrg isl_stream_error(s, tok, "missing operator"); 2008 1.1 mrg if (tok) 2009 1.1 mrg isl_stream_push_token(s, tok); 2010 1.1 mrg goto error; 2011 1.1 mrg } 2012 1.1 mrg type = tok->type; 2013 1.1 mrg isl_token_free(tok); 2014 1.1 mrg for (;;) { 2015 1.1 mrg list2 = accept_affine_list(s, isl_set_get_space(set), v); 2016 1.1 mrg n1 = isl_pw_aff_list_n_pw_aff(list1); 2017 1.1 mrg n2 = isl_pw_aff_list_n_pw_aff(list2); 2018 1.1 mrg if (n1 < 0 || n2 < 0) 2019 1.1 mrg goto error; 2020 1.1 mrg if (is_list_comparator_type(type) && n1 != n2) { 2021 1.1 mrg isl_stream_error(s, NULL, 2022 1.1 mrg "list arguments not of same size"); 2023 1.1 mrg goto error; 2024 1.1 mrg } 2025 1.1 mrg 2026 1.1 mrg set = construct_constraints(set, type, list1, list2, rational); 2027 1.1 mrg isl_pw_aff_list_free(list1); 2028 1.1 mrg list1 = list2; 2029 1.1 mrg 2030 1.1 mrg if (!next_is_comparator(s)) 2031 1.1 mrg break; 2032 1.1 mrg tok = isl_stream_next_token(s); 2033 1.1 mrg type = tok->type; 2034 1.1 mrg isl_token_free(tok); 2035 1.1 mrg } 2036 1.1 mrg isl_pw_aff_list_free(list1); 2037 1.1 mrg 2038 1.1 mrg return isl_set_unwrap(set); 2039 1.1 mrg error: 2040 1.1 mrg isl_pw_aff_list_free(list1); 2041 1.1 mrg isl_pw_aff_list_free(list2); 2042 1.1 mrg isl_set_free(set); 2043 1.1 mrg return NULL; 2044 1.1 mrg } 2045 1.1 mrg 2046 1.1 mrg static __isl_give isl_map *read_exists(__isl_keep isl_stream *s, 2047 1.1 mrg struct vars *v, __isl_take isl_map *map, int rational) 2048 1.1 mrg { 2049 1.1 mrg int n = v->n; 2050 1.1 mrg int seen_paren = isl_stream_eat_if_available(s, '('); 2051 1.1 mrg 2052 1.1 mrg map = isl_map_from_domain(isl_map_wrap(map)); 2053 1.1 mrg map = read_defined_var_list(s, v, map, rational); 2054 1.1 mrg 2055 1.1 mrg if (isl_stream_eat(s, ':')) 2056 1.1 mrg goto error; 2057 1.1 mrg 2058 1.1 mrg map = read_formula(s, v, map, rational); 2059 1.1 mrg map = isl_set_unwrap(isl_map_domain(map)); 2060 1.1 mrg 2061 1.1 mrg vars_drop(v, v->n - n); 2062 1.1 mrg if (seen_paren && isl_stream_eat(s, ')')) 2063 1.1 mrg goto error; 2064 1.1 mrg 2065 1.1 mrg return map; 2066 1.1 mrg error: 2067 1.1 mrg isl_map_free(map); 2068 1.1 mrg return NULL; 2069 1.1 mrg } 2070 1.1 mrg 2071 1.1 mrg /* Parse an expression between parentheses and push the result 2072 1.1 mrg * back on the stream. 2073 1.1 mrg * 2074 1.1 mrg * The parsed expression may be either an affine expression 2075 1.1 mrg * or a condition. The first type is pushed onto the stream 2076 1.1 mrg * as an isl_pw_aff, while the second is pushed as an isl_map. 2077 1.1 mrg * 2078 1.1 mrg * If the initial token indicates the start of a condition, 2079 1.1 mrg * we parse it as such. 2080 1.1 mrg * Otherwise, we first parse an affine expression and push 2081 1.1 mrg * that onto the stream. If the affine expression covers the 2082 1.1 mrg * entire expression between parentheses, we return. 2083 1.1 mrg * Otherwise, we assume that the affine expression is the 2084 1.1 mrg * start of a condition and continue parsing. 2085 1.1 mrg */ 2086 1.1 mrg static int resolve_paren_expr(__isl_keep isl_stream *s, 2087 1.1 mrg struct vars *v, __isl_take isl_map *map, int rational) 2088 1.1 mrg { 2089 1.1 mrg struct isl_token *tok, *tok2; 2090 1.1 mrg int has_paren; 2091 1.1 mrg int line, col; 2092 1.1 mrg isl_pw_aff *pwaff; 2093 1.1 mrg 2094 1.1 mrg tok = isl_stream_next_token(s); 2095 1.1 mrg if (!tok || tok->type != '(') 2096 1.1 mrg goto error; 2097 1.1 mrg 2098 1.1 mrg if (isl_stream_next_token_is(s, '(')) 2099 1.1 mrg if (resolve_paren_expr(s, v, isl_map_copy(map), rational)) 2100 1.1 mrg goto error; 2101 1.1 mrg 2102 1.1 mrg if (next_is_condition_start(s)) { 2103 1.1 mrg map = read_formula(s, v, map, rational); 2104 1.1 mrg if (isl_stream_eat(s, ')')) 2105 1.1 mrg goto error; 2106 1.1 mrg tok->type = ISL_TOKEN_MAP; 2107 1.1 mrg tok->u.map = map; 2108 1.1 mrg isl_stream_push_token(s, tok); 2109 1.1 mrg return 0; 2110 1.1 mrg } 2111 1.1 mrg 2112 1.1 mrg tok2 = isl_stream_next_token(s); 2113 1.1 mrg if (!tok2) 2114 1.1 mrg goto error; 2115 1.1 mrg line = tok2->line; 2116 1.1 mrg col = tok2->col; 2117 1.1 mrg isl_stream_push_token(s, tok2); 2118 1.1 mrg 2119 1.1 mrg pwaff = accept_affine(s, isl_space_wrap(isl_map_get_space(map)), v); 2120 1.1 mrg if (!pwaff) 2121 1.1 mrg goto error; 2122 1.1 mrg 2123 1.1 mrg has_paren = isl_stream_eat_if_available(s, ')'); 2124 1.1 mrg 2125 1.1 mrg if (push_aff(s, line, col, pwaff) < 0) 2126 1.1 mrg goto error; 2127 1.1 mrg 2128 1.1 mrg if (has_paren) { 2129 1.1 mrg isl_token_free(tok); 2130 1.1 mrg isl_map_free(map); 2131 1.1 mrg return 0; 2132 1.1 mrg } 2133 1.1 mrg 2134 1.1 mrg map = read_formula(s, v, map, rational); 2135 1.1 mrg if (isl_stream_eat(s, ')')) 2136 1.1 mrg goto error; 2137 1.1 mrg 2138 1.1 mrg tok->type = ISL_TOKEN_MAP; 2139 1.1 mrg tok->u.map = map; 2140 1.1 mrg isl_stream_push_token(s, tok); 2141 1.1 mrg 2142 1.1 mrg return 0; 2143 1.1 mrg error: 2144 1.1 mrg isl_token_free(tok); 2145 1.1 mrg isl_map_free(map); 2146 1.1 mrg return -1; 2147 1.1 mrg } 2148 1.1 mrg 2149 1.1 mrg static __isl_give isl_map *read_conjunct(__isl_keep isl_stream *s, 2150 1.1 mrg struct vars *v, __isl_take isl_map *map, int rational) 2151 1.1 mrg { 2152 1.1 mrg if (isl_stream_next_token_is(s, '(')) 2153 1.1 mrg if (resolve_paren_expr(s, v, isl_map_copy(map), rational)) 2154 1.1 mrg goto error; 2155 1.1 mrg 2156 1.1 mrg if (isl_stream_next_token_is(s, ISL_TOKEN_MAP)) { 2157 1.1 mrg struct isl_token *tok; 2158 1.1 mrg tok = isl_stream_next_token(s); 2159 1.1 mrg if (!tok) 2160 1.1 mrg goto error; 2161 1.1 mrg isl_map_free(map); 2162 1.1 mrg map = isl_map_copy(tok->u.map); 2163 1.1 mrg isl_token_free(tok); 2164 1.1 mrg return map; 2165 1.1 mrg } 2166 1.1 mrg 2167 1.1 mrg if (isl_stream_eat_if_available(s, ISL_TOKEN_EXISTS)) 2168 1.1 mrg return read_exists(s, v, map, rational); 2169 1.1 mrg 2170 1.1 mrg if (isl_stream_eat_if_available(s, ISL_TOKEN_TRUE)) 2171 1.1 mrg return map; 2172 1.1 mrg 2173 1.1 mrg if (isl_stream_eat_if_available(s, ISL_TOKEN_FALSE)) { 2174 1.1 mrg isl_space *space = isl_map_get_space(map); 2175 1.1 mrg isl_map_free(map); 2176 1.1 mrg return isl_map_empty(space); 2177 1.1 mrg } 2178 1.1 mrg 2179 1.1 mrg return add_constraint(s, v, map, rational); 2180 1.1 mrg error: 2181 1.1 mrg isl_map_free(map); 2182 1.1 mrg return NULL; 2183 1.1 mrg } 2184 1.1 mrg 2185 1.1 mrg static __isl_give isl_map *read_conjuncts(__isl_keep isl_stream *s, 2186 1.1 mrg struct vars *v, __isl_take isl_map *map, int rational) 2187 1.1 mrg { 2188 1.1 mrg isl_map *res; 2189 1.1 mrg int negate; 2190 1.1 mrg 2191 1.1 mrg negate = isl_stream_eat_if_available(s, ISL_TOKEN_NOT); 2192 1.1 mrg res = read_conjunct(s, v, isl_map_copy(map), rational); 2193 1.1 mrg if (negate) 2194 1.1 mrg res = isl_map_subtract(isl_map_copy(map), res); 2195 1.1 mrg 2196 1.1 mrg while (res && isl_stream_eat_if_available(s, ISL_TOKEN_AND)) { 2197 1.1 mrg isl_map *res_i; 2198 1.1 mrg 2199 1.1 mrg negate = isl_stream_eat_if_available(s, ISL_TOKEN_NOT); 2200 1.1 mrg res_i = read_conjunct(s, v, isl_map_copy(map), rational); 2201 1.1 mrg if (negate) 2202 1.1 mrg res = isl_map_subtract(res, res_i); 2203 1.1 mrg else 2204 1.1 mrg res = isl_map_intersect(res, res_i); 2205 1.1 mrg } 2206 1.1 mrg 2207 1.1 mrg isl_map_free(map); 2208 1.1 mrg return res; 2209 1.1 mrg } 2210 1.1 mrg 2211 1.1 mrg static __isl_give isl_map *read_disjuncts(__isl_keep isl_stream *s, 2212 1.1 mrg struct vars *v, __isl_take isl_map *map, int rational) 2213 1.1 mrg { 2214 1.1 mrg isl_map *res; 2215 1.1 mrg 2216 1.1 mrg if (isl_stream_next_token_is(s, '}')) 2217 1.1 mrg return map; 2218 1.1 mrg 2219 1.1 mrg res = read_conjuncts(s, v, isl_map_copy(map), rational); 2220 1.1 mrg while (isl_stream_eat_if_available(s, ISL_TOKEN_OR)) { 2221 1.1 mrg isl_map *res_i; 2222 1.1 mrg 2223 1.1 mrg res_i = read_conjuncts(s, v, isl_map_copy(map), rational); 2224 1.1 mrg res = isl_map_union(res, res_i); 2225 1.1 mrg } 2226 1.1 mrg 2227 1.1 mrg isl_map_free(map); 2228 1.1 mrg return res; 2229 1.1 mrg } 2230 1.1 mrg 2231 1.1 mrg /* Read a first order formula from "s", add the corresponding 2232 1.1 mrg * constraints to "map" and return the result. 2233 1.1 mrg * 2234 1.1 mrg * In particular, read a formula of the form 2235 1.1 mrg * 2236 1.1 mrg * a 2237 1.1 mrg * 2238 1.1 mrg * or 2239 1.1 mrg * 2240 1.1 mrg * a implies b 2241 1.1 mrg * 2242 1.1 mrg * where a and b are disjunctions. 2243 1.1 mrg * 2244 1.1 mrg * In the first case, map is replaced by 2245 1.1 mrg * 2246 1.1 mrg * map \cap { [..] : a } 2247 1.1 mrg * 2248 1.1 mrg * In the second case, it is replaced by 2249 1.1 mrg * 2250 1.1 mrg * (map \setminus { [..] : a}) \cup (map \cap { [..] : b }) 2251 1.1 mrg */ 2252 1.1 mrg static __isl_give isl_map *read_formula(__isl_keep isl_stream *s, 2253 1.1 mrg struct vars *v, __isl_take isl_map *map, int rational) 2254 1.1 mrg { 2255 1.1 mrg isl_map *res; 2256 1.1 mrg 2257 1.1 mrg res = read_disjuncts(s, v, isl_map_copy(map), rational); 2258 1.1 mrg 2259 1.1 mrg if (isl_stream_eat_if_available(s, ISL_TOKEN_IMPLIES)) { 2260 1.1 mrg isl_map *res2; 2261 1.1 mrg 2262 1.1 mrg res = isl_map_subtract(isl_map_copy(map), res); 2263 1.1 mrg res2 = read_disjuncts(s, v, map, rational); 2264 1.1 mrg res = isl_map_union(res, res2); 2265 1.1 mrg } else 2266 1.1 mrg isl_map_free(map); 2267 1.1 mrg 2268 1.1 mrg return res; 2269 1.1 mrg } 2270 1.1 mrg 2271 1.1 mrg static isl_size polylib_pos_to_isl_pos(__isl_keep isl_basic_map *bmap, int pos) 2272 1.1 mrg { 2273 1.1 mrg isl_size n_out, n_in, n_param, n_div; 2274 1.1 mrg 2275 1.1 mrg n_param = isl_basic_map_dim(bmap, isl_dim_param); 2276 1.1 mrg n_in = isl_basic_map_dim(bmap, isl_dim_in); 2277 1.1 mrg n_out = isl_basic_map_dim(bmap, isl_dim_out); 2278 1.1 mrg n_div = isl_basic_map_dim(bmap, isl_dim_div); 2279 1.1 mrg if (n_param < 0 || n_in < 0 || n_out < 0 || n_div < 0) 2280 1.1 mrg return isl_size_error; 2281 1.1 mrg 2282 1.1 mrg if (pos < n_out) 2283 1.1 mrg return 1 + n_param + n_in + pos; 2284 1.1 mrg pos -= n_out; 2285 1.1 mrg 2286 1.1 mrg if (pos < n_in) 2287 1.1 mrg return 1 + n_param + pos; 2288 1.1 mrg pos -= n_in; 2289 1.1 mrg 2290 1.1 mrg if (pos < n_div) 2291 1.1 mrg return 1 + n_param + n_in + n_out + pos; 2292 1.1 mrg pos -= n_div; 2293 1.1 mrg 2294 1.1 mrg if (pos < n_param) 2295 1.1 mrg return 1 + pos; 2296 1.1 mrg 2297 1.1 mrg return 0; 2298 1.1 mrg } 2299 1.1 mrg 2300 1.1 mrg static __isl_give isl_basic_map *basic_map_read_polylib_constraint( 2301 1.1 mrg __isl_keep isl_stream *s, __isl_take isl_basic_map *bmap) 2302 1.1 mrg { 2303 1.1 mrg int j; 2304 1.1 mrg struct isl_token *tok; 2305 1.1 mrg int type; 2306 1.1 mrg int k; 2307 1.1 mrg isl_int *c; 2308 1.1 mrg isl_size total; 2309 1.1 mrg 2310 1.1 mrg if (!bmap) 2311 1.1 mrg return NULL; 2312 1.1 mrg 2313 1.1 mrg tok = isl_stream_next_token(s); 2314 1.1 mrg if (!tok || tok->type != ISL_TOKEN_VALUE) { 2315 1.1 mrg isl_stream_error(s, tok, "expecting coefficient"); 2316 1.1 mrg isl_token_free(tok); 2317 1.1 mrg goto error; 2318 1.1 mrg } 2319 1.1 mrg if (!tok->on_new_line) { 2320 1.1 mrg isl_stream_error(s, tok, "coefficient should appear on new line"); 2321 1.1 mrg isl_token_free(tok); 2322 1.1 mrg goto error; 2323 1.1 mrg } 2324 1.1 mrg 2325 1.1 mrg type = isl_int_get_si(tok->u.v); 2326 1.1 mrg isl_token_free(tok); 2327 1.1 mrg 2328 1.1 mrg isl_assert(s->ctx, type == 0 || type == 1, goto error); 2329 1.1 mrg if (type == 0) { 2330 1.1 mrg k = isl_basic_map_alloc_equality(bmap); 2331 1.1 mrg c = bmap->eq[k]; 2332 1.1 mrg } else { 2333 1.1 mrg k = isl_basic_map_alloc_inequality(bmap); 2334 1.1 mrg c = bmap->ineq[k]; 2335 1.1 mrg } 2336 1.1 mrg if (k < 0) 2337 1.1 mrg goto error; 2338 1.1 mrg 2339 1.1 mrg total = isl_basic_map_dim(bmap, isl_dim_all); 2340 1.1 mrg if (total < 0) 2341 1.1 mrg return isl_basic_map_free(bmap); 2342 1.1 mrg for (j = 0; j < 1 + total; ++j) { 2343 1.1 mrg isl_size pos; 2344 1.1 mrg tok = next_signed_value_on_same_line(s, 2345 1.1 mrg "expecting coefficient on same line"); 2346 1.1 mrg if (!tok) 2347 1.1 mrg goto error; 2348 1.1 mrg pos = polylib_pos_to_isl_pos(bmap, j); 2349 1.1 mrg if (pos >= 0) 2350 1.1 mrg isl_int_set(c[pos], tok->u.v); 2351 1.1 mrg isl_token_free(tok); 2352 1.1 mrg if (pos < 0) 2353 1.1 mrg return isl_basic_map_free(bmap); 2354 1.1 mrg } 2355 1.1 mrg 2356 1.1 mrg return bmap; 2357 1.1 mrg error: 2358 1.1 mrg isl_basic_map_free(bmap); 2359 1.1 mrg return NULL; 2360 1.1 mrg } 2361 1.1 mrg 2362 1.1 mrg static __isl_give isl_basic_map *basic_map_read_polylib( 2363 1.1 mrg __isl_keep isl_stream *s) 2364 1.1 mrg { 2365 1.1 mrg int i; 2366 1.1 mrg struct isl_token *tok; 2367 1.1 mrg struct isl_token *tok2; 2368 1.1 mrg int n_row, n_col; 2369 1.1 mrg int on_new_line; 2370 1.1 mrg unsigned in = 0, out, local = 0; 2371 1.1 mrg struct isl_basic_map *bmap = NULL; 2372 1.1 mrg int nparam = 0; 2373 1.1 mrg 2374 1.1 mrg tok = isl_stream_next_token(s); 2375 1.1 mrg if (!tok) { 2376 1.1 mrg isl_stream_error(s, NULL, "unexpected EOF"); 2377 1.1 mrg return NULL; 2378 1.1 mrg } 2379 1.1 mrg tok2 = isl_stream_next_token(s); 2380 1.1 mrg if (!tok2) { 2381 1.1 mrg isl_token_free(tok); 2382 1.1 mrg isl_stream_error(s, NULL, "unexpected EOF"); 2383 1.1 mrg return NULL; 2384 1.1 mrg } 2385 1.1 mrg if (tok->type != ISL_TOKEN_VALUE || tok2->type != ISL_TOKEN_VALUE) { 2386 1.1 mrg isl_token_free(tok2); 2387 1.1 mrg isl_token_free(tok); 2388 1.1 mrg isl_stream_error(s, NULL, 2389 1.1 mrg "expecting constraint matrix dimensions"); 2390 1.1 mrg return NULL; 2391 1.1 mrg } 2392 1.1 mrg n_row = isl_int_get_si(tok->u.v); 2393 1.1 mrg n_col = isl_int_get_si(tok2->u.v); 2394 1.1 mrg on_new_line = tok2->on_new_line; 2395 1.1 mrg isl_token_free(tok2); 2396 1.1 mrg isl_token_free(tok); 2397 1.1 mrg isl_assert(s->ctx, !on_new_line, return NULL); 2398 1.1 mrg isl_assert(s->ctx, n_row >= 0, return NULL); 2399 1.1 mrg isl_assert(s->ctx, n_col >= 2 + nparam, return NULL); 2400 1.1 mrg tok = isl_stream_next_token_on_same_line(s); 2401 1.1 mrg if (tok) { 2402 1.1 mrg if (tok->type != ISL_TOKEN_VALUE) { 2403 1.1 mrg isl_stream_error(s, tok, 2404 1.1 mrg "expecting number of output dimensions"); 2405 1.1 mrg isl_token_free(tok); 2406 1.1 mrg goto error; 2407 1.1 mrg } 2408 1.1 mrg out = isl_int_get_si(tok->u.v); 2409 1.1 mrg isl_token_free(tok); 2410 1.1 mrg 2411 1.1 mrg tok = isl_stream_next_token_on_same_line(s); 2412 1.1 mrg if (!tok || tok->type != ISL_TOKEN_VALUE) { 2413 1.1 mrg isl_stream_error(s, tok, 2414 1.1 mrg "expecting number of input dimensions"); 2415 1.1 mrg isl_token_free(tok); 2416 1.1 mrg goto error; 2417 1.1 mrg } 2418 1.1 mrg in = isl_int_get_si(tok->u.v); 2419 1.1 mrg isl_token_free(tok); 2420 1.1 mrg 2421 1.1 mrg tok = isl_stream_next_token_on_same_line(s); 2422 1.1 mrg if (!tok || tok->type != ISL_TOKEN_VALUE) { 2423 1.1 mrg isl_stream_error(s, tok, 2424 1.1 mrg "expecting number of existentials"); 2425 1.1 mrg isl_token_free(tok); 2426 1.1 mrg goto error; 2427 1.1 mrg } 2428 1.1 mrg local = isl_int_get_si(tok->u.v); 2429 1.1 mrg isl_token_free(tok); 2430 1.1 mrg 2431 1.1 mrg tok = isl_stream_next_token_on_same_line(s); 2432 1.1 mrg if (!tok || tok->type != ISL_TOKEN_VALUE) { 2433 1.1 mrg isl_stream_error(s, tok, 2434 1.1 mrg "expecting number of parameters"); 2435 1.1 mrg isl_token_free(tok); 2436 1.1 mrg goto error; 2437 1.1 mrg } 2438 1.1 mrg nparam = isl_int_get_si(tok->u.v); 2439 1.1 mrg isl_token_free(tok); 2440 1.1 mrg if (n_col != 1 + out + in + local + nparam + 1) { 2441 1.1 mrg isl_stream_error(s, NULL, 2442 1.1 mrg "dimensions don't match"); 2443 1.1 mrg goto error; 2444 1.1 mrg } 2445 1.1 mrg } else 2446 1.1 mrg out = n_col - 2 - nparam; 2447 1.1 mrg bmap = isl_basic_map_alloc(s->ctx, nparam, in, out, local, n_row, n_row); 2448 1.1 mrg if (!bmap) 2449 1.1 mrg return NULL; 2450 1.1 mrg 2451 1.1 mrg for (i = 0; i < local; ++i) { 2452 1.1 mrg int k = isl_basic_map_alloc_div(bmap); 2453 1.1 mrg if (k < 0) 2454 1.1 mrg goto error; 2455 1.1 mrg isl_seq_clr(bmap->div[k], 1 + 1 + nparam + in + out + local); 2456 1.1 mrg } 2457 1.1 mrg 2458 1.1 mrg for (i = 0; i < n_row; ++i) 2459 1.1 mrg bmap = basic_map_read_polylib_constraint(s, bmap); 2460 1.1 mrg 2461 1.1 mrg if (!bmap) 2462 1.1 mrg return NULL; 2463 1.1 mrg 2464 1.1 mrg tok = isl_stream_next_token_on_same_line(s); 2465 1.1 mrg if (tok) { 2466 1.1 mrg isl_stream_error(s, tok, "unexpected extra token on line"); 2467 1.1 mrg isl_token_free(tok); 2468 1.1 mrg goto error; 2469 1.1 mrg } 2470 1.1 mrg 2471 1.1 mrg bmap = isl_basic_map_simplify(bmap); 2472 1.1 mrg bmap = isl_basic_map_finalize(bmap); 2473 1.1 mrg return bmap; 2474 1.1 mrg error: 2475 1.1 mrg isl_basic_map_free(bmap); 2476 1.1 mrg return NULL; 2477 1.1 mrg } 2478 1.1 mrg 2479 1.1 mrg static __isl_give isl_map *map_read_polylib(__isl_keep isl_stream *s) 2480 1.1 mrg { 2481 1.1 mrg struct isl_token *tok; 2482 1.1 mrg struct isl_token *tok2; 2483 1.1 mrg int i, n; 2484 1.1 mrg struct isl_map *map; 2485 1.1 mrg 2486 1.1 mrg tok = isl_stream_next_token(s); 2487 1.1 mrg if (!tok) { 2488 1.1 mrg isl_stream_error(s, NULL, "unexpected EOF"); 2489 1.1 mrg return NULL; 2490 1.1 mrg } 2491 1.1 mrg tok2 = isl_stream_next_token_on_same_line(s); 2492 1.1 mrg if (tok2 && tok2->type == ISL_TOKEN_VALUE) { 2493 1.1 mrg isl_stream_push_token(s, tok2); 2494 1.1 mrg isl_stream_push_token(s, tok); 2495 1.1 mrg return isl_map_from_basic_map(basic_map_read_polylib(s)); 2496 1.1 mrg } 2497 1.1 mrg if (tok2) { 2498 1.1 mrg isl_stream_error(s, tok2, "unexpected token"); 2499 1.1 mrg isl_stream_push_token(s, tok2); 2500 1.1 mrg isl_stream_push_token(s, tok); 2501 1.1 mrg return NULL; 2502 1.1 mrg } 2503 1.1 mrg n = isl_int_get_si(tok->u.v); 2504 1.1 mrg isl_token_free(tok); 2505 1.1 mrg 2506 1.1 mrg isl_assert(s->ctx, n >= 1, return NULL); 2507 1.1 mrg 2508 1.1 mrg map = isl_map_from_basic_map(basic_map_read_polylib(s)); 2509 1.1 mrg 2510 1.1 mrg for (i = 1; map && i < n; ++i) 2511 1.1 mrg map = isl_map_union(map, 2512 1.1 mrg isl_map_from_basic_map(basic_map_read_polylib(s))); 2513 1.1 mrg 2514 1.1 mrg return map; 2515 1.1 mrg } 2516 1.1 mrg 2517 1.1 mrg static int optional_power(__isl_keep isl_stream *s) 2518 1.1 mrg { 2519 1.1 mrg int pow; 2520 1.1 mrg struct isl_token *tok; 2521 1.1 mrg 2522 1.1 mrg tok = isl_stream_next_token(s); 2523 1.1 mrg if (!tok) 2524 1.1 mrg return 1; 2525 1.1 mrg if (tok->type != '^') { 2526 1.1 mrg isl_stream_push_token(s, tok); 2527 1.1 mrg return 1; 2528 1.1 mrg } 2529 1.1 mrg isl_token_free(tok); 2530 1.1 mrg tok = isl_stream_next_token(s); 2531 1.1 mrg if (!tok || tok->type != ISL_TOKEN_VALUE) { 2532 1.1 mrg isl_stream_error(s, tok, "expecting exponent"); 2533 1.1 mrg if (tok) 2534 1.1 mrg isl_stream_push_token(s, tok); 2535 1.1 mrg return 1; 2536 1.1 mrg } 2537 1.1 mrg pow = isl_int_get_si(tok->u.v); 2538 1.1 mrg isl_token_free(tok); 2539 1.1 mrg return pow; 2540 1.1 mrg } 2541 1.1 mrg 2542 1.1 mrg static __isl_give isl_pw_qpolynomial *read_term(__isl_keep isl_stream *s, 2543 1.1 mrg __isl_keep isl_map *map, struct vars *v); 2544 1.1 mrg 2545 1.1 mrg static __isl_give isl_pw_qpolynomial *read_factor(__isl_keep isl_stream *s, 2546 1.1 mrg __isl_keep isl_map *map, struct vars *v) 2547 1.1 mrg { 2548 1.1 mrg isl_pw_qpolynomial *pwqp; 2549 1.1 mrg struct isl_token *tok; 2550 1.1 mrg 2551 1.1 mrg tok = next_token(s); 2552 1.1 mrg if (!tok) { 2553 1.1 mrg isl_stream_error(s, NULL, "unexpected EOF"); 2554 1.1 mrg return NULL; 2555 1.1 mrg } 2556 1.1 mrg if (tok->type == '(') { 2557 1.1 mrg int pow; 2558 1.1 mrg 2559 1.1 mrg isl_token_free(tok); 2560 1.1 mrg pwqp = read_term(s, map, v); 2561 1.1 mrg if (!pwqp) 2562 1.1 mrg return NULL; 2563 1.1 mrg if (isl_stream_eat(s, ')')) 2564 1.1 mrg goto error; 2565 1.1 mrg pow = optional_power(s); 2566 1.1 mrg pwqp = isl_pw_qpolynomial_pow(pwqp, pow); 2567 1.1 mrg } else if (tok->type == ISL_TOKEN_VALUE) { 2568 1.1 mrg struct isl_token *tok2; 2569 1.1 mrg isl_qpolynomial *qp; 2570 1.1 mrg 2571 1.1 mrg tok2 = isl_stream_next_token(s); 2572 1.1 mrg if (tok2 && tok2->type == '/') { 2573 1.1 mrg isl_token_free(tok2); 2574 1.1 mrg tok2 = next_token(s); 2575 1.1 mrg if (!tok2 || tok2->type != ISL_TOKEN_VALUE) { 2576 1.1 mrg isl_stream_error(s, tok2, "expected denominator"); 2577 1.1 mrg isl_token_free(tok); 2578 1.1 mrg isl_token_free(tok2); 2579 1.1 mrg return NULL; 2580 1.1 mrg } 2581 1.1 mrg qp = isl_qpolynomial_rat_cst_on_domain(isl_map_get_space(map), 2582 1.1 mrg tok->u.v, tok2->u.v); 2583 1.1 mrg isl_token_free(tok2); 2584 1.1 mrg } else { 2585 1.1 mrg isl_stream_push_token(s, tok2); 2586 1.1 mrg qp = isl_qpolynomial_cst_on_domain(isl_map_get_space(map), 2587 1.1 mrg tok->u.v); 2588 1.1 mrg } 2589 1.1 mrg isl_token_free(tok); 2590 1.1 mrg pwqp = isl_pw_qpolynomial_from_qpolynomial(qp); 2591 1.1 mrg } else if (tok->type == ISL_TOKEN_INFTY) { 2592 1.1 mrg isl_qpolynomial *qp; 2593 1.1 mrg isl_token_free(tok); 2594 1.1 mrg qp = isl_qpolynomial_infty_on_domain(isl_map_get_space(map)); 2595 1.1 mrg pwqp = isl_pw_qpolynomial_from_qpolynomial(qp); 2596 1.1 mrg } else if (tok->type == ISL_TOKEN_NAN) { 2597 1.1 mrg isl_qpolynomial *qp; 2598 1.1 mrg isl_token_free(tok); 2599 1.1 mrg qp = isl_qpolynomial_nan_on_domain(isl_map_get_space(map)); 2600 1.1 mrg pwqp = isl_pw_qpolynomial_from_qpolynomial(qp); 2601 1.1 mrg } else if (tok->type == ISL_TOKEN_IDENT) { 2602 1.1 mrg int n = v->n; 2603 1.1 mrg int pos = vars_pos(v, tok->u.s, -1); 2604 1.1 mrg int pow; 2605 1.1 mrg isl_qpolynomial *qp; 2606 1.1 mrg if (pos < 0) { 2607 1.1 mrg isl_token_free(tok); 2608 1.1 mrg return NULL; 2609 1.1 mrg } 2610 1.1 mrg if (pos >= n) { 2611 1.1 mrg vars_drop(v, v->n - n); 2612 1.1 mrg isl_stream_error(s, tok, "unknown identifier"); 2613 1.1 mrg isl_token_free(tok); 2614 1.1 mrg return NULL; 2615 1.1 mrg } 2616 1.1 mrg isl_token_free(tok); 2617 1.1 mrg pow = optional_power(s); 2618 1.1 mrg qp = isl_qpolynomial_var_pow_on_domain(isl_map_get_space(map), pos, pow); 2619 1.1 mrg pwqp = isl_pw_qpolynomial_from_qpolynomial(qp); 2620 1.1 mrg } else if (is_start_of_div(tok)) { 2621 1.1 mrg isl_pw_aff *pwaff; 2622 1.1 mrg int pow; 2623 1.1 mrg 2624 1.1 mrg isl_stream_push_token(s, tok); 2625 1.1 mrg pwaff = accept_div(s, isl_map_get_space(map), v); 2626 1.1 mrg pow = optional_power(s); 2627 1.1 mrg pwqp = isl_pw_qpolynomial_from_pw_aff(pwaff); 2628 1.1 mrg pwqp = isl_pw_qpolynomial_pow(pwqp, pow); 2629 1.1 mrg } else if (tok->type == '-') { 2630 1.1 mrg isl_token_free(tok); 2631 1.1 mrg pwqp = read_factor(s, map, v); 2632 1.1 mrg pwqp = isl_pw_qpolynomial_neg(pwqp); 2633 1.1 mrg } else { 2634 1.1 mrg isl_stream_error(s, tok, "unexpected isl_token"); 2635 1.1 mrg isl_stream_push_token(s, tok); 2636 1.1 mrg return NULL; 2637 1.1 mrg } 2638 1.1 mrg 2639 1.1 mrg if (isl_stream_eat_if_available(s, '*') || 2640 1.1 mrg isl_stream_next_token_is(s, ISL_TOKEN_IDENT)) { 2641 1.1 mrg isl_pw_qpolynomial *pwqp2; 2642 1.1 mrg 2643 1.1 mrg pwqp2 = read_factor(s, map, v); 2644 1.1 mrg pwqp = isl_pw_qpolynomial_mul(pwqp, pwqp2); 2645 1.1 mrg } 2646 1.1 mrg 2647 1.1 mrg return pwqp; 2648 1.1 mrg error: 2649 1.1 mrg isl_pw_qpolynomial_free(pwqp); 2650 1.1 mrg return NULL; 2651 1.1 mrg } 2652 1.1 mrg 2653 1.1 mrg static __isl_give isl_pw_qpolynomial *read_term(__isl_keep isl_stream *s, 2654 1.1 mrg __isl_keep isl_map *map, struct vars *v) 2655 1.1 mrg { 2656 1.1 mrg struct isl_token *tok; 2657 1.1 mrg isl_pw_qpolynomial *pwqp; 2658 1.1 mrg 2659 1.1 mrg pwqp = read_factor(s, map, v); 2660 1.1 mrg 2661 1.1 mrg for (;;) { 2662 1.1 mrg tok = next_token(s); 2663 1.1 mrg if (!tok) 2664 1.1 mrg return pwqp; 2665 1.1 mrg 2666 1.1 mrg if (tok->type == '+') { 2667 1.1 mrg isl_pw_qpolynomial *pwqp2; 2668 1.1 mrg 2669 1.1 mrg isl_token_free(tok); 2670 1.1 mrg pwqp2 = read_factor(s, map, v); 2671 1.1 mrg pwqp = isl_pw_qpolynomial_add(pwqp, pwqp2); 2672 1.1 mrg } else if (tok->type == '-') { 2673 1.1 mrg isl_pw_qpolynomial *pwqp2; 2674 1.1 mrg 2675 1.1 mrg isl_token_free(tok); 2676 1.1 mrg pwqp2 = read_factor(s, map, v); 2677 1.1 mrg pwqp = isl_pw_qpolynomial_sub(pwqp, pwqp2); 2678 1.1 mrg } else { 2679 1.1 mrg isl_stream_push_token(s, tok); 2680 1.1 mrg break; 2681 1.1 mrg } 2682 1.1 mrg } 2683 1.1 mrg 2684 1.1 mrg return pwqp; 2685 1.1 mrg } 2686 1.1 mrg 2687 1.1 mrg static __isl_give isl_map *read_optional_formula(__isl_keep isl_stream *s, 2688 1.1 mrg __isl_take isl_map *map, struct vars *v, int rational) 2689 1.1 mrg { 2690 1.1 mrg struct isl_token *tok; 2691 1.1 mrg 2692 1.1 mrg tok = isl_stream_next_token(s); 2693 1.1 mrg if (!tok) { 2694 1.1 mrg isl_stream_error(s, NULL, "unexpected EOF"); 2695 1.1 mrg goto error; 2696 1.1 mrg } 2697 1.1 mrg if (tok->type == ':' || 2698 1.1 mrg (tok->type == ISL_TOKEN_OR && !strcmp(tok->u.s, "|"))) { 2699 1.1 mrg isl_token_free(tok); 2700 1.1 mrg map = read_formula(s, v, map, rational); 2701 1.1 mrg } else 2702 1.1 mrg isl_stream_push_token(s, tok); 2703 1.1 mrg 2704 1.1 mrg return map; 2705 1.1 mrg error: 2706 1.1 mrg isl_map_free(map); 2707 1.1 mrg return NULL; 2708 1.1 mrg } 2709 1.1 mrg 2710 1.1 mrg static struct isl_obj obj_read_poly(__isl_keep isl_stream *s, 2711 1.1 mrg __isl_take isl_map *map, struct vars *v, int n) 2712 1.1 mrg { 2713 1.1 mrg struct isl_obj obj = { isl_obj_pw_qpolynomial, NULL }; 2714 1.1 mrg isl_pw_qpolynomial *pwqp; 2715 1.1 mrg struct isl_set *set; 2716 1.1 mrg 2717 1.1 mrg pwqp = read_term(s, map, v); 2718 1.1 mrg map = read_optional_formula(s, map, v, 0); 2719 1.1 mrg set = isl_map_range(map); 2720 1.1 mrg 2721 1.1 mrg pwqp = isl_pw_qpolynomial_intersect_domain(pwqp, set); 2722 1.1 mrg 2723 1.1 mrg vars_drop(v, v->n - n); 2724 1.1 mrg 2725 1.1 mrg obj.v = pwqp; 2726 1.1 mrg return obj; 2727 1.1 mrg } 2728 1.1 mrg 2729 1.1 mrg static struct isl_obj obj_read_poly_or_fold(__isl_keep isl_stream *s, 2730 1.1 mrg __isl_take isl_set *set, struct vars *v, int n) 2731 1.1 mrg { 2732 1.1 mrg int min, max; 2733 1.1 mrg struct isl_obj obj = { isl_obj_pw_qpolynomial_fold, NULL }; 2734 1.1 mrg isl_pw_qpolynomial *pwqp; 2735 1.1 mrg isl_pw_qpolynomial_fold *pwf = NULL; 2736 1.1 mrg enum isl_fold fold; 2737 1.1 mrg 2738 1.1 mrg max = isl_stream_eat_if_available(s, ISL_TOKEN_MAX); 2739 1.1 mrg min = !max && isl_stream_eat_if_available(s, ISL_TOKEN_MIN); 2740 1.1 mrg if (!min && !max) 2741 1.1 mrg return obj_read_poly(s, set, v, n); 2742 1.1 mrg fold = max ? isl_fold_max : isl_fold_min; 2743 1.1 mrg 2744 1.1 mrg if (isl_stream_eat(s, '(')) 2745 1.1 mrg goto error; 2746 1.1 mrg 2747 1.1 mrg pwqp = read_term(s, set, v); 2748 1.1 mrg pwf = isl_pw_qpolynomial_fold_from_pw_qpolynomial(fold, pwqp); 2749 1.1 mrg 2750 1.1 mrg while (isl_stream_eat_if_available(s, ',')) { 2751 1.1 mrg isl_pw_qpolynomial_fold *pwf_i; 2752 1.1 mrg pwqp = read_term(s, set, v); 2753 1.1 mrg pwf_i = isl_pw_qpolynomial_fold_from_pw_qpolynomial(fold, pwqp); 2754 1.1 mrg pwf = isl_pw_qpolynomial_fold_fold(pwf, pwf_i); 2755 1.1 mrg } 2756 1.1 mrg 2757 1.1 mrg if (isl_stream_eat(s, ')')) 2758 1.1 mrg goto error; 2759 1.1 mrg 2760 1.1 mrg set = read_optional_formula(s, set, v, 0); 2761 1.1 mrg pwf = isl_pw_qpolynomial_fold_intersect_domain(pwf, set); 2762 1.1 mrg 2763 1.1 mrg vars_drop(v, v->n - n); 2764 1.1 mrg 2765 1.1 mrg obj.v = pwf; 2766 1.1 mrg return obj; 2767 1.1 mrg error: 2768 1.1 mrg isl_set_free(set); 2769 1.1 mrg isl_pw_qpolynomial_fold_free(pwf); 2770 1.1 mrg obj.type = isl_obj_none; 2771 1.1 mrg return obj; 2772 1.1 mrg } 2773 1.1 mrg 2774 1.1 mrg static int is_rational(__isl_keep isl_stream *s) 2775 1.1 mrg { 2776 1.1 mrg struct isl_token *tok; 2777 1.1 mrg 2778 1.1 mrg tok = isl_stream_next_token(s); 2779 1.1 mrg if (!tok) 2780 1.1 mrg return 0; 2781 1.1 mrg if (tok->type == ISL_TOKEN_RAT && isl_stream_next_token_is(s, ':')) { 2782 1.1 mrg isl_token_free(tok); 2783 1.1 mrg isl_stream_eat(s, ':'); 2784 1.1 mrg return 1; 2785 1.1 mrg } 2786 1.1 mrg 2787 1.1 mrg isl_stream_push_token(s, tok); 2788 1.1 mrg 2789 1.1 mrg return 0; 2790 1.1 mrg } 2791 1.1 mrg 2792 1.1 mrg static struct isl_obj obj_read_body(__isl_keep isl_stream *s, 2793 1.1 mrg __isl_take isl_map *map, struct vars *v) 2794 1.1 mrg { 2795 1.1 mrg struct isl_token *tok; 2796 1.1 mrg struct isl_obj obj = { isl_obj_set, NULL }; 2797 1.1 mrg int n = v->n; 2798 1.1 mrg int rational; 2799 1.1 mrg 2800 1.1 mrg rational = is_rational(s); 2801 1.1 mrg if (rational) 2802 1.1 mrg map = isl_map_set_rational(map); 2803 1.1 mrg 2804 1.1 mrg if (isl_stream_next_token_is(s, ':')) { 2805 1.1 mrg obj.type = isl_obj_set; 2806 1.1 mrg obj.v = read_optional_formula(s, map, v, rational); 2807 1.1 mrg return obj; 2808 1.1 mrg } 2809 1.1 mrg 2810 1.1 mrg if (!next_is_tuple(s)) 2811 1.1 mrg return obj_read_poly_or_fold(s, map, v, n); 2812 1.1 mrg 2813 1.1 mrg map = read_map_tuple(s, map, isl_dim_in, v, 0); 2814 1.1 mrg if (!map) 2815 1.1 mrg goto error; 2816 1.1 mrg tok = isl_stream_next_token(s); 2817 1.1 mrg if (!tok) 2818 1.1 mrg goto error; 2819 1.1 mrg if (tok->type == ISL_TOKEN_TO) { 2820 1.1 mrg obj.type = isl_obj_map; 2821 1.1 mrg isl_token_free(tok); 2822 1.1 mrg if (!next_is_tuple(s)) { 2823 1.1 mrg isl_set *set = isl_map_domain(map); 2824 1.1 mrg return obj_read_poly_or_fold(s, set, v, n); 2825 1.1 mrg } 2826 1.1 mrg map = read_map_tuple(s, map, isl_dim_out, v, 0); 2827 1.1 mrg if (!map) 2828 1.1 mrg goto error; 2829 1.1 mrg } else { 2830 1.1 mrg map = isl_map_domain(map); 2831 1.1 mrg isl_stream_push_token(s, tok); 2832 1.1 mrg } 2833 1.1 mrg 2834 1.1 mrg map = read_optional_formula(s, map, v, rational); 2835 1.1 mrg 2836 1.1 mrg vars_drop(v, v->n - n); 2837 1.1 mrg 2838 1.1 mrg obj.v = map; 2839 1.1 mrg return obj; 2840 1.1 mrg error: 2841 1.1 mrg isl_map_free(map); 2842 1.1 mrg obj.type = isl_obj_none; 2843 1.1 mrg return obj; 2844 1.1 mrg } 2845 1.1 mrg 2846 1.1 mrg static struct isl_obj to_union(isl_ctx *ctx, struct isl_obj obj) 2847 1.1 mrg { 2848 1.1 mrg if (obj.type == isl_obj_map) { 2849 1.1 mrg obj.v = isl_union_map_from_map(obj.v); 2850 1.1 mrg obj.type = isl_obj_union_map; 2851 1.1 mrg } else if (obj.type == isl_obj_set) { 2852 1.1 mrg obj.v = isl_union_set_from_set(obj.v); 2853 1.1 mrg obj.type = isl_obj_union_set; 2854 1.1 mrg } else if (obj.type == isl_obj_pw_qpolynomial) { 2855 1.1 mrg obj.v = isl_union_pw_qpolynomial_from_pw_qpolynomial(obj.v); 2856 1.1 mrg obj.type = isl_obj_union_pw_qpolynomial; 2857 1.1 mrg } else if (obj.type == isl_obj_pw_qpolynomial_fold) { 2858 1.1 mrg obj.v = isl_union_pw_qpolynomial_fold_from_pw_qpolynomial_fold(obj.v); 2859 1.1 mrg obj.type = isl_obj_union_pw_qpolynomial_fold; 2860 1.1 mrg } else 2861 1.1 mrg isl_assert(ctx, 0, goto error); 2862 1.1 mrg return obj; 2863 1.1 mrg error: 2864 1.1 mrg obj.type->free(obj.v); 2865 1.1 mrg obj.type = isl_obj_none; 2866 1.1 mrg return obj; 2867 1.1 mrg } 2868 1.1 mrg 2869 1.1 mrg static struct isl_obj obj_add(__isl_keep isl_stream *s, 2870 1.1 mrg struct isl_obj obj1, struct isl_obj obj2) 2871 1.1 mrg { 2872 1.1 mrg if (obj2.type == isl_obj_none || !obj2.v) 2873 1.1 mrg goto error; 2874 1.1 mrg if (obj1.type == isl_obj_set && obj2.type == isl_obj_union_set) 2875 1.1 mrg obj1 = to_union(s->ctx, obj1); 2876 1.1 mrg if (obj1.type == isl_obj_union_set && obj2.type == isl_obj_set) 2877 1.1 mrg obj2 = to_union(s->ctx, obj2); 2878 1.1 mrg if (obj1.type == isl_obj_map && obj2.type == isl_obj_union_map) 2879 1.1 mrg obj1 = to_union(s->ctx, obj1); 2880 1.1 mrg if (obj1.type == isl_obj_union_map && obj2.type == isl_obj_map) 2881 1.1 mrg obj2 = to_union(s->ctx, obj2); 2882 1.1 mrg if (obj1.type == isl_obj_pw_qpolynomial && 2883 1.1 mrg obj2.type == isl_obj_union_pw_qpolynomial) 2884 1.1 mrg obj1 = to_union(s->ctx, obj1); 2885 1.1 mrg if (obj1.type == isl_obj_union_pw_qpolynomial && 2886 1.1 mrg obj2.type == isl_obj_pw_qpolynomial) 2887 1.1 mrg obj2 = to_union(s->ctx, obj2); 2888 1.1 mrg if (obj1.type == isl_obj_pw_qpolynomial_fold && 2889 1.1 mrg obj2.type == isl_obj_union_pw_qpolynomial_fold) 2890 1.1 mrg obj1 = to_union(s->ctx, obj1); 2891 1.1 mrg if (obj1.type == isl_obj_union_pw_qpolynomial_fold && 2892 1.1 mrg obj2.type == isl_obj_pw_qpolynomial_fold) 2893 1.1 mrg obj2 = to_union(s->ctx, obj2); 2894 1.1 mrg if (obj1.type != obj2.type) { 2895 1.1 mrg isl_stream_error(s, NULL, 2896 1.1 mrg "attempt to combine incompatible objects"); 2897 1.1 mrg goto error; 2898 1.1 mrg } 2899 1.1 mrg if (!obj1.type->add) 2900 1.1 mrg isl_die(s->ctx, isl_error_internal, 2901 1.1 mrg "combination not supported on object type", goto error); 2902 1.1 mrg if (obj1.type == isl_obj_map && !isl_map_has_equal_space(obj1.v, obj2.v)) { 2903 1.1 mrg obj1 = to_union(s->ctx, obj1); 2904 1.1 mrg obj2 = to_union(s->ctx, obj2); 2905 1.1 mrg } 2906 1.1 mrg if (obj1.type == isl_obj_set && !isl_set_has_equal_space(obj1.v, obj2.v)) { 2907 1.1 mrg obj1 = to_union(s->ctx, obj1); 2908 1.1 mrg obj2 = to_union(s->ctx, obj2); 2909 1.1 mrg } 2910 1.1 mrg if (obj1.type == isl_obj_pw_qpolynomial && 2911 1.1 mrg !isl_pw_qpolynomial_has_equal_space(obj1.v, obj2.v)) { 2912 1.1 mrg obj1 = to_union(s->ctx, obj1); 2913 1.1 mrg obj2 = to_union(s->ctx, obj2); 2914 1.1 mrg } 2915 1.1 mrg if (obj1.type == isl_obj_pw_qpolynomial_fold && 2916 1.1 mrg !isl_pw_qpolynomial_fold_has_equal_space(obj1.v, obj2.v)) { 2917 1.1 mrg obj1 = to_union(s->ctx, obj1); 2918 1.1 mrg obj2 = to_union(s->ctx, obj2); 2919 1.1 mrg } 2920 1.1 mrg obj1.v = obj1.type->add(obj1.v, obj2.v); 2921 1.1 mrg return obj1; 2922 1.1 mrg error: 2923 1.1 mrg obj1.type->free(obj1.v); 2924 1.1 mrg obj2.type->free(obj2.v); 2925 1.1 mrg obj1.type = isl_obj_none; 2926 1.1 mrg obj1.v = NULL; 2927 1.1 mrg return obj1; 2928 1.1 mrg } 2929 1.1 mrg 2930 1.1 mrg /* Are the first two tokens on "s", "domain" (either as a string 2931 1.1 mrg * or as an identifier) followed by ":"? 2932 1.1 mrg */ 2933 1.1 mrg static int next_is_domain_colon(__isl_keep isl_stream *s) 2934 1.1 mrg { 2935 1.1 mrg struct isl_token *tok; 2936 1.1 mrg char *name; 2937 1.1 mrg int res; 2938 1.1 mrg 2939 1.1 mrg tok = isl_stream_next_token(s); 2940 1.1 mrg if (!tok) 2941 1.1 mrg return 0; 2942 1.1 mrg if (tok->type != ISL_TOKEN_IDENT && tok->type != ISL_TOKEN_STRING) { 2943 1.1 mrg isl_stream_push_token(s, tok); 2944 1.1 mrg return 0; 2945 1.1 mrg } 2946 1.1 mrg 2947 1.1 mrg name = isl_token_get_str(s->ctx, tok); 2948 1.1 mrg res = !strcmp(name, "domain") && isl_stream_next_token_is(s, ':'); 2949 1.1 mrg free(name); 2950 1.1 mrg 2951 1.1 mrg isl_stream_push_token(s, tok); 2952 1.1 mrg 2953 1.1 mrg return res; 2954 1.1 mrg } 2955 1.1 mrg 2956 1.1 mrg /* Do the first tokens on "s" look like a schedule? 2957 1.1 mrg * 2958 1.1 mrg * The root of a schedule is always a domain node, so the first thing 2959 1.1 mrg * we expect in the stream is a domain key, i.e., "domain" followed 2960 1.1 mrg * by ":". If the schedule was printed in YAML flow style, then 2961 1.1 mrg * we additionally expect a "{" to open the outer mapping. 2962 1.1 mrg */ 2963 1.1 mrg static int next_is_schedule(__isl_keep isl_stream *s) 2964 1.1 mrg { 2965 1.1 mrg struct isl_token *tok; 2966 1.1 mrg int is_schedule; 2967 1.1 mrg 2968 1.1 mrg tok = isl_stream_next_token(s); 2969 1.1 mrg if (!tok) 2970 1.1 mrg return 0; 2971 1.1 mrg if (tok->type != '{') { 2972 1.1 mrg isl_stream_push_token(s, tok); 2973 1.1 mrg return next_is_domain_colon(s); 2974 1.1 mrg } 2975 1.1 mrg 2976 1.1 mrg is_schedule = next_is_domain_colon(s); 2977 1.1 mrg isl_stream_push_token(s, tok); 2978 1.1 mrg 2979 1.1 mrg return is_schedule; 2980 1.1 mrg } 2981 1.1 mrg 2982 1.1 mrg /* Read an isl_schedule from "s" and store it in an isl_obj. 2983 1.1 mrg */ 2984 1.1 mrg static struct isl_obj schedule_read(__isl_keep isl_stream *s) 2985 1.1 mrg { 2986 1.1 mrg struct isl_obj obj; 2987 1.1 mrg 2988 1.1 mrg obj.type = isl_obj_schedule; 2989 1.1 mrg obj.v = isl_stream_read_schedule(s); 2990 1.1 mrg 2991 1.1 mrg return obj; 2992 1.1 mrg } 2993 1.1 mrg 2994 1.1 mrg /* Read a disjunction of object bodies from "s". 2995 1.1 mrg * That is, read the inside of the braces, but not the braces themselves. 2996 1.1 mrg * "v" contains a description of the identifiers parsed so far. 2997 1.1 mrg * "map" contains information about the parameters. 2998 1.1 mrg */ 2999 1.1 mrg static struct isl_obj obj_read_disjuncts(__isl_keep isl_stream *s, 3000 1.1 mrg struct vars *v, __isl_keep isl_map *map) 3001 1.1 mrg { 3002 1.1 mrg struct isl_obj obj = { isl_obj_set, NULL }; 3003 1.1 mrg 3004 1.1 mrg if (isl_stream_next_token_is(s, '}')) { 3005 1.1 mrg obj.type = isl_obj_union_set; 3006 1.1 mrg obj.v = isl_union_set_empty(isl_map_get_space(map)); 3007 1.1 mrg return obj; 3008 1.1 mrg } 3009 1.1 mrg 3010 1.1 mrg for (;;) { 3011 1.1 mrg struct isl_obj o; 3012 1.1 mrg o = obj_read_body(s, isl_map_copy(map), v); 3013 1.1 mrg if (!obj.v) 3014 1.1 mrg obj = o; 3015 1.1 mrg else 3016 1.1 mrg obj = obj_add(s, obj, o); 3017 1.1 mrg if (obj.type == isl_obj_none || !obj.v) 3018 1.1 mrg return obj; 3019 1.1 mrg if (!isl_stream_eat_if_available(s, ';')) 3020 1.1 mrg break; 3021 1.1 mrg if (isl_stream_next_token_is(s, '}')) 3022 1.1 mrg break; 3023 1.1 mrg } 3024 1.1 mrg 3025 1.1 mrg return obj; 3026 1.1 mrg } 3027 1.1 mrg 3028 1.1 mrg static struct isl_obj obj_read(__isl_keep isl_stream *s) 3029 1.1 mrg { 3030 1.1 mrg isl_map *map = NULL; 3031 1.1 mrg struct isl_token *tok; 3032 1.1 mrg struct vars *v = NULL; 3033 1.1 mrg struct isl_obj obj = { isl_obj_set, NULL }; 3034 1.1 mrg 3035 1.1 mrg if (next_is_schedule(s)) 3036 1.1 mrg return schedule_read(s); 3037 1.1 mrg 3038 1.1 mrg tok = next_token(s); 3039 1.1 mrg if (!tok) { 3040 1.1 mrg isl_stream_error(s, NULL, "unexpected EOF"); 3041 1.1 mrg goto error; 3042 1.1 mrg } 3043 1.1 mrg if (tok->type == ISL_TOKEN_VALUE) { 3044 1.1 mrg struct isl_token *tok2; 3045 1.1 mrg struct isl_map *map; 3046 1.1 mrg 3047 1.1 mrg tok2 = isl_stream_next_token(s); 3048 1.1 mrg if (!tok2 || tok2->type != ISL_TOKEN_VALUE || 3049 1.1 mrg isl_int_is_neg(tok2->u.v)) { 3050 1.1 mrg if (tok2) 3051 1.1 mrg isl_stream_push_token(s, tok2); 3052 1.1 mrg obj.type = isl_obj_val; 3053 1.1 mrg obj.v = isl_val_int_from_isl_int(s->ctx, tok->u.v); 3054 1.1 mrg isl_token_free(tok); 3055 1.1 mrg return obj; 3056 1.1 mrg } 3057 1.1 mrg isl_stream_push_token(s, tok2); 3058 1.1 mrg isl_stream_push_token(s, tok); 3059 1.1 mrg map = map_read_polylib(s); 3060 1.1 mrg if (!map) 3061 1.1 mrg goto error; 3062 1.1 mrg if (isl_map_may_be_set(map)) 3063 1.1 mrg obj.v = isl_map_range(map); 3064 1.1 mrg else { 3065 1.1 mrg obj.type = isl_obj_map; 3066 1.1 mrg obj.v = map; 3067 1.1 mrg } 3068 1.1 mrg return obj; 3069 1.1 mrg } 3070 1.1 mrg v = vars_new(s->ctx); 3071 1.1 mrg if (!v) { 3072 1.1 mrg isl_stream_push_token(s, tok); 3073 1.1 mrg goto error; 3074 1.1 mrg } 3075 1.1 mrg map = isl_map_universe(isl_space_params_alloc(s->ctx, 0)); 3076 1.1 mrg if (tok->type == '[') { 3077 1.1 mrg isl_stream_push_token(s, tok); 3078 1.1 mrg map = read_map_tuple(s, map, isl_dim_param, v, 0); 3079 1.1 mrg if (!map) 3080 1.1 mrg goto error; 3081 1.1 mrg tok = isl_stream_next_token(s); 3082 1.1 mrg if (!tok || tok->type != ISL_TOKEN_TO) { 3083 1.1 mrg isl_stream_error(s, tok, "expecting '->'"); 3084 1.1 mrg if (tok) 3085 1.1 mrg isl_stream_push_token(s, tok); 3086 1.1 mrg goto error; 3087 1.1 mrg } 3088 1.1 mrg isl_token_free(tok); 3089 1.1 mrg tok = isl_stream_next_token(s); 3090 1.1 mrg } 3091 1.1 mrg if (!tok || tok->type != '{') { 3092 1.1 mrg isl_stream_error(s, tok, "expecting '{'"); 3093 1.1 mrg if (tok) 3094 1.1 mrg isl_stream_push_token(s, tok); 3095 1.1 mrg goto error; 3096 1.1 mrg } 3097 1.1 mrg isl_token_free(tok); 3098 1.1 mrg 3099 1.1 mrg tok = isl_stream_next_token(s); 3100 1.1 mrg if (!tok) 3101 1.1 mrg ; 3102 1.1 mrg else if (tok->type == ISL_TOKEN_IDENT && !strcmp(tok->u.s, "Sym")) { 3103 1.1 mrg isl_token_free(tok); 3104 1.1 mrg if (isl_stream_eat(s, '=')) 3105 1.1 mrg goto error; 3106 1.1 mrg map = read_map_tuple(s, map, isl_dim_param, v, 1); 3107 1.1 mrg if (!map) 3108 1.1 mrg goto error; 3109 1.1 mrg } else 3110 1.1 mrg isl_stream_push_token(s, tok); 3111 1.1 mrg 3112 1.1 mrg obj = obj_read_disjuncts(s, v, map); 3113 1.1 mrg if (obj.type == isl_obj_none || !obj.v) 3114 1.1 mrg goto error; 3115 1.1 mrg 3116 1.1 mrg tok = isl_stream_next_token(s); 3117 1.1 mrg if (tok && tok->type == '}') { 3118 1.1 mrg isl_token_free(tok); 3119 1.1 mrg } else { 3120 1.1 mrg isl_stream_error(s, tok, "unexpected isl_token"); 3121 1.1 mrg if (tok) 3122 1.1 mrg isl_token_free(tok); 3123 1.1 mrg goto error; 3124 1.1 mrg } 3125 1.1 mrg 3126 1.1 mrg vars_free(v); 3127 1.1 mrg isl_map_free(map); 3128 1.1 mrg 3129 1.1 mrg return obj; 3130 1.1 mrg error: 3131 1.1 mrg isl_map_free(map); 3132 1.1 mrg obj.type->free(obj.v); 3133 1.1 mrg if (v) 3134 1.1 mrg vars_free(v); 3135 1.1 mrg obj.v = NULL; 3136 1.1 mrg return obj; 3137 1.1 mrg } 3138 1.1 mrg 3139 1.1 mrg struct isl_obj isl_stream_read_obj(__isl_keep isl_stream *s) 3140 1.1 mrg { 3141 1.1 mrg return obj_read(s); 3142 1.1 mrg } 3143 1.1 mrg 3144 1.1 mrg __isl_give isl_map *isl_stream_read_map(__isl_keep isl_stream *s) 3145 1.1 mrg { 3146 1.1 mrg struct isl_obj obj; 3147 1.1 mrg 3148 1.1 mrg obj = obj_read(s); 3149 1.1 mrg if (obj.v) 3150 1.1 mrg isl_assert(s->ctx, obj.type == isl_obj_map || 3151 1.1 mrg obj.type == isl_obj_set, goto error); 3152 1.1 mrg 3153 1.1 mrg if (obj.type == isl_obj_set) 3154 1.1 mrg obj.v = isl_map_from_range(obj.v); 3155 1.1 mrg 3156 1.1 mrg return obj.v; 3157 1.1 mrg error: 3158 1.1 mrg obj.type->free(obj.v); 3159 1.1 mrg return NULL; 3160 1.1 mrg } 3161 1.1 mrg 3162 1.1 mrg __isl_give isl_set *isl_stream_read_set(__isl_keep isl_stream *s) 3163 1.1 mrg { 3164 1.1 mrg struct isl_obj obj; 3165 1.1 mrg 3166 1.1 mrg obj = obj_read(s); 3167 1.1 mrg if (obj.v) { 3168 1.1 mrg if (obj.type == isl_obj_map && isl_map_may_be_set(obj.v)) { 3169 1.1 mrg obj.v = isl_map_range(obj.v); 3170 1.1 mrg obj.type = isl_obj_set; 3171 1.1 mrg } 3172 1.1 mrg isl_assert(s->ctx, obj.type == isl_obj_set, goto error); 3173 1.1 mrg } 3174 1.1 mrg 3175 1.1 mrg return obj.v; 3176 1.1 mrg error: 3177 1.1 mrg obj.type->free(obj.v); 3178 1.1 mrg return NULL; 3179 1.1 mrg } 3180 1.1 mrg 3181 1.1 mrg __isl_give isl_union_map *isl_stream_read_union_map(__isl_keep isl_stream *s) 3182 1.1 mrg { 3183 1.1 mrg struct isl_obj obj; 3184 1.1 mrg 3185 1.1 mrg obj = obj_read(s); 3186 1.1 mrg if (obj.type == isl_obj_map) { 3187 1.1 mrg obj.type = isl_obj_union_map; 3188 1.1 mrg obj.v = isl_union_map_from_map(obj.v); 3189 1.1 mrg } 3190 1.1 mrg if (obj.type == isl_obj_set) { 3191 1.1 mrg obj.type = isl_obj_union_set; 3192 1.1 mrg obj.v = isl_union_set_from_set(obj.v); 3193 1.1 mrg } 3194 1.1 mrg if (obj.v && obj.type == isl_obj_union_set && 3195 1.1 mrg isl_union_set_is_empty(obj.v)) 3196 1.1 mrg obj.type = isl_obj_union_map; 3197 1.1 mrg if (obj.v && obj.type != isl_obj_union_map) 3198 1.1 mrg isl_die(s->ctx, isl_error_invalid, "invalid input", goto error); 3199 1.1 mrg 3200 1.1 mrg return obj.v; 3201 1.1 mrg error: 3202 1.1 mrg obj.type->free(obj.v); 3203 1.1 mrg return NULL; 3204 1.1 mrg } 3205 1.1 mrg 3206 1.1 mrg /* Extract an isl_union_set from "obj". 3207 1.1 mrg * This only works if the object was detected as either a set 3208 1.1 mrg * (in which case it is converted to a union set) or a union set. 3209 1.1 mrg */ 3210 1.1 mrg static __isl_give isl_union_set *extract_union_set(isl_ctx *ctx, 3211 1.1 mrg struct isl_obj obj) 3212 1.1 mrg { 3213 1.1 mrg if (obj.type == isl_obj_set) { 3214 1.1 mrg obj.type = isl_obj_union_set; 3215 1.1 mrg obj.v = isl_union_set_from_set(obj.v); 3216 1.1 mrg } 3217 1.1 mrg if (obj.v) 3218 1.1 mrg isl_assert(ctx, obj.type == isl_obj_union_set, goto error); 3219 1.1 mrg 3220 1.1 mrg return obj.v; 3221 1.1 mrg error: 3222 1.1 mrg obj.type->free(obj.v); 3223 1.1 mrg return NULL; 3224 1.1 mrg } 3225 1.1 mrg 3226 1.1 mrg /* Read an isl_union_set from "s". 3227 1.1 mrg * First read a generic object and then try and extract 3228 1.1 mrg * an isl_union_set from that. 3229 1.1 mrg */ 3230 1.1 mrg __isl_give isl_union_set *isl_stream_read_union_set(__isl_keep isl_stream *s) 3231 1.1 mrg { 3232 1.1 mrg struct isl_obj obj; 3233 1.1 mrg 3234 1.1 mrg obj = obj_read(s); 3235 1.1 mrg return extract_union_set(s->ctx, obj); 3236 1.1 mrg } 3237 1.1 mrg 3238 1.1 mrg static __isl_give isl_basic_map *isl_stream_read_basic_map( 3239 1.1 mrg __isl_keep isl_stream *s) 3240 1.1 mrg { 3241 1.1 mrg struct isl_obj obj; 3242 1.1 mrg struct isl_map *map; 3243 1.1 mrg struct isl_basic_map *bmap; 3244 1.1 mrg 3245 1.1 mrg obj = obj_read(s); 3246 1.1 mrg if (obj.v && (obj.type != isl_obj_map && obj.type != isl_obj_set)) 3247 1.1 mrg isl_die(s->ctx, isl_error_invalid, "not a (basic) set or map", 3248 1.1 mrg goto error); 3249 1.1 mrg map = obj.v; 3250 1.1 mrg if (!map) 3251 1.1 mrg return NULL; 3252 1.1 mrg 3253 1.1 mrg if (map->n > 1) 3254 1.1 mrg isl_die(s->ctx, isl_error_invalid, 3255 1.1 mrg "set or map description involves " 3256 1.1 mrg "more than one disjunct", goto error); 3257 1.1 mrg 3258 1.1 mrg if (map->n == 0) 3259 1.1 mrg bmap = isl_basic_map_empty(isl_map_get_space(map)); 3260 1.1 mrg else 3261 1.1 mrg bmap = isl_basic_map_copy(map->p[0]); 3262 1.1 mrg 3263 1.1 mrg isl_map_free(map); 3264 1.1 mrg 3265 1.1 mrg return bmap; 3266 1.1 mrg error: 3267 1.1 mrg obj.type->free(obj.v); 3268 1.1 mrg return NULL; 3269 1.1 mrg } 3270 1.1 mrg 3271 1.1 mrg /* Read an isl_basic_set object from "s". 3272 1.1 mrg */ 3273 1.1 mrg __isl_give isl_basic_set *isl_stream_read_basic_set(__isl_keep isl_stream *s) 3274 1.1 mrg { 3275 1.1 mrg isl_basic_map *bmap; 3276 1.1 mrg bmap = isl_stream_read_basic_map(s); 3277 1.1 mrg if (!bmap) 3278 1.1 mrg return NULL; 3279 1.1 mrg if (!isl_basic_map_may_be_set(bmap)) 3280 1.1 mrg isl_die(s->ctx, isl_error_invalid, 3281 1.1 mrg "input is not a set", goto error); 3282 1.1 mrg return isl_basic_map_range(bmap); 3283 1.1 mrg error: 3284 1.1 mrg isl_basic_map_free(bmap); 3285 1.1 mrg return NULL; 3286 1.1 mrg } 3287 1.1 mrg 3288 1.1 mrg __isl_give isl_basic_map *isl_basic_map_read_from_file(isl_ctx *ctx, 3289 1.1 mrg FILE *input) 3290 1.1 mrg { 3291 1.1 mrg struct isl_basic_map *bmap; 3292 1.1 mrg isl_stream *s = isl_stream_new_file(ctx, input); 3293 1.1 mrg if (!s) 3294 1.1 mrg return NULL; 3295 1.1 mrg bmap = isl_stream_read_basic_map(s); 3296 1.1 mrg isl_stream_free(s); 3297 1.1 mrg return bmap; 3298 1.1 mrg } 3299 1.1 mrg 3300 1.1 mrg __isl_give isl_basic_set *isl_basic_set_read_from_file(isl_ctx *ctx, 3301 1.1 mrg FILE *input) 3302 1.1 mrg { 3303 1.1 mrg isl_basic_set *bset; 3304 1.1 mrg isl_stream *s = isl_stream_new_file(ctx, input); 3305 1.1 mrg if (!s) 3306 1.1 mrg return NULL; 3307 1.1 mrg bset = isl_stream_read_basic_set(s); 3308 1.1 mrg isl_stream_free(s); 3309 1.1 mrg return bset; 3310 1.1 mrg } 3311 1.1 mrg 3312 1.1 mrg #undef TYPE_BASE 3313 1.1 mrg #define TYPE_BASE basic_map 3314 1.1 mrg #include "isl_read_from_str_templ.c" 3315 1.1 mrg 3316 1.1 mrg #undef TYPE_BASE 3317 1.1 mrg #define TYPE_BASE basic_set 3318 1.1 mrg #include "isl_read_from_str_templ.c" 3319 1.1 mrg 3320 1.1 mrg __isl_give isl_map *isl_map_read_from_file(struct isl_ctx *ctx, 3321 1.1 mrg FILE *input) 3322 1.1 mrg { 3323 1.1 mrg struct isl_map *map; 3324 1.1 mrg isl_stream *s = isl_stream_new_file(ctx, input); 3325 1.1 mrg if (!s) 3326 1.1 mrg return NULL; 3327 1.1 mrg map = isl_stream_read_map(s); 3328 1.1 mrg isl_stream_free(s); 3329 1.1 mrg return map; 3330 1.1 mrg } 3331 1.1 mrg 3332 1.1 mrg #undef TYPE_BASE 3333 1.1 mrg #define TYPE_BASE map 3334 1.1 mrg #include "isl_read_from_str_templ.c" 3335 1.1 mrg 3336 1.1 mrg __isl_give isl_set *isl_set_read_from_file(struct isl_ctx *ctx, 3337 1.1 mrg FILE *input) 3338 1.1 mrg { 3339 1.1 mrg isl_set *set; 3340 1.1 mrg isl_stream *s = isl_stream_new_file(ctx, input); 3341 1.1 mrg if (!s) 3342 1.1 mrg return NULL; 3343 1.1 mrg set = isl_stream_read_set(s); 3344 1.1 mrg isl_stream_free(s); 3345 1.1 mrg return set; 3346 1.1 mrg } 3347 1.1 mrg 3348 1.1 mrg #undef TYPE_BASE 3349 1.1 mrg #define TYPE_BASE set 3350 1.1 mrg #include "isl_read_from_str_templ.c" 3351 1.1 mrg 3352 1.1 mrg __isl_give isl_union_map *isl_union_map_read_from_file(isl_ctx *ctx, 3353 1.1 mrg FILE *input) 3354 1.1 mrg { 3355 1.1 mrg isl_union_map *umap; 3356 1.1 mrg isl_stream *s = isl_stream_new_file(ctx, input); 3357 1.1 mrg if (!s) 3358 1.1 mrg return NULL; 3359 1.1 mrg umap = isl_stream_read_union_map(s); 3360 1.1 mrg isl_stream_free(s); 3361 1.1 mrg return umap; 3362 1.1 mrg } 3363 1.1 mrg 3364 1.1 mrg #undef TYPE_BASE 3365 1.1 mrg #define TYPE_BASE union_map 3366 1.1 mrg #include "isl_read_from_str_templ.c" 3367 1.1 mrg 3368 1.1 mrg __isl_give isl_union_set *isl_union_set_read_from_file(isl_ctx *ctx, 3369 1.1 mrg FILE *input) 3370 1.1 mrg { 3371 1.1 mrg isl_union_set *uset; 3372 1.1 mrg isl_stream *s = isl_stream_new_file(ctx, input); 3373 1.1 mrg if (!s) 3374 1.1 mrg return NULL; 3375 1.1 mrg uset = isl_stream_read_union_set(s); 3376 1.1 mrg isl_stream_free(s); 3377 1.1 mrg return uset; 3378 1.1 mrg } 3379 1.1 mrg 3380 1.1 mrg #undef TYPE_BASE 3381 1.1 mrg #define TYPE_BASE union_set 3382 1.1 mrg #include "isl_read_from_str_templ.c" 3383 1.1 mrg 3384 1.1 mrg static __isl_give isl_vec *isl_vec_read_polylib(__isl_keep isl_stream *s) 3385 1.1 mrg { 3386 1.1 mrg struct isl_vec *vec = NULL; 3387 1.1 mrg struct isl_token *tok; 3388 1.1 mrg unsigned size; 3389 1.1 mrg int j; 3390 1.1 mrg 3391 1.1 mrg tok = isl_stream_next_token(s); 3392 1.1 mrg if (!tok || tok->type != ISL_TOKEN_VALUE) { 3393 1.1 mrg isl_stream_error(s, tok, "expecting vector length"); 3394 1.1 mrg goto error; 3395 1.1 mrg } 3396 1.1 mrg 3397 1.1 mrg size = isl_int_get_si(tok->u.v); 3398 1.1 mrg isl_token_free(tok); 3399 1.1 mrg 3400 1.1 mrg vec = isl_vec_alloc(s->ctx, size); 3401 1.1 mrg 3402 1.1 mrg for (j = 0; j < size; ++j) { 3403 1.1 mrg tok = next_signed_value(s, "expecting constant value"); 3404 1.1 mrg if (!tok) 3405 1.1 mrg goto error; 3406 1.1 mrg isl_int_set(vec->el[j], tok->u.v); 3407 1.1 mrg isl_token_free(tok); 3408 1.1 mrg } 3409 1.1 mrg 3410 1.1 mrg return vec; 3411 1.1 mrg error: 3412 1.1 mrg isl_token_free(tok); 3413 1.1 mrg isl_vec_free(vec); 3414 1.1 mrg return NULL; 3415 1.1 mrg } 3416 1.1 mrg 3417 1.1 mrg static __isl_give isl_vec *vec_read(__isl_keep isl_stream *s) 3418 1.1 mrg { 3419 1.1 mrg return isl_vec_read_polylib(s); 3420 1.1 mrg } 3421 1.1 mrg 3422 1.1 mrg __isl_give isl_vec *isl_vec_read_from_file(isl_ctx *ctx, FILE *input) 3423 1.1 mrg { 3424 1.1 mrg isl_vec *v; 3425 1.1 mrg isl_stream *s = isl_stream_new_file(ctx, input); 3426 1.1 mrg if (!s) 3427 1.1 mrg return NULL; 3428 1.1 mrg v = vec_read(s); 3429 1.1 mrg isl_stream_free(s); 3430 1.1 mrg return v; 3431 1.1 mrg } 3432 1.1 mrg 3433 1.1 mrg __isl_give isl_pw_qpolynomial *isl_stream_read_pw_qpolynomial( 3434 1.1 mrg __isl_keep isl_stream *s) 3435 1.1 mrg { 3436 1.1 mrg struct isl_obj obj; 3437 1.1 mrg 3438 1.1 mrg obj = obj_read(s); 3439 1.1 mrg if (obj.v) 3440 1.1 mrg isl_assert(s->ctx, obj.type == isl_obj_pw_qpolynomial, 3441 1.1 mrg goto error); 3442 1.1 mrg 3443 1.1 mrg return obj.v; 3444 1.1 mrg error: 3445 1.1 mrg obj.type->free(obj.v); 3446 1.1 mrg return NULL; 3447 1.1 mrg } 3448 1.1 mrg 3449 1.1 mrg #undef TYPE_BASE 3450 1.1 mrg #define TYPE_BASE pw_qpolynomial 3451 1.1 mrg #include "isl_read_from_str_templ.c" 3452 1.1 mrg 3453 1.1 mrg __isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_read_from_file(isl_ctx *ctx, 3454 1.1 mrg FILE *input) 3455 1.1 mrg { 3456 1.1 mrg isl_pw_qpolynomial *pwqp; 3457 1.1 mrg isl_stream *s = isl_stream_new_file(ctx, input); 3458 1.1 mrg if (!s) 3459 1.1 mrg return NULL; 3460 1.1 mrg pwqp = isl_stream_read_pw_qpolynomial(s); 3461 1.1 mrg isl_stream_free(s); 3462 1.1 mrg return pwqp; 3463 1.1 mrg } 3464 1.1 mrg 3465 1.1 mrg /* Read an isl_pw_qpolynomial_fold from "s". 3466 1.1 mrg * First read a generic object and 3467 1.1 mrg * then check that it is an isl_pw_qpolynomial_fold. 3468 1.1 mrg */ 3469 1.1 mrg __isl_give isl_pw_qpolynomial_fold *isl_stream_read_pw_qpolynomial_fold( 3470 1.1 mrg __isl_keep isl_stream *s) 3471 1.1 mrg { 3472 1.1 mrg struct isl_obj obj; 3473 1.1 mrg 3474 1.1 mrg obj = obj_read(s); 3475 1.1 mrg if (obj.v && obj.type != isl_obj_pw_qpolynomial_fold) 3476 1.1 mrg isl_die(s->ctx, isl_error_invalid, "invalid input", goto error); 3477 1.1 mrg 3478 1.1 mrg return obj.v; 3479 1.1 mrg error: 3480 1.1 mrg obj.type->free(obj.v); 3481 1.1 mrg return NULL; 3482 1.1 mrg } 3483 1.1 mrg 3484 1.1 mrg #undef TYPE_BASE 3485 1.1 mrg #define TYPE_BASE pw_qpolynomial_fold 3486 1.1 mrg #include "isl_read_from_str_templ.c" 3487 1.1 mrg 3488 1.1 mrg /* Is the next token an identifier not in "v"? 3489 1.1 mrg */ 3490 1.1 mrg static int next_is_fresh_ident(__isl_keep isl_stream *s, struct vars *v) 3491 1.1 mrg { 3492 1.1 mrg int n = v->n; 3493 1.1 mrg int fresh; 3494 1.1 mrg struct isl_token *tok; 3495 1.1 mrg 3496 1.1 mrg tok = isl_stream_next_token(s); 3497 1.1 mrg if (!tok) 3498 1.1 mrg return 0; 3499 1.1 mrg fresh = tok->type == ISL_TOKEN_IDENT && vars_pos(v, tok->u.s, -1) >= n; 3500 1.1 mrg isl_stream_push_token(s, tok); 3501 1.1 mrg 3502 1.1 mrg vars_drop(v, v->n - n); 3503 1.1 mrg 3504 1.1 mrg return fresh; 3505 1.1 mrg } 3506 1.1 mrg 3507 1.1 mrg /* First read the domain of the affine expression, which may be 3508 1.1 mrg * a parameter space or a set. 3509 1.1 mrg * The tricky part is that we don't know if the domain is a set or not, 3510 1.1 mrg * so when we are trying to read the domain, we may actually be reading 3511 1.1 mrg * the affine expression itself (defined on a parameter domains) 3512 1.1 mrg * If the tuple we are reading is named, we assume it's the domain. 3513 1.1 mrg * Also, if inside the tuple, the first thing we find is a nested tuple 3514 1.1 mrg * or a new identifier, we again assume it's the domain. 3515 1.1 mrg * Finally, if the tuple is empty, then it must be the domain 3516 1.1 mrg * since it does not contain an affine expression. 3517 1.1 mrg * Otherwise, we assume we are reading an affine expression. 3518 1.1 mrg */ 3519 1.1 mrg static __isl_give isl_set *read_aff_domain(__isl_keep isl_stream *s, 3520 1.1 mrg __isl_take isl_set *dom, struct vars *v) 3521 1.1 mrg { 3522 1.1 mrg struct isl_token *tok, *tok2; 3523 1.1 mrg int is_empty; 3524 1.1 mrg 3525 1.1 mrg tok = isl_stream_next_token(s); 3526 1.1 mrg if (tok && (tok->type == ISL_TOKEN_IDENT || tok->is_keyword)) { 3527 1.1 mrg isl_stream_push_token(s, tok); 3528 1.1 mrg return read_map_tuple(s, dom, isl_dim_set, v, 0); 3529 1.1 mrg } 3530 1.1 mrg if (!tok || tok->type != '[') { 3531 1.1 mrg isl_stream_error(s, tok, "expecting '['"); 3532 1.1 mrg goto error; 3533 1.1 mrg } 3534 1.1 mrg tok2 = isl_stream_next_token(s); 3535 1.1 mrg is_empty = tok2 && tok2->type == ']'; 3536 1.1 mrg if (tok2) 3537 1.1 mrg isl_stream_push_token(s, tok2); 3538 1.1 mrg if (is_empty || next_is_tuple(s) || next_is_fresh_ident(s, v)) { 3539 1.1 mrg isl_stream_push_token(s, tok); 3540 1.1 mrg dom = read_map_tuple(s, dom, isl_dim_set, v, 0); 3541 1.1 mrg } else 3542 1.1 mrg isl_stream_push_token(s, tok); 3543 1.1 mrg 3544 1.1 mrg return dom; 3545 1.1 mrg error: 3546 1.1 mrg if (tok) 3547 1.1 mrg isl_stream_push_token(s, tok); 3548 1.1 mrg isl_set_free(dom); 3549 1.1 mrg return NULL; 3550 1.1 mrg } 3551 1.1 mrg 3552 1.1 mrg /* Read an affine expression from "s". 3553 1.1 mrg */ 3554 1.1 mrg __isl_give isl_aff *isl_stream_read_aff(__isl_keep isl_stream *s) 3555 1.1 mrg { 3556 1.1 mrg isl_aff *aff; 3557 1.1 mrg isl_multi_aff *ma; 3558 1.1 mrg isl_size dim; 3559 1.1 mrg 3560 1.1 mrg ma = isl_stream_read_multi_aff(s); 3561 1.1 mrg dim = isl_multi_aff_dim(ma, isl_dim_out); 3562 1.1 mrg if (dim < 0) 3563 1.1 mrg goto error; 3564 1.1 mrg if (dim != 1) 3565 1.1 mrg isl_die(s->ctx, isl_error_invalid, 3566 1.1 mrg "expecting single affine expression", 3567 1.1 mrg goto error); 3568 1.1 mrg 3569 1.1 mrg aff = isl_multi_aff_get_aff(ma, 0); 3570 1.1 mrg isl_multi_aff_free(ma); 3571 1.1 mrg return aff; 3572 1.1 mrg error: 3573 1.1 mrg isl_multi_aff_free(ma); 3574 1.1 mrg return NULL; 3575 1.1 mrg } 3576 1.1 mrg 3577 1.1 mrg /* Read a piecewise affine expression from "s" with domain (space) "dom". 3578 1.1 mrg */ 3579 1.1 mrg static __isl_give isl_pw_aff *read_pw_aff_with_dom(__isl_keep isl_stream *s, 3580 1.1 mrg __isl_take isl_set *dom, struct vars *v) 3581 1.1 mrg { 3582 1.1 mrg isl_pw_aff *pwaff = NULL; 3583 1.1 mrg 3584 1.1 mrg if (!isl_set_is_params(dom) && isl_stream_eat(s, ISL_TOKEN_TO)) 3585 1.1 mrg goto error; 3586 1.1 mrg 3587 1.1 mrg if (isl_stream_eat(s, '[')) 3588 1.1 mrg goto error; 3589 1.1 mrg 3590 1.1 mrg pwaff = accept_affine(s, isl_set_get_space(dom), v); 3591 1.1 mrg 3592 1.1 mrg if (isl_stream_eat(s, ']')) 3593 1.1 mrg goto error; 3594 1.1 mrg 3595 1.1 mrg dom = read_optional_formula(s, dom, v, 0); 3596 1.1 mrg pwaff = isl_pw_aff_intersect_domain(pwaff, dom); 3597 1.1 mrg 3598 1.1 mrg return pwaff; 3599 1.1 mrg error: 3600 1.1 mrg isl_set_free(dom); 3601 1.1 mrg isl_pw_aff_free(pwaff); 3602 1.1 mrg return NULL; 3603 1.1 mrg } 3604 1.1 mrg 3605 1.1 mrg /* Read an affine expression, together with optional constraints 3606 1.1 mrg * on the domain from "s". "dom" represents the initial constraints 3607 1.1 mrg * on the parameter domain. 3608 1.1 mrg * "v" contains a description of the identifiers parsed so far. 3609 1.1 mrg */ 3610 1.1 mrg static __isl_give isl_pw_aff *read_conditional_aff(__isl_keep isl_stream *s, 3611 1.1 mrg __isl_take isl_set *dom, struct vars *v) 3612 1.1 mrg { 3613 1.1 mrg isl_set *aff_dom; 3614 1.1 mrg isl_pw_aff *pa; 3615 1.1 mrg int n; 3616 1.1 mrg 3617 1.1 mrg n = v->n; 3618 1.1 mrg aff_dom = read_aff_domain(s, dom, v); 3619 1.1 mrg pa = read_pw_aff_with_dom(s, aff_dom, v); 3620 1.1 mrg vars_drop(v, v->n - n); 3621 1.1 mrg 3622 1.1 mrg return pa; 3623 1.1 mrg } 3624 1.1 mrg 3625 1.1 mrg #undef BASE 3626 1.1 mrg #define BASE aff 3627 1.1 mrg #include "isl_stream_read_pw_with_params_templ.c" 3628 1.1 mrg 3629 1.1 mrg #undef TYPE_BASE 3630 1.1 mrg #define TYPE_BASE aff 3631 1.1 mrg #include "isl_read_from_str_templ.c" 3632 1.1 mrg 3633 1.1 mrg #undef TYPE_BASE 3634 1.1 mrg #define TYPE_BASE pw_aff 3635 1.1 mrg #include "isl_stream_read_with_params_templ.c" 3636 1.1 mrg #include "isl_read_from_str_templ.c" 3637 1.1 mrg 3638 1.1 mrg /* Given that "pa" is the element at position "pos" of a tuple 3639 1.1 mrg * returned by read_tuple, check that it does not involve any 3640 1.1 mrg * output/set dimensions (appearing at the "n" positions starting at "first"), 3641 1.1 mrg * remove those from the domain and replace the domain space 3642 1.1 mrg * with "domain_space". 3643 1.1 mrg * 3644 1.1 mrg * In particular, the result of read_tuple is of the form 3645 1.1 mrg * [input, output] -> [output], with anonymous domain. 3646 1.1 mrg * The function read_tuple accepts tuples where some output or 3647 1.1 mrg * set dimensions are defined in terms of other output or set dimensions 3648 1.1 mrg * since this function is also used to read maps. As a special case, 3649 1.1 mrg * read_tuple also accepts dimensions that are defined in terms of themselves 3650 1.1 mrg * (i.e., that are not defined). 3651 1.1 mrg * These cases are not allowed here. 3652 1.1 mrg */ 3653 1.1 mrg static __isl_give isl_pw_aff *separate_tuple_entry(__isl_take isl_pw_aff *pa, 3654 1.1 mrg int pos, unsigned first, unsigned n, __isl_take isl_space *domain_space) 3655 1.1 mrg { 3656 1.1 mrg isl_bool involves; 3657 1.1 mrg 3658 1.1 mrg involves = isl_pw_aff_involves_dims(pa, isl_dim_in, first, pos + 1); 3659 1.1 mrg if (involves < 0) { 3660 1.1 mrg pa = isl_pw_aff_free(pa); 3661 1.1 mrg } else if (involves) { 3662 1.1 mrg isl_die(isl_pw_aff_get_ctx(pa), isl_error_invalid, 3663 1.1 mrg "not an affine expression", 3664 1.1 mrg pa = isl_pw_aff_free(pa)); 3665 1.1 mrg } 3666 1.1 mrg pa = isl_pw_aff_drop_dims(pa, isl_dim_in, first, n); 3667 1.1 mrg pa = isl_pw_aff_reset_domain_space(pa, domain_space); 3668 1.1 mrg 3669 1.1 mrg return pa; 3670 1.1 mrg } 3671 1.1 mrg 3672 1.1 mrg /* Set entry "pos" of "mpa" to the corresponding entry in "tuple", 3673 1.1 mrg * as obtained from read_tuple(). 3674 1.1 mrg * The "n" output dimensions also appear among the input dimensions 3675 1.1 mrg * at position "first". 3676 1.1 mrg * 3677 1.1 mrg * The entry is not allowed to depend on any (other) output dimensions. 3678 1.1 mrg */ 3679 1.1 mrg static __isl_give isl_multi_pw_aff *isl_multi_pw_aff_set_tuple_entry( 3680 1.1 mrg __isl_take isl_multi_pw_aff *mpa, __isl_take isl_pw_aff *tuple_el, 3681 1.1 mrg int pos, unsigned first, unsigned n) 3682 1.1 mrg { 3683 1.1 mrg isl_space *space; 3684 1.1 mrg isl_pw_aff *pa; 3685 1.1 mrg 3686 1.1 mrg space = isl_multi_pw_aff_get_domain_space(mpa); 3687 1.1 mrg pa = separate_tuple_entry(tuple_el, pos, first, n, space); 3688 1.1 mrg return isl_multi_pw_aff_set_pw_aff(mpa, pos, pa); 3689 1.1 mrg } 3690 1.1 mrg 3691 1.1 mrg #undef BASE 3692 1.1 mrg #define BASE pw_aff 3693 1.1 mrg 3694 1.1 mrg #include <isl_multi_from_tuple_templ.c> 3695 1.1 mrg 3696 1.1 mrg /* Read a tuple of piecewise affine expressions, 3697 1.1 mrg * including optional constraints on the domain from "s". 3698 1.1 mrg * "dom" represents the initial constraints on the domain. 3699 1.1 mrg * 3700 1.1 mrg * The input format is similar to that of a map, except that any conditions 3701 1.1 mrg * on the domains should be specified inside the tuple since each 3702 1.1 mrg * piecewise affine expression may have a different domain. 3703 1.1 mrg * However, additional, shared conditions can also be specified. 3704 1.1 mrg * This is especially useful for setting the explicit domain 3705 1.1 mrg * of a zero-dimensional isl_multi_pw_aff. 3706 1.1 mrg * 3707 1.1 mrg * The isl_multi_pw_aff may live in either a set or a map space. 3708 1.1 mrg * First read the first tuple and check if it is followed by a "->". 3709 1.1 mrg * If so, convert the tuple into the domain of the isl_multi_pw_aff and 3710 1.1 mrg * read in the next tuple. This tuple (or the first tuple if it was 3711 1.1 mrg * not followed by a "->") is then converted into an isl_multi_pw_aff 3712 1.1 mrg * through a call to isl_multi_pw_aff_from_tuple. 3713 1.1 mrg * The domain of the result is intersected with the domain. 3714 1.1 mrg * 3715 1.1 mrg * Note that the last tuple may introduce new identifiers, 3716 1.1 mrg * but these cannot be referenced in the description of the domain. 3717 1.1 mrg */ 3718 1.1 mrg static __isl_give isl_multi_pw_aff *read_conditional_multi_pw_aff( 3719 1.1 mrg __isl_keep isl_stream *s, __isl_take isl_set *dom, struct vars *v) 3720 1.1 mrg { 3721 1.1 mrg isl_multi_pw_aff *tuple; 3722 1.1 mrg isl_multi_pw_aff *mpa; 3723 1.1 mrg int n = v->n; 3724 1.1 mrg int n_dom; 3725 1.1 mrg 3726 1.1 mrg n_dom = v->n; 3727 1.1 mrg tuple = read_tuple(s, v, 0, 0); 3728 1.1 mrg if (!tuple) 3729 1.1 mrg goto error; 3730 1.1 mrg if (isl_stream_eat_if_available(s, ISL_TOKEN_TO)) { 3731 1.1 mrg isl_map *map = map_from_tuple(tuple, dom, isl_dim_in, v, 0); 3732 1.1 mrg dom = isl_map_domain(map); 3733 1.1 mrg n_dom = v->n; 3734 1.1 mrg tuple = read_tuple(s, v, 0, 0); 3735 1.1 mrg if (!tuple) 3736 1.1 mrg goto error; 3737 1.1 mrg } 3738 1.1 mrg mpa = isl_multi_pw_aff_from_tuple(isl_set_get_space(dom), tuple); 3739 1.1 mrg if (!mpa) 3740 1.1 mrg dom = isl_set_free(dom); 3741 1.1 mrg 3742 1.1 mrg vars_drop(v, v->n - n_dom); 3743 1.1 mrg dom = read_optional_formula(s, dom, v, 0); 3744 1.1 mrg 3745 1.1 mrg vars_drop(v, v->n - n); 3746 1.1 mrg 3747 1.1 mrg mpa = isl_multi_pw_aff_intersect_domain(mpa, dom); 3748 1.1 mrg 3749 1.1 mrg return mpa; 3750 1.1 mrg error: 3751 1.1 mrg isl_set_free(dom); 3752 1.1 mrg return NULL; 3753 1.1 mrg } 3754 1.1 mrg 3755 1.1 mrg /* Read a tuple of affine expressions, together with optional constraints 3756 1.1 mrg * on the domain from "s". "dom" represents the initial constraints 3757 1.1 mrg * on the domain. 3758 1.1 mrg * 3759 1.1 mrg * Read a tuple of piecewise affine expressions with optional constraints and 3760 1.1 mrg * convert the result to an isl_pw_multi_aff on the shared domain. 3761 1.1 mrg */ 3762 1.1 mrg static __isl_give isl_pw_multi_aff *read_conditional_multi_aff( 3763 1.1 mrg __isl_keep isl_stream *s, __isl_take isl_set *dom, struct vars *v) 3764 1.1 mrg { 3765 1.1 mrg isl_multi_pw_aff *mpa; 3766 1.1 mrg 3767 1.1 mrg mpa = read_conditional_multi_pw_aff(s, dom, v); 3768 1.1 mrg return isl_pw_multi_aff_from_multi_pw_aff(mpa); 3769 1.1 mrg } 3770 1.1 mrg 3771 1.1 mrg /* Read an isl_union_pw_multi_aff from "s" with parameter domain "dom". 3772 1.1 mrg * "v" contains a description of the identifiers parsed so far. 3773 1.1 mrg * 3774 1.1 mrg * In particular, read a sequence 3775 1.1 mrg * of zero or more tuples of affine expressions with optional conditions and 3776 1.1 mrg * add them up. 3777 1.1 mrg */ 3778 1.1 mrg static __isl_give isl_union_pw_multi_aff * 3779 1.1 mrg isl_stream_read_with_params_union_pw_multi_aff(__isl_keep isl_stream *s, 3780 1.1 mrg __isl_keep isl_set *dom, struct vars *v) 3781 1.1 mrg { 3782 1.1 mrg isl_union_pw_multi_aff *upma; 3783 1.1 mrg 3784 1.1 mrg upma = isl_union_pw_multi_aff_empty(isl_set_get_space(dom)); 3785 1.1 mrg 3786 1.1 mrg do { 3787 1.1 mrg isl_pw_multi_aff *pma; 3788 1.1 mrg isl_union_pw_multi_aff *upma2; 3789 1.1 mrg 3790 1.1 mrg if (isl_stream_next_token_is(s, '}')) 3791 1.1 mrg break; 3792 1.1 mrg 3793 1.1 mrg pma = read_conditional_multi_aff(s, isl_set_copy(dom), v); 3794 1.1 mrg upma2 = isl_union_pw_multi_aff_from_pw_multi_aff(pma); 3795 1.1 mrg upma = isl_union_pw_multi_aff_union_add(upma, upma2); 3796 1.1 mrg if (!upma) 3797 1.1 mrg return NULL; 3798 1.1 mrg } while (isl_stream_eat_if_available(s, ';')); 3799 1.1 mrg 3800 1.1 mrg return upma; 3801 1.1 mrg } 3802 1.1 mrg 3803 1.1 mrg #undef BASE 3804 1.1 mrg #define BASE multi_aff 3805 1.1 mrg #include "isl_stream_read_pw_with_params_templ.c" 3806 1.1 mrg 3807 1.1 mrg #undef TYPE_BASE 3808 1.1 mrg #define TYPE_BASE pw_multi_aff 3809 1.1 mrg #include "isl_stream_read_with_params_templ.c" 3810 1.1 mrg #include "isl_read_from_str_templ.c" 3811 1.1 mrg 3812 1.1 mrg #undef TYPE_BASE 3813 1.1 mrg #define TYPE_BASE union_pw_multi_aff 3814 1.1 mrg #include "isl_stream_read_with_params_templ.c" 3815 1.1 mrg #include "isl_read_from_str_templ.c" 3816 1.1 mrg 3817 1.1 mrg #undef BASE 3818 1.1 mrg #define BASE val 3819 1.1 mrg 3820 1.1 mrg #include <isl_multi_read_no_explicit_domain_templ.c> 3821 1.1 mrg 3822 1.1 mrg #undef BASE 3823 1.1 mrg #define BASE id 3824 1.1 mrg 3825 1.1 mrg #include <isl_multi_read_no_explicit_domain_templ.c> 3826 1.1 mrg 3827 1.1 mrg /* Set entry "pos" of "ma" to the corresponding entry in "tuple", 3828 1.1 mrg * as obtained from read_tuple(). 3829 1.1 mrg * The "n" output dimensions also appear among the input dimensions 3830 1.1 mrg * at position "first". 3831 1.1 mrg * 3832 1.1 mrg * The entry is not allowed to depend on any (other) output dimensions. 3833 1.1 mrg */ 3834 1.1 mrg static __isl_give isl_multi_aff *isl_multi_aff_set_tuple_entry( 3835 1.1 mrg __isl_take isl_multi_aff *ma, __isl_take isl_pw_aff *tuple_el, 3836 1.1 mrg int pos, unsigned first, unsigned n) 3837 1.1 mrg { 3838 1.1 mrg isl_space *space; 3839 1.1 mrg isl_pw_aff *pa; 3840 1.1 mrg isl_aff *aff; 3841 1.1 mrg 3842 1.1 mrg space = isl_multi_aff_get_domain_space(ma); 3843 1.1 mrg pa = separate_tuple_entry(tuple_el, pos, first, n, space); 3844 1.1 mrg aff = isl_pw_aff_as_aff(pa); 3845 1.1 mrg return isl_multi_aff_set_aff(ma, pos, aff); 3846 1.1 mrg } 3847 1.1 mrg 3848 1.1 mrg #undef BASE 3849 1.1 mrg #define BASE aff 3850 1.1 mrg 3851 1.1 mrg #include <isl_multi_from_tuple_templ.c> 3852 1.1 mrg 3853 1.1 mrg /* Read a multi-affine expression from "s". 3854 1.1 mrg * If the multi-affine expression has a domain, then the tuple 3855 1.1 mrg * representing this domain cannot involve any affine expressions. 3856 1.1 mrg * The tuple representing the actual expressions needs to consist 3857 1.1 mrg * of only affine expressions. 3858 1.1 mrg */ 3859 1.1 mrg __isl_give isl_multi_aff *isl_stream_read_multi_aff(__isl_keep isl_stream *s) 3860 1.1 mrg { 3861 1.1 mrg struct vars *v; 3862 1.1 mrg isl_multi_pw_aff *tuple = NULL; 3863 1.1 mrg isl_space *dom_space = NULL; 3864 1.1 mrg isl_multi_aff *ma = NULL; 3865 1.1 mrg 3866 1.1 mrg v = vars_new(s->ctx); 3867 1.1 mrg if (!v) 3868 1.1 mrg return NULL; 3869 1.1 mrg 3870 1.1 mrg dom_space = read_params(s, v); 3871 1.1 mrg if (!dom_space) 3872 1.1 mrg goto error; 3873 1.1 mrg if (isl_stream_eat(s, '{')) 3874 1.1 mrg goto error; 3875 1.1 mrg 3876 1.1 mrg tuple = read_tuple(s, v, 0, 0); 3877 1.1 mrg if (!tuple) 3878 1.1 mrg goto error; 3879 1.1 mrg if (isl_stream_eat_if_available(s, ISL_TOKEN_TO)) { 3880 1.1 mrg isl_space *space; 3881 1.1 mrg isl_bool has_expr; 3882 1.1 mrg 3883 1.1 mrg has_expr = tuple_has_expr(tuple); 3884 1.1 mrg if (has_expr < 0) 3885 1.1 mrg goto error; 3886 1.1 mrg if (has_expr) 3887 1.1 mrg isl_die(s->ctx, isl_error_invalid, 3888 1.1 mrg "expecting universe domain", goto error); 3889 1.1 mrg space = isl_space_range(isl_multi_pw_aff_get_space(tuple)); 3890 1.1 mrg dom_space = isl_space_align_params(space, dom_space); 3891 1.1 mrg isl_multi_pw_aff_free(tuple); 3892 1.1 mrg tuple = read_tuple(s, v, 0, 0); 3893 1.1 mrg if (!tuple) 3894 1.1 mrg goto error; 3895 1.1 mrg } 3896 1.1 mrg 3897 1.1 mrg if (isl_stream_eat(s, '}')) 3898 1.1 mrg goto error; 3899 1.1 mrg 3900 1.1 mrg ma = isl_multi_aff_from_tuple(dom_space, tuple); 3901 1.1 mrg 3902 1.1 mrg vars_free(v); 3903 1.1 mrg return ma; 3904 1.1 mrg error: 3905 1.1 mrg isl_multi_pw_aff_free(tuple); 3906 1.1 mrg vars_free(v); 3907 1.1 mrg isl_space_free(dom_space); 3908 1.1 mrg isl_multi_aff_free(ma); 3909 1.1 mrg return NULL; 3910 1.1 mrg } 3911 1.1 mrg 3912 1.1 mrg #undef TYPE_BASE 3913 1.1 mrg #define TYPE_BASE multi_aff 3914 1.1 mrg #include "isl_read_from_str_templ.c" 3915 1.1 mrg 3916 1.1 mrg /* Read an isl_multi_pw_aff from "s" with parameter domain "dom".. 3917 1.1 mrg * "v" contains a description of the identifiers parsed so far. 3918 1.1 mrg */ 3919 1.1 mrg static __isl_give isl_multi_pw_aff *isl_stream_read_with_params_multi_pw_aff( 3920 1.1 mrg __isl_keep isl_stream *s, __isl_keep isl_set *dom, struct vars *v) 3921 1.1 mrg { 3922 1.1 mrg return read_conditional_multi_pw_aff(s, isl_set_copy(dom), v); 3923 1.1 mrg } 3924 1.1 mrg 3925 1.1 mrg #undef TYPE_BASE 3926 1.1 mrg #define TYPE_BASE multi_pw_aff 3927 1.1 mrg #include "isl_stream_read_with_params_templ.c" 3928 1.1 mrg #include "isl_read_from_str_templ.c" 3929 1.1 mrg 3930 1.1 mrg /* Read the body of an isl_union_pw_aff from "s" with parameter domain "dom". 3931 1.1 mrg */ 3932 1.1 mrg static __isl_give isl_union_pw_aff *read_union_pw_aff_with_dom( 3933 1.1 mrg __isl_keep isl_stream *s, __isl_take isl_set *dom, struct vars *v) 3934 1.1 mrg { 3935 1.1 mrg isl_pw_aff *pa; 3936 1.1 mrg isl_union_pw_aff *upa = NULL; 3937 1.1 mrg isl_set *aff_dom; 3938 1.1 mrg int n; 3939 1.1 mrg 3940 1.1 mrg n = v->n; 3941 1.1 mrg aff_dom = read_aff_domain(s, isl_set_copy(dom), v); 3942 1.1 mrg pa = read_pw_aff_with_dom(s, aff_dom, v); 3943 1.1 mrg vars_drop(v, v->n - n); 3944 1.1 mrg 3945 1.1 mrg upa = isl_union_pw_aff_from_pw_aff(pa); 3946 1.1 mrg 3947 1.1 mrg while (isl_stream_eat_if_available(s, ';')) { 3948 1.1 mrg isl_pw_aff *pa_i; 3949 1.1 mrg isl_union_pw_aff *upa_i; 3950 1.1 mrg 3951 1.1 mrg n = v->n; 3952 1.1 mrg aff_dom = read_aff_domain(s, isl_set_copy(dom), v); 3953 1.1 mrg pa_i = read_pw_aff_with_dom(s, aff_dom, v); 3954 1.1 mrg vars_drop(v, v->n - n); 3955 1.1 mrg 3956 1.1 mrg upa_i = isl_union_pw_aff_from_pw_aff(pa_i); 3957 1.1 mrg upa = isl_union_pw_aff_union_add(upa, upa_i); 3958 1.1 mrg } 3959 1.1 mrg 3960 1.1 mrg isl_set_free(dom); 3961 1.1 mrg return upa; 3962 1.1 mrg } 3963 1.1 mrg 3964 1.1 mrg /* Read an isl_union_pw_aff from "s" with parameter domain "dom". 3965 1.1 mrg * "v" contains a description of the identifiers parsed so far. 3966 1.1 mrg */ 3967 1.1 mrg static __isl_give isl_union_pw_aff *isl_stream_read_with_params_union_pw_aff( 3968 1.1 mrg __isl_keep isl_stream *s, __isl_keep isl_set *dom, struct vars *v) 3969 1.1 mrg { 3970 1.1 mrg return read_union_pw_aff_with_dom(s, isl_set_copy(dom), v); 3971 1.1 mrg } 3972 1.1 mrg 3973 1.1 mrg #undef TYPE_BASE 3974 1.1 mrg #define TYPE_BASE union_pw_aff 3975 1.1 mrg #include "isl_stream_read_with_params_templ.c" 3976 1.1 mrg #include "isl_read_from_str_templ.c" 3977 1.1 mrg 3978 1.1 mrg /* This function is called for each element in a tuple inside 3979 1.1 mrg * isl_stream_read_multi_union_pw_aff. 3980 1.1 mrg * 3981 1.1 mrg * Read a '{', the union piecewise affine expression body and a '}' and 3982 1.1 mrg * add the isl_union_pw_aff to *list. 3983 1.1 mrg */ 3984 1.1 mrg static __isl_give isl_space *read_union_pw_aff_el(__isl_keep isl_stream *s, 3985 1.1 mrg struct vars *v, __isl_take isl_space *space, int rational, void *user) 3986 1.1 mrg { 3987 1.1 mrg isl_set *dom; 3988 1.1 mrg isl_union_pw_aff *upa; 3989 1.1 mrg isl_union_pw_aff_list **list = (isl_union_pw_aff_list **) user; 3990 1.1 mrg 3991 1.1 mrg dom = isl_set_universe(isl_space_params(isl_space_copy(space))); 3992 1.1 mrg if (isl_stream_eat(s, '{')) 3993 1.1 mrg goto error; 3994 1.1 mrg upa = read_union_pw_aff_with_dom(s, dom, v); 3995 1.1 mrg *list = isl_union_pw_aff_list_add(*list, upa); 3996 1.1 mrg if (isl_stream_eat(s, '}')) 3997 1.1 mrg return isl_space_free(space); 3998 1.1 mrg if (!*list) 3999 1.1 mrg return isl_space_free(space); 4000 1.1 mrg return space; 4001 1.1 mrg error: 4002 1.1 mrg isl_set_free(dom); 4003 1.1 mrg return isl_space_free(space); 4004 1.1 mrg } 4005 1.1 mrg 4006 1.1 mrg /* Do the next tokens in "s" correspond to an empty tuple? 4007 1.1 mrg * In particular, does the stream start with a '[', followed by a ']', 4008 1.1 mrg * not followed by a "->"? 4009 1.1 mrg */ 4010 1.1 mrg static int next_is_empty_tuple(__isl_keep isl_stream *s) 4011 1.1 mrg { 4012 1.1 mrg struct isl_token *tok, *tok2, *tok3; 4013 1.1 mrg int is_empty_tuple = 0; 4014 1.1 mrg 4015 1.1 mrg tok = isl_stream_next_token(s); 4016 1.1 mrg if (!tok) 4017 1.1 mrg return 0; 4018 1.1 mrg if (tok->type != '[') { 4019 1.1 mrg isl_stream_push_token(s, tok); 4020 1.1 mrg return 0; 4021 1.1 mrg } 4022 1.1 mrg 4023 1.1 mrg tok2 = isl_stream_next_token(s); 4024 1.1 mrg if (tok2 && tok2->type == ']') { 4025 1.1 mrg tok3 = isl_stream_next_token(s); 4026 1.1 mrg is_empty_tuple = !tok || tok->type != ISL_TOKEN_TO; 4027 1.1 mrg if (tok3) 4028 1.1 mrg isl_stream_push_token(s, tok3); 4029 1.1 mrg } 4030 1.1 mrg if (tok2) 4031 1.1 mrg isl_stream_push_token(s, tok2); 4032 1.1 mrg isl_stream_push_token(s, tok); 4033 1.1 mrg 4034 1.1 mrg return is_empty_tuple; 4035 1.1 mrg } 4036 1.1 mrg 4037 1.1 mrg /* Do the next tokens in "s" correspond to a tuple of parameters? 4038 1.1 mrg * In particular, does the stream start with a '[' that is not 4039 1.1 mrg * followed by a '{' or a nested tuple? 4040 1.1 mrg */ 4041 1.1 mrg static int next_is_param_tuple(__isl_keep isl_stream *s) 4042 1.1 mrg { 4043 1.1 mrg struct isl_token *tok, *tok2; 4044 1.1 mrg int is_tuple; 4045 1.1 mrg 4046 1.1 mrg tok = isl_stream_next_token(s); 4047 1.1 mrg if (!tok) 4048 1.1 mrg return 0; 4049 1.1 mrg if (tok->type != '[' || next_is_tuple(s)) { 4050 1.1 mrg isl_stream_push_token(s, tok); 4051 1.1 mrg return 0; 4052 1.1 mrg } 4053 1.1 mrg 4054 1.1 mrg tok2 = isl_stream_next_token(s); 4055 1.1 mrg is_tuple = tok2 && tok2->type != '{'; 4056 1.1 mrg if (tok2) 4057 1.1 mrg isl_stream_push_token(s, tok2); 4058 1.1 mrg isl_stream_push_token(s, tok); 4059 1.1 mrg 4060 1.1 mrg return is_tuple; 4061 1.1 mrg } 4062 1.1 mrg 4063 1.1 mrg /* Read the core of a body of an isl_multi_union_pw_aff from "s", 4064 1.1 mrg * i.e., everything except the parameter specification and 4065 1.1 mrg * without shared domain constraints. 4066 1.1 mrg * "v" contains a description of the identifiers parsed so far. 4067 1.1 mrg * The parameters, if any, are specified by "space". 4068 1.1 mrg * 4069 1.1 mrg * The body is of the form 4070 1.1 mrg * 4071 1.1 mrg * [{ [..] : ... ; [..] : ... }, { [..] : ... ; [..] : ... }] 4072 1.1 mrg * 4073 1.1 mrg * Read the tuple, collecting the individual isl_union_pw_aff 4074 1.1 mrg * elements in a list and construct the result from the tuple space and 4075 1.1 mrg * the list. 4076 1.1 mrg */ 4077 1.1 mrg static __isl_give isl_multi_union_pw_aff *read_multi_union_pw_aff_body_core( 4078 1.1 mrg __isl_keep isl_stream *s, struct vars *v, __isl_take isl_space *space) 4079 1.1 mrg { 4080 1.1 mrg isl_union_pw_aff_list *list; 4081 1.1 mrg isl_multi_union_pw_aff *mupa; 4082 1.1 mrg 4083 1.1 mrg list = isl_union_pw_aff_list_alloc(s->ctx, 0); 4084 1.1 mrg space = read_tuple_space(s, v, space, 1, 0, 4085 1.1 mrg &read_union_pw_aff_el, &list); 4086 1.1 mrg mupa = isl_multi_union_pw_aff_from_union_pw_aff_list(space, list); 4087 1.1 mrg 4088 1.1 mrg return mupa; 4089 1.1 mrg } 4090 1.1 mrg 4091 1.1 mrg /* Read the body of an isl_union_set from "s", 4092 1.1 mrg * i.e., everything except the parameter specification. 4093 1.1 mrg * "v" contains a description of the identifiers parsed so far. 4094 1.1 mrg * The parameters, if any, are specified by "space". 4095 1.1 mrg * 4096 1.1 mrg * First read a generic disjunction of object bodies and then try and extract 4097 1.1 mrg * an isl_union_set from that. 4098 1.1 mrg */ 4099 1.1 mrg static __isl_give isl_union_set *read_union_set_body(__isl_keep isl_stream *s, 4100 1.1 mrg struct vars *v, __isl_take isl_space *space) 4101 1.1 mrg { 4102 1.1 mrg struct isl_obj obj = { isl_obj_set, NULL }; 4103 1.1 mrg isl_map *map; 4104 1.1 mrg 4105 1.1 mrg map = isl_set_universe(space); 4106 1.1 mrg if (isl_stream_eat(s, '{') < 0) 4107 1.1 mrg goto error; 4108 1.1 mrg obj = obj_read_disjuncts(s, v, map); 4109 1.1 mrg if (isl_stream_eat(s, '}') < 0) 4110 1.1 mrg goto error; 4111 1.1 mrg isl_map_free(map); 4112 1.1 mrg 4113 1.1 mrg return extract_union_set(s->ctx, obj); 4114 1.1 mrg error: 4115 1.1 mrg obj.type->free(obj.v); 4116 1.1 mrg isl_map_free(map); 4117 1.1 mrg return NULL; 4118 1.1 mrg } 4119 1.1 mrg 4120 1.1 mrg /* Read the body of an isl_multi_union_pw_aff from "s", 4121 1.1 mrg * i.e., everything except the parameter specification. 4122 1.1 mrg * "v" contains a description of the identifiers parsed so far. 4123 1.1 mrg * The parameters, if any, are specified by "space". 4124 1.1 mrg * 4125 1.1 mrg * In particular, handle the special case with shared domain constraints. 4126 1.1 mrg * These are specified as 4127 1.1 mrg * 4128 1.1 mrg * ([...] : ...) 4129 1.1 mrg * 4130 1.1 mrg * and are especially useful for setting the explicit domain 4131 1.1 mrg * of a zero-dimensional isl_multi_union_pw_aff. 4132 1.1 mrg * The core isl_multi_union_pw_aff body ([...]) is read by 4133 1.1 mrg * read_multi_union_pw_aff_body_core. 4134 1.1 mrg */ 4135 1.1 mrg static __isl_give isl_multi_union_pw_aff *read_multi_union_pw_aff_body( 4136 1.1 mrg __isl_keep isl_stream *s, struct vars *v, __isl_take isl_space *space) 4137 1.1 mrg { 4138 1.1 mrg isl_multi_union_pw_aff *mupa; 4139 1.1 mrg 4140 1.1 mrg if (!isl_stream_next_token_is(s, '(')) 4141 1.1 mrg return read_multi_union_pw_aff_body_core(s, v, space); 4142 1.1 mrg 4143 1.1 mrg if (isl_stream_eat(s, '(') < 0) 4144 1.1 mrg goto error; 4145 1.1 mrg mupa = read_multi_union_pw_aff_body_core(s, v, isl_space_copy(space)); 4146 1.1 mrg if (isl_stream_eat_if_available(s, ':')) { 4147 1.1 mrg isl_union_set *dom; 4148 1.1 mrg 4149 1.1 mrg dom = read_union_set_body(s, v, space); 4150 1.1 mrg mupa = isl_multi_union_pw_aff_intersect_domain(mupa, dom); 4151 1.1 mrg } else { 4152 1.1 mrg isl_space_free(space); 4153 1.1 mrg } 4154 1.1 mrg if (isl_stream_eat(s, ')') < 0) 4155 1.1 mrg return isl_multi_union_pw_aff_free(mupa); 4156 1.1 mrg 4157 1.1 mrg return mupa; 4158 1.1 mrg error: 4159 1.1 mrg isl_space_free(space); 4160 1.1 mrg return NULL; 4161 1.1 mrg } 4162 1.1 mrg 4163 1.1 mrg /* Read an isl_multi_union_pw_aff from "s". 4164 1.1 mrg * 4165 1.1 mrg * The input has the form 4166 1.1 mrg * 4167 1.1 mrg * [{ [..] : ... ; [..] : ... }, { [..] : ... ; [..] : ... }] 4168 1.1 mrg * 4169 1.1 mrg * or 4170 1.1 mrg * 4171 1.1 mrg * [..] -> [{ [..] : ... ; [..] : ... }, { [..] : ... ; [..] : ... }] 4172 1.1 mrg * 4173 1.1 mrg * Additionally, a shared domain may be specified as 4174 1.1 mrg * 4175 1.1 mrg * ([..] : ...) 4176 1.1 mrg * 4177 1.1 mrg * or 4178 1.1 mrg * 4179 1.1 mrg * [..] -> ([..] : ...) 4180 1.1 mrg * 4181 1.1 mrg * The first case is handled by the caller, the second case 4182 1.1 mrg * is handled by read_multi_union_pw_aff_body. 4183 1.1 mrg * 4184 1.1 mrg * We first check for the special case of an empty tuple "[]". 4185 1.1 mrg * Then we check if there are any parameters. 4186 1.1 mrg * Finally, read the tuple and construct the result. 4187 1.1 mrg */ 4188 1.1 mrg static __isl_give isl_multi_union_pw_aff *read_multi_union_pw_aff_core( 4189 1.1 mrg __isl_keep isl_stream *s) 4190 1.1 mrg { 4191 1.1 mrg struct vars *v; 4192 1.1 mrg isl_set *dom = NULL; 4193 1.1 mrg isl_space *space; 4194 1.1 mrg isl_multi_union_pw_aff *mupa = NULL; 4195 1.1 mrg 4196 1.1 mrg if (next_is_empty_tuple(s)) { 4197 1.1 mrg if (isl_stream_eat(s, '[')) 4198 1.1 mrg return NULL; 4199 1.1 mrg if (isl_stream_eat(s, ']')) 4200 1.1 mrg return NULL; 4201 1.1 mrg space = isl_space_set_alloc(s->ctx, 0, 0); 4202 1.1 mrg return isl_multi_union_pw_aff_zero(space); 4203 1.1 mrg } 4204 1.1 mrg 4205 1.1 mrg v = vars_new(s->ctx); 4206 1.1 mrg if (!v) 4207 1.1 mrg return NULL; 4208 1.1 mrg 4209 1.1 mrg dom = isl_set_universe(isl_space_params_alloc(s->ctx, 0)); 4210 1.1 mrg if (next_is_param_tuple(s)) { 4211 1.1 mrg dom = read_map_tuple(s, dom, isl_dim_param, v, 0); 4212 1.1 mrg if (isl_stream_eat(s, ISL_TOKEN_TO)) 4213 1.1 mrg goto error; 4214 1.1 mrg } 4215 1.1 mrg space = isl_set_get_space(dom); 4216 1.1 mrg isl_set_free(dom); 4217 1.1 mrg mupa = read_multi_union_pw_aff_body(s, v, space); 4218 1.1 mrg 4219 1.1 mrg vars_free(v); 4220 1.1 mrg 4221 1.1 mrg return mupa; 4222 1.1 mrg error: 4223 1.1 mrg vars_free(v); 4224 1.1 mrg isl_set_free(dom); 4225 1.1 mrg isl_multi_union_pw_aff_free(mupa); 4226 1.1 mrg return NULL; 4227 1.1 mrg } 4228 1.1 mrg 4229 1.1 mrg /* Read an isl_multi_union_pw_aff from "s". 4230 1.1 mrg * 4231 1.1 mrg * In particular, handle the special case with shared domain constraints. 4232 1.1 mrg * These are specified as 4233 1.1 mrg * 4234 1.1 mrg * ([...] : ...) 4235 1.1 mrg * 4236 1.1 mrg * and are especially useful for setting the explicit domain 4237 1.1 mrg * of a zero-dimensional isl_multi_union_pw_aff. 4238 1.1 mrg * The core isl_multi_union_pw_aff ([...]) is read by 4239 1.1 mrg * read_multi_union_pw_aff_core. 4240 1.1 mrg */ 4241 1.1 mrg __isl_give isl_multi_union_pw_aff *isl_stream_read_multi_union_pw_aff( 4242 1.1 mrg __isl_keep isl_stream *s) 4243 1.1 mrg { 4244 1.1 mrg isl_multi_union_pw_aff *mupa; 4245 1.1 mrg 4246 1.1 mrg if (!isl_stream_next_token_is(s, '(')) 4247 1.1 mrg return read_multi_union_pw_aff_core(s); 4248 1.1 mrg 4249 1.1 mrg if (isl_stream_eat(s, '(') < 0) 4250 1.1 mrg return NULL; 4251 1.1 mrg mupa = read_multi_union_pw_aff_core(s); 4252 1.1 mrg if (isl_stream_eat_if_available(s, ':')) { 4253 1.1 mrg isl_union_set *dom; 4254 1.1 mrg 4255 1.1 mrg dom = isl_stream_read_union_set(s); 4256 1.1 mrg mupa = isl_multi_union_pw_aff_intersect_domain(mupa, dom); 4257 1.1 mrg } 4258 1.1 mrg if (isl_stream_eat(s, ')') < 0) 4259 1.1 mrg return isl_multi_union_pw_aff_free(mupa); 4260 1.1 mrg return mupa; 4261 1.1 mrg } 4262 1.1 mrg 4263 1.1 mrg #undef TYPE_BASE 4264 1.1 mrg #define TYPE_BASE multi_union_pw_aff 4265 1.1 mrg #include "isl_read_from_str_templ.c" 4266 1.1 mrg 4267 1.1 mrg __isl_give isl_union_pw_qpolynomial *isl_stream_read_union_pw_qpolynomial( 4268 1.1 mrg __isl_keep isl_stream *s) 4269 1.1 mrg { 4270 1.1 mrg struct isl_obj obj; 4271 1.1 mrg 4272 1.1 mrg obj = obj_read(s); 4273 1.1 mrg if (obj.type == isl_obj_pw_qpolynomial) { 4274 1.1 mrg obj.type = isl_obj_union_pw_qpolynomial; 4275 1.1 mrg obj.v = isl_union_pw_qpolynomial_from_pw_qpolynomial(obj.v); 4276 1.1 mrg } 4277 1.1 mrg if (obj.v) 4278 1.1 mrg isl_assert(s->ctx, obj.type == isl_obj_union_pw_qpolynomial, 4279 1.1 mrg goto error); 4280 1.1 mrg 4281 1.1 mrg return obj.v; 4282 1.1 mrg error: 4283 1.1 mrg obj.type->free(obj.v); 4284 1.1 mrg return NULL; 4285 1.1 mrg } 4286 1.1 mrg 4287 1.1 mrg #undef TYPE_BASE 4288 1.1 mrg #define TYPE_BASE union_pw_qpolynomial 4289 1.1 mrg #include "isl_read_from_str_templ.c" 4290