1 /* 2 * Copyright 2008-2009 Katholieke Universiteit Leuven 3 * Copyright 2010 INRIA Saclay 4 * Copyright 2012-2013 Ecole Normale Superieure 5 * Copyright 2019 Cerebras Systems 6 * 7 * Use of this software is governed by the MIT license 8 * 9 * Written by Sven Verdoolaege, K.U.Leuven, Departement 10 * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium 11 * and INRIA Saclay - Ile-de-France, Parc Club Orsay Universite, 12 * ZAC des vignes, 4 rue Jacques Monod, 91893 Orsay, France 13 * and Ecole Normale Superieure, 45 rue d'Ulm, 75230 Paris, France 14 * and Cerebras Systems, 175 S San Antonio Rd, Los Altos, CA, USA 15 */ 16 17 #include <stdlib.h> 18 #include <string.h> 19 #include <isl_ctx_private.h> 20 #include <isl_map_private.h> 21 #include <isl/set.h> 22 #include <isl_seq.h> 23 #include <isl_polynomial_private.h> 24 #include <isl_printer_private.h> 25 #include <isl_space_private.h> 26 #include <isl_mat_private.h> 27 #include <isl_vec_private.h> 28 #include <isl/union_set.h> 29 #include <isl/union_map.h> 30 #include <isl/constraint.h> 31 #include <isl_local.h> 32 #include <isl_local_space_private.h> 33 #include <isl_aff_private.h> 34 #include <isl_id_private.h> 35 #include <isl_val_private.h> 36 #include <isl_constraint_private.h> 37 #include <isl/ast_build.h> 38 #include <isl_sort.h> 39 #include <isl_output_private.h> 40 41 #include <bset_to_bmap.c> 42 #include <set_to_map.c> 43 #include <uset_to_umap.c> 44 45 static const char *s_to[2] = { " -> ", " \\to " }; 46 static const char *s_and[2] = { " and ", " \\wedge " }; 47 static const char *s_or[2] = { " or ", " \\vee " }; 48 static const char *s_le[2] = { "<=", "\\le" }; 49 static const char *s_ge[2] = { ">=", "\\ge" }; 50 static const char *s_open_set[2] = { "{ ", "\\{\\, " }; 51 static const char *s_close_set[2] = { " }", " \\,\\}" }; 52 static const char *s_open_list[2] = { "[", "(" }; 53 static const char *s_close_list[2] = { "]", ")" }; 54 static const char *s_such_that[2] = { " : ", " \\mid " }; 55 static const char *s_open_exists[2] = { "exists (", "\\exists \\, " }; 56 static const char *s_close_exists[2] = { ")", "" }; 57 static const char *s_div_prefix[2] = { "e", "\\alpha_" }; 58 static const char *s_mod[2] = { "mod", "\\bmod" }; 59 static const char *s_param_prefix[2] = { "p", "p_" }; 60 static const char *s_input_prefix[2] = { "i", "i_" }; 61 static const char *s_output_prefix[2] = { "o", "o_" }; 62 63 static __isl_give isl_printer *print_constraint_polylib( 64 struct isl_basic_map *bmap, int ineq, int n, __isl_take isl_printer *p) 65 { 66 int i; 67 isl_size n_in = isl_basic_map_dim(bmap, isl_dim_in); 68 isl_size n_out = isl_basic_map_dim(bmap, isl_dim_out); 69 isl_size nparam = isl_basic_map_dim(bmap, isl_dim_param); 70 isl_int *c = ineq ? bmap->ineq[n] : bmap->eq[n]; 71 72 if (n_in < 0 || n_out < 0 || nparam < 0) 73 return isl_printer_free(p); 74 75 p = isl_printer_start_line(p); 76 p = isl_printer_print_int(p, ineq); 77 for (i = 0; i < n_out; ++i) { 78 p = isl_printer_print_str(p, " "); 79 p = isl_printer_print_isl_int(p, c[1+nparam+n_in+i]); 80 } 81 for (i = 0; i < n_in; ++i) { 82 p = isl_printer_print_str(p, " "); 83 p = isl_printer_print_isl_int(p, c[1+nparam+i]); 84 } 85 for (i = 0; i < bmap->n_div; ++i) { 86 p = isl_printer_print_str(p, " "); 87 p = isl_printer_print_isl_int(p, c[1+nparam+n_in+n_out+i]); 88 } 89 for (i = 0; i < nparam; ++i) { 90 p = isl_printer_print_str(p, " "); 91 p = isl_printer_print_isl_int(p, c[1+i]); 92 } 93 p = isl_printer_print_str(p, " "); 94 p = isl_printer_print_isl_int(p, c[0]); 95 p = isl_printer_end_line(p); 96 return p; 97 } 98 99 static __isl_give isl_printer *print_constraints_polylib( 100 struct isl_basic_map *bmap, __isl_take isl_printer *p) 101 { 102 int i; 103 104 p = isl_printer_set_isl_int_width(p, 5); 105 106 for (i = 0; i < bmap->n_eq; ++i) 107 p = print_constraint_polylib(bmap, 0, i, p); 108 for (i = 0; i < bmap->n_ineq; ++i) 109 p = print_constraint_polylib(bmap, 1, i, p); 110 111 return p; 112 } 113 114 static __isl_give isl_printer *bset_print_constraints_polylib( 115 struct isl_basic_set *bset, __isl_take isl_printer *p) 116 { 117 return print_constraints_polylib(bset_to_bmap(bset), p); 118 } 119 120 static __isl_give isl_printer *isl_basic_map_print_polylib( 121 __isl_keep isl_basic_map *bmap, __isl_take isl_printer *p, int ext) 122 { 123 isl_size total; 124 125 total = isl_basic_map_dim(bmap, isl_dim_all); 126 if (total < 0) 127 return isl_printer_free(p); 128 p = isl_printer_start_line(p); 129 p = isl_printer_print_int(p, bmap->n_eq + bmap->n_ineq); 130 p = isl_printer_print_str(p, " "); 131 p = isl_printer_print_int(p, 1 + total + 1); 132 if (ext) { 133 isl_size n_in = isl_basic_map_dim(bmap, isl_dim_in); 134 isl_size n_out = isl_basic_map_dim(bmap, isl_dim_out); 135 isl_size n_div = isl_basic_map_dim(bmap, isl_dim_div); 136 isl_size nparam = isl_basic_map_dim(bmap, isl_dim_param); 137 138 if (n_in < 0 || n_out < 0 || n_div < 0 || nparam < 0) 139 return isl_printer_free(p); 140 141 p = isl_printer_print_str(p, " "); 142 p = isl_printer_print_int(p, n_out); 143 p = isl_printer_print_str(p, " "); 144 p = isl_printer_print_int(p, n_in); 145 p = isl_printer_print_str(p, " "); 146 p = isl_printer_print_int(p, n_div); 147 p = isl_printer_print_str(p, " "); 148 p = isl_printer_print_int(p, nparam); 149 } 150 p = isl_printer_end_line(p); 151 return print_constraints_polylib(bmap, p); 152 } 153 154 static __isl_give isl_printer *isl_basic_set_print_polylib( 155 __isl_keep isl_basic_set *bset, __isl_take isl_printer *p, int ext) 156 { 157 return isl_basic_map_print_polylib(bset_to_bmap(bset), p, ext); 158 } 159 160 static __isl_give isl_printer *isl_map_print_polylib(__isl_keep isl_map *map, 161 __isl_take isl_printer *p, int ext) 162 { 163 int i; 164 165 p = isl_printer_start_line(p); 166 p = isl_printer_print_int(p, map->n); 167 p = isl_printer_end_line(p); 168 for (i = 0; i < map->n; ++i) { 169 p = isl_printer_start_line(p); 170 p = isl_printer_end_line(p); 171 p = isl_basic_map_print_polylib(map->p[i], p, ext); 172 } 173 return p; 174 } 175 176 static __isl_give isl_printer *isl_set_print_polylib(__isl_keep isl_set *set, 177 __isl_take isl_printer *p, int ext) 178 { 179 return isl_map_print_polylib(set_to_map(set), p, ext); 180 } 181 182 static isl_size count_same_name(__isl_keep isl_space *space, 183 enum isl_dim_type type, unsigned pos, const char *name) 184 { 185 enum isl_dim_type t; 186 int p; 187 isl_size s; 188 int count = 0; 189 190 for (t = isl_dim_param; t <= type && t <= isl_dim_out; ++t) { 191 s = t == type ? pos : isl_space_dim(space, t); 192 if (s < 0) 193 return isl_size_error; 194 for (p = 0; p < s; ++p) { 195 const char *n = isl_space_get_dim_name(space, t, p); 196 if (n && !strcmp(n, name)) 197 count++; 198 } 199 } 200 return count; 201 } 202 203 /* Print the name of the variable of type "type" and position "pos" 204 * in "space" to "p". 205 */ 206 static __isl_give isl_printer *print_name(__isl_keep isl_space *space, 207 __isl_take isl_printer *p, enum isl_dim_type type, unsigned pos, 208 int latex) 209 { 210 const char *name; 211 char buffer[20]; 212 isl_size primes; 213 214 name = type == isl_dim_div ? NULL 215 : isl_space_get_dim_name(space, type, pos); 216 217 if (!name) { 218 const char *prefix; 219 if (type == isl_dim_param) 220 prefix = s_param_prefix[latex]; 221 else if (type == isl_dim_div) 222 prefix = s_div_prefix[latex]; 223 else if (isl_space_is_set(space) || type == isl_dim_in) 224 prefix = s_input_prefix[latex]; 225 else 226 prefix = s_output_prefix[latex]; 227 snprintf(buffer, sizeof(buffer), "%s%d", prefix, pos); 228 name = buffer; 229 } 230 primes = count_same_name(space, name == buffer ? isl_dim_div : type, 231 pos, name); 232 if (primes < 0) 233 return isl_printer_free(p); 234 p = isl_printer_print_str(p, name); 235 while (primes-- > 0) 236 p = isl_printer_print_str(p, "'"); 237 return p; 238 } 239 240 static isl_stat pos2type(__isl_keep isl_space *space, 241 enum isl_dim_type *type, unsigned *pos) 242 { 243 isl_size n_in = isl_space_dim(space, isl_dim_in); 244 isl_size n_out = isl_space_dim(space, isl_dim_out); 245 isl_size nparam = isl_space_dim(space, isl_dim_param); 246 247 if (n_in < 0 || n_out < 0 || nparam < 0) 248 return isl_stat_error; 249 250 if (*pos < 1 + nparam) { 251 *type = isl_dim_param; 252 *pos -= 1; 253 } else if (*pos < 1 + nparam + n_in) { 254 *type = isl_dim_in; 255 *pos -= 1 + nparam; 256 } else if (*pos < 1 + nparam + n_in + n_out) { 257 *type = isl_dim_out; 258 *pos -= 1 + nparam + n_in; 259 } else { 260 *type = isl_dim_div; 261 *pos -= 1 + nparam + n_in + n_out; 262 } 263 264 return isl_stat_ok; 265 } 266 267 /* Can the div expression of the integer division at position "row" of "div" 268 * be printed? 269 * In particular, are the div expressions available and does the selected 270 * variable have a known explicit representation? 271 * Furthermore, the Omega format does not allow any div expressions 272 * to be printed. 273 */ 274 static isl_bool can_print_div_expr(__isl_keep isl_printer *p, 275 __isl_keep isl_mat *div, int pos) 276 { 277 if (p->output_format == ISL_FORMAT_OMEGA) 278 return isl_bool_false; 279 if (!div) 280 return isl_bool_false; 281 return isl_bool_not(isl_local_div_is_marked_unknown(div, pos)); 282 } 283 284 static __isl_give isl_printer *print_div(__isl_keep isl_space *space, 285 __isl_keep isl_mat *div, int pos, __isl_take isl_printer *p); 286 287 static __isl_give isl_printer *print_term(__isl_keep isl_space *space, 288 __isl_keep isl_mat *div, 289 isl_int c, unsigned pos, __isl_take isl_printer *p, int latex) 290 { 291 enum isl_dim_type type; 292 int print_div_def; 293 294 if (!p || !space) 295 return isl_printer_free(p); 296 297 if (pos == 0) 298 return isl_printer_print_isl_int(p, c); 299 300 if (pos2type(space, &type, &pos) < 0) 301 return isl_printer_free(p); 302 print_div_def = type == isl_dim_div && can_print_div_expr(p, div, pos); 303 304 if (isl_int_is_one(c)) 305 ; 306 else if (isl_int_is_negone(c)) 307 p = isl_printer_print_str(p, "-"); 308 else { 309 p = isl_printer_print_isl_int(p, c); 310 if (p->output_format == ISL_FORMAT_C || print_div_def) 311 p = isl_printer_print_str(p, "*"); 312 } 313 if (print_div_def) 314 p = print_div(space, div, pos, p); 315 else 316 p = print_name(space, p, type, pos, latex); 317 return p; 318 } 319 320 static __isl_give isl_printer *print_affine_of_len(__isl_keep isl_space *space, 321 __isl_keep isl_mat *div, 322 __isl_take isl_printer *p, isl_int *c, int len) 323 { 324 int i; 325 int first; 326 327 for (i = 0, first = 1; i < len; ++i) { 328 int flip = 0; 329 if (isl_int_is_zero(c[i])) 330 continue; 331 if (!first) { 332 if (isl_int_is_neg(c[i])) { 333 flip = 1; 334 isl_int_neg(c[i], c[i]); 335 p = isl_printer_print_str(p, " - "); 336 } else 337 p = isl_printer_print_str(p, " + "); 338 } 339 first = 0; 340 p = print_term(space, div, c[i], i, p, 0); 341 if (flip) 342 isl_int_neg(c[i], c[i]); 343 } 344 if (first) 345 p = isl_printer_print_str(p, "0"); 346 return p; 347 } 348 349 /* Print an affine expression "c" 350 * to "p", with the variable names taken from "space" and 351 * the integer division definitions taken from "div". 352 */ 353 static __isl_give isl_printer *print_affine(__isl_take isl_printer *p, 354 __isl_keep isl_space *space, __isl_keep isl_mat *div, isl_int *c) 355 { 356 isl_size n_div, total; 357 unsigned len; 358 359 total = isl_space_dim(space, isl_dim_all); 360 n_div = isl_mat_rows(div); 361 if (total < 0 || n_div < 0) 362 return isl_printer_free(p); 363 len = 1 + total + n_div; 364 return print_affine_of_len(space, div, p, c, len); 365 } 366 367 /* offset is the offset of local_space inside data->type of data->space. 368 */ 369 static __isl_give isl_printer *print_nested_var_list(__isl_take isl_printer *p, 370 __isl_keep isl_space *local_space, enum isl_dim_type local_type, 371 struct isl_print_space_data *data, int offset) 372 { 373 int i; 374 isl_size dim; 375 376 if (data->space != local_space && local_type == isl_dim_out) 377 offset += local_space->n_in; 378 379 dim = isl_space_dim(local_space, local_type); 380 if (dim < 0) 381 return isl_printer_free(p); 382 for (i = 0; i < dim; ++i) { 383 if (i) 384 p = isl_printer_print_str(p, ", "); 385 if (data->print_dim) 386 p = data->print_dim(p, data, offset + i); 387 else 388 p = print_name(data->space, p, data->type, offset + i, 389 data->latex); 390 } 391 return p; 392 } 393 394 static __isl_give isl_printer *print_var_list(__isl_take isl_printer *p, 395 __isl_keep isl_space *space, enum isl_dim_type type) 396 { 397 struct isl_print_space_data data = { .space = space, .type = type }; 398 399 return print_nested_var_list(p, space, type, &data, 0); 400 } 401 402 static __isl_give isl_printer *print_nested_map_dim(__isl_take isl_printer *p, 403 __isl_keep isl_space *local_dim, 404 struct isl_print_space_data *data, int offset); 405 406 static __isl_give isl_printer *print_nested_tuple(__isl_take isl_printer *p, 407 __isl_keep isl_space *local_space, enum isl_dim_type local_type, 408 struct isl_print_space_data *data, int offset) 409 { 410 const char *name = NULL; 411 isl_size n = isl_space_dim(local_space, local_type); 412 413 if (n < 0) 414 return isl_printer_free(p); 415 if ((local_type == isl_dim_in || local_type == isl_dim_out)) { 416 name = isl_space_get_tuple_name(local_space, local_type); 417 if (name) { 418 if (data->latex) 419 p = isl_printer_print_str(p, "\\mathrm{"); 420 p = isl_printer_print_str(p, name); 421 if (data->latex) 422 p = isl_printer_print_str(p, "}"); 423 } 424 } 425 if (!data->latex || n != 1 || name) 426 p = isl_printer_print_str(p, s_open_list[data->latex]); 427 if ((local_type == isl_dim_in || local_type == isl_dim_out) && 428 local_space->nested[local_type - isl_dim_in]) { 429 if (data->space != local_space && local_type == isl_dim_out) 430 offset += local_space->n_in; 431 p = print_nested_map_dim(p, 432 local_space->nested[local_type - isl_dim_in], 433 data, offset); 434 } else 435 p = print_nested_var_list(p, local_space, local_type, data, 436 offset); 437 if (!data->latex || n != 1 || name) 438 p = isl_printer_print_str(p, s_close_list[data->latex]); 439 return p; 440 } 441 442 static __isl_give isl_printer *print_tuple(__isl_keep isl_space *space, 443 __isl_take isl_printer *p, enum isl_dim_type type, 444 struct isl_print_space_data *data) 445 { 446 data->space = space; 447 data->type = type; 448 return print_nested_tuple(p, space, type, data, 0); 449 } 450 451 static __isl_give isl_printer *print_nested_map_dim(__isl_take isl_printer *p, 452 __isl_keep isl_space *local_dim, 453 struct isl_print_space_data *data, int offset) 454 { 455 p = print_nested_tuple(p, local_dim, isl_dim_in, data, offset); 456 p = isl_printer_print_str(p, s_to[data->latex]); 457 p = print_nested_tuple(p, local_dim, isl_dim_out, data, offset); 458 459 return p; 460 } 461 462 __isl_give isl_printer *isl_print_space(__isl_keep isl_space *space, 463 __isl_take isl_printer *p, int rational, 464 struct isl_print_space_data *data) 465 { 466 if (rational && !data->latex) 467 p = isl_printer_print_str(p, "rat: "); 468 if (isl_space_is_params(space)) 469 ; 470 else if (isl_space_is_set(space)) 471 p = print_tuple(space, p, isl_dim_set, data); 472 else { 473 p = print_tuple(space, p, isl_dim_in, data); 474 p = isl_printer_print_str(p, s_to[data->latex]); 475 p = print_tuple(space, p, isl_dim_out, data); 476 } 477 478 return p; 479 } 480 481 static __isl_give isl_printer *print_omega_parameters( 482 __isl_keep isl_space *space, __isl_take isl_printer *p) 483 { 484 isl_size nparam = isl_space_dim(space, isl_dim_param); 485 486 if (nparam < 0) 487 return isl_printer_free(p); 488 if (nparam == 0) 489 return p; 490 491 p = isl_printer_start_line(p); 492 p = isl_printer_print_str(p, "symbolic "); 493 p = print_var_list(p, space, isl_dim_param); 494 p = isl_printer_print_str(p, ";"); 495 p = isl_printer_end_line(p); 496 return p; 497 } 498 499 /* Does the inequality constraint following "i" in "bmap" 500 * have an opposite value for the same last coefficient? 501 * "last" is the position of the last coefficient of inequality "i". 502 * If the next constraint is a div constraint, then it is ignored 503 * since div constraints are not printed. 504 */ 505 static isl_bool next_is_opposite(__isl_keep isl_basic_map *bmap, int i, 506 int last) 507 { 508 int r; 509 isl_size total = isl_basic_map_dim(bmap, isl_dim_all); 510 unsigned o_div = isl_basic_map_offset(bmap, isl_dim_div); 511 512 if (total < 0) 513 return isl_bool_error; 514 if (i + 1 >= bmap->n_ineq) 515 return isl_bool_false; 516 if (isl_seq_last_non_zero(bmap->ineq[i + 1], 1 + total) != last) 517 return isl_bool_false; 518 if (last >= o_div) { 519 isl_bool is_div; 520 is_div = isl_basic_map_is_div_constraint(bmap, 521 bmap->ineq[i + 1], last - o_div); 522 if (is_div < 0) 523 return isl_bool_error; 524 if (is_div) 525 return isl_bool_false; 526 } 527 r = isl_int_abs_eq(bmap->ineq[i][last], bmap->ineq[i + 1][last]) && 528 !isl_int_eq(bmap->ineq[i][last], bmap->ineq[i + 1][last]); 529 return isl_bool_ok(r); 530 } 531 532 /* Return a string representation of the operator used when 533 * printing a constraint where the LHS is greater than or equal to the LHS 534 * (sign > 0) or smaller than or equal to the LHS (sign < 0). 535 * If "strict" is set, then return the strict version of the comparison 536 * operator. 537 */ 538 static const char *constraint_op(int sign, int strict, int latex) 539 { 540 if (strict) 541 return sign < 0 ? "<" : ">"; 542 if (sign < 0) 543 return s_le[latex]; 544 else 545 return s_ge[latex]; 546 } 547 548 /* Print one side of a constraint "c" to "p", with 549 * the variable names taken from "space" and the integer division definitions 550 * taken from "div". 551 * "last" is the position of the last non-zero coefficient. 552 * Let c' be the result of zeroing out this coefficient, then 553 * the partial constraint 554 * 555 * c' op 556 * 557 * is printed. 558 */ 559 static __isl_give isl_printer *print_half_constraint(__isl_take isl_printer *p, 560 __isl_keep isl_space *space, __isl_keep isl_mat *div, 561 isl_int *c, int last, const char *op, int latex) 562 { 563 isl_int_set_si(c[last], 0); 564 p = print_affine(p, space, div, c); 565 566 p = isl_printer_print_str(p, " "); 567 p = isl_printer_print_str(p, op); 568 p = isl_printer_print_str(p, " "); 569 570 return p; 571 } 572 573 /* Print a constraint "c" to "p", with the variable names 574 * taken from "space" and the integer division definitions taken from "div". 575 * "last" is the position of the last non-zero coefficient, which is 576 * moreover assumed to be negative. 577 * Let c' be the result of zeroing out this coefficient, then 578 * the constraint is printed in the form 579 * 580 * -c[last] op c' 581 */ 582 static __isl_give isl_printer *print_constraint(__isl_take isl_printer *p, 583 __isl_keep isl_space *space, __isl_keep isl_mat *div, 584 isl_int *c, int last, const char *op, int latex) 585 { 586 isl_int_abs(c[last], c[last]); 587 588 p = print_term(space, div, c[last], last, p, latex); 589 590 p = isl_printer_print_str(p, " "); 591 p = isl_printer_print_str(p, op); 592 p = isl_printer_print_str(p, " "); 593 594 isl_int_set_si(c[last], 0); 595 p = print_affine(p, space, div, c); 596 597 return p; 598 } 599 600 /* Given an integer division 601 * 602 * floor(f/m) 603 * 604 * at position "pos" in "div", print the corresponding modulo expression 605 * 606 * (f) mod m 607 * 608 * to "p". The variable names are taken from "space", while any 609 * nested integer division definitions are taken from "div". 610 */ 611 static __isl_give isl_printer *print_mod(__isl_take isl_printer *p, 612 __isl_keep isl_space *space, __isl_keep isl_mat *div, int pos, 613 int latex) 614 { 615 if (!p || !div) 616 return isl_printer_free(p); 617 618 p = isl_printer_print_str(p, "("); 619 p = print_affine_of_len(space, div, p, 620 div->row[pos] + 1, div->n_col - 1); 621 p = isl_printer_print_str(p, ") "); 622 p = isl_printer_print_str(p, s_mod[latex]); 623 p = isl_printer_print_str(p, " "); 624 p = isl_printer_print_isl_int(p, div->row[pos][0]); 625 return p; 626 } 627 628 /* Given an equality constraint with a non-zero coefficient "c" 629 * in position "pos", is this term of the form 630 * 631 * a m floor(g/m), 632 * 633 * with c = a m? 634 * Return the position of the corresponding integer division if so. 635 * Return the number of integer divisions if not. 636 * Return isl_size_error on error. 637 * 638 * Modulo constraints are currently not printed in C format. 639 * Other than that, "pos" needs to correspond to an integer division 640 * with explicit representation and "c" needs to be a multiple 641 * of the denominator of the integer division. 642 */ 643 static isl_size print_as_modulo_pos(__isl_keep isl_printer *p, 644 __isl_keep isl_space *space, __isl_keep isl_mat *div, unsigned pos, 645 isl_int c) 646 { 647 isl_bool can_print; 648 isl_size n_div; 649 enum isl_dim_type type; 650 651 n_div = isl_mat_rows(div); 652 if (!p || !space || n_div < 0) 653 return isl_size_error; 654 if (p->output_format == ISL_FORMAT_C) 655 return n_div; 656 if (pos2type(space, &type, &pos) < 0) 657 return isl_size_error; 658 if (type != isl_dim_div) 659 return n_div; 660 can_print = can_print_div_expr(p, div, pos); 661 if (can_print < 0) 662 return isl_size_error; 663 if (!can_print) 664 return n_div; 665 if (!isl_int_is_divisible_by(c, div->row[pos][0])) 666 return n_div; 667 return pos; 668 } 669 670 /* Print equality constraint "c" to "p" as a modulo constraint, 671 * with the variable names taken from "space" and 672 * the integer division definitions taken from "div". 673 * "last" is the position of the last non-zero coefficient, which is 674 * moreover assumed to be negative and a multiple of the denominator 675 * of the corresponding integer division. "div_pos" is the corresponding 676 * position in the sequence of integer divisions. 677 * 678 * The equality is of the form 679 * 680 * f - a m floor(g/m) = 0. 681 * 682 * Print it as 683 * 684 * a (g mod m) = -f + a g 685 */ 686 static __isl_give isl_printer *print_eq_mod_constraint( 687 __isl_take isl_printer *p, __isl_keep isl_space *space, 688 __isl_keep isl_mat *div, unsigned div_pos, 689 isl_int *c, int last, int latex) 690 { 691 isl_ctx *ctx; 692 int multiple; 693 694 ctx = isl_printer_get_ctx(p); 695 isl_int_divexact(c[last], c[last], div->row[div_pos][0]); 696 isl_int_abs(c[last], c[last]); 697 multiple = !isl_int_is_one(c[last]); 698 if (multiple) { 699 p = isl_printer_print_isl_int(p, c[last]); 700 p = isl_printer_print_str(p, "*("); 701 } 702 p = print_mod(p, space, div, div_pos, latex); 703 if (multiple) 704 p = isl_printer_print_str(p, ")"); 705 p = isl_printer_print_str(p, " = "); 706 isl_seq_combine(c, ctx->negone, c, 707 c[last], div->row[div_pos] + 1, last); 708 isl_int_set_si(c[last], 0); 709 p = print_affine(p, space, div, c); 710 return p; 711 } 712 713 /* Print equality constraint "c" to "p", with the variable names 714 * taken from "space" and the integer division definitions taken from "div". 715 * "last" is the position of the last non-zero coefficient, which is 716 * moreover assumed to be negative. 717 * 718 * If possible, print the equality constraint as a modulo constraint. 719 */ 720 static __isl_give isl_printer *print_eq_constraint(__isl_take isl_printer *p, 721 __isl_keep isl_space *space, __isl_keep isl_mat *div, isl_int *c, 722 int last, int latex) 723 { 724 isl_size n_div; 725 isl_size div_pos; 726 727 n_div = isl_mat_rows(div); 728 div_pos = print_as_modulo_pos(p, space, div, last, c[last]); 729 if (n_div < 0 || div_pos < 0) 730 return isl_printer_free(p); 731 if (div_pos < n_div) 732 return print_eq_mod_constraint(p, space, div, div_pos, 733 c, last, latex); 734 return print_constraint(p, space, div, c, last, "=", latex); 735 } 736 737 /* Print the constraints of "bmap" to "p". 738 * The names of the variables are taken from "space" and 739 * the integer division definitions are taken from "div". 740 * Div constraints are only printed in "dump" mode. 741 * The constraints are sorted prior to printing (except in "dump" mode). 742 * 743 * If x is the last variable with a non-zero coefficient, 744 * then a lower bound 745 * 746 * f - a x >= 0 747 * 748 * is printed as 749 * 750 * a x <= f 751 * 752 * while an upper bound 753 * 754 * f + a x >= 0 755 * 756 * is printed as 757 * 758 * a x >= -f 759 * 760 * If the next constraint has an opposite sign for the same last coefficient, 761 * then it is printed as 762 * 763 * f >= a x 764 * 765 * or 766 * 767 * -f <= a x 768 * 769 * instead. In fact, the "a x" part is not printed explicitly, but 770 * reused from the next constraint, which is therefore treated as 771 * a first constraint in the conjunction. 772 * 773 * If the constant term of "f" is -1, then "f" is replaced by "f + 1" and 774 * the comparison operator is replaced by the strict variant. 775 * Essentially, ">= 1" is replaced by "> 0". 776 */ 777 static __isl_give isl_printer *print_constraints(__isl_keep isl_basic_map *bmap, 778 __isl_keep isl_space *space, __isl_keep isl_mat *div, 779 __isl_take isl_printer *p, int latex) 780 { 781 int i; 782 isl_vec *c = NULL; 783 int rational = ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL); 784 isl_size total = isl_basic_map_dim(bmap, isl_dim_all); 785 unsigned o_div = isl_basic_map_offset(bmap, isl_dim_div); 786 int first = 1; 787 int dump; 788 789 if (total < 0 || !p) 790 return isl_printer_free(p); 791 bmap = isl_basic_map_copy(bmap); 792 dump = p->dump; 793 if (!dump) 794 bmap = isl_basic_map_sort_constraints(bmap); 795 if (!bmap) 796 goto error; 797 798 c = isl_vec_alloc(bmap->ctx, 1 + total); 799 if (!c) 800 goto error; 801 802 for (i = bmap->n_eq - 1; i >= 0; --i) { 803 int l = isl_seq_last_non_zero(bmap->eq[i], 1 + total); 804 if (l < 0) { 805 if (i != bmap->n_eq - 1) 806 p = isl_printer_print_str(p, s_and[latex]); 807 p = isl_printer_print_str(p, "0 = 0"); 808 continue; 809 } 810 if (!first) 811 p = isl_printer_print_str(p, s_and[latex]); 812 if (isl_int_is_neg(bmap->eq[i][l])) 813 isl_seq_cpy(c->el, bmap->eq[i], 1 + total); 814 else 815 isl_seq_neg(c->el, bmap->eq[i], 1 + total); 816 p = print_eq_constraint(p, space, div, c->el, l, latex); 817 first = 0; 818 } 819 for (i = 0; i < bmap->n_ineq; ++i) { 820 isl_bool combine; 821 int l = isl_seq_last_non_zero(bmap->ineq[i], 1 + total); 822 int strict; 823 int s; 824 const char *op; 825 if (l < 0) 826 continue; 827 if (!dump && l >= o_div && 828 can_print_div_expr(p, div, l - o_div)) { 829 isl_bool is_div; 830 is_div = isl_basic_map_is_div_constraint(bmap, 831 bmap->ineq[i], l - o_div); 832 if (is_div < 0) 833 goto error; 834 if (is_div) 835 continue; 836 } 837 if (!first) 838 p = isl_printer_print_str(p, s_and[latex]); 839 s = isl_int_sgn(bmap->ineq[i][l]); 840 strict = !rational && isl_int_is_negone(bmap->ineq[i][0]); 841 if (s < 0) 842 isl_seq_cpy(c->el, bmap->ineq[i], 1 + total); 843 else 844 isl_seq_neg(c->el, bmap->ineq[i], 1 + total); 845 if (strict) 846 isl_int_set_si(c->el[0], 0); 847 combine = dump ? isl_bool_false : next_is_opposite(bmap, i, l); 848 if (combine < 0) 849 goto error; 850 if (combine) { 851 op = constraint_op(-s, strict, latex); 852 p = print_half_constraint(p, space, div, c->el, l, 853 op, latex); 854 first = 1; 855 } else { 856 op = constraint_op(s, strict, latex); 857 p = print_constraint(p, space, div, c->el, l, 858 op, latex); 859 first = 0; 860 } 861 } 862 863 isl_basic_map_free(bmap); 864 isl_vec_free(c); 865 866 return p; 867 error: 868 isl_basic_map_free(bmap); 869 isl_vec_free(c); 870 isl_printer_free(p); 871 return NULL; 872 } 873 874 static __isl_give isl_printer *print_div(__isl_keep isl_space *space, 875 __isl_keep isl_mat *div, int pos, __isl_take isl_printer *p) 876 { 877 int c; 878 879 if (!p || !div) 880 return isl_printer_free(p); 881 882 c = p->output_format == ISL_FORMAT_C; 883 p = isl_printer_print_str(p, c ? "floord(" : "floor(("); 884 p = print_affine_of_len(space, div, p, 885 div->row[pos] + 1, div->n_col - 1); 886 p = isl_printer_print_str(p, c ? ", " : ")/"); 887 p = isl_printer_print_isl_int(p, div->row[pos][0]); 888 p = isl_printer_print_str(p, ")"); 889 return p; 890 } 891 892 /* Print a comma separated list of div names, except those that have 893 * a definition that can be printed. 894 * If "print_defined_divs" is set, then those div names are printed 895 * as well, along with their definitions. 896 */ 897 static __isl_give isl_printer *print_div_list(__isl_take isl_printer *p, 898 __isl_keep isl_space *space, __isl_keep isl_mat *div, int latex, 899 int print_defined_divs) 900 { 901 int i; 902 int first = 1; 903 isl_size n_div; 904 905 n_div = isl_mat_rows(div); 906 if (!p || !space || n_div < 0) 907 return isl_printer_free(p); 908 909 for (i = 0; i < n_div; ++i) { 910 if (!print_defined_divs && can_print_div_expr(p, div, i)) 911 continue; 912 if (!first) 913 p = isl_printer_print_str(p, ", "); 914 p = print_name(space, p, isl_dim_div, i, latex); 915 first = 0; 916 if (!can_print_div_expr(p, div, i)) 917 continue; 918 p = isl_printer_print_str(p, " = "); 919 p = print_div(space, div, i, p); 920 } 921 922 return p; 923 } 924 925 /* Does printing an object with local variables described by "div" 926 * require an "exists" clause? 927 * That is, are there any local variables without an explicit representation? 928 * An exists clause is also needed in "dump" mode because 929 * explicit div representations are not printed inline in that case. 930 */ 931 static isl_bool need_exists(__isl_keep isl_printer *p, __isl_keep isl_mat *div) 932 { 933 int i; 934 isl_size n; 935 936 n = isl_mat_rows(div); 937 if (!p || n < 0) 938 return isl_bool_error; 939 if (n == 0) 940 return isl_bool_false; 941 if (p->dump) 942 return isl_bool_true; 943 for (i = 0; i < n; ++i) 944 if (!can_print_div_expr(p, div, i)) 945 return isl_bool_true; 946 return isl_bool_false; 947 } 948 949 /* Print the start of an exists clause, i.e., 950 * 951 * (exists variables: 952 * 953 * In dump mode, local variables with an explicit definition are printed 954 * as well because they will not be printed inline. 955 */ 956 static __isl_give isl_printer *open_exists(__isl_take isl_printer *p, 957 __isl_keep isl_space *space, __isl_keep isl_mat *div, int latex) 958 { 959 int dump; 960 961 if (!p) 962 return NULL; 963 964 dump = p->dump; 965 p = isl_printer_print_str(p, s_open_exists[latex]); 966 p = print_div_list(p, space, div, latex, dump); 967 p = isl_printer_print_str(p, ": "); 968 969 return p; 970 } 971 972 /* Remove the explicit representations of all local variables in "div". 973 */ 974 static __isl_give isl_mat *mark_all_unknown(__isl_take isl_mat *div) 975 { 976 int i; 977 isl_size n_div; 978 979 n_div = isl_mat_rows(div); 980 if (n_div < 0) 981 return isl_mat_free(div); 982 983 for (i = 0; i < n_div; ++i) 984 div = isl_mat_set_element_si(div, i, 0, 0); 985 return div; 986 } 987 988 /* Print the constraints of "bmap" to "p". 989 * The names of the variables are taken from "space". 990 * "latex" is set if the constraints should be printed in LaTeX format. 991 * Do not print inline explicit div representations in "dump" mode. 992 */ 993 static __isl_give isl_printer *print_disjunct(__isl_keep isl_basic_map *bmap, 994 __isl_keep isl_space *space, __isl_take isl_printer *p, int latex) 995 { 996 int dump; 997 isl_mat *div; 998 isl_bool exists; 999 1000 if (!p) 1001 return NULL; 1002 dump = p->dump; 1003 div = isl_basic_map_get_divs(bmap); 1004 exists = need_exists(p, div); 1005 if (exists >= 0 && exists) 1006 p = open_exists(p, space, div, latex); 1007 1008 if (dump) 1009 div = mark_all_unknown(div); 1010 p = print_constraints(bmap, space, div, p, latex); 1011 isl_mat_free(div); 1012 1013 if (exists >= 0 && exists) 1014 p = isl_printer_print_str(p, s_close_exists[latex]); 1015 return p; 1016 } 1017 1018 /* Print a colon followed by the constraints of "bmap" 1019 * to "p", provided there are any constraints. 1020 * The names of the variables are taken from "space". 1021 * "latex" is set if the constraints should be printed in LaTeX format. 1022 */ 1023 static __isl_give isl_printer *print_optional_disjunct( 1024 __isl_keep isl_basic_map *bmap, __isl_keep isl_space *space, 1025 __isl_take isl_printer *p, int latex) 1026 { 1027 if (isl_basic_map_plain_is_universe(bmap)) 1028 return p; 1029 1030 p = isl_printer_print_str(p, ": "); 1031 p = print_disjunct(bmap, space, p, latex); 1032 1033 return p; 1034 } 1035 1036 static __isl_give isl_printer *basic_map_print_omega( 1037 __isl_keep isl_basic_map *bmap, __isl_take isl_printer *p) 1038 { 1039 p = isl_printer_print_str(p, "{ ["); 1040 p = print_var_list(p, bmap->dim, isl_dim_in); 1041 p = isl_printer_print_str(p, "] -> ["); 1042 p = print_var_list(p, bmap->dim, isl_dim_out); 1043 p = isl_printer_print_str(p, "] "); 1044 p = print_optional_disjunct(bmap, bmap->dim, p, 0); 1045 p = isl_printer_print_str(p, " }"); 1046 return p; 1047 } 1048 1049 static __isl_give isl_printer *basic_set_print_omega( 1050 __isl_keep isl_basic_set *bset, __isl_take isl_printer *p) 1051 { 1052 p = isl_printer_print_str(p, "{ ["); 1053 p = print_var_list(p, bset->dim, isl_dim_set); 1054 p = isl_printer_print_str(p, "] "); 1055 p = print_optional_disjunct(bset, bset->dim, p, 0); 1056 p = isl_printer_print_str(p, " }"); 1057 return p; 1058 } 1059 1060 static __isl_give isl_printer *isl_map_print_omega(__isl_keep isl_map *map, 1061 __isl_take isl_printer *p) 1062 { 1063 int i; 1064 1065 for (i = 0; i < map->n; ++i) { 1066 if (i) 1067 p = isl_printer_print_str(p, " union "); 1068 p = basic_map_print_omega(map->p[i], p); 1069 } 1070 return p; 1071 } 1072 1073 static __isl_give isl_printer *isl_set_print_omega(__isl_keep isl_set *set, 1074 __isl_take isl_printer *p) 1075 { 1076 int i; 1077 1078 for (i = 0; i < set->n; ++i) { 1079 if (i) 1080 p = isl_printer_print_str(p, " union "); 1081 p = basic_set_print_omega(set->p[i], p); 1082 } 1083 return p; 1084 } 1085 1086 /* Print the list of parameters in "space", followed by an arrow, to "p", 1087 * if there are any parameters. 1088 */ 1089 static __isl_give isl_printer *print_param_tuple(__isl_take isl_printer *p, 1090 __isl_keep isl_space *space, struct isl_print_space_data *data) 1091 { 1092 isl_size nparam; 1093 1094 nparam = isl_space_dim(space, isl_dim_param); 1095 if (!p || nparam < 0) 1096 return isl_printer_free(p); 1097 if (nparam == 0) 1098 return p; 1099 1100 p = print_tuple(space, p, isl_dim_param, data); 1101 p = isl_printer_print_str(p, s_to[data->latex]); 1102 1103 return p; 1104 } 1105 1106 static __isl_give isl_printer *isl_basic_map_print_isl( 1107 __isl_keep isl_basic_map *bmap, __isl_take isl_printer *p, 1108 int latex) 1109 { 1110 struct isl_print_space_data data = { .latex = latex }; 1111 int rational = ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL); 1112 1113 p = print_param_tuple(p, bmap->dim, &data); 1114 p = isl_printer_print_str(p, "{ "); 1115 p = isl_print_space(bmap->dim, p, rational, &data); 1116 p = isl_printer_print_str(p, " : "); 1117 p = print_disjunct(bmap, bmap->dim, p, latex); 1118 p = isl_printer_print_str(p, " }"); 1119 return p; 1120 } 1121 1122 /* Print the disjuncts of a map (or set) "map" to "p". 1123 * The names of the variables are taken from "space". 1124 * "latex" is set if the constraints should be printed in LaTeX format. 1125 */ 1126 static __isl_give isl_printer *print_disjuncts_core(__isl_keep isl_map *map, 1127 __isl_keep isl_space *space, __isl_take isl_printer *p, int latex) 1128 { 1129 int i; 1130 1131 if (map->n == 0) 1132 p = isl_printer_print_str(p, "false"); 1133 for (i = 0; i < map->n; ++i) { 1134 if (i) 1135 p = isl_printer_print_str(p, s_or[latex]); 1136 if (map->n > 1 && map->p[i]->n_eq + map->p[i]->n_ineq > 1) 1137 p = isl_printer_print_str(p, "("); 1138 p = print_disjunct(map->p[i], space, p, latex); 1139 if (map->n > 1 && map->p[i]->n_eq + map->p[i]->n_ineq > 1) 1140 p = isl_printer_print_str(p, ")"); 1141 } 1142 return p; 1143 } 1144 1145 /* Print the disjuncts of a map (or set) "map" to "p". 1146 * The names of the variables are taken from "space". 1147 * "hull" describes constraints shared by all disjuncts of "map". 1148 * "latex" is set if the constraints should be printed in LaTeX format. 1149 * 1150 * Print the disjuncts as a conjunction of "hull" and 1151 * the result of removing the constraints of "hull" from "map". 1152 * If this result turns out to be the universe, then simply print "hull". 1153 */ 1154 static __isl_give isl_printer *print_disjuncts_in_hull(__isl_keep isl_map *map, 1155 __isl_keep isl_space *space, __isl_take isl_basic_map *hull, 1156 __isl_take isl_printer *p, int latex) 1157 { 1158 isl_bool is_universe; 1159 1160 p = print_disjunct(hull, space, p, latex); 1161 map = isl_map_plain_gist_basic_map(isl_map_copy(map), hull); 1162 is_universe = isl_map_plain_is_universe(map); 1163 if (is_universe < 0) 1164 goto error; 1165 if (!is_universe) { 1166 p = isl_printer_print_str(p, s_and[latex]); 1167 p = isl_printer_print_str(p, "("); 1168 p = print_disjuncts_core(map, space, p, latex); 1169 p = isl_printer_print_str(p, ")"); 1170 } 1171 isl_map_free(map); 1172 1173 return p; 1174 error: 1175 isl_map_free(map); 1176 isl_printer_free(p); 1177 return NULL; 1178 } 1179 1180 /* Print the disjuncts of a map (or set) "map" to "p". 1181 * The names of the variables are taken from "space". 1182 * "latex" is set if the constraints should be printed in LaTeX format. 1183 * 1184 * If there are at least two disjuncts and "dump" mode is not turned out, 1185 * check for any shared constraints among all disjuncts. 1186 * If there are any, then print them separately in print_disjuncts_in_hull. 1187 */ 1188 static __isl_give isl_printer *print_disjuncts(__isl_keep isl_map *map, 1189 __isl_keep isl_space *space, __isl_take isl_printer *p, int latex) 1190 { 1191 if (isl_map_plain_is_universe(map)) 1192 return p; 1193 1194 p = isl_printer_print_str(p, s_such_that[latex]); 1195 if (!p) 1196 return NULL; 1197 1198 if (!p->dump && map->n >= 2) { 1199 isl_basic_map *hull; 1200 isl_bool is_universe; 1201 1202 hull = isl_map_plain_unshifted_simple_hull(isl_map_copy(map)); 1203 is_universe = isl_basic_map_plain_is_universe(hull); 1204 if (is_universe < 0) 1205 p = isl_printer_free(p); 1206 else if (!is_universe) 1207 return print_disjuncts_in_hull(map, space, hull, 1208 p, latex); 1209 isl_basic_map_free(hull); 1210 } 1211 1212 return print_disjuncts_core(map, space, p, latex); 1213 } 1214 1215 /* Print the disjuncts of a map (or set). 1216 * The names of the variables are taken from "space". 1217 * "latex" is set if the constraints should be printed in LaTeX format. 1218 * 1219 * If the map turns out to be a universal parameter domain, then 1220 * we need to print the colon. Otherwise, the output looks identical 1221 * to the empty set. 1222 */ 1223 static __isl_give isl_printer *print_disjuncts_map(__isl_keep isl_map *map, 1224 __isl_keep isl_space *space, __isl_take isl_printer *p, int latex) 1225 { 1226 if (isl_map_plain_is_universe(map) && isl_space_is_params(map->dim)) 1227 return isl_printer_print_str(p, s_such_that[latex]); 1228 else 1229 return print_disjuncts(map, space, p, latex); 1230 } 1231 1232 /* Print the disjuncts of a set. 1233 * The names of the variables are taken from "space". 1234 * "latex" is set if the constraints should be printed in LaTeX format. 1235 */ 1236 static __isl_give isl_printer *print_disjuncts_set(__isl_keep isl_set *set, 1237 __isl_keep isl_space *space, __isl_take isl_printer *p, int latex) 1238 { 1239 return print_disjuncts_map(set_to_map(set), space, p, latex); 1240 } 1241 1242 struct isl_aff_split { 1243 isl_basic_map *aff; 1244 isl_map *map; 1245 }; 1246 1247 static void free_split(__isl_take struct isl_aff_split *split, int n) 1248 { 1249 int i; 1250 1251 if (!split) 1252 return; 1253 1254 for (i = 0; i < n; ++i) { 1255 isl_basic_map_free(split[i].aff); 1256 isl_map_free(split[i].map); 1257 } 1258 1259 free(split); 1260 } 1261 1262 static __isl_give isl_basic_map *get_aff(__isl_take isl_basic_map *bmap) 1263 { 1264 int i, j; 1265 isl_size nparam, n_in, n_out, total; 1266 1267 bmap = isl_basic_map_cow(bmap); 1268 if (!bmap) 1269 return NULL; 1270 bmap = isl_basic_map_free_inequality(bmap, bmap->n_ineq); 1271 1272 nparam = isl_basic_map_dim(bmap, isl_dim_param); 1273 n_in = isl_basic_map_dim(bmap, isl_dim_in); 1274 n_out = isl_basic_map_dim(bmap, isl_dim_out); 1275 total = isl_basic_map_dim(bmap, isl_dim_all); 1276 if (n_in < 0 || n_out < 0 || nparam < 0 || total < 0) 1277 return isl_basic_map_free(bmap); 1278 1279 for (i = bmap->n_eq - 1; i >= 0; --i) { 1280 j = isl_seq_last_non_zero(bmap->eq[i] + 1, total); 1281 if (j >= nparam && j < nparam + n_in + n_out && 1282 (isl_int_is_one(bmap->eq[i][1 + j]) || 1283 isl_int_is_negone(bmap->eq[i][1 + j]))) 1284 continue; 1285 if (isl_basic_map_drop_equality(bmap, i) < 0) 1286 goto error; 1287 } 1288 1289 bmap = isl_basic_map_finalize(bmap); 1290 1291 return bmap; 1292 error: 1293 isl_basic_map_free(bmap); 1294 return NULL; 1295 } 1296 1297 static int aff_split_cmp(const void *p1, const void *p2, void *user) 1298 { 1299 const struct isl_aff_split *s1, *s2; 1300 s1 = (const struct isl_aff_split *) p1; 1301 s2 = (const struct isl_aff_split *) p2; 1302 1303 return isl_basic_map_plain_cmp(s1->aff, s2->aff); 1304 } 1305 1306 static __isl_give isl_basic_map *drop_aff(__isl_take isl_basic_map *bmap, 1307 __isl_keep isl_basic_map *aff) 1308 { 1309 int i, j; 1310 isl_size v_div; 1311 1312 v_div = isl_basic_map_var_offset(bmap, isl_dim_div); 1313 if (v_div < 0 || !aff) 1314 goto error; 1315 1316 for (i = bmap->n_eq - 1; i >= 0; --i) { 1317 if (isl_seq_first_non_zero(bmap->eq[i] + 1 + v_div, 1318 bmap->n_div) != -1) 1319 continue; 1320 for (j = 0; j < aff->n_eq; ++j) { 1321 if (!isl_seq_eq(bmap->eq[i], aff->eq[j], 1 + v_div) && 1322 !isl_seq_is_neg(bmap->eq[i], aff->eq[j], 1 + v_div)) 1323 continue; 1324 if (isl_basic_map_drop_equality(bmap, i) < 0) 1325 goto error; 1326 break; 1327 } 1328 } 1329 1330 return bmap; 1331 error: 1332 isl_basic_map_free(bmap); 1333 return NULL; 1334 } 1335 1336 static __isl_give struct isl_aff_split *split_aff(__isl_keep isl_map *map) 1337 { 1338 int i, n; 1339 struct isl_aff_split *split; 1340 isl_ctx *ctx; 1341 1342 ctx = isl_map_get_ctx(map); 1343 split = isl_calloc_array(ctx, struct isl_aff_split, map->n); 1344 if (!split) 1345 return NULL; 1346 1347 for (i = 0; i < map->n; ++i) { 1348 isl_basic_map *bmap; 1349 split[i].aff = get_aff(isl_basic_map_copy(map->p[i])); 1350 bmap = isl_basic_map_copy(map->p[i]); 1351 bmap = isl_basic_map_cow(bmap); 1352 bmap = drop_aff(bmap, split[i].aff); 1353 split[i].map = isl_map_from_basic_map(bmap); 1354 if (!split[i].aff || !split[i].map) 1355 goto error; 1356 } 1357 1358 if (isl_sort(split, map->n, sizeof(struct isl_aff_split), 1359 &aff_split_cmp, NULL) < 0) 1360 goto error; 1361 1362 n = map->n; 1363 for (i = n - 1; i >= 1; --i) { 1364 if (!isl_basic_map_plain_is_equal(split[i - 1].aff, 1365 split[i].aff)) 1366 continue; 1367 isl_basic_map_free(split[i].aff); 1368 split[i - 1].map = isl_map_union(split[i - 1].map, 1369 split[i].map); 1370 if (i != n - 1) 1371 split[i] = split[n - 1]; 1372 split[n - 1].aff = NULL; 1373 split[n - 1].map = NULL; 1374 --n; 1375 } 1376 1377 return split; 1378 error: 1379 free_split(split, map->n); 1380 return NULL; 1381 } 1382 1383 /* Given a set of equality constraints "eq" obtained from get_aff, 1384 * i.e., with a (positive or negative) unit coefficient in the last position, 1385 * look for an equality constraint in "eq" that defines 1386 * the "type" variable at position "pos" in "space", 1387 * i.e., where that last coefficient corresponds to the given variable. 1388 * If so, return the position of that equality constraint. 1389 * Return a value beyond the number of equality constraints 1390 * if no such constraint can be found. 1391 * Return isl_size_error in case of error. 1392 * 1393 * If a suitable constraint is found, then also make sure 1394 * it has a negative unit coefficient for the given variable. 1395 */ 1396 static isl_size defining_equality(__isl_keep isl_basic_map *eq, 1397 __isl_keep isl_space *space, enum isl_dim_type type, int pos) 1398 { 1399 int i; 1400 isl_size total, off; 1401 isl_size n_eq; 1402 1403 total = isl_basic_map_dim(eq, isl_dim_all); 1404 n_eq = isl_basic_map_n_equality(eq); 1405 off = isl_space_offset(space, type); 1406 if (total < 0 || n_eq < 0 || off < 0) 1407 return isl_size_error; 1408 1409 pos += off; 1410 1411 for (i = 0; i < n_eq; ++i) { 1412 if (isl_seq_last_non_zero(eq->eq[i] + 1, total) != pos) 1413 continue; 1414 if (isl_int_is_one(eq->eq[i][1 + pos])) 1415 isl_seq_neg(eq->eq[i], eq->eq[i], 1 + total); 1416 return i; 1417 } 1418 1419 return n_eq; 1420 } 1421 1422 /* Print dimension "pos" of data->space to "p". 1423 * 1424 * data->user is assumed to be an isl_basic_map keeping track of equalities. 1425 * 1426 * If the current dimension is defined by these equalities, then print 1427 * the corresponding expression, assigned to the name of the dimension 1428 * if there is any. Otherwise, print the name of the dimension. 1429 */ 1430 static __isl_give isl_printer *print_dim_eq(__isl_take isl_printer *p, 1431 struct isl_print_space_data *data, unsigned pos) 1432 { 1433 isl_basic_map *eq = data->user; 1434 isl_size j, n_eq; 1435 1436 n_eq = isl_basic_map_n_equality(eq); 1437 j = defining_equality(eq, data->space, data->type, pos); 1438 if (j < 0 || n_eq < 0) 1439 return isl_printer_free(p); 1440 if (j < n_eq) { 1441 isl_size off; 1442 1443 if (isl_space_has_dim_name(data->space, data->type, pos)) { 1444 p = print_name(data->space, p, data->type, pos, 1445 data->latex); 1446 p = isl_printer_print_str(p, " = "); 1447 } 1448 off = isl_space_offset(data->space, data->type); 1449 if (off < 0) 1450 return isl_printer_free(p); 1451 pos += 1 + off; 1452 p = print_affine_of_len(data->space, NULL, p, eq->eq[j], pos); 1453 } else { 1454 p = print_name(data->space, p, data->type, pos, data->latex); 1455 } 1456 1457 return p; 1458 } 1459 1460 static __isl_give isl_printer *print_split_map(__isl_take isl_printer *p, 1461 struct isl_aff_split *split, int n, __isl_keep isl_space *space) 1462 { 1463 struct isl_print_space_data data = { 0 }; 1464 int i; 1465 int rational; 1466 1467 data.print_dim = &print_dim_eq; 1468 for (i = 0; i < n; ++i) { 1469 if (!split[i].map) 1470 break; 1471 rational = split[i].map->n > 0 && 1472 ISL_F_ISSET(split[i].map->p[0], ISL_BASIC_MAP_RATIONAL); 1473 if (i) 1474 p = isl_printer_print_str(p, "; "); 1475 data.user = split[i].aff; 1476 p = isl_print_space(space, p, rational, &data); 1477 p = print_disjuncts_map(split[i].map, space, p, 0); 1478 } 1479 1480 return p; 1481 } 1482 1483 static __isl_give isl_printer *print_body_map(__isl_take isl_printer *p, 1484 __isl_keep isl_map *map) 1485 { 1486 struct isl_print_space_data data = { 0 }; 1487 struct isl_aff_split *split = NULL; 1488 int rational; 1489 1490 if (!p || !map) 1491 return isl_printer_free(p); 1492 if (!p->dump && map->n > 0) 1493 split = split_aff(map); 1494 if (split) { 1495 p = print_split_map(p, split, map->n, map->dim); 1496 } else { 1497 rational = map->n > 0 && 1498 ISL_F_ISSET(map->p[0], ISL_BASIC_MAP_RATIONAL); 1499 p = isl_print_space(map->dim, p, rational, &data); 1500 p = print_disjuncts_map(map, map->dim, p, 0); 1501 } 1502 free_split(split, map->n); 1503 return p; 1504 } 1505 1506 static __isl_give isl_printer *isl_map_print_isl(__isl_keep isl_map *map, 1507 __isl_take isl_printer *p) 1508 { 1509 struct isl_print_space_data data = { 0 }; 1510 1511 p = print_param_tuple(p, map->dim, &data); 1512 p = isl_printer_print_str(p, s_open_set[0]); 1513 p = print_body_map(p, map); 1514 p = isl_printer_print_str(p, s_close_set[0]); 1515 return p; 1516 } 1517 1518 static __isl_give isl_printer *print_latex_map(__isl_keep isl_map *map, 1519 __isl_take isl_printer *p, __isl_keep isl_basic_map *aff) 1520 { 1521 struct isl_print_space_data data = { 0 }; 1522 1523 data.latex = 1; 1524 p = print_param_tuple(p, map->dim, &data); 1525 p = isl_printer_print_str(p, s_open_set[1]); 1526 data.print_dim = &print_dim_eq; 1527 data.user = aff; 1528 p = isl_print_space(map->dim, p, 0, &data); 1529 p = print_disjuncts_map(map, map->dim, p, 1); 1530 p = isl_printer_print_str(p, s_close_set[1]); 1531 1532 return p; 1533 } 1534 1535 static __isl_give isl_printer *isl_map_print_latex(__isl_keep isl_map *map, 1536 __isl_take isl_printer *p) 1537 { 1538 int i; 1539 struct isl_aff_split *split = NULL; 1540 1541 if (map->n > 0) 1542 split = split_aff(map); 1543 1544 if (!split) 1545 return print_latex_map(map, p, NULL); 1546 1547 for (i = 0; i < map->n; ++i) { 1548 if (!split[i].map) 1549 break; 1550 if (i) 1551 p = isl_printer_print_str(p, " \\cup "); 1552 p = print_latex_map(split[i].map, p, split[i].aff); 1553 } 1554 1555 free_split(split, map->n); 1556 return p; 1557 } 1558 1559 __isl_give isl_printer *isl_printer_print_basic_map(__isl_take isl_printer *p, 1560 __isl_keep isl_basic_map *bmap) 1561 { 1562 if (!p || !bmap) 1563 goto error; 1564 if (p->output_format == ISL_FORMAT_ISL) 1565 return isl_basic_map_print_isl(bmap, p, 0); 1566 else if (p->output_format == ISL_FORMAT_OMEGA) 1567 return basic_map_print_omega(bmap, p); 1568 isl_assert(bmap->ctx, 0, goto error); 1569 error: 1570 isl_printer_free(p); 1571 return NULL; 1572 } 1573 1574 __isl_give isl_printer *isl_printer_print_basic_set(__isl_take isl_printer *p, 1575 __isl_keep isl_basic_set *bset) 1576 { 1577 if (!p || !bset) 1578 goto error; 1579 1580 if (p->output_format == ISL_FORMAT_ISL) 1581 return isl_basic_map_print_isl(bset, p, 0); 1582 else if (p->output_format == ISL_FORMAT_POLYLIB) 1583 return isl_basic_set_print_polylib(bset, p, 0); 1584 else if (p->output_format == ISL_FORMAT_EXT_POLYLIB) 1585 return isl_basic_set_print_polylib(bset, p, 1); 1586 else if (p->output_format == ISL_FORMAT_POLYLIB_CONSTRAINTS) 1587 return bset_print_constraints_polylib(bset, p); 1588 else if (p->output_format == ISL_FORMAT_OMEGA) 1589 return basic_set_print_omega(bset, p); 1590 isl_assert(p->ctx, 0, goto error); 1591 error: 1592 isl_printer_free(p); 1593 return NULL; 1594 } 1595 1596 __isl_give isl_printer *isl_printer_print_set(__isl_take isl_printer *p, 1597 __isl_keep isl_set *set) 1598 { 1599 if (!p || !set) 1600 goto error; 1601 if (p->output_format == ISL_FORMAT_ISL) 1602 return isl_map_print_isl(set_to_map(set), p); 1603 else if (p->output_format == ISL_FORMAT_POLYLIB) 1604 return isl_set_print_polylib(set, p, 0); 1605 else if (p->output_format == ISL_FORMAT_EXT_POLYLIB) 1606 return isl_set_print_polylib(set, p, 1); 1607 else if (p->output_format == ISL_FORMAT_OMEGA) 1608 return isl_set_print_omega(set, p); 1609 else if (p->output_format == ISL_FORMAT_LATEX) 1610 return isl_map_print_latex(set_to_map(set), p); 1611 isl_assert(set->ctx, 0, goto error); 1612 error: 1613 isl_printer_free(p); 1614 return NULL; 1615 } 1616 1617 __isl_give isl_printer *isl_printer_print_map(__isl_take isl_printer *p, 1618 __isl_keep isl_map *map) 1619 { 1620 if (!p || !map) 1621 goto error; 1622 1623 if (p->output_format == ISL_FORMAT_ISL) 1624 return isl_map_print_isl(map, p); 1625 else if (p->output_format == ISL_FORMAT_POLYLIB) 1626 return isl_map_print_polylib(map, p, 0); 1627 else if (p->output_format == ISL_FORMAT_EXT_POLYLIB) 1628 return isl_map_print_polylib(map, p, 1); 1629 else if (p->output_format == ISL_FORMAT_OMEGA) 1630 return isl_map_print_omega(map, p); 1631 else if (p->output_format == ISL_FORMAT_LATEX) 1632 return isl_map_print_latex(map, p); 1633 isl_assert(map->ctx, 0, goto error); 1634 error: 1635 isl_printer_free(p); 1636 return NULL; 1637 } 1638 1639 struct isl_union_print_data { 1640 isl_printer *p; 1641 int first; 1642 }; 1643 1644 #undef BASE 1645 #define BASE map 1646 #include "isl_union_print_templ.c" 1647 1648 /* Print the body of "uset" (everything except the parameter declarations) 1649 * to "p" in isl format. 1650 */ 1651 static __isl_give isl_printer *isl_printer_print_union_set_isl_body( 1652 __isl_take isl_printer *p, __isl_keep isl_union_set *uset) 1653 { 1654 return print_body_union_map(p, uset_to_umap(uset)); 1655 } 1656 1657 static isl_stat print_latex_map_body(__isl_take isl_map *map, void *user) 1658 { 1659 struct isl_union_print_data *data; 1660 data = (struct isl_union_print_data *)user; 1661 1662 if (!data->first) 1663 data->p = isl_printer_print_str(data->p, " \\cup "); 1664 data->first = 0; 1665 1666 data->p = isl_map_print_latex(map, data->p); 1667 isl_map_free(map); 1668 1669 return isl_stat_ok; 1670 } 1671 1672 static __isl_give isl_printer *isl_union_map_print_latex( 1673 __isl_keep isl_union_map *umap, __isl_take isl_printer *p) 1674 { 1675 struct isl_union_print_data data = { p, 1 }; 1676 isl_union_map_foreach_map(umap, &print_latex_map_body, &data); 1677 p = data.p; 1678 return p; 1679 } 1680 1681 __isl_give isl_printer *isl_printer_print_union_map(__isl_take isl_printer *p, 1682 __isl_keep isl_union_map *umap) 1683 { 1684 if (!p || !umap) 1685 goto error; 1686 1687 if (p->output_format == ISL_FORMAT_ISL) 1688 return print_union_map_isl(p, umap); 1689 if (p->output_format == ISL_FORMAT_LATEX) 1690 return isl_union_map_print_latex(umap, p); 1691 1692 isl_die(p->ctx, isl_error_invalid, 1693 "invalid output format for isl_union_map", goto error); 1694 error: 1695 isl_printer_free(p); 1696 return NULL; 1697 } 1698 1699 __isl_give isl_printer *isl_printer_print_union_set(__isl_take isl_printer *p, 1700 __isl_keep isl_union_set *uset) 1701 { 1702 if (!p || !uset) 1703 goto error; 1704 1705 if (p->output_format == ISL_FORMAT_ISL) 1706 return print_union_map_isl(p, uset_to_umap(uset)); 1707 if (p->output_format == ISL_FORMAT_LATEX) 1708 return isl_union_map_print_latex(uset_to_umap(uset), p); 1709 1710 isl_die(p->ctx, isl_error_invalid, 1711 "invalid output format for isl_union_set", goto error); 1712 error: 1713 isl_printer_free(p); 1714 return NULL; 1715 } 1716 1717 static isl_size poly_rec_n_non_zero(__isl_keep isl_poly_rec *rec) 1718 { 1719 int i; 1720 int n; 1721 1722 if (!rec) 1723 return isl_size_error; 1724 1725 for (i = 0, n = 0; i < rec->n; ++i) { 1726 isl_bool is_zero = isl_poly_is_zero(rec->p[i]); 1727 1728 if (is_zero < 0) 1729 return isl_size_error; 1730 if (!is_zero) 1731 ++n; 1732 } 1733 1734 return n; 1735 } 1736 1737 static __isl_give isl_printer *poly_print_cst(__isl_keep isl_poly *poly, 1738 __isl_take isl_printer *p, int first) 1739 { 1740 isl_poly_cst *cst; 1741 int neg; 1742 1743 cst = isl_poly_as_cst(poly); 1744 if (!cst) 1745 goto error; 1746 neg = !first && isl_int_is_neg(cst->n); 1747 if (!first) 1748 p = isl_printer_print_str(p, neg ? " - " : " + "); 1749 if (neg) 1750 isl_int_neg(cst->n, cst->n); 1751 if (isl_int_is_zero(cst->d)) { 1752 int sgn = isl_int_sgn(cst->n); 1753 p = isl_printer_print_str(p, sgn < 0 ? "-infty" : 1754 sgn == 0 ? "NaN" : "infty"); 1755 } else 1756 p = isl_printer_print_isl_int(p, cst->n); 1757 if (neg) 1758 isl_int_neg(cst->n, cst->n); 1759 if (!isl_int_is_zero(cst->d) && !isl_int_is_one(cst->d)) { 1760 p = isl_printer_print_str(p, "/"); 1761 p = isl_printer_print_isl_int(p, cst->d); 1762 } 1763 return p; 1764 error: 1765 isl_printer_free(p); 1766 return NULL; 1767 } 1768 1769 static __isl_give isl_printer *print_base(__isl_take isl_printer *p, 1770 __isl_keep isl_space *space, __isl_keep isl_mat *div, int var) 1771 { 1772 isl_size total; 1773 1774 total = isl_space_dim(space, isl_dim_all); 1775 if (total < 0) 1776 return isl_printer_free(p); 1777 if (var < total) 1778 p = print_term(space, NULL, space->ctx->one, 1 + var, p, 0); 1779 else 1780 p = print_div(space, div, var - total, p); 1781 return p; 1782 } 1783 1784 static __isl_give isl_printer *print_pow(__isl_take isl_printer *p, 1785 __isl_keep isl_space *space, __isl_keep isl_mat *div, int var, int exp) 1786 { 1787 p = print_base(p, space, div, var); 1788 if (exp == 1) 1789 return p; 1790 if (p->output_format == ISL_FORMAT_C) { 1791 int i; 1792 for (i = 1; i < exp; ++i) { 1793 p = isl_printer_print_str(p, "*"); 1794 p = print_base(p, space, div, var); 1795 } 1796 } else { 1797 p = isl_printer_print_str(p, "^"); 1798 p = isl_printer_print_int(p, exp); 1799 } 1800 return p; 1801 } 1802 1803 /* Print the polynomial "poly" defined over the domain space "space" and 1804 * local variables defined by "div" to "p". 1805 */ 1806 static __isl_give isl_printer *poly_print(__isl_keep isl_poly *poly, 1807 __isl_keep isl_space *space, __isl_keep isl_mat *div, 1808 __isl_take isl_printer *p) 1809 { 1810 int i, first, print_parens; 1811 isl_size n; 1812 isl_bool is_cst; 1813 isl_poly_rec *rec; 1814 1815 is_cst = isl_poly_is_cst(poly); 1816 if (!p || is_cst < 0 || !space || !div) 1817 goto error; 1818 1819 if (is_cst) 1820 return poly_print_cst(poly, p, 1); 1821 1822 rec = isl_poly_as_rec(poly); 1823 n = poly_rec_n_non_zero(rec); 1824 if (n < 0) 1825 return isl_printer_free(p); 1826 print_parens = n > 1; 1827 if (print_parens) 1828 p = isl_printer_print_str(p, "("); 1829 for (i = 0, first = 1; i < rec->n; ++i) { 1830 isl_bool is_zero = isl_poly_is_zero(rec->p[i]); 1831 isl_bool is_one = isl_poly_is_one(rec->p[i]); 1832 isl_bool is_negone = isl_poly_is_negone(rec->p[i]); 1833 isl_bool is_cst = isl_poly_is_cst(rec->p[i]); 1834 1835 if (is_zero < 0 || is_one < 0 || is_negone < 0) 1836 return isl_printer_free(p); 1837 if (is_zero) 1838 continue; 1839 if (is_negone) { 1840 if (!i) 1841 p = isl_printer_print_str(p, "-1"); 1842 else if (first) 1843 p = isl_printer_print_str(p, "-"); 1844 else 1845 p = isl_printer_print_str(p, " - "); 1846 } else if (is_cst && !is_one) 1847 p = poly_print_cst(rec->p[i], p, first); 1848 else { 1849 if (!first) 1850 p = isl_printer_print_str(p, " + "); 1851 if (i == 0 || !is_one) 1852 p = poly_print(rec->p[i], space, div, p); 1853 } 1854 first = 0; 1855 if (i == 0) 1856 continue; 1857 if (!is_one && !is_negone) 1858 p = isl_printer_print_str(p, " * "); 1859 p = print_pow(p, space, div, rec->poly.var, i); 1860 } 1861 if (print_parens) 1862 p = isl_printer_print_str(p, ")"); 1863 return p; 1864 error: 1865 isl_printer_free(p); 1866 return NULL; 1867 } 1868 1869 static __isl_give isl_printer *print_qpolynomial(__isl_take isl_printer *p, 1870 __isl_keep isl_qpolynomial *qp) 1871 { 1872 if (!p || !qp) 1873 goto error; 1874 p = poly_print(qp->poly, qp->dim, qp->div, p); 1875 return p; 1876 error: 1877 isl_printer_free(p); 1878 return NULL; 1879 } 1880 1881 static __isl_give isl_printer *print_qpolynomial_isl(__isl_take isl_printer *p, 1882 __isl_keep isl_qpolynomial *qp) 1883 { 1884 struct isl_print_space_data data = { 0 }; 1885 1886 if (!p || !qp) 1887 goto error; 1888 1889 p = print_param_tuple(p, qp->dim, &data); 1890 p = isl_printer_print_str(p, "{ "); 1891 if (!isl_space_is_params(qp->dim)) { 1892 p = isl_print_space(qp->dim, p, 0, &data); 1893 p = isl_printer_print_str(p, " -> "); 1894 } 1895 p = print_qpolynomial(p, qp); 1896 p = isl_printer_print_str(p, " }"); 1897 return p; 1898 error: 1899 isl_printer_free(p); 1900 return NULL; 1901 } 1902 1903 /* Print the quasi-polynomial "qp" to "p" in C format, with the variable names 1904 * taken from the domain space "space". 1905 */ 1906 static __isl_give isl_printer *print_qpolynomial_c(__isl_take isl_printer *p, 1907 __isl_keep isl_space *space, __isl_keep isl_qpolynomial *qp) 1908 { 1909 isl_bool is_one; 1910 isl_val *den; 1911 1912 den = isl_qpolynomial_get_den(qp); 1913 qp = isl_qpolynomial_copy(qp); 1914 qp = isl_qpolynomial_scale_val(qp, isl_val_copy(den)); 1915 is_one = isl_val_is_one(den); 1916 if (is_one < 0) 1917 p = isl_printer_free(p); 1918 if (!is_one) 1919 p = isl_printer_print_str(p, "("); 1920 if (qp) 1921 p = poly_print(qp->poly, space, qp->div, p); 1922 else 1923 p = isl_printer_free(p); 1924 if (!is_one) { 1925 p = isl_printer_print_str(p, ")/"); 1926 p = isl_printer_print_val(p, den); 1927 } 1928 isl_qpolynomial_free(qp); 1929 isl_val_free(den); 1930 return p; 1931 } 1932 1933 __isl_give isl_printer *isl_printer_print_qpolynomial( 1934 __isl_take isl_printer *p, __isl_keep isl_qpolynomial *qp) 1935 { 1936 if (!p || !qp) 1937 goto error; 1938 1939 if (p->output_format == ISL_FORMAT_ISL) 1940 return print_qpolynomial_isl(p, qp); 1941 else if (p->output_format == ISL_FORMAT_C) 1942 return print_qpolynomial_c(p, qp->dim, qp); 1943 else 1944 isl_die(qp->dim->ctx, isl_error_unsupported, 1945 "output format not supported for isl_qpolynomials", 1946 goto error); 1947 error: 1948 isl_printer_free(p); 1949 return NULL; 1950 } 1951 1952 void isl_qpolynomial_print(__isl_keep isl_qpolynomial *qp, FILE *out, 1953 unsigned output_format) 1954 { 1955 isl_printer *p; 1956 1957 if (!qp) 1958 return; 1959 1960 isl_assert(qp->dim->ctx, output_format == ISL_FORMAT_ISL, return); 1961 p = isl_printer_to_file(qp->dim->ctx, out); 1962 p = isl_printer_print_qpolynomial(p, qp); 1963 isl_printer_free(p); 1964 } 1965 1966 static __isl_give isl_printer *qpolynomial_fold_print( 1967 __isl_keep isl_qpolynomial_fold *fold, __isl_take isl_printer *p) 1968 { 1969 int i; 1970 isl_qpolynomial_list *list; 1971 isl_size n; 1972 1973 list = isl_qpolynomial_fold_peek_list(fold); 1974 n = isl_qpolynomial_list_size(list); 1975 if (n < 0) 1976 return isl_printer_free(p); 1977 if (fold->type == isl_fold_min) 1978 p = isl_printer_print_str(p, "min"); 1979 else if (fold->type == isl_fold_max) 1980 p = isl_printer_print_str(p, "max"); 1981 p = isl_printer_print_str(p, "("); 1982 for (i = 0; i < n; ++i) { 1983 isl_qpolynomial *qp; 1984 1985 if (i) 1986 p = isl_printer_print_str(p, ", "); 1987 qp = isl_qpolynomial_list_peek(list, i); 1988 p = print_qpolynomial(p, qp); 1989 } 1990 p = isl_printer_print_str(p, ")"); 1991 return p; 1992 } 1993 1994 void isl_qpolynomial_fold_print(__isl_keep isl_qpolynomial_fold *fold, 1995 FILE *out, unsigned output_format) 1996 { 1997 isl_printer *p; 1998 1999 if (!fold) 2000 return; 2001 2002 isl_assert(fold->dim->ctx, output_format == ISL_FORMAT_ISL, return); 2003 2004 p = isl_printer_to_file(fold->dim->ctx, out); 2005 p = isl_printer_print_qpolynomial_fold(p, fold); 2006 2007 isl_printer_free(p); 2008 } 2009 2010 static __isl_give isl_printer *print_body_pw_qpolynomial( 2011 __isl_take isl_printer *p, __isl_keep isl_pw_qpolynomial *pwqp) 2012 { 2013 struct isl_print_space_data data = { 0 }; 2014 int i = 0; 2015 2016 for (i = 0; i < pwqp->n; ++i) { 2017 isl_space *space; 2018 2019 if (i) 2020 p = isl_printer_print_str(p, "; "); 2021 space = isl_qpolynomial_get_domain_space(pwqp->p[i].qp); 2022 if (!isl_space_is_params(space)) { 2023 p = isl_print_space(space, p, 0, &data); 2024 p = isl_printer_print_str(p, " -> "); 2025 } 2026 p = print_qpolynomial(p, pwqp->p[i].qp); 2027 p = print_disjuncts(set_to_map(pwqp->p[i].set), space, p, 0); 2028 isl_space_free(space); 2029 } 2030 2031 return p; 2032 } 2033 2034 static __isl_give isl_printer *print_pw_qpolynomial_isl( 2035 __isl_take isl_printer *p, __isl_keep isl_pw_qpolynomial *pwqp) 2036 { 2037 struct isl_print_space_data data = { 0 }; 2038 2039 if (!p || !pwqp) 2040 goto error; 2041 2042 p = print_param_tuple(p, pwqp->dim, &data); 2043 p = isl_printer_print_str(p, "{ "); 2044 if (pwqp->n == 0) { 2045 if (!isl_space_is_set(pwqp->dim)) { 2046 p = print_tuple(pwqp->dim, p, isl_dim_in, &data); 2047 p = isl_printer_print_str(p, " -> "); 2048 } 2049 p = isl_printer_print_str(p, "0"); 2050 } 2051 p = print_body_pw_qpolynomial(p, pwqp); 2052 p = isl_printer_print_str(p, " }"); 2053 return p; 2054 error: 2055 isl_printer_free(p); 2056 return NULL; 2057 } 2058 2059 void isl_pw_qpolynomial_print(__isl_keep isl_pw_qpolynomial *pwqp, FILE *out, 2060 unsigned output_format) 2061 { 2062 isl_printer *p; 2063 2064 if (!pwqp) 2065 return; 2066 2067 p = isl_printer_to_file(pwqp->dim->ctx, out); 2068 p = isl_printer_set_output_format(p, output_format); 2069 p = isl_printer_print_pw_qpolynomial(p, pwqp); 2070 2071 isl_printer_free(p); 2072 } 2073 2074 static __isl_give isl_printer *print_body_pw_qpolynomial_fold( 2075 __isl_take isl_printer *p, __isl_keep isl_pw_qpolynomial_fold *pwf) 2076 { 2077 struct isl_print_space_data data = { 0 }; 2078 int i = 0; 2079 2080 for (i = 0; i < pwf->n; ++i) { 2081 isl_space *space; 2082 2083 if (i) 2084 p = isl_printer_print_str(p, "; "); 2085 space = isl_qpolynomial_fold_get_domain_space(pwf->p[i].fold); 2086 if (!isl_space_is_params(space)) { 2087 p = isl_print_space(space, p, 0, &data); 2088 p = isl_printer_print_str(p, " -> "); 2089 } 2090 p = qpolynomial_fold_print(pwf->p[i].fold, p); 2091 p = print_disjuncts(set_to_map(pwf->p[i].set), space, p, 0); 2092 isl_space_free(space); 2093 } 2094 2095 return p; 2096 } 2097 2098 static __isl_give isl_printer *print_pw_qpolynomial_fold_isl( 2099 __isl_take isl_printer *p, __isl_keep isl_pw_qpolynomial_fold *pwf) 2100 { 2101 struct isl_print_space_data data = { 0 }; 2102 2103 p = print_param_tuple(p, pwf->dim, &data); 2104 p = isl_printer_print_str(p, "{ "); 2105 if (pwf->n == 0) { 2106 if (!isl_space_is_set(pwf->dim)) { 2107 p = print_tuple(pwf->dim, p, isl_dim_in, &data); 2108 p = isl_printer_print_str(p, " -> "); 2109 } 2110 p = isl_printer_print_str(p, "0"); 2111 } 2112 p = print_body_pw_qpolynomial_fold(p, pwf); 2113 p = isl_printer_print_str(p, " }"); 2114 return p; 2115 } 2116 2117 static __isl_give isl_printer *print_ls_affine_c(__isl_take isl_printer *p, 2118 __isl_keep isl_local_space *ls, isl_int *c); 2119 2120 /* We skip the constraint if it is implied by the div expression. 2121 * 2122 * *first indicates whether this is the first constraint in the conjunction and 2123 * is updated if the constraint is actually printed. 2124 */ 2125 static __isl_give isl_printer *print_constraint_c(__isl_take isl_printer *p, 2126 __isl_keep isl_local_space *ls, isl_int *c, const char *op, int *first) 2127 { 2128 unsigned o_div; 2129 isl_size n_div; 2130 int div; 2131 2132 o_div = isl_local_space_offset(ls, isl_dim_div); 2133 n_div = isl_local_space_dim(ls, isl_dim_div); 2134 if (n_div < 0) 2135 return isl_printer_free(p); 2136 div = isl_seq_last_non_zero(c + o_div, n_div); 2137 if (div >= 0) { 2138 isl_bool is_div = isl_local_space_is_div_constraint(ls, c, div); 2139 if (is_div < 0) 2140 return isl_printer_free(p); 2141 if (is_div) 2142 return p; 2143 } 2144 2145 if (!*first) 2146 p = isl_printer_print_str(p, " && "); 2147 2148 p = print_ls_affine_c(p, ls, c); 2149 p = isl_printer_print_str(p, " "); 2150 p = isl_printer_print_str(p, op); 2151 p = isl_printer_print_str(p, " 0"); 2152 2153 *first = 0; 2154 2155 return p; 2156 } 2157 2158 static __isl_give isl_printer *print_ls_partial_affine_c( 2159 __isl_take isl_printer *p, __isl_keep isl_local_space *ls, 2160 isl_int *c, unsigned len); 2161 2162 static __isl_give isl_printer *print_basic_set_c(__isl_take isl_printer *p, 2163 __isl_keep isl_space *space, __isl_keep isl_basic_set *bset) 2164 { 2165 int i, j; 2166 int first = 1; 2167 isl_size n_div = isl_basic_set_dim(bset, isl_dim_div); 2168 isl_size total = isl_basic_set_dim(bset, isl_dim_all); 2169 isl_mat *div; 2170 isl_local_space *ls; 2171 2172 if (n_div < 0 || total < 0) 2173 return isl_printer_free(p); 2174 2175 total -= n_div; 2176 div = isl_basic_set_get_divs(bset); 2177 ls = isl_local_space_alloc_div(isl_space_copy(space), div); 2178 for (i = 0; i < bset->n_eq; ++i) { 2179 j = isl_seq_last_non_zero(bset->eq[i] + 1 + total, n_div); 2180 if (j < 0) 2181 p = print_constraint_c(p, ls, 2182 bset->eq[i], "==", &first); 2183 else { 2184 if (i) 2185 p = isl_printer_print_str(p, " && "); 2186 p = isl_printer_print_str(p, "("); 2187 p = print_ls_partial_affine_c(p, ls, bset->eq[i], 2188 1 + total + j); 2189 p = isl_printer_print_str(p, ") % "); 2190 p = isl_printer_print_isl_int(p, 2191 bset->eq[i][1 + total + j]); 2192 p = isl_printer_print_str(p, " == 0"); 2193 first = 0; 2194 } 2195 } 2196 for (i = 0; i < bset->n_ineq; ++i) 2197 p = print_constraint_c(p, ls, bset->ineq[i], ">=", &first); 2198 isl_local_space_free(ls); 2199 return p; 2200 } 2201 2202 static __isl_give isl_printer *print_set_c(__isl_take isl_printer *p, 2203 __isl_keep isl_space *space, __isl_keep isl_set *set) 2204 { 2205 int i; 2206 2207 if (!set) 2208 return isl_printer_free(p); 2209 2210 if (set->n == 0) 2211 p = isl_printer_print_str(p, "0"); 2212 2213 for (i = 0; i < set->n; ++i) { 2214 if (i) 2215 p = isl_printer_print_str(p, " || "); 2216 if (set->n > 1) 2217 p = isl_printer_print_str(p, "("); 2218 p = print_basic_set_c(p, space, set->p[i]); 2219 if (set->n > 1) 2220 p = isl_printer_print_str(p, ")"); 2221 } 2222 return p; 2223 } 2224 2225 /* Print the piecewise quasi-polynomial "pwqp" to "p" in C format. 2226 */ 2227 static __isl_give isl_printer *print_pw_qpolynomial_c( 2228 __isl_take isl_printer *p, __isl_keep isl_pw_qpolynomial *pwqp) 2229 { 2230 int i; 2231 isl_space *space; 2232 2233 space = isl_pw_qpolynomial_get_domain_space(pwqp); 2234 if (pwqp->n == 1 && isl_set_plain_is_universe(pwqp->p[0].set)) { 2235 p = print_qpolynomial_c(p, space, pwqp->p[0].qp); 2236 isl_space_free(space); 2237 return p; 2238 } 2239 2240 for (i = 0; i < pwqp->n; ++i) { 2241 p = isl_printer_print_str(p, "("); 2242 p = print_set_c(p, space, pwqp->p[i].set); 2243 p = isl_printer_print_str(p, ") ? ("); 2244 p = print_qpolynomial_c(p, space, pwqp->p[i].qp); 2245 p = isl_printer_print_str(p, ") : "); 2246 } 2247 2248 isl_space_free(space); 2249 p = isl_printer_print_str(p, "0"); 2250 return p; 2251 } 2252 2253 __isl_give isl_printer *isl_printer_print_pw_qpolynomial( 2254 __isl_take isl_printer *p, __isl_keep isl_pw_qpolynomial *pwqp) 2255 { 2256 if (!p || !pwqp) 2257 goto error; 2258 2259 if (p->output_format == ISL_FORMAT_ISL) 2260 return print_pw_qpolynomial_isl(p, pwqp); 2261 else if (p->output_format == ISL_FORMAT_C) 2262 return print_pw_qpolynomial_c(p, pwqp); 2263 isl_assert(p->ctx, 0, goto error); 2264 error: 2265 isl_printer_free(p); 2266 return NULL; 2267 } 2268 2269 #undef BASE 2270 #define BASE pw_qpolynomial 2271 #include "isl_union_print_templ.c" 2272 2273 __isl_give isl_printer *isl_printer_print_union_pw_qpolynomial( 2274 __isl_take isl_printer *p, __isl_keep isl_union_pw_qpolynomial *upwqp) 2275 { 2276 if (!p || !upwqp) 2277 goto error; 2278 2279 if (p->output_format == ISL_FORMAT_ISL) 2280 return print_union_pw_qpolynomial_isl(p, upwqp); 2281 isl_die(p->ctx, isl_error_invalid, 2282 "invalid output format for isl_union_pw_qpolynomial", 2283 goto error); 2284 error: 2285 isl_printer_free(p); 2286 return NULL; 2287 } 2288 2289 /* Print the quasi-polynomial reduction "fold" to "p" in C format, 2290 * with the variable names taken from the domain space "space". 2291 */ 2292 static __isl_give isl_printer *print_qpolynomial_fold_c( 2293 __isl_take isl_printer *p, __isl_keep isl_space *space, 2294 __isl_keep isl_qpolynomial_fold *fold) 2295 { 2296 int i; 2297 isl_qpolynomial_list *list; 2298 isl_size n; 2299 2300 list = isl_qpolynomial_fold_peek_list(fold); 2301 n = isl_qpolynomial_list_size(list); 2302 if (n < 0) 2303 return isl_printer_free(p); 2304 for (i = 0; i < n - 1; ++i) 2305 if (fold->type == isl_fold_min) 2306 p = isl_printer_print_str(p, "min("); 2307 else if (fold->type == isl_fold_max) 2308 p = isl_printer_print_str(p, "max("); 2309 2310 for (i = 0; i < n; ++i) { 2311 isl_qpolynomial *qp; 2312 2313 if (i) 2314 p = isl_printer_print_str(p, ", "); 2315 qp = isl_qpolynomial_list_peek(list, i); 2316 p = print_qpolynomial_c(p, space, qp); 2317 if (i) 2318 p = isl_printer_print_str(p, ")"); 2319 } 2320 return p; 2321 } 2322 2323 __isl_give isl_printer *isl_printer_print_qpolynomial_fold( 2324 __isl_take isl_printer *p, __isl_keep isl_qpolynomial_fold *fold) 2325 { 2326 if (!p || !fold) 2327 goto error; 2328 if (p->output_format == ISL_FORMAT_ISL) 2329 return qpolynomial_fold_print(fold, p); 2330 else if (p->output_format == ISL_FORMAT_C) 2331 return print_qpolynomial_fold_c(p, fold->dim, fold); 2332 isl_die(p->ctx, isl_error_unsupported, "unsupported output format", 2333 goto error); 2334 error: 2335 isl_printer_free(p); 2336 return NULL; 2337 } 2338 2339 /* Print the piecewise quasi-polynomial reduction "pwf" to "p" in C format. 2340 */ 2341 static __isl_give isl_printer *print_pw_qpolynomial_fold_c( 2342 __isl_take isl_printer *p, __isl_keep isl_pw_qpolynomial_fold *pwf) 2343 { 2344 int i; 2345 isl_space *space; 2346 2347 space = isl_pw_qpolynomial_fold_get_domain_space(pwf); 2348 if (pwf->n == 1 && isl_set_plain_is_universe(pwf->p[0].set)) { 2349 p = print_qpolynomial_fold_c(p, space, pwf->p[0].fold); 2350 isl_space_free(space); 2351 return p; 2352 } 2353 2354 for (i = 0; i < pwf->n; ++i) { 2355 p = isl_printer_print_str(p, "("); 2356 p = print_set_c(p, space, pwf->p[i].set); 2357 p = isl_printer_print_str(p, ") ? ("); 2358 p = print_qpolynomial_fold_c(p, space, pwf->p[i].fold); 2359 p = isl_printer_print_str(p, ") : "); 2360 } 2361 2362 isl_space_free(space); 2363 p = isl_printer_print_str(p, "0"); 2364 return p; 2365 } 2366 2367 __isl_give isl_printer *isl_printer_print_pw_qpolynomial_fold( 2368 __isl_take isl_printer *p, __isl_keep isl_pw_qpolynomial_fold *pwf) 2369 { 2370 if (!p || !pwf) 2371 goto error; 2372 2373 if (p->output_format == ISL_FORMAT_ISL) 2374 return print_pw_qpolynomial_fold_isl(p, pwf); 2375 else if (p->output_format == ISL_FORMAT_C) 2376 return print_pw_qpolynomial_fold_c(p, pwf); 2377 isl_assert(p->ctx, 0, goto error); 2378 error: 2379 isl_printer_free(p); 2380 return NULL; 2381 } 2382 2383 void isl_pw_qpolynomial_fold_print(__isl_keep isl_pw_qpolynomial_fold *pwf, 2384 FILE *out, unsigned output_format) 2385 { 2386 isl_printer *p; 2387 2388 if (!pwf) 2389 return; 2390 2391 p = isl_printer_to_file(pwf->dim->ctx, out); 2392 p = isl_printer_set_output_format(p, output_format); 2393 p = isl_printer_print_pw_qpolynomial_fold(p, pwf); 2394 2395 isl_printer_free(p); 2396 } 2397 2398 #undef BASE 2399 #define BASE pw_qpolynomial_fold 2400 #include "isl_union_print_templ.c" 2401 2402 __isl_give isl_printer *isl_printer_print_union_pw_qpolynomial_fold( 2403 __isl_take isl_printer *p, 2404 __isl_keep isl_union_pw_qpolynomial_fold *upwf) 2405 { 2406 if (!p || !upwf) 2407 goto error; 2408 2409 if (p->output_format == ISL_FORMAT_ISL) 2410 return print_union_pw_qpolynomial_fold_isl(p, upwf); 2411 isl_die(p->ctx, isl_error_invalid, 2412 "invalid output format for isl_union_pw_qpolynomial_fold", 2413 goto error); 2414 error: 2415 isl_printer_free(p); 2416 return NULL; 2417 } 2418 2419 /* Print the isl_constraint "c" to "p". 2420 */ 2421 __isl_give isl_printer *isl_printer_print_constraint(__isl_take isl_printer *p, 2422 __isl_keep isl_constraint *c) 2423 { 2424 struct isl_print_space_data data = { 0 }; 2425 isl_local_space *ls; 2426 isl_space *space; 2427 isl_bool exists; 2428 2429 if (!p || !c) 2430 goto error; 2431 2432 ls = isl_constraint_get_local_space(c); 2433 if (!ls) 2434 return isl_printer_free(p); 2435 space = isl_local_space_get_space(ls); 2436 p = print_param_tuple(p, space, &data); 2437 p = isl_printer_print_str(p, "{ "); 2438 p = isl_print_space(space, p, 0, &data); 2439 p = isl_printer_print_str(p, " : "); 2440 exists = need_exists(p, ls->div); 2441 if (exists < 0) 2442 p = isl_printer_free(p); 2443 if (exists >= 0 && exists) 2444 p = open_exists(p, space, ls->div, 0); 2445 p = print_affine_of_len(space, ls->div, p, c->v->el, c->v->size); 2446 if (isl_constraint_is_equality(c)) 2447 p = isl_printer_print_str(p, " = 0"); 2448 else 2449 p = isl_printer_print_str(p, " >= 0"); 2450 if (exists >= 0 && exists) 2451 p = isl_printer_print_str(p, s_close_exists[0]); 2452 p = isl_printer_print_str(p, " }"); 2453 isl_space_free(space); 2454 isl_local_space_free(ls); 2455 2456 return p; 2457 error: 2458 isl_printer_free(p); 2459 return NULL; 2460 } 2461 2462 static __isl_give isl_printer *isl_printer_print_space_isl( 2463 __isl_take isl_printer *p, __isl_keep isl_space *space) 2464 { 2465 struct isl_print_space_data data = { 0 }; 2466 2467 if (!space) 2468 goto error; 2469 2470 p = print_param_tuple(p, space, &data); 2471 2472 p = isl_printer_print_str(p, "{ "); 2473 if (isl_space_is_params(space)) 2474 p = isl_printer_print_str(p, s_such_that[0]); 2475 else 2476 p = isl_print_space(space, p, 0, &data); 2477 p = isl_printer_print_str(p, " }"); 2478 2479 return p; 2480 error: 2481 isl_printer_free(p); 2482 return NULL; 2483 } 2484 2485 __isl_give isl_printer *isl_printer_print_space(__isl_take isl_printer *p, 2486 __isl_keep isl_space *space) 2487 { 2488 if (!p || !space) 2489 return isl_printer_free(p); 2490 if (p->output_format == ISL_FORMAT_ISL) 2491 return isl_printer_print_space_isl(p, space); 2492 else if (p->output_format == ISL_FORMAT_OMEGA) 2493 return print_omega_parameters(space, p); 2494 2495 isl_die(isl_space_get_ctx(space), isl_error_unsupported, 2496 "output format not supported for space", 2497 return isl_printer_free(p)); 2498 } 2499 2500 __isl_give isl_printer *isl_printer_print_local_space(__isl_take isl_printer *p, 2501 __isl_keep isl_local_space *ls) 2502 { 2503 struct isl_print_space_data data = { 0 }; 2504 isl_size n_div; 2505 2506 n_div = isl_local_space_dim(ls, isl_dim_div); 2507 if (n_div < 0) 2508 goto error; 2509 2510 p = print_param_tuple(p, ls->dim, &data); 2511 p = isl_printer_print_str(p, "{ "); 2512 p = isl_print_space(ls->dim, p, 0, &data); 2513 if (n_div > 0) { 2514 p = isl_printer_print_str(p, " : "); 2515 p = isl_printer_print_str(p, s_open_exists[0]); 2516 p = print_div_list(p, ls->dim, ls->div, 0, 1); 2517 p = isl_printer_print_str(p, s_close_exists[0]); 2518 } else if (isl_space_is_params(ls->dim)) 2519 p = isl_printer_print_str(p, s_such_that[0]); 2520 p = isl_printer_print_str(p, " }"); 2521 return p; 2522 error: 2523 isl_printer_free(p); 2524 return NULL; 2525 } 2526 2527 /* Look for the last of the "n" integer divisions that is used in "aff" and 2528 * that can be printed as a modulo and 2529 * return the position of this integer division. 2530 * Return "n" if no such integer division can be found. 2531 * Return isl_size_error on error. 2532 * 2533 * In particular, look for an integer division that appears in "aff" 2534 * with a coefficient that is a multiple of the denominator 2535 * of the integer division. 2536 * That is, check if the numerator of "aff" is of the form 2537 * 2538 * f(...) + a m floor(g/m) 2539 * 2540 * and return the position of "floor(g/m)". 2541 * 2542 * Note that, unlike print_as_modulo_pos, no check needs to be made 2543 * for whether the integer division can be printed, since it will 2544 * need to be printed as an integer division anyway if it is not printed 2545 * as a modulo. 2546 */ 2547 static isl_size last_modulo(__isl_keep isl_printer *p, __isl_keep isl_aff *aff, 2548 unsigned n) 2549 { 2550 isl_size o_div; 2551 int i; 2552 2553 if (n == 0) 2554 return n; 2555 o_div = isl_aff_domain_offset(aff, isl_dim_div); 2556 if (o_div < 0) 2557 return isl_size_error; 2558 for (i = n - 1; i >= 0; --i) { 2559 if (isl_int_is_zero(aff->v->el[1 + o_div + i])) 2560 continue; 2561 if (isl_int_is_divisible_by(aff->v->el[1 + o_div + i], 2562 aff->ls->div->row[i][0])) 2563 return i; 2564 } 2565 2566 return n; 2567 } 2568 2569 /* Print the numerator of the affine expression "aff" to "p", 2570 * with the variable names taken from "space". 2571 */ 2572 static __isl_give isl_printer *print_aff_num_base(__isl_take isl_printer *p, 2573 __isl_keep isl_space *space, __isl_keep isl_aff *aff) 2574 { 2575 isl_size total; 2576 2577 total = isl_aff_domain_dim(aff, isl_dim_all); 2578 if (total < 0) 2579 return isl_printer_free(p); 2580 p = print_affine_of_len(space, aff->ls->div, p, 2581 aff->v->el + 1, 1 + total); 2582 2583 return p; 2584 } 2585 2586 static __isl_give isl_printer *print_aff_num(__isl_take isl_printer *p, 2587 __isl_keep isl_space *space, __isl_keep isl_aff *aff); 2588 2589 /* Print the modulo term "c" * ("aff" mod "mod") to "p", 2590 * with the variable names taken from "space". 2591 * If "first" is set, then this is the first term of an expression. 2592 */ 2593 static __isl_give isl_printer *print_mod_term(__isl_take isl_printer *p, 2594 __isl_keep isl_space *space, __isl_keep isl_aff *aff, int first, 2595 __isl_take isl_val *c, __isl_keep isl_val *mod) 2596 { 2597 isl_bool is_one, is_neg; 2598 2599 is_neg = isl_val_is_neg(c); 2600 if (is_neg < 0) 2601 p = isl_printer_free(p); 2602 if (!first) { 2603 if (is_neg) 2604 c = isl_val_neg(c); 2605 p = isl_printer_print_str(p, is_neg ? " - " : " + "); 2606 } 2607 is_one = isl_val_is_one(c); 2608 if (is_one < 0) 2609 p = isl_printer_free(p); 2610 if (!is_one) { 2611 p = isl_printer_print_val(p, c); 2612 p = isl_printer_print_str(p, "*("); 2613 } 2614 p = isl_printer_print_str(p, "("); 2615 p = print_aff_num(p, space, aff); 2616 p = isl_printer_print_str(p, ")"); 2617 p = isl_printer_print_str(p, " mod "); 2618 p = isl_printer_print_val(p, mod); 2619 if (!is_one) 2620 p = isl_printer_print_str(p, ")"); 2621 2622 isl_val_free(c); 2623 2624 return p; 2625 } 2626 2627 /* Print the numerator of the affine expression "aff" to "p", 2628 * with the variable names taken from "space", 2629 * given that the numerator of "aff" is of the form 2630 * 2631 * f(...) + a m floor(g/m) 2632 * 2633 * with "floor(g/m)" the integer division at position "last". 2634 * 2635 * First replace "aff" by its numerator and rewrite it as 2636 * 2637 * f(...) + a g - a (g mod m) 2638 * 2639 * Recursively write out (the numerator of) "f(...) + a g" 2640 * (which may involve other modulo expressions) and 2641 * then write out "- a (g mod m)". 2642 */ 2643 static __isl_give isl_printer *print_aff_num_mod(__isl_take isl_printer *p, 2644 __isl_keep isl_space *space, __isl_keep isl_aff *aff, unsigned last) 2645 { 2646 isl_bool is_zero; 2647 isl_val *a, *m; 2648 isl_aff *div, *term; 2649 2650 aff = isl_aff_copy(aff); 2651 aff = isl_aff_scale_val(aff, isl_aff_get_denominator_val(aff)); 2652 a = isl_aff_get_coefficient_val(aff, isl_dim_div, last); 2653 aff = isl_aff_set_coefficient_si(aff, isl_dim_div, last, 0); 2654 div = isl_aff_get_div(aff, last); 2655 m = isl_aff_get_denominator_val(div); 2656 a = isl_val_div(a, isl_val_copy(m)); 2657 div = isl_aff_scale_val(div, isl_val_copy(m)); 2658 term = isl_aff_scale_val(isl_aff_copy(div), isl_val_copy(a)); 2659 aff = isl_aff_add(aff, term); 2660 2661 is_zero = isl_aff_plain_is_zero(aff); 2662 if (is_zero < 0) { 2663 p = isl_printer_free(p); 2664 } else { 2665 if (!is_zero) 2666 p = print_aff_num(p, space, aff); 2667 a = isl_val_neg(a); 2668 p = print_mod_term(p, space, div, is_zero, isl_val_copy(a), m); 2669 } 2670 2671 isl_val_free(a); 2672 isl_val_free(m); 2673 isl_aff_free(aff); 2674 isl_aff_free(div); 2675 2676 return p; 2677 } 2678 2679 /* Print the numerator of the affine expression "aff" to "p", 2680 * with the variable names taken from "space", 2681 * separating out any (obvious) modulo expressions. 2682 * 2683 * In particular, look for modulo expressions in "aff", 2684 * separating them out if found and simply printing out "aff" otherwise. 2685 */ 2686 static __isl_give isl_printer *print_aff_num(__isl_take isl_printer *p, 2687 __isl_keep isl_space *space, __isl_keep isl_aff *aff) 2688 { 2689 isl_size n_div, mod; 2690 2691 n_div = isl_aff_dim(aff, isl_dim_div); 2692 if (n_div < 0) 2693 return isl_printer_free(p); 2694 mod = last_modulo(p, aff, n_div); 2695 if (mod < 0) 2696 return isl_printer_free(p); 2697 if (mod < n_div) 2698 return print_aff_num_mod(p, space, aff, mod); 2699 else 2700 return print_aff_num_base(p, space, aff); 2701 } 2702 2703 /* Print the (potentially rational) affine expression "aff" to "p", 2704 * with the variable names taken from "space". 2705 */ 2706 static __isl_give isl_printer *print_aff_body(__isl_take isl_printer *p, 2707 __isl_keep isl_space *space, __isl_keep isl_aff *aff) 2708 { 2709 if (isl_aff_is_nan(aff)) 2710 return isl_printer_print_str(p, "NaN"); 2711 2712 p = isl_printer_print_str(p, "("); 2713 p = print_aff_num(p, space, aff); 2714 if (isl_int_is_one(aff->v->el[0])) 2715 p = isl_printer_print_str(p, ")"); 2716 else { 2717 p = isl_printer_print_str(p, ")/"); 2718 p = isl_printer_print_isl_int(p, aff->v->el[0]); 2719 } 2720 2721 return p; 2722 } 2723 2724 static __isl_give isl_printer *print_body_aff(__isl_take isl_printer *p, 2725 __isl_keep isl_aff *aff) 2726 { 2727 struct isl_print_space_data data = { 0 }; 2728 2729 if (isl_space_is_params(aff->ls->dim)) 2730 ; 2731 else { 2732 p = print_tuple(aff->ls->dim, p, isl_dim_set, &data); 2733 p = isl_printer_print_str(p, " -> "); 2734 } 2735 p = isl_printer_print_str(p, "["); 2736 p = print_aff_body(p, aff->ls->dim, aff); 2737 p = isl_printer_print_str(p, "]"); 2738 2739 return p; 2740 } 2741 2742 static __isl_give isl_printer *print_aff_isl(__isl_take isl_printer *p, 2743 __isl_keep isl_aff *aff) 2744 { 2745 struct isl_print_space_data data = { 0 }; 2746 2747 if (!aff) 2748 goto error; 2749 2750 p = print_param_tuple(p, aff->ls->dim, &data); 2751 p = isl_printer_print_str(p, "{ "); 2752 p = print_body_aff(p, aff); 2753 p = isl_printer_print_str(p, " }"); 2754 return p; 2755 error: 2756 isl_printer_free(p); 2757 return NULL; 2758 } 2759 2760 #undef BASE 2761 #define BASE aff 2762 #include "isl_pw_print_templ.c" 2763 2764 static __isl_give isl_printer *print_ls_name_c(__isl_take isl_printer *p, 2765 __isl_keep isl_local_space *ls, enum isl_dim_type type, unsigned pos) 2766 { 2767 if (type == isl_dim_div) { 2768 p = isl_printer_print_str(p, "floord("); 2769 p = print_ls_affine_c(p, ls, ls->div->row[pos] + 1); 2770 p = isl_printer_print_str(p, ", "); 2771 p = isl_printer_print_isl_int(p, ls->div->row[pos][0]); 2772 p = isl_printer_print_str(p, ")"); 2773 } else { 2774 const char *name; 2775 2776 name = isl_space_get_dim_name(ls->dim, type, pos); 2777 if (!name) 2778 name = "UNNAMED"; 2779 p = isl_printer_print_str(p, name); 2780 } 2781 return p; 2782 } 2783 2784 static __isl_give isl_printer *print_ls_term_c(__isl_take isl_printer *p, 2785 __isl_keep isl_local_space *ls, isl_int c, unsigned pos) 2786 { 2787 enum isl_dim_type type; 2788 2789 if (!p || !ls) 2790 return isl_printer_free(p); 2791 2792 if (pos == 0) 2793 return isl_printer_print_isl_int(p, c); 2794 2795 if (isl_int_is_one(c)) 2796 ; 2797 else if (isl_int_is_negone(c)) 2798 p = isl_printer_print_str(p, "-"); 2799 else { 2800 p = isl_printer_print_isl_int(p, c); 2801 p = isl_printer_print_str(p, "*"); 2802 } 2803 if (pos2type(ls->dim, &type, &pos) < 0) 2804 return isl_printer_free(p); 2805 p = print_ls_name_c(p, ls, type, pos); 2806 return p; 2807 } 2808 2809 static __isl_give isl_printer *print_ls_partial_affine_c( 2810 __isl_take isl_printer *p, __isl_keep isl_local_space *ls, 2811 isl_int *c, unsigned len) 2812 { 2813 int i; 2814 int first; 2815 2816 for (i = 0, first = 1; i < len; ++i) { 2817 int flip = 0; 2818 if (isl_int_is_zero(c[i])) 2819 continue; 2820 if (!first) { 2821 if (isl_int_is_neg(c[i])) { 2822 flip = 1; 2823 isl_int_neg(c[i], c[i]); 2824 p = isl_printer_print_str(p, " - "); 2825 } else 2826 p = isl_printer_print_str(p, " + "); 2827 } 2828 first = 0; 2829 p = print_ls_term_c(p, ls, c[i], i); 2830 if (flip) 2831 isl_int_neg(c[i], c[i]); 2832 } 2833 if (first) 2834 p = isl_printer_print_str(p, "0"); 2835 return p; 2836 } 2837 2838 static __isl_give isl_printer *print_ls_affine_c(__isl_take isl_printer *p, 2839 __isl_keep isl_local_space *ls, isl_int *c) 2840 { 2841 isl_size total = isl_local_space_dim(ls, isl_dim_all); 2842 2843 if (total < 0) 2844 return isl_printer_free(p); 2845 return print_ls_partial_affine_c(p, ls, c, 1 + total); 2846 } 2847 2848 static __isl_give isl_printer *print_aff_c(__isl_take isl_printer *p, 2849 __isl_keep isl_aff *aff) 2850 { 2851 isl_size total; 2852 2853 total = isl_aff_domain_dim(aff, isl_dim_all); 2854 if (total < 0) 2855 return isl_printer_free(p); 2856 if (!isl_int_is_one(aff->v->el[0])) 2857 p = isl_printer_print_str(p, "("); 2858 p = print_ls_partial_affine_c(p, aff->ls, aff->v->el + 1, 1 + total); 2859 if (!isl_int_is_one(aff->v->el[0])) { 2860 p = isl_printer_print_str(p, ")/"); 2861 p = isl_printer_print_isl_int(p, aff->v->el[0]); 2862 } 2863 return p; 2864 } 2865 2866 /* In the C format, we cannot express that "pwaff" may be undefined 2867 * on parts of the domain space. We therefore assume that the expression 2868 * will only be evaluated on its definition domain and compute the gist 2869 * of each cell with respect to this domain. 2870 */ 2871 static __isl_give isl_printer *print_pw_aff_c(__isl_take isl_printer *p, 2872 __isl_keep isl_pw_aff *pwaff) 2873 { 2874 isl_set *domain; 2875 isl_ast_build *build; 2876 isl_ast_expr *expr; 2877 2878 if (pwaff->n < 1) 2879 isl_die(p->ctx, isl_error_unsupported, 2880 "cannot print empty isl_pw_aff in C format", 2881 return isl_printer_free(p)); 2882 2883 domain = isl_pw_aff_domain(isl_pw_aff_copy(pwaff)); 2884 build = isl_ast_build_from_context(domain); 2885 expr = isl_ast_build_expr_from_pw_aff(build, isl_pw_aff_copy(pwaff)); 2886 p = isl_printer_print_ast_expr(p, expr); 2887 isl_ast_expr_free(expr); 2888 isl_ast_build_free(build); 2889 2890 return p; 2891 } 2892 2893 __isl_give isl_printer *isl_printer_print_aff(__isl_take isl_printer *p, 2894 __isl_keep isl_aff *aff) 2895 { 2896 if (!p || !aff) 2897 goto error; 2898 2899 if (p->output_format == ISL_FORMAT_ISL) 2900 return print_aff_isl(p, aff); 2901 else if (p->output_format == ISL_FORMAT_C) 2902 return print_aff_c(p, aff); 2903 isl_die(p->ctx, isl_error_unsupported, "unsupported output format", 2904 goto error); 2905 error: 2906 isl_printer_free(p); 2907 return NULL; 2908 } 2909 2910 __isl_give isl_printer *isl_printer_print_pw_aff(__isl_take isl_printer *p, 2911 __isl_keep isl_pw_aff *pwaff) 2912 { 2913 if (!p || !pwaff) 2914 goto error; 2915 2916 if (p->output_format == ISL_FORMAT_ISL) 2917 return print_pw_aff_isl(p, pwaff); 2918 else if (p->output_format == ISL_FORMAT_C) 2919 return print_pw_aff_c(p, pwaff); 2920 isl_die(p->ctx, isl_error_unsupported, "unsupported output format", 2921 goto error); 2922 error: 2923 isl_printer_free(p); 2924 return NULL; 2925 } 2926 2927 #undef BASE 2928 #define BASE pw_aff 2929 #include "isl_union_print_templ.c" 2930 2931 /* Print the isl_union_pw_aff "upa" to "p". 2932 * 2933 * We currently only support an isl format. 2934 */ 2935 __isl_give isl_printer *isl_printer_print_union_pw_aff( 2936 __isl_take isl_printer *p, __isl_keep isl_union_pw_aff *upa) 2937 { 2938 if (!p || !upa) 2939 return isl_printer_free(p); 2940 2941 if (p->output_format == ISL_FORMAT_ISL) 2942 return print_union_pw_aff_isl(p, upa); 2943 isl_die(isl_printer_get_ctx(p), isl_error_unsupported, 2944 "unsupported output format", return isl_printer_free(p)); 2945 } 2946 2947 /* Print dimension "pos" of data->space to "p". 2948 * 2949 * data->user is assumed to be an isl_multi_aff. 2950 * 2951 * If the current dimension is an output dimension, then print 2952 * the corresponding expression. Otherwise, print the name of the dimension. 2953 * Make sure to use the domain space for printing names as 2954 * that is the space that will be used for printing constraints (if any). 2955 */ 2956 static __isl_give isl_printer *print_dim_ma(__isl_take isl_printer *p, 2957 struct isl_print_space_data *data, unsigned pos) 2958 { 2959 isl_multi_aff *ma = data->user; 2960 isl_space *space; 2961 2962 space = isl_multi_aff_get_domain_space(ma); 2963 if (data->type == isl_dim_out) { 2964 p = print_aff_body(p, space, ma->u.p[pos]); 2965 } else { 2966 enum isl_dim_type type = data->type; 2967 2968 if (type == isl_dim_in) 2969 type = isl_dim_set; 2970 p = print_name(space, p, type, pos, data->latex); 2971 } 2972 isl_space_free(space); 2973 2974 return p; 2975 } 2976 2977 static __isl_give isl_printer *print_body_multi_aff(__isl_take isl_printer *p, 2978 __isl_keep isl_multi_aff *maff) 2979 { 2980 struct isl_print_space_data data = { 0 }; 2981 2982 data.print_dim = &print_dim_ma; 2983 data.user = maff; 2984 return isl_print_space(maff->space, p, 0, &data); 2985 } 2986 2987 static __isl_give isl_printer *print_multi_aff_isl(__isl_take isl_printer *p, 2988 __isl_keep isl_multi_aff *maff) 2989 { 2990 struct isl_print_space_data data = { 0 }; 2991 2992 if (!maff) 2993 goto error; 2994 2995 p = print_param_tuple(p, maff->space, &data); 2996 p = isl_printer_print_str(p, "{ "); 2997 p = print_body_multi_aff(p, maff); 2998 p = isl_printer_print_str(p, " }"); 2999 return p; 3000 error: 3001 isl_printer_free(p); 3002 return NULL; 3003 } 3004 3005 __isl_give isl_printer *isl_printer_print_multi_aff(__isl_take isl_printer *p, 3006 __isl_keep isl_multi_aff *maff) 3007 { 3008 if (!p || !maff) 3009 goto error; 3010 3011 if (p->output_format == ISL_FORMAT_ISL) 3012 return print_multi_aff_isl(p, maff); 3013 isl_die(p->ctx, isl_error_unsupported, "unsupported output format", 3014 goto error); 3015 error: 3016 isl_printer_free(p); 3017 return NULL; 3018 } 3019 3020 #undef BASE 3021 #define BASE multi_aff 3022 #include "isl_pw_print_templ.c" 3023 3024 /* Print the unnamed, single-dimensional piecewise multi affine expression "pma" 3025 * to "p". 3026 */ 3027 static __isl_give isl_printer *print_unnamed_pw_multi_aff_c( 3028 __isl_take isl_printer *p, __isl_keep isl_pw_multi_aff *pma) 3029 { 3030 int i; 3031 isl_space *space; 3032 3033 space = isl_pw_multi_aff_get_domain_space(pma); 3034 for (i = 0; i < pma->n - 1; ++i) { 3035 p = isl_printer_print_str(p, "("); 3036 p = print_set_c(p, space, pma->p[i].set); 3037 p = isl_printer_print_str(p, ") ? ("); 3038 p = print_aff_c(p, pma->p[i].maff->u.p[0]); 3039 p = isl_printer_print_str(p, ") : "); 3040 } 3041 isl_space_free(space); 3042 3043 return print_aff_c(p, pma->p[pma->n - 1].maff->u.p[0]); 3044 } 3045 3046 static __isl_give isl_printer *print_pw_multi_aff_c(__isl_take isl_printer *p, 3047 __isl_keep isl_pw_multi_aff *pma) 3048 { 3049 isl_size n; 3050 const char *name; 3051 3052 if (!pma) 3053 goto error; 3054 if (pma->n < 1) 3055 isl_die(p->ctx, isl_error_unsupported, 3056 "cannot print empty isl_pw_multi_aff in C format", 3057 goto error); 3058 n = isl_pw_multi_aff_dim(pma, isl_dim_out); 3059 if (n < 0) 3060 return isl_printer_free(p); 3061 name = isl_pw_multi_aff_get_tuple_name(pma, isl_dim_out); 3062 if (!name && n == 1) 3063 return print_unnamed_pw_multi_aff_c(p, pma); 3064 if (!name) 3065 isl_die(p->ctx, isl_error_unsupported, 3066 "cannot print unnamed isl_pw_multi_aff in C format", 3067 goto error); 3068 3069 p = isl_printer_print_str(p, name); 3070 if (n != 0) 3071 isl_die(p->ctx, isl_error_unsupported, 3072 "not supported yet", goto error); 3073 3074 return p; 3075 error: 3076 isl_printer_free(p); 3077 return NULL; 3078 } 3079 3080 __isl_give isl_printer *isl_printer_print_pw_multi_aff( 3081 __isl_take isl_printer *p, __isl_keep isl_pw_multi_aff *pma) 3082 { 3083 if (!p || !pma) 3084 goto error; 3085 3086 if (p->output_format == ISL_FORMAT_ISL) 3087 return print_pw_multi_aff_isl(p, pma); 3088 if (p->output_format == ISL_FORMAT_C) 3089 return print_pw_multi_aff_c(p, pma); 3090 isl_die(p->ctx, isl_error_unsupported, "unsupported output format", 3091 goto error); 3092 error: 3093 isl_printer_free(p); 3094 return NULL; 3095 } 3096 3097 #undef BASE 3098 #define BASE pw_multi_aff 3099 #include "isl_union_print_templ.c" 3100 3101 __isl_give isl_printer *isl_printer_print_union_pw_multi_aff( 3102 __isl_take isl_printer *p, __isl_keep isl_union_pw_multi_aff *upma) 3103 { 3104 if (!p || !upma) 3105 goto error; 3106 3107 if (p->output_format == ISL_FORMAT_ISL) 3108 return print_union_pw_multi_aff_isl(p, upma); 3109 isl_die(p->ctx, isl_error_unsupported, "unsupported output format", 3110 goto error); 3111 error: 3112 isl_printer_free(p); 3113 return NULL; 3114 } 3115 3116 /* Print dimension "pos" of data->space to "p". 3117 * 3118 * data->user is assumed to be an isl_multi_pw_aff. 3119 * 3120 * If the current dimension is an output dimension, then print 3121 * the corresponding piecewise affine expression. 3122 * Otherwise, print the name of the dimension. 3123 * Make sure to use the same space in both cases. 3124 * In particular, use the domain space for printing names as 3125 * that is the space that is used for printing constraints. 3126 */ 3127 static __isl_give isl_printer *print_dim_mpa(__isl_take isl_printer *p, 3128 struct isl_print_space_data *data, unsigned pos) 3129 { 3130 int i; 3131 int need_parens; 3132 isl_space *space; 3133 isl_multi_pw_aff *mpa = data->user; 3134 isl_pw_aff *pa; 3135 3136 if (data->type != isl_dim_out) { 3137 enum isl_dim_type type = data->type; 3138 3139 if (type == isl_dim_in) 3140 type = isl_dim_set; 3141 space = isl_multi_pw_aff_get_domain_space(mpa); 3142 p = print_name(space, p, type, pos, data->latex); 3143 isl_space_free(space); 3144 return p; 3145 } 3146 3147 pa = mpa->u.p[pos]; 3148 if (pa->n == 0) 3149 return isl_printer_print_str(p, "(0 : false)"); 3150 3151 need_parens = pa->n != 1 || !isl_set_plain_is_universe(pa->p[0].set); 3152 if (need_parens) 3153 p = isl_printer_print_str(p, "("); 3154 space = isl_multi_pw_aff_get_domain_space(mpa); 3155 for (i = 0; i < pa->n; ++i) { 3156 3157 if (i) 3158 p = isl_printer_print_str(p, "; "); 3159 p = print_aff_body(p, space, pa->p[i].aff); 3160 p = print_disjuncts(pa->p[i].set, space, p, 0); 3161 } 3162 isl_space_free(space); 3163 if (need_parens) 3164 p = isl_printer_print_str(p, ")"); 3165 3166 return p; 3167 } 3168 3169 /* Print "mpa" to "p" in isl format. 3170 * 3171 * If "mpa" is zero-dimensional and has a non-trivial explicit domain, 3172 * then it is printed after the tuple of affine expressions. 3173 */ 3174 static __isl_give isl_printer *print_multi_pw_aff_isl(__isl_take isl_printer *p, 3175 __isl_keep isl_multi_pw_aff *mpa) 3176 { 3177 struct isl_print_space_data data = { 0 }; 3178 isl_bool has_domain; 3179 3180 if (!mpa) 3181 return isl_printer_free(p); 3182 3183 p = print_param_tuple(p, mpa->space, &data); 3184 p = isl_printer_print_str(p, "{ "); 3185 data.print_dim = &print_dim_mpa; 3186 data.user = mpa; 3187 p = isl_print_space(mpa->space, p, 0, &data); 3188 has_domain = isl_multi_pw_aff_has_non_trivial_domain(mpa); 3189 if (has_domain < 0) 3190 return isl_printer_free(p); 3191 if (has_domain) { 3192 isl_space *space; 3193 3194 space = isl_space_domain(isl_space_copy(mpa->space)); 3195 p = print_disjuncts_set(mpa->u.dom, space, p, 0); 3196 isl_space_free(space); 3197 } 3198 p = isl_printer_print_str(p, " }"); 3199 return p; 3200 } 3201 3202 __isl_give isl_printer *isl_printer_print_multi_pw_aff( 3203 __isl_take isl_printer *p, __isl_keep isl_multi_pw_aff *mpa) 3204 { 3205 if (!p || !mpa) 3206 return isl_printer_free(p); 3207 3208 if (p->output_format == ISL_FORMAT_ISL) 3209 return print_multi_pw_aff_isl(p, mpa); 3210 isl_die(p->ctx, isl_error_unsupported, "unsupported output format", 3211 return isl_printer_free(p)); 3212 } 3213 3214 /* Print dimension "pos" of data->space to "p". 3215 * 3216 * data->user is assumed to be an isl_multi_val. 3217 * 3218 * If the current dimension is an output dimension, then print 3219 * the corresponding value. Otherwise, print the name of the dimension. 3220 */ 3221 static __isl_give isl_printer *print_dim_mv(__isl_take isl_printer *p, 3222 struct isl_print_space_data *data, unsigned pos) 3223 { 3224 isl_multi_val *mv = data->user; 3225 3226 if (data->type == isl_dim_out) 3227 return isl_printer_print_val(p, mv->u.p[pos]); 3228 else 3229 return print_name(data->space, p, data->type, pos, data->latex); 3230 } 3231 3232 /* Print the isl_multi_val "mv" to "p" in isl format. 3233 */ 3234 static __isl_give isl_printer *print_multi_val_isl(__isl_take isl_printer *p, 3235 __isl_keep isl_multi_val *mv) 3236 { 3237 struct isl_print_space_data data = { 0 }; 3238 3239 if (!mv) 3240 return isl_printer_free(p); 3241 3242 p = print_param_tuple(p, mv->space, &data); 3243 p = isl_printer_print_str(p, "{ "); 3244 data.print_dim = &print_dim_mv; 3245 data.user = mv; 3246 p = isl_print_space(mv->space, p, 0, &data); 3247 p = isl_printer_print_str(p, " }"); 3248 return p; 3249 } 3250 3251 /* Print the isl_multi_val "mv" to "p". 3252 * 3253 * Currently only supported in isl format. 3254 */ 3255 __isl_give isl_printer *isl_printer_print_multi_val( 3256 __isl_take isl_printer *p, __isl_keep isl_multi_val *mv) 3257 { 3258 if (!p || !mv) 3259 return isl_printer_free(p); 3260 3261 if (p->output_format == ISL_FORMAT_ISL) 3262 return print_multi_val_isl(p, mv); 3263 isl_die(p->ctx, isl_error_unsupported, "unsupported output format", 3264 return isl_printer_free(p)); 3265 } 3266 3267 /* Print dimension "pos" of data->space to "p". 3268 * 3269 * data->user is assumed to be an isl_multi_id. 3270 * 3271 * If the current dimension is an output dimension, then print 3272 * the corresponding identifier. Otherwise, print the name of the dimension. 3273 */ 3274 static __isl_give isl_printer *print_dim_mi(__isl_take isl_printer *p, 3275 struct isl_print_space_data *data, unsigned pos) 3276 { 3277 isl_multi_id *mi = data->user; 3278 3279 if (data->type == isl_dim_out) 3280 return isl_printer_print_id(p, mi->u.p[pos]); 3281 else 3282 return print_name(data->space, p, data->type, pos, data->latex); 3283 } 3284 3285 /* Print the isl_multi_id "mi" to "p" in isl format. 3286 */ 3287 static __isl_give isl_printer *print_multi_id_isl(__isl_take isl_printer *p, 3288 __isl_keep isl_multi_id *mi) 3289 { 3290 isl_space *space; 3291 struct isl_print_space_data data = { 0 }; 3292 3293 space = isl_multi_id_peek_space(mi); 3294 p = print_param_tuple(p, space, &data); 3295 p = isl_printer_print_str(p, "{ "); 3296 data.print_dim = &print_dim_mi; 3297 data.user = mi; 3298 p = isl_print_space(space, p, 0, &data); 3299 p = isl_printer_print_str(p, " }"); 3300 return p; 3301 } 3302 3303 /* Print the isl_multi_id "mi" to "p". 3304 * 3305 * Currently only supported in isl format. 3306 */ 3307 __isl_give isl_printer *isl_printer_print_multi_id( 3308 __isl_take isl_printer *p, __isl_keep isl_multi_id *mi) 3309 { 3310 if (!p || !mi) 3311 return isl_printer_free(p); 3312 3313 if (p->output_format == ISL_FORMAT_ISL) 3314 return print_multi_id_isl(p, mi); 3315 isl_die(isl_printer_get_ctx(p), isl_error_unsupported, 3316 "unsupported output format", return isl_printer_free(p)); 3317 } 3318 3319 /* Print dimension "pos" of data->space to "p". 3320 * 3321 * data->user is assumed to be an isl_multi_union_pw_aff. 3322 * 3323 * The current dimension is necessarily a set dimension, so 3324 * we print the corresponding isl_union_pw_aff, including 3325 * the braces. 3326 */ 3327 static __isl_give isl_printer *print_union_pw_aff_dim(__isl_take isl_printer *p, 3328 struct isl_print_space_data *data, unsigned pos) 3329 { 3330 isl_multi_union_pw_aff *mupa = data->user; 3331 isl_union_pw_aff *upa; 3332 3333 upa = isl_multi_union_pw_aff_get_union_pw_aff(mupa, pos); 3334 p = print_body_union_pw_aff(p, upa); 3335 isl_union_pw_aff_free(upa); 3336 3337 return p; 3338 } 3339 3340 /* Print the isl_multi_union_pw_aff "mupa" to "p" in isl format. 3341 * 3342 * If "mupa" is zero-dimensional and has a non-trivial explicit domain, 3343 * then it is printed after the tuple of affine expressions. 3344 * In order to clarify that this domain belongs to the expression, 3345 * the tuple along with the domain are placed inside parentheses. 3346 * If "mupa" has any parameters, then the opening parenthesis 3347 * appears after the parameter declarations. 3348 */ 3349 static __isl_give isl_printer *print_multi_union_pw_aff_isl( 3350 __isl_take isl_printer *p, __isl_keep isl_multi_union_pw_aff *mupa) 3351 { 3352 struct isl_print_space_data data = { 0 }; 3353 isl_bool has_domain; 3354 isl_space *space; 3355 3356 if (!mupa) 3357 return isl_printer_free(p); 3358 has_domain = isl_multi_union_pw_aff_has_non_trivial_domain(mupa); 3359 if (has_domain < 0) 3360 return isl_printer_free(p); 3361 3362 space = isl_multi_union_pw_aff_get_space(mupa); 3363 p = print_param_tuple(p, space, &data); 3364 3365 if (has_domain) 3366 p = isl_printer_print_str(p, "("); 3367 3368 data.print_dim = &print_union_pw_aff_dim; 3369 data.user = mupa; 3370 3371 p = isl_print_space(space, p, 0, &data); 3372 isl_space_free(space); 3373 3374 if (has_domain) { 3375 p = isl_printer_print_str(p, " : "); 3376 p = isl_printer_print_union_set_isl_body(p, mupa->u.dom); 3377 p = isl_printer_print_str(p, ")"); 3378 } 3379 3380 return p; 3381 } 3382 3383 /* Print the isl_multi_union_pw_aff "mupa" to "p" in isl format. 3384 * 3385 * We currently only support an isl format. 3386 */ 3387 __isl_give isl_printer *isl_printer_print_multi_union_pw_aff( 3388 __isl_take isl_printer *p, __isl_keep isl_multi_union_pw_aff *mupa) 3389 { 3390 if (!p || !mupa) 3391 return isl_printer_free(p); 3392 3393 if (p->output_format == ISL_FORMAT_ISL) 3394 return print_multi_union_pw_aff_isl(p, mupa); 3395 isl_die(isl_printer_get_ctx(p), isl_error_unsupported, 3396 "unsupported output format", return isl_printer_free(p)); 3397 } 3398