3374 lines · c
1/*2 * Copyright 2008-2009 Katholieke Universiteit Leuven3 * Copyright 2010 INRIA Saclay4 * Copyright 2012-2013 Ecole Normale Superieure5 * Copyright 2019 Cerebras Systems6 *7 * Use of this software is governed by the MIT license8 *9 * Written by Sven Verdoolaege, K.U.Leuven, Departement10 * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium11 * 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, France14 * and Cerebras Systems, 175 S San Antonio Rd, Los Altos, CA, USA15 */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 45static const char *s_to[2] = { " -> ", " \\to " };46static const char *s_and[2] = { " and ", " \\wedge " };47static const char *s_or[2] = { " or ", " \\vee " };48static const char *s_le[2] = { "<=", "\\le" };49static const char *s_ge[2] = { ">=", "\\ge" };50static const char *s_open_set[2] = { "{ ", "\\{\\, " };51static const char *s_close_set[2] = { " }", " \\,\\}" };52static const char *s_open_list[2] = { "[", "(" };53static const char *s_close_list[2] = { "]", ")" };54static const char *s_such_that[2] = { " : ", " \\mid " };55static const char *s_open_exists[2] = { "exists (", "\\exists \\, " };56static const char *s_close_exists[2] = { ")", "" };57static const char *s_div_prefix[2] = { "e", "\\alpha_" };58static const char *s_mod[2] = { "mod", "\\bmod" };59static const char *s_param_prefix[2] = { "p", "p_" };60static const char *s_input_prefix[2] = { "i", "i_" };61static const char *s_output_prefix[2] = { "o", "o_" };62 63static __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 99static __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 114static __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 120static __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 154static __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 160static __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 176static __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 182static 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 */206static __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 ? NULL215 : 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 else226 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 240static 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 selected270 * variable have a known explicit representation?271 * Furthermore, the Omega format does not allow any div expressions272 * to be printed.273 */274static 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 284static __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 287static __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 else316 p = print_name(space, p, type, pos, latex);317 return p;318}319 320static __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" and351 * the integer division definitions taken from "div".352 */353static __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 */369static __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 else388 p = print_name(data->space, p, data->type, offset + i,389 data->latex);390 }391 return p;392}393 394static __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 402static __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 406static __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 } else435 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 442static __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 451static __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 481static __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 ignored503 * since div constraints are not printed.504 */505static 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 when533 * printing a constraint where the LHS is greater than or equal to the LHS534 * (sign > 0) or smaller than or equal to the LHS (sign < 0).535 * If "strict" is set, then return the strict version of the comparison536 * operator.537 */538static 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 else545 return s_ge[latex];546}547 548/* Print one side of a constraint "c" to "p", with549 * the variable names taken from "space" and the integer division definitions550 * 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, then553 * the partial constraint554 *555 * c' op556 *557 * is printed.558 */559static __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 names574 * taken from "space" and the integer division definitions taken from "div".575 * "last" is the position of the last non-zero coefficient, which is576 * moreover assumed to be negative.577 * Let c' be the result of zeroing out this coefficient, then578 * the constraint is printed in the form579 *580 * -c[last] op c'581 */582static __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 division601 *602 * floor(f/m)603 *604 * at position "pos" in "div", print the corresponding modulo expression605 *606 * (f) mod m607 *608 * to "p". The variable names are taken from "space", while any609 * nested integer division definitions are taken from "div".610 */611static __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 form630 *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 division640 * with explicit representation and "c" needs to be a multiple641 * of the denominator of the integer division.642 */643static 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" and672 * the integer division definitions taken from "div".673 * "last" is the position of the last non-zero coefficient, which is674 * moreover assumed to be negative and a multiple of the denominator675 * of the corresponding integer division. "div_pos" is the corresponding676 * position in the sequence of integer divisions.677 *678 * The equality is of the form679 *680 * f - a m floor(g/m) = 0.681 *682 * Print it as683 *684 * a (g mod m) = -f + a g685 */686static __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 names714 * taken from "space" and the integer division definitions taken from "div".715 * "last" is the position of the last non-zero coefficient, which is716 * moreover assumed to be negative.717 *718 * If possible, print the equality constraint as a modulo constraint.719 */720static __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" and739 * 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 bound745 *746 * f - a x >= 0747 *748 * is printed as749 *750 * a x <= f751 *752 * while an upper bound753 *754 * f + a x >= 0755 *756 * is printed as757 *758 * a x >= -f759 *760 * If the next constraint has an opposite sign for the same last coefficient,761 * then it is printed as762 *763 * f >= a x764 *765 * or766 *767 * -f <= a x768 *769 * instead. In fact, the "a x" part is not printed explicitly, but770 * reused from the next constraint, which is therefore treated as771 * a first constraint in the conjunction.772 *773 * If the constant term of "f" is -1, then "f" is replaced by "f + 1" and774 * the comparison operator is replaced by the strict variant.775 * Essentially, ">= 1" is replaced by "> 0".776 */777static __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 else815 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 else844 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;867error:868 isl_basic_map_free(bmap);869 isl_vec_free(c);870 isl_printer_free(p);871 return NULL;872}873 874static __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 have893 * a definition that can be printed.894 * If "print_defined_divs" is set, then those div names are printed895 * as well, along with their definitions.896 */897static __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 because929 * explicit div representations are not printed inline in that case.930 */931static 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 printed954 * as well because they will not be printed inline.955 */956static __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 */974static __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 */993static __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 */1023static __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 1036static __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 1049static __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 1060static __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 1073static __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 */1089static __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 1106static __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 */1126static __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" and1151 * 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 */1154static __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;1174error: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 */1188static __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, then1220 * we need to print the colon. Otherwise, the output looks identical1221 * to the empty set.1222 */1223static __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 else1229 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 */1236static __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 1242struct isl_aff_split {1243 isl_basic_map *aff;1244 isl_map *map;1245};1246 1247static 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 1262static __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;1292error:1293 isl_basic_map_free(bmap);1294 return NULL;1295}1296 1297static 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 1306static __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;1331error:1332 isl_basic_map_free(bmap);1333 return NULL;1334}1335 1336static __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;1378error:1379 free_split(split, map->n);1380 return NULL;1381}1382 1383static int defining_equality(__isl_keep isl_basic_map *eq,1384 __isl_keep isl_space *space, enum isl_dim_type type, int pos)1385{1386 int i;1387 isl_size total;1388 1389 total = isl_basic_map_dim(eq, isl_dim_all);1390 if (total < 0)1391 return -1;1392 1393 pos += isl_space_offset(space, type);1394 1395 for (i = 0; i < eq->n_eq; ++i) {1396 if (isl_seq_last_non_zero(eq->eq[i] + 1, total) != pos)1397 continue;1398 if (isl_int_is_one(eq->eq[i][1 + pos]))1399 isl_seq_neg(eq->eq[i], eq->eq[i], 1 + total);1400 return i;1401 }1402 1403 return -1;1404}1405 1406/* Print dimension "pos" of data->space to "p".1407 *1408 * data->user is assumed to be an isl_basic_map keeping track of equalities.1409 *1410 * If the current dimension is defined by these equalities, then print1411 * the corresponding expression, assigned to the name of the dimension1412 * if there is any. Otherwise, print the name of the dimension.1413 */1414static __isl_give isl_printer *print_dim_eq(__isl_take isl_printer *p,1415 struct isl_print_space_data *data, unsigned pos)1416{1417 isl_basic_map *eq = data->user;1418 int j;1419 1420 j = defining_equality(eq, data->space, data->type, pos);1421 if (j >= 0) {1422 if (isl_space_has_dim_name(data->space, data->type, pos)) {1423 p = print_name(data->space, p, data->type, pos,1424 data->latex);1425 p = isl_printer_print_str(p, " = ");1426 }1427 pos += 1 + isl_space_offset(data->space, data->type);1428 p = print_affine_of_len(data->space, NULL, p, eq->eq[j], pos);1429 } else {1430 p = print_name(data->space, p, data->type, pos, data->latex);1431 }1432 1433 return p;1434}1435 1436static __isl_give isl_printer *print_split_map(__isl_take isl_printer *p,1437 struct isl_aff_split *split, int n, __isl_keep isl_space *space)1438{1439 struct isl_print_space_data data = { 0 };1440 int i;1441 int rational;1442 1443 data.print_dim = &print_dim_eq;1444 for (i = 0; i < n; ++i) {1445 if (!split[i].map)1446 break;1447 rational = split[i].map->n > 0 &&1448 ISL_F_ISSET(split[i].map->p[0], ISL_BASIC_MAP_RATIONAL);1449 if (i)1450 p = isl_printer_print_str(p, "; ");1451 data.user = split[i].aff;1452 p = isl_print_space(space, p, rational, &data);1453 p = print_disjuncts_map(split[i].map, space, p, 0);1454 }1455 1456 return p;1457}1458 1459static __isl_give isl_printer *print_body_map(__isl_take isl_printer *p,1460 __isl_keep isl_map *map)1461{1462 struct isl_print_space_data data = { 0 };1463 struct isl_aff_split *split = NULL;1464 int rational;1465 1466 if (!p || !map)1467 return isl_printer_free(p);1468 if (!p->dump && map->n > 0)1469 split = split_aff(map);1470 if (split) {1471 p = print_split_map(p, split, map->n, map->dim);1472 } else {1473 rational = map->n > 0 &&1474 ISL_F_ISSET(map->p[0], ISL_BASIC_MAP_RATIONAL);1475 p = isl_print_space(map->dim, p, rational, &data);1476 p = print_disjuncts_map(map, map->dim, p, 0);1477 }1478 free_split(split, map->n);1479 return p;1480}1481 1482static __isl_give isl_printer *isl_map_print_isl(__isl_keep isl_map *map,1483 __isl_take isl_printer *p)1484{1485 struct isl_print_space_data data = { 0 };1486 1487 p = print_param_tuple(p, map->dim, &data);1488 p = isl_printer_print_str(p, s_open_set[0]);1489 p = print_body_map(p, map);1490 p = isl_printer_print_str(p, s_close_set[0]);1491 return p;1492}1493 1494static __isl_give isl_printer *print_latex_map(__isl_keep isl_map *map,1495 __isl_take isl_printer *p, __isl_keep isl_basic_map *aff)1496{1497 struct isl_print_space_data data = { 0 };1498 1499 data.latex = 1;1500 p = print_param_tuple(p, map->dim, &data);1501 p = isl_printer_print_str(p, s_open_set[1]);1502 data.print_dim = &print_dim_eq;1503 data.user = aff;1504 p = isl_print_space(map->dim, p, 0, &data);1505 p = print_disjuncts_map(map, map->dim, p, 1);1506 p = isl_printer_print_str(p, s_close_set[1]);1507 1508 return p;1509}1510 1511static __isl_give isl_printer *isl_map_print_latex(__isl_keep isl_map *map,1512 __isl_take isl_printer *p)1513{1514 int i;1515 struct isl_aff_split *split = NULL;1516 1517 if (map->n > 0)1518 split = split_aff(map);1519 1520 if (!split)1521 return print_latex_map(map, p, NULL);1522 1523 for (i = 0; i < map->n; ++i) {1524 if (!split[i].map)1525 break;1526 if (i)1527 p = isl_printer_print_str(p, " \\cup ");1528 p = print_latex_map(split[i].map, p, split[i].aff);1529 }1530 1531 free_split(split, map->n);1532 return p;1533}1534 1535__isl_give isl_printer *isl_printer_print_basic_map(__isl_take isl_printer *p,1536 __isl_keep isl_basic_map *bmap)1537{1538 if (!p || !bmap)1539 goto error;1540 if (p->output_format == ISL_FORMAT_ISL)1541 return isl_basic_map_print_isl(bmap, p, 0);1542 else if (p->output_format == ISL_FORMAT_OMEGA)1543 return basic_map_print_omega(bmap, p);1544 isl_assert(bmap->ctx, 0, goto error);1545error:1546 isl_printer_free(p);1547 return NULL;1548}1549 1550__isl_give isl_printer *isl_printer_print_basic_set(__isl_take isl_printer *p,1551 __isl_keep isl_basic_set *bset)1552{1553 if (!p || !bset)1554 goto error;1555 1556 if (p->output_format == ISL_FORMAT_ISL)1557 return isl_basic_map_print_isl(bset, p, 0);1558 else if (p->output_format == ISL_FORMAT_POLYLIB)1559 return isl_basic_set_print_polylib(bset, p, 0);1560 else if (p->output_format == ISL_FORMAT_EXT_POLYLIB)1561 return isl_basic_set_print_polylib(bset, p, 1);1562 else if (p->output_format == ISL_FORMAT_POLYLIB_CONSTRAINTS)1563 return bset_print_constraints_polylib(bset, p);1564 else if (p->output_format == ISL_FORMAT_OMEGA)1565 return basic_set_print_omega(bset, p);1566 isl_assert(p->ctx, 0, goto error);1567error:1568 isl_printer_free(p);1569 return NULL;1570}1571 1572__isl_give isl_printer *isl_printer_print_set(__isl_take isl_printer *p,1573 __isl_keep isl_set *set)1574{1575 if (!p || !set)1576 goto error;1577 if (p->output_format == ISL_FORMAT_ISL)1578 return isl_map_print_isl(set_to_map(set), p);1579 else if (p->output_format == ISL_FORMAT_POLYLIB)1580 return isl_set_print_polylib(set, p, 0);1581 else if (p->output_format == ISL_FORMAT_EXT_POLYLIB)1582 return isl_set_print_polylib(set, p, 1);1583 else if (p->output_format == ISL_FORMAT_OMEGA)1584 return isl_set_print_omega(set, p);1585 else if (p->output_format == ISL_FORMAT_LATEX)1586 return isl_map_print_latex(set_to_map(set), p);1587 isl_assert(set->ctx, 0, goto error);1588error:1589 isl_printer_free(p);1590 return NULL;1591}1592 1593__isl_give isl_printer *isl_printer_print_map(__isl_take isl_printer *p,1594 __isl_keep isl_map *map)1595{1596 if (!p || !map)1597 goto error;1598 1599 if (p->output_format == ISL_FORMAT_ISL)1600 return isl_map_print_isl(map, p);1601 else if (p->output_format == ISL_FORMAT_POLYLIB)1602 return isl_map_print_polylib(map, p, 0);1603 else if (p->output_format == ISL_FORMAT_EXT_POLYLIB)1604 return isl_map_print_polylib(map, p, 1);1605 else if (p->output_format == ISL_FORMAT_OMEGA)1606 return isl_map_print_omega(map, p);1607 else if (p->output_format == ISL_FORMAT_LATEX)1608 return isl_map_print_latex(map, p);1609 isl_assert(map->ctx, 0, goto error);1610error:1611 isl_printer_free(p);1612 return NULL;1613}1614 1615struct isl_union_print_data {1616 isl_printer *p;1617 int first;1618};1619 1620#undef BASE1621#define BASE map1622#include "isl_union_print_templ.c"1623 1624/* Print the body of "uset" (everything except the parameter declarations)1625 * to "p" in isl format.1626 */1627static __isl_give isl_printer *isl_printer_print_union_set_isl_body(1628 __isl_take isl_printer *p, __isl_keep isl_union_set *uset)1629{1630 return print_body_union_map(p, uset_to_umap(uset));1631}1632 1633static isl_stat print_latex_map_body(__isl_take isl_map *map, void *user)1634{1635 struct isl_union_print_data *data;1636 data = (struct isl_union_print_data *)user;1637 1638 if (!data->first)1639 data->p = isl_printer_print_str(data->p, " \\cup ");1640 data->first = 0;1641 1642 data->p = isl_map_print_latex(map, data->p);1643 isl_map_free(map);1644 1645 return isl_stat_ok;1646}1647 1648static __isl_give isl_printer *isl_union_map_print_latex(1649 __isl_keep isl_union_map *umap, __isl_take isl_printer *p)1650{1651 struct isl_union_print_data data = { p, 1 };1652 isl_union_map_foreach_map(umap, &print_latex_map_body, &data);1653 p = data.p;1654 return p;1655}1656 1657__isl_give isl_printer *isl_printer_print_union_map(__isl_take isl_printer *p,1658 __isl_keep isl_union_map *umap)1659{1660 if (!p || !umap)1661 goto error;1662 1663 if (p->output_format == ISL_FORMAT_ISL)1664 return print_union_map_isl(p, umap);1665 if (p->output_format == ISL_FORMAT_LATEX)1666 return isl_union_map_print_latex(umap, p);1667 1668 isl_die(p->ctx, isl_error_invalid,1669 "invalid output format for isl_union_map", goto error);1670error:1671 isl_printer_free(p);1672 return NULL;1673}1674 1675__isl_give isl_printer *isl_printer_print_union_set(__isl_take isl_printer *p,1676 __isl_keep isl_union_set *uset)1677{1678 if (!p || !uset)1679 goto error;1680 1681 if (p->output_format == ISL_FORMAT_ISL)1682 return print_union_map_isl(p, uset_to_umap(uset));1683 if (p->output_format == ISL_FORMAT_LATEX)1684 return isl_union_map_print_latex(uset_to_umap(uset), p);1685 1686 isl_die(p->ctx, isl_error_invalid,1687 "invalid output format for isl_union_set", goto error);1688error:1689 isl_printer_free(p);1690 return NULL;1691}1692 1693static isl_size poly_rec_n_non_zero(__isl_keep isl_poly_rec *rec)1694{1695 int i;1696 int n;1697 1698 if (!rec)1699 return isl_size_error;1700 1701 for (i = 0, n = 0; i < rec->n; ++i) {1702 isl_bool is_zero = isl_poly_is_zero(rec->p[i]);1703 1704 if (is_zero < 0)1705 return isl_size_error;1706 if (!is_zero)1707 ++n;1708 }1709 1710 return n;1711}1712 1713static __isl_give isl_printer *poly_print_cst(__isl_keep isl_poly *poly,1714 __isl_take isl_printer *p, int first)1715{1716 isl_poly_cst *cst;1717 int neg;1718 1719 cst = isl_poly_as_cst(poly);1720 if (!cst)1721 goto error;1722 neg = !first && isl_int_is_neg(cst->n);1723 if (!first)1724 p = isl_printer_print_str(p, neg ? " - " : " + ");1725 if (neg)1726 isl_int_neg(cst->n, cst->n);1727 if (isl_int_is_zero(cst->d)) {1728 int sgn = isl_int_sgn(cst->n);1729 p = isl_printer_print_str(p, sgn < 0 ? "-infty" :1730 sgn == 0 ? "NaN" : "infty");1731 } else1732 p = isl_printer_print_isl_int(p, cst->n);1733 if (neg)1734 isl_int_neg(cst->n, cst->n);1735 if (!isl_int_is_zero(cst->d) && !isl_int_is_one(cst->d)) {1736 p = isl_printer_print_str(p, "/");1737 p = isl_printer_print_isl_int(p, cst->d);1738 }1739 return p;1740error:1741 isl_printer_free(p);1742 return NULL;1743}1744 1745static __isl_give isl_printer *print_base(__isl_take isl_printer *p,1746 __isl_keep isl_space *space, __isl_keep isl_mat *div, int var)1747{1748 isl_size total;1749 1750 total = isl_space_dim(space, isl_dim_all);1751 if (total < 0)1752 return isl_printer_free(p);1753 if (var < total)1754 p = print_term(space, NULL, space->ctx->one, 1 + var, p, 0);1755 else1756 p = print_div(space, div, var - total, p);1757 return p;1758}1759 1760static __isl_give isl_printer *print_pow(__isl_take isl_printer *p,1761 __isl_keep isl_space *space, __isl_keep isl_mat *div, int var, int exp)1762{1763 p = print_base(p, space, div, var);1764 if (exp == 1)1765 return p;1766 if (p->output_format == ISL_FORMAT_C) {1767 int i;1768 for (i = 1; i < exp; ++i) {1769 p = isl_printer_print_str(p, "*");1770 p = print_base(p, space, div, var);1771 }1772 } else {1773 p = isl_printer_print_str(p, "^");1774 p = isl_printer_print_int(p, exp);1775 }1776 return p;1777}1778 1779/* Print the polynomial "poly" defined over the domain space "space" and1780 * local variables defined by "div" to "p".1781 */1782static __isl_give isl_printer *poly_print(__isl_keep isl_poly *poly,1783 __isl_keep isl_space *space, __isl_keep isl_mat *div,1784 __isl_take isl_printer *p)1785{1786 int i, first, print_parens;1787 isl_size n;1788 isl_bool is_cst;1789 isl_poly_rec *rec;1790 1791 is_cst = isl_poly_is_cst(poly);1792 if (!p || is_cst < 0 || !space || !div)1793 goto error;1794 1795 if (is_cst)1796 return poly_print_cst(poly, p, 1);1797 1798 rec = isl_poly_as_rec(poly);1799 n = poly_rec_n_non_zero(rec);1800 if (n < 0)1801 return isl_printer_free(p);1802 print_parens = n > 1;1803 if (print_parens)1804 p = isl_printer_print_str(p, "(");1805 for (i = 0, first = 1; i < rec->n; ++i) {1806 isl_bool is_zero = isl_poly_is_zero(rec->p[i]);1807 isl_bool is_one = isl_poly_is_one(rec->p[i]);1808 isl_bool is_negone = isl_poly_is_negone(rec->p[i]);1809 isl_bool is_cst = isl_poly_is_cst(rec->p[i]);1810 1811 if (is_zero < 0 || is_one < 0 || is_negone < 0)1812 return isl_printer_free(p);1813 if (is_zero)1814 continue;1815 if (is_negone) {1816 if (!i)1817 p = isl_printer_print_str(p, "-1");1818 else if (first)1819 p = isl_printer_print_str(p, "-");1820 else1821 p = isl_printer_print_str(p, " - ");1822 } else if (is_cst && !is_one)1823 p = poly_print_cst(rec->p[i], p, first);1824 else {1825 if (!first)1826 p = isl_printer_print_str(p, " + ");1827 if (i == 0 || !is_one)1828 p = poly_print(rec->p[i], space, div, p);1829 }1830 first = 0;1831 if (i == 0)1832 continue;1833 if (!is_one && !is_negone)1834 p = isl_printer_print_str(p, " * ");1835 p = print_pow(p, space, div, rec->poly.var, i);1836 }1837 if (print_parens)1838 p = isl_printer_print_str(p, ")");1839 return p;1840error:1841 isl_printer_free(p);1842 return NULL;1843}1844 1845static __isl_give isl_printer *print_qpolynomial(__isl_take isl_printer *p,1846 __isl_keep isl_qpolynomial *qp)1847{1848 if (!p || !qp)1849 goto error;1850 p = poly_print(qp->poly, qp->dim, qp->div, p);1851 return p;1852error:1853 isl_printer_free(p);1854 return NULL;1855}1856 1857static __isl_give isl_printer *print_qpolynomial_isl(__isl_take isl_printer *p,1858 __isl_keep isl_qpolynomial *qp)1859{1860 struct isl_print_space_data data = { 0 };1861 1862 if (!p || !qp)1863 goto error;1864 1865 p = print_param_tuple(p, qp->dim, &data);1866 p = isl_printer_print_str(p, "{ ");1867 if (!isl_space_is_params(qp->dim)) {1868 p = isl_print_space(qp->dim, p, 0, &data);1869 p = isl_printer_print_str(p, " -> ");1870 }1871 p = print_qpolynomial(p, qp);1872 p = isl_printer_print_str(p, " }");1873 return p;1874error:1875 isl_printer_free(p);1876 return NULL;1877}1878 1879/* Print the quasi-polynomial "qp" to "p" in C format, with the variable names1880 * taken from the domain space "space".1881 */1882static __isl_give isl_printer *print_qpolynomial_c(__isl_take isl_printer *p,1883 __isl_keep isl_space *space, __isl_keep isl_qpolynomial *qp)1884{1885 isl_bool is_one;1886 isl_val *den;1887 1888 den = isl_qpolynomial_get_den(qp);1889 qp = isl_qpolynomial_copy(qp);1890 qp = isl_qpolynomial_scale_val(qp, isl_val_copy(den));1891 is_one = isl_val_is_one(den);1892 if (is_one < 0)1893 p = isl_printer_free(p);1894 if (!is_one)1895 p = isl_printer_print_str(p, "(");1896 if (qp)1897 p = poly_print(qp->poly, space, qp->div, p);1898 else1899 p = isl_printer_free(p);1900 if (!is_one) {1901 p = isl_printer_print_str(p, ")/");1902 p = isl_printer_print_val(p, den);1903 }1904 isl_qpolynomial_free(qp);1905 isl_val_free(den);1906 return p;1907}1908 1909__isl_give isl_printer *isl_printer_print_qpolynomial(1910 __isl_take isl_printer *p, __isl_keep isl_qpolynomial *qp)1911{1912 if (!p || !qp)1913 goto error;1914 1915 if (p->output_format == ISL_FORMAT_ISL)1916 return print_qpolynomial_isl(p, qp);1917 else if (p->output_format == ISL_FORMAT_C)1918 return print_qpolynomial_c(p, qp->dim, qp);1919 else1920 isl_die(qp->dim->ctx, isl_error_unsupported,1921 "output format not supported for isl_qpolynomials",1922 goto error);1923error:1924 isl_printer_free(p);1925 return NULL;1926}1927 1928void isl_qpolynomial_print(__isl_keep isl_qpolynomial *qp, FILE *out,1929 unsigned output_format)1930{1931 isl_printer *p;1932 1933 if (!qp)1934 return;1935 1936 isl_assert(qp->dim->ctx, output_format == ISL_FORMAT_ISL, return);1937 p = isl_printer_to_file(qp->dim->ctx, out);1938 p = isl_printer_print_qpolynomial(p, qp);1939 isl_printer_free(p);1940}1941 1942static __isl_give isl_printer *qpolynomial_fold_print(1943 __isl_keep isl_qpolynomial_fold *fold, __isl_take isl_printer *p)1944{1945 int i;1946 isl_qpolynomial_list *list;1947 isl_size n;1948 1949 list = isl_qpolynomial_fold_peek_list(fold);1950 n = isl_qpolynomial_list_size(list);1951 if (n < 0)1952 return isl_printer_free(p);1953 if (fold->type == isl_fold_min)1954 p = isl_printer_print_str(p, "min");1955 else if (fold->type == isl_fold_max)1956 p = isl_printer_print_str(p, "max");1957 p = isl_printer_print_str(p, "(");1958 for (i = 0; i < n; ++i) {1959 isl_qpolynomial *qp;1960 1961 if (i)1962 p = isl_printer_print_str(p, ", ");1963 qp = isl_qpolynomial_list_peek(list, i);1964 p = print_qpolynomial(p, qp);1965 }1966 p = isl_printer_print_str(p, ")");1967 return p;1968}1969 1970void isl_qpolynomial_fold_print(__isl_keep isl_qpolynomial_fold *fold,1971 FILE *out, unsigned output_format)1972{1973 isl_printer *p;1974 1975 if (!fold)1976 return;1977 1978 isl_assert(fold->dim->ctx, output_format == ISL_FORMAT_ISL, return);1979 1980 p = isl_printer_to_file(fold->dim->ctx, out);1981 p = isl_printer_print_qpolynomial_fold(p, fold);1982 1983 isl_printer_free(p);1984}1985 1986static __isl_give isl_printer *print_body_pw_qpolynomial(1987 __isl_take isl_printer *p, __isl_keep isl_pw_qpolynomial *pwqp)1988{1989 struct isl_print_space_data data = { 0 };1990 int i = 0;1991 1992 for (i = 0; i < pwqp->n; ++i) {1993 isl_space *space;1994 1995 if (i)1996 p = isl_printer_print_str(p, "; ");1997 space = isl_qpolynomial_get_domain_space(pwqp->p[i].qp);1998 if (!isl_space_is_params(space)) {1999 p = isl_print_space(space, p, 0, &data);2000 p = isl_printer_print_str(p, " -> ");2001 }2002 p = print_qpolynomial(p, pwqp->p[i].qp);2003 p = print_disjuncts(set_to_map(pwqp->p[i].set), space, p, 0);2004 isl_space_free(space);2005 }2006 2007 return p;2008}2009 2010static __isl_give isl_printer *print_pw_qpolynomial_isl(2011 __isl_take isl_printer *p, __isl_keep isl_pw_qpolynomial *pwqp)2012{2013 struct isl_print_space_data data = { 0 };2014 2015 if (!p || !pwqp)2016 goto error;2017 2018 p = print_param_tuple(p, pwqp->dim, &data);2019 p = isl_printer_print_str(p, "{ ");2020 if (pwqp->n == 0) {2021 if (!isl_space_is_set(pwqp->dim)) {2022 p = print_tuple(pwqp->dim, p, isl_dim_in, &data);2023 p = isl_printer_print_str(p, " -> ");2024 }2025 p = isl_printer_print_str(p, "0");2026 }2027 p = print_body_pw_qpolynomial(p, pwqp);2028 p = isl_printer_print_str(p, " }");2029 return p;2030error:2031 isl_printer_free(p);2032 return NULL;2033}2034 2035void isl_pw_qpolynomial_print(__isl_keep isl_pw_qpolynomial *pwqp, FILE *out,2036 unsigned output_format)2037{2038 isl_printer *p;2039 2040 if (!pwqp)2041 return;2042 2043 p = isl_printer_to_file(pwqp->dim->ctx, out);2044 p = isl_printer_set_output_format(p, output_format);2045 p = isl_printer_print_pw_qpolynomial(p, pwqp);2046 2047 isl_printer_free(p);2048}2049 2050static __isl_give isl_printer *print_body_pw_qpolynomial_fold(2051 __isl_take isl_printer *p, __isl_keep isl_pw_qpolynomial_fold *pwf)2052{2053 struct isl_print_space_data data = { 0 };2054 int i = 0;2055 2056 for (i = 0; i < pwf->n; ++i) {2057 isl_space *space;2058 2059 if (i)2060 p = isl_printer_print_str(p, "; ");2061 space = isl_qpolynomial_fold_get_domain_space(pwf->p[i].fold);2062 if (!isl_space_is_params(space)) {2063 p = isl_print_space(space, p, 0, &data);2064 p = isl_printer_print_str(p, " -> ");2065 }2066 p = qpolynomial_fold_print(pwf->p[i].fold, p);2067 p = print_disjuncts(set_to_map(pwf->p[i].set), space, p, 0);2068 isl_space_free(space);2069 }2070 2071 return p;2072}2073 2074static __isl_give isl_printer *print_pw_qpolynomial_fold_isl(2075 __isl_take isl_printer *p, __isl_keep isl_pw_qpolynomial_fold *pwf)2076{2077 struct isl_print_space_data data = { 0 };2078 2079 p = print_param_tuple(p, pwf->dim, &data);2080 p = isl_printer_print_str(p, "{ ");2081 if (pwf->n == 0) {2082 if (!isl_space_is_set(pwf->dim)) {2083 p = print_tuple(pwf->dim, p, isl_dim_in, &data);2084 p = isl_printer_print_str(p, " -> ");2085 }2086 p = isl_printer_print_str(p, "0");2087 }2088 p = print_body_pw_qpolynomial_fold(p, pwf);2089 p = isl_printer_print_str(p, " }");2090 return p;2091}2092 2093static __isl_give isl_printer *print_ls_affine_c(__isl_take isl_printer *p,2094 __isl_keep isl_local_space *ls, isl_int *c);2095 2096/* We skip the constraint if it is implied by the div expression.2097 *2098 * *first indicates whether this is the first constraint in the conjunction and2099 * is updated if the constraint is actually printed.2100 */2101static __isl_give isl_printer *print_constraint_c(__isl_take isl_printer *p,2102 __isl_keep isl_local_space *ls, isl_int *c, const char *op, int *first)2103{2104 unsigned o_div;2105 isl_size n_div;2106 int div;2107 2108 o_div = isl_local_space_offset(ls, isl_dim_div);2109 n_div = isl_local_space_dim(ls, isl_dim_div);2110 if (n_div < 0)2111 return isl_printer_free(p);2112 div = isl_seq_last_non_zero(c + o_div, n_div);2113 if (div >= 0) {2114 isl_bool is_div = isl_local_space_is_div_constraint(ls, c, div);2115 if (is_div < 0)2116 return isl_printer_free(p);2117 if (is_div)2118 return p;2119 }2120 2121 if (!*first)2122 p = isl_printer_print_str(p, " && ");2123 2124 p = print_ls_affine_c(p, ls, c);2125 p = isl_printer_print_str(p, " ");2126 p = isl_printer_print_str(p, op);2127 p = isl_printer_print_str(p, " 0");2128 2129 *first = 0;2130 2131 return p;2132}2133 2134static __isl_give isl_printer *print_ls_partial_affine_c(2135 __isl_take isl_printer *p, __isl_keep isl_local_space *ls,2136 isl_int *c, unsigned len);2137 2138static __isl_give isl_printer *print_basic_set_c(__isl_take isl_printer *p,2139 __isl_keep isl_space *space, __isl_keep isl_basic_set *bset)2140{2141 int i, j;2142 int first = 1;2143 isl_size n_div = isl_basic_set_dim(bset, isl_dim_div);2144 isl_size total = isl_basic_set_dim(bset, isl_dim_all);2145 isl_mat *div;2146 isl_local_space *ls;2147 2148 if (n_div < 0 || total < 0)2149 return isl_printer_free(p);2150 2151 total -= n_div;2152 div = isl_basic_set_get_divs(bset);2153 ls = isl_local_space_alloc_div(isl_space_copy(space), div);2154 for (i = 0; i < bset->n_eq; ++i) {2155 j = isl_seq_last_non_zero(bset->eq[i] + 1 + total, n_div);2156 if (j < 0)2157 p = print_constraint_c(p, ls,2158 bset->eq[i], "==", &first);2159 else {2160 if (i)2161 p = isl_printer_print_str(p, " && ");2162 p = isl_printer_print_str(p, "(");2163 p = print_ls_partial_affine_c(p, ls, bset->eq[i],2164 1 + total + j);2165 p = isl_printer_print_str(p, ") % ");2166 p = isl_printer_print_isl_int(p,2167 bset->eq[i][1 + total + j]);2168 p = isl_printer_print_str(p, " == 0");2169 first = 0;2170 }2171 }2172 for (i = 0; i < bset->n_ineq; ++i)2173 p = print_constraint_c(p, ls, bset->ineq[i], ">=", &first);2174 isl_local_space_free(ls);2175 return p;2176}2177 2178static __isl_give isl_printer *print_set_c(__isl_take isl_printer *p,2179 __isl_keep isl_space *space, __isl_keep isl_set *set)2180{2181 int i;2182 2183 if (!set)2184 return isl_printer_free(p);2185 2186 if (set->n == 0)2187 p = isl_printer_print_str(p, "0");2188 2189 for (i = 0; i < set->n; ++i) {2190 if (i)2191 p = isl_printer_print_str(p, " || ");2192 if (set->n > 1)2193 p = isl_printer_print_str(p, "(");2194 p = print_basic_set_c(p, space, set->p[i]);2195 if (set->n > 1)2196 p = isl_printer_print_str(p, ")");2197 }2198 return p;2199}2200 2201/* Print the piecewise quasi-polynomial "pwqp" to "p" in C format.2202 */2203static __isl_give isl_printer *print_pw_qpolynomial_c(2204 __isl_take isl_printer *p, __isl_keep isl_pw_qpolynomial *pwqp)2205{2206 int i;2207 isl_space *space;2208 2209 space = isl_pw_qpolynomial_get_domain_space(pwqp);2210 if (pwqp->n == 1 && isl_set_plain_is_universe(pwqp->p[0].set)) {2211 p = print_qpolynomial_c(p, space, pwqp->p[0].qp);2212 isl_space_free(space);2213 return p;2214 }2215 2216 for (i = 0; i < pwqp->n; ++i) {2217 p = isl_printer_print_str(p, "(");2218 p = print_set_c(p, space, pwqp->p[i].set);2219 p = isl_printer_print_str(p, ") ? (");2220 p = print_qpolynomial_c(p, space, pwqp->p[i].qp);2221 p = isl_printer_print_str(p, ") : ");2222 }2223 2224 isl_space_free(space);2225 p = isl_printer_print_str(p, "0");2226 return p;2227}2228 2229__isl_give isl_printer *isl_printer_print_pw_qpolynomial(2230 __isl_take isl_printer *p, __isl_keep isl_pw_qpolynomial *pwqp)2231{2232 if (!p || !pwqp)2233 goto error;2234 2235 if (p->output_format == ISL_FORMAT_ISL)2236 return print_pw_qpolynomial_isl(p, pwqp);2237 else if (p->output_format == ISL_FORMAT_C)2238 return print_pw_qpolynomial_c(p, pwqp);2239 isl_assert(p->ctx, 0, goto error);2240error:2241 isl_printer_free(p);2242 return NULL;2243}2244 2245#undef BASE2246#define BASE pw_qpolynomial2247#include "isl_union_print_templ.c"2248 2249__isl_give isl_printer *isl_printer_print_union_pw_qpolynomial(2250 __isl_take isl_printer *p, __isl_keep isl_union_pw_qpolynomial *upwqp)2251{2252 if (!p || !upwqp)2253 goto error;2254 2255 if (p->output_format == ISL_FORMAT_ISL)2256 return print_union_pw_qpolynomial_isl(p, upwqp);2257 isl_die(p->ctx, isl_error_invalid,2258 "invalid output format for isl_union_pw_qpolynomial",2259 goto error);2260error:2261 isl_printer_free(p);2262 return NULL;2263}2264 2265/* Print the quasi-polynomial reduction "fold" to "p" in C format,2266 * with the variable names taken from the domain space "space".2267 */2268static __isl_give isl_printer *print_qpolynomial_fold_c(2269 __isl_take isl_printer *p, __isl_keep isl_space *space,2270 __isl_keep isl_qpolynomial_fold *fold)2271{2272 int i;2273 isl_qpolynomial_list *list;2274 isl_size n;2275 2276 list = isl_qpolynomial_fold_peek_list(fold);2277 n = isl_qpolynomial_list_size(list);2278 if (n < 0)2279 return isl_printer_free(p);2280 for (i = 0; i < n - 1; ++i)2281 if (fold->type == isl_fold_min)2282 p = isl_printer_print_str(p, "min(");2283 else if (fold->type == isl_fold_max)2284 p = isl_printer_print_str(p, "max(");2285 2286 for (i = 0; i < n; ++i) {2287 isl_qpolynomial *qp;2288 2289 if (i)2290 p = isl_printer_print_str(p, ", ");2291 qp = isl_qpolynomial_list_peek(list, i);2292 p = print_qpolynomial_c(p, space, qp);2293 if (i)2294 p = isl_printer_print_str(p, ")");2295 }2296 return p;2297}2298 2299__isl_give isl_printer *isl_printer_print_qpolynomial_fold(2300 __isl_take isl_printer *p, __isl_keep isl_qpolynomial_fold *fold)2301{2302 if (!p || !fold)2303 goto error;2304 if (p->output_format == ISL_FORMAT_ISL)2305 return qpolynomial_fold_print(fold, p);2306 else if (p->output_format == ISL_FORMAT_C)2307 return print_qpolynomial_fold_c(p, fold->dim, fold);2308 isl_die(p->ctx, isl_error_unsupported, "unsupported output format",2309 goto error);2310error:2311 isl_printer_free(p);2312 return NULL;2313}2314 2315/* Print the piecewise quasi-polynomial reduction "pwf" to "p" in C format.2316 */2317static __isl_give isl_printer *print_pw_qpolynomial_fold_c(2318 __isl_take isl_printer *p, __isl_keep isl_pw_qpolynomial_fold *pwf)2319{2320 int i;2321 isl_space *space;2322 2323 space = isl_pw_qpolynomial_fold_get_domain_space(pwf);2324 if (pwf->n == 1 && isl_set_plain_is_universe(pwf->p[0].set)) {2325 p = print_qpolynomial_fold_c(p, space, pwf->p[0].fold);2326 isl_space_free(space);2327 return p;2328 }2329 2330 for (i = 0; i < pwf->n; ++i) {2331 p = isl_printer_print_str(p, "(");2332 p = print_set_c(p, space, pwf->p[i].set);2333 p = isl_printer_print_str(p, ") ? (");2334 p = print_qpolynomial_fold_c(p, space, pwf->p[i].fold);2335 p = isl_printer_print_str(p, ") : ");2336 }2337 2338 isl_space_free(space);2339 p = isl_printer_print_str(p, "0");2340 return p;2341}2342 2343__isl_give isl_printer *isl_printer_print_pw_qpolynomial_fold(2344 __isl_take isl_printer *p, __isl_keep isl_pw_qpolynomial_fold *pwf)2345{2346 if (!p || !pwf)2347 goto error;2348 2349 if (p->output_format == ISL_FORMAT_ISL)2350 return print_pw_qpolynomial_fold_isl(p, pwf);2351 else if (p->output_format == ISL_FORMAT_C)2352 return print_pw_qpolynomial_fold_c(p, pwf);2353 isl_assert(p->ctx, 0, goto error);2354error:2355 isl_printer_free(p);2356 return NULL;2357}2358 2359void isl_pw_qpolynomial_fold_print(__isl_keep isl_pw_qpolynomial_fold *pwf,2360 FILE *out, unsigned output_format)2361{2362 isl_printer *p;2363 2364 if (!pwf)2365 return;2366 2367 p = isl_printer_to_file(pwf->dim->ctx, out);2368 p = isl_printer_set_output_format(p, output_format);2369 p = isl_printer_print_pw_qpolynomial_fold(p, pwf);2370 2371 isl_printer_free(p);2372}2373 2374#undef BASE2375#define BASE pw_qpolynomial_fold2376#include "isl_union_print_templ.c"2377 2378__isl_give isl_printer *isl_printer_print_union_pw_qpolynomial_fold(2379 __isl_take isl_printer *p,2380 __isl_keep isl_union_pw_qpolynomial_fold *upwf)2381{2382 if (!p || !upwf)2383 goto error;2384 2385 if (p->output_format == ISL_FORMAT_ISL)2386 return print_union_pw_qpolynomial_fold_isl(p, upwf);2387 isl_die(p->ctx, isl_error_invalid,2388 "invalid output format for isl_union_pw_qpolynomial_fold",2389 goto error);2390error:2391 isl_printer_free(p);2392 return NULL;2393}2394 2395/* Print the isl_constraint "c" to "p".2396 */2397__isl_give isl_printer *isl_printer_print_constraint(__isl_take isl_printer *p,2398 __isl_keep isl_constraint *c)2399{2400 struct isl_print_space_data data = { 0 };2401 isl_local_space *ls;2402 isl_space *space;2403 isl_bool exists;2404 2405 if (!p || !c)2406 goto error;2407 2408 ls = isl_constraint_get_local_space(c);2409 if (!ls)2410 return isl_printer_free(p);2411 space = isl_local_space_get_space(ls);2412 p = print_param_tuple(p, space, &data);2413 p = isl_printer_print_str(p, "{ ");2414 p = isl_print_space(space, p, 0, &data);2415 p = isl_printer_print_str(p, " : ");2416 exists = need_exists(p, ls->div);2417 if (exists < 0)2418 p = isl_printer_free(p);2419 if (exists >= 0 && exists)2420 p = open_exists(p, space, ls->div, 0);2421 p = print_affine_of_len(space, ls->div, p, c->v->el, c->v->size);2422 if (isl_constraint_is_equality(c))2423 p = isl_printer_print_str(p, " = 0");2424 else2425 p = isl_printer_print_str(p, " >= 0");2426 if (exists >= 0 && exists)2427 p = isl_printer_print_str(p, s_close_exists[0]);2428 p = isl_printer_print_str(p, " }");2429 isl_space_free(space);2430 isl_local_space_free(ls);2431 2432 return p;2433error:2434 isl_printer_free(p);2435 return NULL;2436}2437 2438static __isl_give isl_printer *isl_printer_print_space_isl(2439 __isl_take isl_printer *p, __isl_keep isl_space *space)2440{2441 struct isl_print_space_data data = { 0 };2442 2443 if (!space)2444 goto error;2445 2446 p = print_param_tuple(p, space, &data);2447 2448 p = isl_printer_print_str(p, "{ ");2449 if (isl_space_is_params(space))2450 p = isl_printer_print_str(p, s_such_that[0]);2451 else2452 p = isl_print_space(space, p, 0, &data);2453 p = isl_printer_print_str(p, " }");2454 2455 return p;2456error:2457 isl_printer_free(p);2458 return NULL;2459}2460 2461__isl_give isl_printer *isl_printer_print_space(__isl_take isl_printer *p,2462 __isl_keep isl_space *space)2463{2464 if (!p || !space)2465 return isl_printer_free(p);2466 if (p->output_format == ISL_FORMAT_ISL)2467 return isl_printer_print_space_isl(p, space);2468 else if (p->output_format == ISL_FORMAT_OMEGA)2469 return print_omega_parameters(space, p);2470 2471 isl_die(isl_space_get_ctx(space), isl_error_unsupported,2472 "output format not supported for space",2473 return isl_printer_free(p));2474}2475 2476__isl_give isl_printer *isl_printer_print_local_space(__isl_take isl_printer *p,2477 __isl_keep isl_local_space *ls)2478{2479 struct isl_print_space_data data = { 0 };2480 isl_size n_div;2481 2482 n_div = isl_local_space_dim(ls, isl_dim_div);2483 if (n_div < 0)2484 goto error;2485 2486 p = print_param_tuple(p, ls->dim, &data);2487 p = isl_printer_print_str(p, "{ ");2488 p = isl_print_space(ls->dim, p, 0, &data);2489 if (n_div > 0) {2490 p = isl_printer_print_str(p, " : ");2491 p = isl_printer_print_str(p, s_open_exists[0]);2492 p = print_div_list(p, ls->dim, ls->div, 0, 1);2493 p = isl_printer_print_str(p, s_close_exists[0]);2494 } else if (isl_space_is_params(ls->dim))2495 p = isl_printer_print_str(p, s_such_that[0]);2496 p = isl_printer_print_str(p, " }");2497 return p;2498error:2499 isl_printer_free(p);2500 return NULL;2501}2502 2503/* Look for the last of the "n" integer divisions that is used in "aff" and2504 * that can be printed as a modulo and2505 * return the position of this integer division.2506 * Return "n" if no such integer division can be found.2507 * Return isl_size_error on error.2508 *2509 * In particular, look for an integer division that appears in "aff"2510 * with a coefficient that is a multiple of the denominator2511 * of the integer division.2512 * That is, check if the numerator of "aff" is of the form2513 *2514 * f(...) + a m floor(g/m)2515 *2516 * and return the position of "floor(g/m)".2517 *2518 * Note that, unlike print_as_modulo_pos, no check needs to be made2519 * for whether the integer division can be printed, since it will2520 * need to be printed as an integer division anyway if it is not printed2521 * as a modulo.2522 */2523static isl_size last_modulo(__isl_keep isl_printer *p, __isl_keep isl_aff *aff,2524 unsigned n)2525{2526 isl_size o_div;2527 int i;2528 2529 if (n == 0)2530 return n;2531 o_div = isl_aff_domain_offset(aff, isl_dim_div);2532 if (o_div < 0)2533 return isl_size_error;2534 for (i = n - 1; i >= 0; --i) {2535 if (isl_int_is_zero(aff->v->el[1 + o_div + i]))2536 continue;2537 if (isl_int_is_divisible_by(aff->v->el[1 + o_div + i],2538 aff->ls->div->row[i][0]))2539 return i;2540 }2541 2542 return n;2543}2544 2545/* Print the numerator of the affine expression "aff" to "p",2546 * with the variable names taken from "space".2547 */2548static __isl_give isl_printer *print_aff_num_base(__isl_take isl_printer *p,2549 __isl_keep isl_space *space, __isl_keep isl_aff *aff)2550{2551 isl_size total;2552 2553 total = isl_aff_domain_dim(aff, isl_dim_all);2554 if (total < 0)2555 return isl_printer_free(p);2556 p = print_affine_of_len(space, aff->ls->div, p,2557 aff->v->el + 1, 1 + total);2558 2559 return p;2560}2561 2562static __isl_give isl_printer *print_aff_num(__isl_take isl_printer *p,2563 __isl_keep isl_space *space, __isl_keep isl_aff *aff);2564 2565/* Print the modulo term "c" * ("aff" mod "mod") to "p",2566 * with the variable names taken from "space".2567 * If "first" is set, then this is the first term of an expression.2568 */2569static __isl_give isl_printer *print_mod_term(__isl_take isl_printer *p,2570 __isl_keep isl_space *space, __isl_keep isl_aff *aff, int first,2571 __isl_take isl_val *c, __isl_keep isl_val *mod)2572{2573 isl_bool is_one, is_neg;2574 2575 is_neg = isl_val_is_neg(c);2576 if (is_neg < 0)2577 p = isl_printer_free(p);2578 if (!first) {2579 if (is_neg)2580 c = isl_val_neg(c);2581 p = isl_printer_print_str(p, is_neg ? " - " : " + ");2582 }2583 is_one = isl_val_is_one(c);2584 if (is_one < 0)2585 p = isl_printer_free(p);2586 if (!is_one) {2587 p = isl_printer_print_val(p, c);2588 p = isl_printer_print_str(p, "*(");2589 }2590 p = isl_printer_print_str(p, "(");2591 p = print_aff_num(p, space, aff);2592 p = isl_printer_print_str(p, ")");2593 p = isl_printer_print_str(p, " mod ");2594 p = isl_printer_print_val(p, mod);2595 if (!is_one)2596 p = isl_printer_print_str(p, ")");2597 2598 isl_val_free(c);2599 2600 return p;2601}2602 2603/* Print the numerator of the affine expression "aff" to "p",2604 * with the variable names taken from "space",2605 * given that the numerator of "aff" is of the form2606 *2607 * f(...) + a m floor(g/m)2608 *2609 * with "floor(g/m)" the integer division at position "last".2610 *2611 * First replace "aff" by its numerator and rewrite it as2612 *2613 * f(...) + a g - a (g mod m)2614 *2615 * Recursively write out (the numerator of) "f(...) + a g"2616 * (which may involve other modulo expressions) and2617 * then write out "- a (g mod m)".2618 */2619static __isl_give isl_printer *print_aff_num_mod(__isl_take isl_printer *p,2620 __isl_keep isl_space *space, __isl_keep isl_aff *aff, unsigned last)2621{2622 isl_bool is_zero;2623 isl_val *a, *m;2624 isl_aff *div, *term;2625 2626 aff = isl_aff_copy(aff);2627 aff = isl_aff_scale_val(aff, isl_aff_get_denominator_val(aff));2628 a = isl_aff_get_coefficient_val(aff, isl_dim_div, last);2629 aff = isl_aff_set_coefficient_si(aff, isl_dim_div, last, 0);2630 div = isl_aff_get_div(aff, last);2631 m = isl_aff_get_denominator_val(div);2632 a = isl_val_div(a, isl_val_copy(m));2633 div = isl_aff_scale_val(div, isl_val_copy(m));2634 term = isl_aff_scale_val(isl_aff_copy(div), isl_val_copy(a));2635 aff = isl_aff_add(aff, term);2636 2637 is_zero = isl_aff_plain_is_zero(aff);2638 if (is_zero < 0) {2639 p = isl_printer_free(p);2640 } else {2641 if (!is_zero)2642 p = print_aff_num(p, space, aff);2643 a = isl_val_neg(a);2644 p = print_mod_term(p, space, div, is_zero, isl_val_copy(a), m);2645 }2646 2647 isl_val_free(a);2648 isl_val_free(m);2649 isl_aff_free(aff);2650 isl_aff_free(div);2651 2652 return p;2653}2654 2655/* Print the numerator of the affine expression "aff" to "p",2656 * with the variable names taken from "space",2657 * separating out any (obvious) modulo expressions.2658 *2659 * In particular, look for modulo expressions in "aff",2660 * separating them out if found and simply printing out "aff" otherwise.2661 */2662static __isl_give isl_printer *print_aff_num(__isl_take isl_printer *p,2663 __isl_keep isl_space *space, __isl_keep isl_aff *aff)2664{2665 isl_size n_div, mod;2666 2667 n_div = isl_aff_dim(aff, isl_dim_div);2668 if (n_div < 0)2669 return isl_printer_free(p);2670 mod = last_modulo(p, aff, n_div);2671 if (mod < 0)2672 return isl_printer_free(p);2673 if (mod < n_div)2674 return print_aff_num_mod(p, space, aff, mod);2675 else2676 return print_aff_num_base(p, space, aff);2677}2678 2679/* Print the (potentially rational) affine expression "aff" to "p",2680 * with the variable names taken from "space".2681 */2682static __isl_give isl_printer *print_aff_body(__isl_take isl_printer *p,2683 __isl_keep isl_space *space, __isl_keep isl_aff *aff)2684{2685 if (isl_aff_is_nan(aff))2686 return isl_printer_print_str(p, "NaN");2687 2688 p = isl_printer_print_str(p, "(");2689 p = print_aff_num(p, space, aff);2690 if (isl_int_is_one(aff->v->el[0]))2691 p = isl_printer_print_str(p, ")");2692 else {2693 p = isl_printer_print_str(p, ")/");2694 p = isl_printer_print_isl_int(p, aff->v->el[0]);2695 }2696 2697 return p;2698}2699 2700static __isl_give isl_printer *print_body_aff(__isl_take isl_printer *p,2701 __isl_keep isl_aff *aff)2702{2703 struct isl_print_space_data data = { 0 };2704 2705 if (isl_space_is_params(aff->ls->dim))2706 ;2707 else {2708 p = print_tuple(aff->ls->dim, p, isl_dim_set, &data);2709 p = isl_printer_print_str(p, " -> ");2710 }2711 p = isl_printer_print_str(p, "[");2712 p = print_aff_body(p, aff->ls->dim, aff);2713 p = isl_printer_print_str(p, "]");2714 2715 return p;2716}2717 2718static __isl_give isl_printer *print_aff_isl(__isl_take isl_printer *p,2719 __isl_keep isl_aff *aff)2720{2721 struct isl_print_space_data data = { 0 };2722 2723 if (!aff)2724 goto error;2725 2726 p = print_param_tuple(p, aff->ls->dim, &data);2727 p = isl_printer_print_str(p, "{ ");2728 p = print_body_aff(p, aff);2729 p = isl_printer_print_str(p, " }");2730 return p;2731error:2732 isl_printer_free(p);2733 return NULL;2734}2735 2736#undef BASE2737#define BASE aff2738#include "isl_pw_print_templ.c"2739 2740static __isl_give isl_printer *print_ls_name_c(__isl_take isl_printer *p,2741 __isl_keep isl_local_space *ls, enum isl_dim_type type, unsigned pos)2742{2743 if (type == isl_dim_div) {2744 p = isl_printer_print_str(p, "floord(");2745 p = print_ls_affine_c(p, ls, ls->div->row[pos] + 1);2746 p = isl_printer_print_str(p, ", ");2747 p = isl_printer_print_isl_int(p, ls->div->row[pos][0]);2748 p = isl_printer_print_str(p, ")");2749 } else {2750 const char *name;2751 2752 name = isl_space_get_dim_name(ls->dim, type, pos);2753 if (!name)2754 name = "UNNAMED";2755 p = isl_printer_print_str(p, name);2756 }2757 return p;2758}2759 2760static __isl_give isl_printer *print_ls_term_c(__isl_take isl_printer *p,2761 __isl_keep isl_local_space *ls, isl_int c, unsigned pos)2762{2763 enum isl_dim_type type;2764 2765 if (!p || !ls)2766 return isl_printer_free(p);2767 2768 if (pos == 0)2769 return isl_printer_print_isl_int(p, c);2770 2771 if (isl_int_is_one(c))2772 ;2773 else if (isl_int_is_negone(c))2774 p = isl_printer_print_str(p, "-");2775 else {2776 p = isl_printer_print_isl_int(p, c);2777 p = isl_printer_print_str(p, "*");2778 }2779 if (pos2type(ls->dim, &type, &pos) < 0)2780 return isl_printer_free(p);2781 p = print_ls_name_c(p, ls, type, pos);2782 return p;2783}2784 2785static __isl_give isl_printer *print_ls_partial_affine_c(2786 __isl_take isl_printer *p, __isl_keep isl_local_space *ls,2787 isl_int *c, unsigned len)2788{2789 int i;2790 int first;2791 2792 for (i = 0, first = 1; i < len; ++i) {2793 int flip = 0;2794 if (isl_int_is_zero(c[i]))2795 continue;2796 if (!first) {2797 if (isl_int_is_neg(c[i])) {2798 flip = 1;2799 isl_int_neg(c[i], c[i]);2800 p = isl_printer_print_str(p, " - ");2801 } else 2802 p = isl_printer_print_str(p, " + ");2803 }2804 first = 0;2805 p = print_ls_term_c(p, ls, c[i], i);2806 if (flip)2807 isl_int_neg(c[i], c[i]);2808 }2809 if (first)2810 p = isl_printer_print_str(p, "0");2811 return p;2812}2813 2814static __isl_give isl_printer *print_ls_affine_c(__isl_take isl_printer *p,2815 __isl_keep isl_local_space *ls, isl_int *c)2816{2817 isl_size total = isl_local_space_dim(ls, isl_dim_all);2818 2819 if (total < 0)2820 return isl_printer_free(p);2821 return print_ls_partial_affine_c(p, ls, c, 1 + total);2822}2823 2824static __isl_give isl_printer *print_aff_c(__isl_take isl_printer *p,2825 __isl_keep isl_aff *aff)2826{2827 isl_size total;2828 2829 total = isl_aff_domain_dim(aff, isl_dim_all);2830 if (total < 0)2831 return isl_printer_free(p);2832 if (!isl_int_is_one(aff->v->el[0]))2833 p = isl_printer_print_str(p, "(");2834 p = print_ls_partial_affine_c(p, aff->ls, aff->v->el + 1, 1 + total);2835 if (!isl_int_is_one(aff->v->el[0])) {2836 p = isl_printer_print_str(p, ")/");2837 p = isl_printer_print_isl_int(p, aff->v->el[0]);2838 }2839 return p;2840}2841 2842/* In the C format, we cannot express that "pwaff" may be undefined2843 * on parts of the domain space. We therefore assume that the expression2844 * will only be evaluated on its definition domain and compute the gist2845 * of each cell with respect to this domain.2846 */2847static __isl_give isl_printer *print_pw_aff_c(__isl_take isl_printer *p,2848 __isl_keep isl_pw_aff *pwaff)2849{2850 isl_set *domain;2851 isl_ast_build *build;2852 isl_ast_expr *expr;2853 2854 if (pwaff->n < 1)2855 isl_die(p->ctx, isl_error_unsupported,2856 "cannot print empty isl_pw_aff in C format",2857 return isl_printer_free(p));2858 2859 domain = isl_pw_aff_domain(isl_pw_aff_copy(pwaff));2860 build = isl_ast_build_from_context(domain);2861 expr = isl_ast_build_expr_from_pw_aff(build, isl_pw_aff_copy(pwaff));2862 p = isl_printer_print_ast_expr(p, expr);2863 isl_ast_expr_free(expr);2864 isl_ast_build_free(build);2865 2866 return p;2867}2868 2869__isl_give isl_printer *isl_printer_print_aff(__isl_take isl_printer *p,2870 __isl_keep isl_aff *aff)2871{2872 if (!p || !aff)2873 goto error;2874 2875 if (p->output_format == ISL_FORMAT_ISL)2876 return print_aff_isl(p, aff);2877 else if (p->output_format == ISL_FORMAT_C)2878 return print_aff_c(p, aff);2879 isl_die(p->ctx, isl_error_unsupported, "unsupported output format",2880 goto error);2881error:2882 isl_printer_free(p);2883 return NULL;2884}2885 2886__isl_give isl_printer *isl_printer_print_pw_aff(__isl_take isl_printer *p,2887 __isl_keep isl_pw_aff *pwaff)2888{2889 if (!p || !pwaff)2890 goto error;2891 2892 if (p->output_format == ISL_FORMAT_ISL)2893 return print_pw_aff_isl(p, pwaff);2894 else if (p->output_format == ISL_FORMAT_C)2895 return print_pw_aff_c(p, pwaff);2896 isl_die(p->ctx, isl_error_unsupported, "unsupported output format",2897 goto error);2898error:2899 isl_printer_free(p);2900 return NULL;2901}2902 2903#undef BASE2904#define BASE pw_aff2905#include "isl_union_print_templ.c"2906 2907/* Print the isl_union_pw_aff "upa" to "p".2908 *2909 * We currently only support an isl format.2910 */2911__isl_give isl_printer *isl_printer_print_union_pw_aff(2912 __isl_take isl_printer *p, __isl_keep isl_union_pw_aff *upa)2913{2914 if (!p || !upa)2915 return isl_printer_free(p);2916 2917 if (p->output_format == ISL_FORMAT_ISL)2918 return print_union_pw_aff_isl(p, upa);2919 isl_die(isl_printer_get_ctx(p), isl_error_unsupported,2920 "unsupported output format", return isl_printer_free(p));2921}2922 2923/* Print dimension "pos" of data->space to "p".2924 *2925 * data->user is assumed to be an isl_multi_aff.2926 *2927 * If the current dimension is an output dimension, then print2928 * the corresponding expression. Otherwise, print the name of the dimension.2929 * Make sure to use the domain space for printing names as2930 * that is the space that will be used for printing constraints (if any).2931 */2932static __isl_give isl_printer *print_dim_ma(__isl_take isl_printer *p,2933 struct isl_print_space_data *data, unsigned pos)2934{2935 isl_multi_aff *ma = data->user;2936 isl_space *space;2937 2938 space = isl_multi_aff_get_domain_space(ma);2939 if (data->type == isl_dim_out) {2940 p = print_aff_body(p, space, ma->u.p[pos]);2941 } else {2942 enum isl_dim_type type = data->type;2943 2944 if (type == isl_dim_in)2945 type = isl_dim_set;2946 p = print_name(space, p, type, pos, data->latex);2947 }2948 isl_space_free(space);2949 2950 return p;2951}2952 2953static __isl_give isl_printer *print_body_multi_aff(__isl_take isl_printer *p,2954 __isl_keep isl_multi_aff *maff)2955{2956 struct isl_print_space_data data = { 0 };2957 2958 data.print_dim = &print_dim_ma;2959 data.user = maff;2960 return isl_print_space(maff->space, p, 0, &data);2961}2962 2963static __isl_give isl_printer *print_multi_aff_isl(__isl_take isl_printer *p,2964 __isl_keep isl_multi_aff *maff)2965{2966 struct isl_print_space_data data = { 0 };2967 2968 if (!maff)2969 goto error;2970 2971 p = print_param_tuple(p, maff->space, &data);2972 p = isl_printer_print_str(p, "{ ");2973 p = print_body_multi_aff(p, maff);2974 p = isl_printer_print_str(p, " }");2975 return p;2976error:2977 isl_printer_free(p);2978 return NULL;2979}2980 2981__isl_give isl_printer *isl_printer_print_multi_aff(__isl_take isl_printer *p,2982 __isl_keep isl_multi_aff *maff)2983{2984 if (!p || !maff)2985 goto error;2986 2987 if (p->output_format == ISL_FORMAT_ISL)2988 return print_multi_aff_isl(p, maff);2989 isl_die(p->ctx, isl_error_unsupported, "unsupported output format",2990 goto error);2991error:2992 isl_printer_free(p);2993 return NULL;2994}2995 2996#undef BASE2997#define BASE multi_aff2998#include "isl_pw_print_templ.c"2999 3000/* Print the unnamed, single-dimensional piecewise multi affine expression "pma"3001 * to "p".3002 */3003static __isl_give isl_printer *print_unnamed_pw_multi_aff_c(3004 __isl_take isl_printer *p, __isl_keep isl_pw_multi_aff *pma)3005{3006 int i;3007 isl_space *space;3008 3009 space = isl_pw_multi_aff_get_domain_space(pma);3010 for (i = 0; i < pma->n - 1; ++i) {3011 p = isl_printer_print_str(p, "(");3012 p = print_set_c(p, space, pma->p[i].set);3013 p = isl_printer_print_str(p, ") ? (");3014 p = print_aff_c(p, pma->p[i].maff->u.p[0]);3015 p = isl_printer_print_str(p, ") : ");3016 }3017 isl_space_free(space);3018 3019 return print_aff_c(p, pma->p[pma->n - 1].maff->u.p[0]);3020}3021 3022static __isl_give isl_printer *print_pw_multi_aff_c(__isl_take isl_printer *p,3023 __isl_keep isl_pw_multi_aff *pma)3024{3025 isl_size n;3026 const char *name;3027 3028 if (!pma)3029 goto error;3030 if (pma->n < 1)3031 isl_die(p->ctx, isl_error_unsupported,3032 "cannot print empty isl_pw_multi_aff in C format",3033 goto error);3034 n = isl_pw_multi_aff_dim(pma, isl_dim_out);3035 if (n < 0)3036 return isl_printer_free(p);3037 name = isl_pw_multi_aff_get_tuple_name(pma, isl_dim_out);3038 if (!name && n == 1)3039 return print_unnamed_pw_multi_aff_c(p, pma);3040 if (!name)3041 isl_die(p->ctx, isl_error_unsupported,3042 "cannot print unnamed isl_pw_multi_aff in C format",3043 goto error);3044 3045 p = isl_printer_print_str(p, name);3046 if (n != 0)3047 isl_die(p->ctx, isl_error_unsupported,3048 "not supported yet", goto error);3049 3050 return p;3051error:3052 isl_printer_free(p);3053 return NULL;3054}3055 3056__isl_give isl_printer *isl_printer_print_pw_multi_aff(3057 __isl_take isl_printer *p, __isl_keep isl_pw_multi_aff *pma)3058{3059 if (!p || !pma)3060 goto error;3061 3062 if (p->output_format == ISL_FORMAT_ISL)3063 return print_pw_multi_aff_isl(p, pma);3064 if (p->output_format == ISL_FORMAT_C)3065 return print_pw_multi_aff_c(p, pma);3066 isl_die(p->ctx, isl_error_unsupported, "unsupported output format",3067 goto error);3068error:3069 isl_printer_free(p);3070 return NULL;3071}3072 3073#undef BASE3074#define BASE pw_multi_aff3075#include "isl_union_print_templ.c"3076 3077__isl_give isl_printer *isl_printer_print_union_pw_multi_aff(3078 __isl_take isl_printer *p, __isl_keep isl_union_pw_multi_aff *upma)3079{3080 if (!p || !upma)3081 goto error;3082 3083 if (p->output_format == ISL_FORMAT_ISL)3084 return print_union_pw_multi_aff_isl(p, upma);3085 isl_die(p->ctx, isl_error_unsupported, "unsupported output format",3086 goto error);3087error:3088 isl_printer_free(p);3089 return NULL;3090}3091 3092/* Print dimension "pos" of data->space to "p".3093 *3094 * data->user is assumed to be an isl_multi_pw_aff.3095 *3096 * If the current dimension is an output dimension, then print3097 * the corresponding piecewise affine expression.3098 * Otherwise, print the name of the dimension.3099 * Make sure to use the same space in both cases.3100 * In particular, use the domain space for printing names as3101 * that is the space that is used for printing constraints.3102 */3103static __isl_give isl_printer *print_dim_mpa(__isl_take isl_printer *p,3104 struct isl_print_space_data *data, unsigned pos)3105{3106 int i;3107 int need_parens;3108 isl_space *space;3109 isl_multi_pw_aff *mpa = data->user;3110 isl_pw_aff *pa;3111 3112 if (data->type != isl_dim_out) {3113 enum isl_dim_type type = data->type;3114 3115 if (type == isl_dim_in)3116 type = isl_dim_set;3117 space = isl_multi_pw_aff_get_domain_space(mpa);3118 p = print_name(space, p, type, pos, data->latex);3119 isl_space_free(space);3120 return p;3121 }3122 3123 pa = mpa->u.p[pos];3124 if (pa->n == 0)3125 return isl_printer_print_str(p, "(0 : false)");3126 3127 need_parens = pa->n != 1 || !isl_set_plain_is_universe(pa->p[0].set);3128 if (need_parens)3129 p = isl_printer_print_str(p, "(");3130 space = isl_multi_pw_aff_get_domain_space(mpa);3131 for (i = 0; i < pa->n; ++i) {3132 3133 if (i)3134 p = isl_printer_print_str(p, "; ");3135 p = print_aff_body(p, space, pa->p[i].aff);3136 p = print_disjuncts(pa->p[i].set, space, p, 0);3137 }3138 isl_space_free(space);3139 if (need_parens)3140 p = isl_printer_print_str(p, ")");3141 3142 return p;3143}3144 3145/* Print "mpa" to "p" in isl format.3146 *3147 * If "mpa" is zero-dimensional and has a non-trivial explicit domain,3148 * then it is printed after the tuple of affine expressions.3149 */3150static __isl_give isl_printer *print_multi_pw_aff_isl(__isl_take isl_printer *p,3151 __isl_keep isl_multi_pw_aff *mpa)3152{3153 struct isl_print_space_data data = { 0 };3154 isl_bool has_domain;3155 3156 if (!mpa)3157 return isl_printer_free(p);3158 3159 p = print_param_tuple(p, mpa->space, &data);3160 p = isl_printer_print_str(p, "{ ");3161 data.print_dim = &print_dim_mpa;3162 data.user = mpa;3163 p = isl_print_space(mpa->space, p, 0, &data);3164 has_domain = isl_multi_pw_aff_has_non_trivial_domain(mpa);3165 if (has_domain < 0)3166 return isl_printer_free(p);3167 if (has_domain) {3168 isl_space *space;3169 3170 space = isl_space_domain(isl_space_copy(mpa->space));3171 p = print_disjuncts_set(mpa->u.dom, space, p, 0);3172 isl_space_free(space);3173 }3174 p = isl_printer_print_str(p, " }");3175 return p;3176}3177 3178__isl_give isl_printer *isl_printer_print_multi_pw_aff(3179 __isl_take isl_printer *p, __isl_keep isl_multi_pw_aff *mpa)3180{3181 if (!p || !mpa)3182 return isl_printer_free(p);3183 3184 if (p->output_format == ISL_FORMAT_ISL)3185 return print_multi_pw_aff_isl(p, mpa);3186 isl_die(p->ctx, isl_error_unsupported, "unsupported output format",3187 return isl_printer_free(p));3188}3189 3190/* Print dimension "pos" of data->space to "p".3191 *3192 * data->user is assumed to be an isl_multi_val.3193 *3194 * If the current dimension is an output dimension, then print3195 * the corresponding value. Otherwise, print the name of the dimension.3196 */3197static __isl_give isl_printer *print_dim_mv(__isl_take isl_printer *p,3198 struct isl_print_space_data *data, unsigned pos)3199{3200 isl_multi_val *mv = data->user;3201 3202 if (data->type == isl_dim_out)3203 return isl_printer_print_val(p, mv->u.p[pos]);3204 else3205 return print_name(data->space, p, data->type, pos, data->latex);3206}3207 3208/* Print the isl_multi_val "mv" to "p" in isl format.3209 */3210static __isl_give isl_printer *print_multi_val_isl(__isl_take isl_printer *p,3211 __isl_keep isl_multi_val *mv)3212{3213 struct isl_print_space_data data = { 0 };3214 3215 if (!mv)3216 return isl_printer_free(p);3217 3218 p = print_param_tuple(p, mv->space, &data);3219 p = isl_printer_print_str(p, "{ ");3220 data.print_dim = &print_dim_mv;3221 data.user = mv;3222 p = isl_print_space(mv->space, p, 0, &data);3223 p = isl_printer_print_str(p, " }");3224 return p;3225}3226 3227/* Print the isl_multi_val "mv" to "p".3228 *3229 * Currently only supported in isl format.3230 */3231__isl_give isl_printer *isl_printer_print_multi_val(3232 __isl_take isl_printer *p, __isl_keep isl_multi_val *mv)3233{3234 if (!p || !mv)3235 return isl_printer_free(p);3236 3237 if (p->output_format == ISL_FORMAT_ISL)3238 return print_multi_val_isl(p, mv);3239 isl_die(p->ctx, isl_error_unsupported, "unsupported output format",3240 return isl_printer_free(p));3241}3242 3243/* Print dimension "pos" of data->space to "p".3244 *3245 * data->user is assumed to be an isl_multi_id.3246 *3247 * If the current dimension is an output dimension, then print3248 * the corresponding identifier. Otherwise, print the name of the dimension.3249 */3250static __isl_give isl_printer *print_dim_mi(__isl_take isl_printer *p,3251 struct isl_print_space_data *data, unsigned pos)3252{3253 isl_multi_id *mi = data->user;3254 3255 if (data->type == isl_dim_out)3256 return isl_printer_print_id(p, mi->u.p[pos]);3257 else3258 return print_name(data->space, p, data->type, pos, data->latex);3259}3260 3261/* Print the isl_multi_id "mi" to "p" in isl format.3262 */3263static __isl_give isl_printer *print_multi_id_isl(__isl_take isl_printer *p,3264 __isl_keep isl_multi_id *mi)3265{3266 isl_space *space;3267 struct isl_print_space_data data = { 0 };3268 3269 space = isl_multi_id_peek_space(mi);3270 p = print_param_tuple(p, space, &data);3271 p = isl_printer_print_str(p, "{ ");3272 data.print_dim = &print_dim_mi;3273 data.user = mi;3274 p = isl_print_space(space, p, 0, &data);3275 p = isl_printer_print_str(p, " }");3276 return p;3277}3278 3279/* Print the isl_multi_id "mi" to "p".3280 *3281 * Currently only supported in isl format.3282 */3283__isl_give isl_printer *isl_printer_print_multi_id(3284 __isl_take isl_printer *p, __isl_keep isl_multi_id *mi)3285{3286 if (!p || !mi)3287 return isl_printer_free(p);3288 3289 if (p->output_format == ISL_FORMAT_ISL)3290 return print_multi_id_isl(p, mi);3291 isl_die(isl_printer_get_ctx(p), isl_error_unsupported,3292 "unsupported output format", return isl_printer_free(p));3293}3294 3295/* Print dimension "pos" of data->space to "p".3296 *3297 * data->user is assumed to be an isl_multi_union_pw_aff.3298 *3299 * The current dimension is necessarily a set dimension, so3300 * we print the corresponding isl_union_pw_aff, including3301 * the braces.3302 */3303static __isl_give isl_printer *print_union_pw_aff_dim(__isl_take isl_printer *p,3304 struct isl_print_space_data *data, unsigned pos)3305{3306 isl_multi_union_pw_aff *mupa = data->user;3307 isl_union_pw_aff *upa;3308 3309 upa = isl_multi_union_pw_aff_get_union_pw_aff(mupa, pos);3310 p = print_body_union_pw_aff(p, upa);3311 isl_union_pw_aff_free(upa);3312 3313 return p;3314}3315 3316/* Print the isl_multi_union_pw_aff "mupa" to "p" in isl format.3317 *3318 * If "mupa" is zero-dimensional and has a non-trivial explicit domain,3319 * then it is printed after the tuple of affine expressions.3320 * In order to clarify that this domain belongs to the expression,3321 * the tuple along with the domain are placed inside parentheses.3322 * If "mupa" has any parameters, then the opening parenthesis3323 * appears after the parameter declarations.3324 */3325static __isl_give isl_printer *print_multi_union_pw_aff_isl(3326 __isl_take isl_printer *p, __isl_keep isl_multi_union_pw_aff *mupa)3327{3328 struct isl_print_space_data data = { 0 };3329 isl_bool has_domain;3330 isl_space *space;3331 3332 if (!mupa)3333 return isl_printer_free(p);3334 has_domain = isl_multi_union_pw_aff_has_non_trivial_domain(mupa);3335 if (has_domain < 0)3336 return isl_printer_free(p);3337 3338 space = isl_multi_union_pw_aff_get_space(mupa);3339 p = print_param_tuple(p, space, &data);3340 3341 if (has_domain)3342 p = isl_printer_print_str(p, "(");3343 3344 data.print_dim = &print_union_pw_aff_dim;3345 data.user = mupa;3346 3347 p = isl_print_space(space, p, 0, &data);3348 isl_space_free(space);3349 3350 if (has_domain) {3351 p = isl_printer_print_str(p, " : ");3352 p = isl_printer_print_union_set_isl_body(p, mupa->u.dom);3353 p = isl_printer_print_str(p, ")");3354 }3355 3356 return p;3357}3358 3359/* Print the isl_multi_union_pw_aff "mupa" to "p" in isl format.3360 *3361 * We currently only support an isl format.3362 */3363__isl_give isl_printer *isl_printer_print_multi_union_pw_aff(3364 __isl_take isl_printer *p, __isl_keep isl_multi_union_pw_aff *mupa)3365{3366 if (!p || !mupa)3367 return isl_printer_free(p);3368 3369 if (p->output_format == ISL_FORMAT_ISL)3370 return print_multi_union_pw_aff_isl(p, mupa);3371 isl_die(isl_printer_get_ctx(p), isl_error_unsupported,3372 "unsupported output format", return isl_printer_free(p));3373}3374