bound.c: use isl_val instead of isl_int
[isl.git] / isl_output.c
blob7fd2deccccd9f91957e2d9aec4879b89ec9a4f54
1 /*
2 * Copyright 2008-2009 Katholieke Universiteit Leuven
3 * Copyright 2010 INRIA Saclay
4 * Copyright 2012-2013 Ecole Normale Superieure
6 * Use of this software is governed by the MIT license
8 * Written by Sven Verdoolaege, K.U.Leuven, Departement
9 * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
10 * and INRIA Saclay - Ile-de-France, Parc Club Orsay Universite,
11 * ZAC des vignes, 4 rue Jacques Monod, 91893 Orsay, France
12 * and Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France
15 #include <stdlib.h>
16 #include <string.h>
17 #include <isl_ctx_private.h>
18 #include <isl_map_private.h>
19 #include <isl/set.h>
20 #include <isl_seq.h>
21 #include <isl_polynomial_private.h>
22 #include <isl_printer_private.h>
23 #include <isl_space_private.h>
24 #include <isl_mat_private.h>
25 #include <isl_vec_private.h>
26 #include <isl/union_map.h>
27 #include <isl/constraint.h>
28 #include <isl_local_space_private.h>
29 #include <isl_aff_private.h>
30 #include <isl_val_private.h>
31 #include <isl_constraint_private.h>
32 #include <isl/ast_build.h>
33 #include <isl_sort.h>
34 #include <isl_output_private.h>
36 #include <bset_to_bmap.c>
37 #include <set_to_map.c>
39 static const char *s_to[2] = { " -> ", " \\to " };
40 static const char *s_and[2] = { " and ", " \\wedge " };
41 static const char *s_or[2] = { " or ", " \\vee " };
42 static const char *s_le[2] = { "<=", "\\le" };
43 static const char *s_ge[2] = { ">=", "\\ge" };
44 static const char *s_open_set[2] = { "{ ", "\\{\\, " };
45 static const char *s_close_set[2] = { " }", " \\,\\}" };
46 static const char *s_open_list[2] = { "[", "(" };
47 static const char *s_close_list[2] = { "]", ")" };
48 static const char *s_such_that[2] = { " : ", " \\mid " };
49 static const char *s_open_exists[2] = { "exists (", "\\exists \\, " };
50 static const char *s_close_exists[2] = { ")", "" };
51 static const char *s_div_prefix[2] = { "e", "\\alpha_" };
52 static const char *s_mod[2] = { "mod", "\\bmod" };
53 static const char *s_param_prefix[2] = { "p", "p_" };
54 static const char *s_input_prefix[2] = { "i", "i_" };
55 static const char *s_output_prefix[2] = { "o", "o_" };
57 static __isl_give isl_printer *print_constraint_polylib(
58 struct isl_basic_map *bmap, int ineq, int n, __isl_take isl_printer *p)
60 int i;
61 unsigned n_in = isl_basic_map_dim(bmap, isl_dim_in);
62 unsigned n_out = isl_basic_map_dim(bmap, isl_dim_out);
63 unsigned nparam = isl_basic_map_dim(bmap, isl_dim_param);
64 isl_int *c = ineq ? bmap->ineq[n] : bmap->eq[n];
66 p = isl_printer_start_line(p);
67 p = isl_printer_print_int(p, ineq);
68 for (i = 0; i < n_out; ++i) {
69 p = isl_printer_print_str(p, " ");
70 p = isl_printer_print_isl_int(p, c[1+nparam+n_in+i]);
72 for (i = 0; i < n_in; ++i) {
73 p = isl_printer_print_str(p, " ");
74 p = isl_printer_print_isl_int(p, c[1+nparam+i]);
76 for (i = 0; i < bmap->n_div; ++i) {
77 p = isl_printer_print_str(p, " ");
78 p = isl_printer_print_isl_int(p, c[1+nparam+n_in+n_out+i]);
80 for (i = 0; i < nparam; ++i) {
81 p = isl_printer_print_str(p, " ");
82 p = isl_printer_print_isl_int(p, c[1+i]);
84 p = isl_printer_print_str(p, " ");
85 p = isl_printer_print_isl_int(p, c[0]);
86 p = isl_printer_end_line(p);
87 return p;
90 static __isl_give isl_printer *print_constraints_polylib(
91 struct isl_basic_map *bmap, __isl_take isl_printer *p)
93 int i;
95 p = isl_printer_set_isl_int_width(p, 5);
97 for (i = 0; i < bmap->n_eq; ++i)
98 p = print_constraint_polylib(bmap, 0, i, p);
99 for (i = 0; i < bmap->n_ineq; ++i)
100 p = print_constraint_polylib(bmap, 1, i, p);
102 return p;
105 static __isl_give isl_printer *bset_print_constraints_polylib(
106 struct isl_basic_set *bset, __isl_take isl_printer *p)
108 return print_constraints_polylib(bset_to_bmap(bset), p);
111 static __isl_give isl_printer *isl_basic_map_print_polylib(
112 __isl_keep isl_basic_map *bmap, __isl_take isl_printer *p, int ext)
114 unsigned total = isl_basic_map_total_dim(bmap);
115 p = isl_printer_start_line(p);
116 p = isl_printer_print_int(p, bmap->n_eq + bmap->n_ineq);
117 p = isl_printer_print_str(p, " ");
118 p = isl_printer_print_int(p, 1 + total + 1);
119 if (ext) {
120 p = isl_printer_print_str(p, " ");
121 p = isl_printer_print_int(p,
122 isl_basic_map_dim(bmap, isl_dim_out));
123 p = isl_printer_print_str(p, " ");
124 p = isl_printer_print_int(p,
125 isl_basic_map_dim(bmap, isl_dim_in));
126 p = isl_printer_print_str(p, " ");
127 p = isl_printer_print_int(p,
128 isl_basic_map_dim(bmap, isl_dim_div));
129 p = isl_printer_print_str(p, " ");
130 p = isl_printer_print_int(p,
131 isl_basic_map_dim(bmap, isl_dim_param));
133 p = isl_printer_end_line(p);
134 return print_constraints_polylib(bmap, p);
137 static __isl_give isl_printer *isl_basic_set_print_polylib(
138 __isl_keep isl_basic_set *bset, __isl_take isl_printer *p, int ext)
140 return isl_basic_map_print_polylib(bset_to_bmap(bset), p, ext);
143 static __isl_give isl_printer *isl_map_print_polylib(__isl_keep isl_map *map,
144 __isl_take isl_printer *p, int ext)
146 int i;
148 p = isl_printer_start_line(p);
149 p = isl_printer_print_int(p, map->n);
150 p = isl_printer_end_line(p);
151 for (i = 0; i < map->n; ++i) {
152 p = isl_printer_start_line(p);
153 p = isl_printer_end_line(p);
154 p = isl_basic_map_print_polylib(map->p[i], p, ext);
156 return p;
159 static __isl_give isl_printer *isl_set_print_polylib(__isl_keep isl_set *set,
160 __isl_take isl_printer *p, int ext)
162 return isl_map_print_polylib(set_to_map(set), p, ext);
165 static int count_same_name(__isl_keep isl_space *dim,
166 enum isl_dim_type type, unsigned pos, const char *name)
168 enum isl_dim_type t;
169 unsigned p, s;
170 int count = 0;
172 for (t = isl_dim_param; t <= type && t <= isl_dim_out; ++t) {
173 s = t == type ? pos : isl_space_dim(dim, t);
174 for (p = 0; p < s; ++p) {
175 const char *n = isl_space_get_dim_name(dim, t, p);
176 if (n && !strcmp(n, name))
177 count++;
180 return count;
183 /* Print the name of the variable of type "type" and position "pos"
184 * in "space" to "p".
186 static __isl_give isl_printer *print_name(__isl_keep isl_space *space,
187 __isl_take isl_printer *p, enum isl_dim_type type, unsigned pos,
188 int latex)
190 const char *name;
191 char buffer[20];
192 int primes;
194 name = type == isl_dim_div ? NULL
195 : isl_space_get_dim_name(space, type, pos);
197 if (!name) {
198 const char *prefix;
199 if (type == isl_dim_param)
200 prefix = s_param_prefix[latex];
201 else if (type == isl_dim_div)
202 prefix = s_div_prefix[latex];
203 else if (isl_space_is_set(space) || type == isl_dim_in)
204 prefix = s_input_prefix[latex];
205 else
206 prefix = s_output_prefix[latex];
207 snprintf(buffer, sizeof(buffer), "%s%d", prefix, pos);
208 name = buffer;
210 primes = count_same_name(space, name == buffer ? isl_dim_div : type,
211 pos, name);
212 p = isl_printer_print_str(p, name);
213 while (primes-- > 0)
214 p = isl_printer_print_str(p, "'");
215 return p;
218 static enum isl_dim_type pos2type(__isl_keep isl_space *dim, unsigned *pos)
220 enum isl_dim_type type;
221 unsigned n_in = isl_space_dim(dim, isl_dim_in);
222 unsigned n_out = isl_space_dim(dim, isl_dim_out);
223 unsigned nparam = isl_space_dim(dim, isl_dim_param);
225 if (*pos < 1 + nparam) {
226 type = isl_dim_param;
227 *pos -= 1;
228 } else if (*pos < 1 + nparam + n_in) {
229 type = isl_dim_in;
230 *pos -= 1 + nparam;
231 } else if (*pos < 1 + nparam + n_in + n_out) {
232 type = isl_dim_out;
233 *pos -= 1 + nparam + n_in;
234 } else {
235 type = isl_dim_div;
236 *pos -= 1 + nparam + n_in + n_out;
239 return type;
242 /* Can the div expression of the integer division at position "row" of "div"
243 * be printed?
244 * In particular, are the div expressions available and does the selected
245 * variable have a known explicit representation?
246 * Furthermore, the Omega format does not allow any div expressions
247 * to be printed.
249 static isl_bool can_print_div_expr(__isl_keep isl_printer *p,
250 __isl_keep isl_mat *div, int pos)
252 if (p->output_format == ISL_FORMAT_OMEGA)
253 return isl_bool_false;
254 if (!div)
255 return isl_bool_false;
256 return !isl_int_is_zero(div->row[pos][0]);
259 static __isl_give isl_printer *print_div(__isl_keep isl_space *dim,
260 __isl_keep isl_mat *div, int pos, __isl_take isl_printer *p);
262 static __isl_give isl_printer *print_term(__isl_keep isl_space *space,
263 __isl_keep isl_mat *div,
264 isl_int c, unsigned pos, __isl_take isl_printer *p, int latex)
266 enum isl_dim_type type;
267 int print_div_def;
269 if (pos == 0)
270 return isl_printer_print_isl_int(p, c);
272 type = pos2type(space, &pos);
273 print_div_def = type == isl_dim_div && can_print_div_expr(p, div, pos);
275 if (isl_int_is_one(c))
277 else if (isl_int_is_negone(c))
278 p = isl_printer_print_str(p, "-");
279 else {
280 p = isl_printer_print_isl_int(p, c);
281 if (p->output_format == ISL_FORMAT_C || print_div_def)
282 p = isl_printer_print_str(p, "*");
284 if (print_div_def)
285 p = print_div(space, div, pos, p);
286 else
287 p = print_name(space, p, type, pos, latex);
288 return p;
291 static __isl_give isl_printer *print_affine_of_len(__isl_keep isl_space *dim,
292 __isl_keep isl_mat *div,
293 __isl_take isl_printer *p, isl_int *c, int len)
295 int i;
296 int first;
298 for (i = 0, first = 1; i < len; ++i) {
299 int flip = 0;
300 if (isl_int_is_zero(c[i]))
301 continue;
302 if (!first) {
303 if (isl_int_is_neg(c[i])) {
304 flip = 1;
305 isl_int_neg(c[i], c[i]);
306 p = isl_printer_print_str(p, " - ");
307 } else
308 p = isl_printer_print_str(p, " + ");
310 first = 0;
311 p = print_term(dim, div, c[i], i, p, 0);
312 if (flip)
313 isl_int_neg(c[i], c[i]);
315 if (first)
316 p = isl_printer_print_str(p, "0");
317 return p;
320 /* Print an affine expression "c"
321 * to "p", with the variable names taken from "space" and
322 * the integer division definitions taken from "div".
324 static __isl_give isl_printer *print_affine(__isl_take isl_printer *p,
325 __isl_keep isl_space *space, __isl_keep isl_mat *div, isl_int *c)
327 unsigned n_div;
328 unsigned len;
330 if (!space || !div)
331 return isl_printer_free(p);
332 n_div = isl_mat_rows(div);
333 len = 1 + isl_space_dim(space, isl_dim_all) + n_div;
334 return print_affine_of_len(space, div, p, c, len);
337 /* offset is the offset of local_dim inside data->type of data->space.
339 static __isl_give isl_printer *print_nested_var_list(__isl_take isl_printer *p,
340 __isl_keep isl_space *local_dim, enum isl_dim_type local_type,
341 struct isl_print_space_data *data, int offset)
343 int i;
345 if (data->space != local_dim && local_type == isl_dim_out)
346 offset += local_dim->n_in;
348 for (i = 0; i < isl_space_dim(local_dim, local_type); ++i) {
349 if (i)
350 p = isl_printer_print_str(p, ", ");
351 if (data->print_dim)
352 p = data->print_dim(p, data, offset + i);
353 else
354 p = print_name(data->space, p, data->type, offset + i,
355 data->latex);
357 return p;
360 static __isl_give isl_printer *print_var_list(__isl_take isl_printer *p,
361 __isl_keep isl_space *space, enum isl_dim_type type)
363 struct isl_print_space_data data = { .space = space, .type = type };
365 return print_nested_var_list(p, space, type, &data, 0);
368 static __isl_give isl_printer *print_nested_map_dim(__isl_take isl_printer *p,
369 __isl_keep isl_space *local_dim,
370 struct isl_print_space_data *data, int offset);
372 static __isl_give isl_printer *print_nested_tuple(__isl_take isl_printer *p,
373 __isl_keep isl_space *local_dim, enum isl_dim_type local_type,
374 struct isl_print_space_data *data, int offset)
376 const char *name = NULL;
377 unsigned n = isl_space_dim(local_dim, local_type);
378 if ((local_type == isl_dim_in || local_type == isl_dim_out)) {
379 name = isl_space_get_tuple_name(local_dim, local_type);
380 if (name) {
381 if (data->latex)
382 p = isl_printer_print_str(p, "\\mathrm{");
383 p = isl_printer_print_str(p, name);
384 if (data->latex)
385 p = isl_printer_print_str(p, "}");
388 if (!data->latex || n != 1 || name)
389 p = isl_printer_print_str(p, s_open_list[data->latex]);
390 if ((local_type == isl_dim_in || local_type == isl_dim_out) &&
391 local_dim->nested[local_type - isl_dim_in]) {
392 if (data->space != local_dim && local_type == isl_dim_out)
393 offset += local_dim->n_in;
394 p = print_nested_map_dim(p,
395 local_dim->nested[local_type - isl_dim_in],
396 data, offset);
397 } else
398 p = print_nested_var_list(p, local_dim, local_type, data,
399 offset);
400 if (!data->latex || n != 1 || name)
401 p = isl_printer_print_str(p, s_close_list[data->latex]);
402 return p;
405 static __isl_give isl_printer *print_tuple(__isl_keep isl_space *dim,
406 __isl_take isl_printer *p, enum isl_dim_type type,
407 struct isl_print_space_data *data)
409 data->space = dim;
410 data->type = type;
411 return print_nested_tuple(p, dim, type, data, 0);
414 static __isl_give isl_printer *print_nested_map_dim(__isl_take isl_printer *p,
415 __isl_keep isl_space *local_dim,
416 struct isl_print_space_data *data, int offset)
418 p = print_nested_tuple(p, local_dim, isl_dim_in, data, offset);
419 p = isl_printer_print_str(p, s_to[data->latex]);
420 p = print_nested_tuple(p, local_dim, isl_dim_out, data, offset);
422 return p;
425 __isl_give isl_printer *isl_print_space(__isl_keep isl_space *space,
426 __isl_take isl_printer *p, int rational,
427 struct isl_print_space_data *data)
429 if (rational && !data->latex)
430 p = isl_printer_print_str(p, "rat: ");
431 if (isl_space_is_params(space))
433 else if (isl_space_is_set(space))
434 p = print_tuple(space, p, isl_dim_set, data);
435 else {
436 p = print_tuple(space, p, isl_dim_in, data);
437 p = isl_printer_print_str(p, s_to[data->latex]);
438 p = print_tuple(space, p, isl_dim_out, data);
441 return p;
444 static __isl_give isl_printer *print_omega_parameters(__isl_keep isl_space *dim,
445 __isl_take isl_printer *p)
447 if (isl_space_dim(dim, isl_dim_param) == 0)
448 return p;
450 p = isl_printer_start_line(p);
451 p = isl_printer_print_str(p, "symbolic ");
452 p = print_var_list(p, dim, isl_dim_param);
453 p = isl_printer_print_str(p, ";");
454 p = isl_printer_end_line(p);
455 return p;
458 /* Does the inequality constraint following "i" in "bmap"
459 * have an opposite value for the same last coefficient?
460 * "last" is the position of the last coefficient of inequality "i".
461 * If the next constraint is a div constraint, then it is ignored
462 * since div constraints are not printed.
464 static int next_is_opposite(__isl_keep isl_basic_map *bmap, int i, int last)
466 unsigned total = isl_basic_map_total_dim(bmap);
467 unsigned o_div = isl_basic_map_offset(bmap, isl_dim_div);
469 if (i + 1 >= bmap->n_ineq)
470 return 0;
471 if (isl_seq_last_non_zero(bmap->ineq[i + 1], 1 + total) != last)
472 return 0;
473 if (last >= o_div) {
474 isl_bool is_div;
475 is_div = isl_basic_map_is_div_constraint(bmap,
476 bmap->ineq[i + 1], last - o_div);
477 if (is_div < 0)
478 return -1;
479 if (is_div)
480 return 0;
482 return isl_int_abs_eq(bmap->ineq[i][last], bmap->ineq[i + 1][last]) &&
483 !isl_int_eq(bmap->ineq[i][last], bmap->ineq[i + 1][last]);
486 /* Return a string representation of the operator used when
487 * printing a constraint where the LHS is greater than or equal to the LHS
488 * (sign > 0) or smaller than or equal to the LHS (sign < 0).
489 * If "strict" is set, then return the strict version of the comparison
490 * operator.
492 static const char *constraint_op(int sign, int strict, int latex)
494 if (strict)
495 return sign < 0 ? "<" : ">";
496 if (sign < 0)
497 return s_le[latex];
498 else
499 return s_ge[latex];
502 /* Print one side of a constraint "c" to "p", with
503 * the variable names taken from "space" and the integer division definitions
504 * taken from "div".
505 * "last" is the position of the last non-zero coefficient.
506 * Let c' be the result of zeroing out this coefficient, then
507 * the partial constraint
509 * c' op
511 * is printed.
513 static __isl_give isl_printer *print_half_constraint(__isl_take isl_printer *p,
514 __isl_keep isl_space *space, __isl_keep isl_mat *div,
515 isl_int *c, int last, const char *op, int latex)
517 isl_int_set_si(c[last], 0);
518 p = print_affine(p, space, div, c);
520 p = isl_printer_print_str(p, " ");
521 p = isl_printer_print_str(p, op);
522 p = isl_printer_print_str(p, " ");
524 return p;
527 /* Print a constraint "c" to "p", with the variable names
528 * taken from "space" and the integer division definitions taken from "div".
529 * "last" is the position of the last non-zero coefficient, which is
530 * moreover assumed to be negative.
531 * Let c' be the result of zeroing out this coefficient, then
532 * the constraint is printed in the form
534 * -c[last] op c'
536 static __isl_give isl_printer *print_constraint(__isl_take isl_printer *p,
537 __isl_keep isl_space *space, __isl_keep isl_mat *div,
538 isl_int *c, int last, const char *op, int latex)
540 isl_int_abs(c[last], c[last]);
542 p = print_term(space, div, c[last], last, p, latex);
544 p = isl_printer_print_str(p, " ");
545 p = isl_printer_print_str(p, op);
546 p = isl_printer_print_str(p, " ");
548 isl_int_set_si(c[last], 0);
549 p = print_affine(p, space, div, c);
551 return p;
554 /* Given an integer division
556 * floor(f/m)
558 * at position "pos" in "div", print the corresponding modulo expression
560 * (f) mod m
562 * to "p". The variable names are taken from "space", while any
563 * nested integer division definitions are taken from "div".
565 static __isl_give isl_printer *print_mod(__isl_take isl_printer *p,
566 __isl_keep isl_space *space, __isl_keep isl_mat *div, int pos,
567 int latex)
569 if (!p || !div)
570 return isl_printer_free(p);
572 p = isl_printer_print_str(p, "(");
573 p = print_affine_of_len(space, div, p,
574 div->row[pos] + 1, div->n_col - 1);
575 p = isl_printer_print_str(p, ") ");
576 p = isl_printer_print_str(p, s_mod[latex]);
577 p = isl_printer_print_str(p, " ");
578 p = isl_printer_print_isl_int(p, div->row[pos][0]);
579 return p;
582 /* Can the equality constraints "c" be printed as a modulo constraint?
583 * In particular, is of the form
585 * f - a m floor(g/m) = 0,
587 * with c = -a m the coefficient at position "pos"?
588 * Return the position of the corresponding integer division if so.
589 * Return the number of integer divisions if not.
590 * Return -1 on error.
592 * Modulo constraints are currently not printed in C format.
593 * Other than that, "pos" needs to correspond to an integer division
594 * with explicit representation and "c" needs to be a multiple
595 * of the denominator of the integer division.
597 static int print_as_modulo_pos(__isl_keep isl_printer *p,
598 __isl_keep isl_space *space, __isl_keep isl_mat *div, unsigned pos,
599 isl_int c)
601 isl_bool can_print;
602 unsigned n_div;
603 enum isl_dim_type type;
605 if (!p)
606 return -1;
607 n_div = isl_mat_rows(div);
608 if (p->output_format == ISL_FORMAT_C)
609 return n_div;
610 type = pos2type(space, &pos);
611 if (type != isl_dim_div)
612 return n_div;
613 can_print = can_print_div_expr(p, div, pos);
614 if (can_print < 0)
615 return -1;
616 if (!can_print)
617 return n_div;
618 if (!isl_int_is_divisible_by(c, div->row[pos][0]))
619 return n_div;
620 return pos;
623 /* Print equality constraint "c" to "p" as a modulo constraint,
624 * with the variable names taken from "space" and
625 * the integer division definitions taken from "div".
626 * "last" is the position of the last non-zero coefficient, which is
627 * moreover assumed to be negative and a multiple of the denominator
628 * of the corresponding integer division. "div_pos" is the corresponding
629 * position in the sequence of integer divisions.
631 * The equality is of the form
633 * f - a m floor(g/m) = 0.
635 * Print it as
637 * a (g mod m) = -f + a g
639 static __isl_give isl_printer *print_eq_mod_constraint(
640 __isl_take isl_printer *p, __isl_keep isl_space *space,
641 __isl_keep isl_mat *div, unsigned div_pos,
642 isl_int *c, int last, int latex)
644 isl_ctx *ctx;
645 int multiple;
647 ctx = isl_printer_get_ctx(p);
648 isl_int_divexact(c[last], c[last], div->row[div_pos][0]);
649 isl_int_abs(c[last], c[last]);
650 multiple = !isl_int_is_one(c[last]);
651 if (multiple) {
652 p = isl_printer_print_isl_int(p, c[last]);
653 p = isl_printer_print_str(p, "*(");
655 p = print_mod(p, space, div, div_pos, latex);
656 if (multiple)
657 p = isl_printer_print_str(p, ")");
658 p = isl_printer_print_str(p, " = ");
659 isl_seq_combine(c, ctx->negone, c,
660 c[last], div->row[div_pos] + 1, last);
661 isl_int_set_si(c[last], 0);
662 p = print_affine(p, space, div, c);
663 return p;
666 /* Print equality constraint "c" to "p", with the variable names
667 * taken from "space" and the integer division definitions taken from "div".
668 * "last" is the position of the last non-zero coefficient, which is
669 * moreover assumed to be negative.
671 * If possible, print the equality constraint as a modulo constraint.
673 static __isl_give isl_printer *print_eq_constraint(__isl_take isl_printer *p,
674 __isl_keep isl_space *space, __isl_keep isl_mat *div, isl_int *c,
675 int last, int latex)
677 unsigned n_div;
678 int div_pos;
680 n_div = isl_mat_rows(div);
681 div_pos = print_as_modulo_pos(p, space, div, last, c[last]);
682 if (div_pos < 0)
683 return isl_printer_free(p);
684 if (div_pos < n_div)
685 return print_eq_mod_constraint(p, space, div, div_pos,
686 c, last, latex);
687 return print_constraint(p, space, div, c, last, "=", latex);
690 /* Print the constraints of "bmap" to "p".
691 * The names of the variables are taken from "space" and
692 * the integer division definitions are taken from "div".
693 * Div constraints are only printed in "dump" mode.
694 * The constraints are sorted prior to printing (except in "dump" mode).
696 * If x is the last variable with a non-zero coefficient,
697 * then a lower bound
699 * f - a x >= 0
701 * is printed as
703 * a x <= f
705 * while an upper bound
707 * f + a x >= 0
709 * is printed as
711 * a x >= -f
713 * If the next constraint has an opposite sign for the same last coefficient,
714 * then it is printed as
716 * f >= a x
718 * or
720 * -f <= a x
722 * instead. In fact, the "a x" part is not printed explicitly, but
723 * reused from the next constraint, which is therefore treated as
724 * a first constraint in the conjunction.
726 * If the constant term of "f" is -1, then "f" is replaced by "f + 1" and
727 * the comparison operator is replaced by the strict variant.
728 * Essentially, ">= 1" is replaced by "> 0".
730 static __isl_give isl_printer *print_constraints(__isl_keep isl_basic_map *bmap,
731 __isl_keep isl_space *space, __isl_keep isl_mat *div,
732 __isl_take isl_printer *p, int latex)
734 int i;
735 isl_vec *c = NULL;
736 int rational = ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL);
737 unsigned total = isl_basic_map_total_dim(bmap);
738 unsigned o_div = isl_basic_map_offset(bmap, isl_dim_div);
739 int first = 1;
740 int dump;
742 if (!p)
743 return NULL;
744 bmap = isl_basic_map_copy(bmap);
745 dump = p->dump;
746 if (!dump)
747 bmap = isl_basic_map_sort_constraints(bmap);
748 if (!bmap)
749 goto error;
751 c = isl_vec_alloc(bmap->ctx, 1 + total);
752 if (!c)
753 goto error;
755 for (i = bmap->n_eq - 1; i >= 0; --i) {
756 int l = isl_seq_last_non_zero(bmap->eq[i], 1 + total);
757 if (l < 0) {
758 if (i != bmap->n_eq - 1)
759 p = isl_printer_print_str(p, s_and[latex]);
760 p = isl_printer_print_str(p, "0 = 0");
761 continue;
763 if (!first)
764 p = isl_printer_print_str(p, s_and[latex]);
765 if (isl_int_is_neg(bmap->eq[i][l]))
766 isl_seq_cpy(c->el, bmap->eq[i], 1 + total);
767 else
768 isl_seq_neg(c->el, bmap->eq[i], 1 + total);
769 p = print_eq_constraint(p, space, div, c->el, l, latex);
770 first = 0;
772 for (i = 0; i < bmap->n_ineq; ++i) {
773 int l = isl_seq_last_non_zero(bmap->ineq[i], 1 + total);
774 int strict;
775 int s;
776 const char *op;
777 if (l < 0)
778 continue;
779 if (!dump && l >= o_div &&
780 can_print_div_expr(p, div, l - o_div)) {
781 isl_bool is_div;
782 is_div = isl_basic_map_is_div_constraint(bmap,
783 bmap->ineq[i], l - o_div);
784 if (is_div < 0)
785 goto error;
786 if (is_div)
787 continue;
789 if (!first)
790 p = isl_printer_print_str(p, s_and[latex]);
791 s = isl_int_sgn(bmap->ineq[i][l]);
792 strict = !rational && isl_int_is_negone(bmap->ineq[i][0]);
793 if (s < 0)
794 isl_seq_cpy(c->el, bmap->ineq[i], 1 + total);
795 else
796 isl_seq_neg(c->el, bmap->ineq[i], 1 + total);
797 if (strict)
798 isl_int_set_si(c->el[0], 0);
799 if (!dump && next_is_opposite(bmap, i, l)) {
800 op = constraint_op(-s, strict, latex);
801 p = print_half_constraint(p, space, div, c->el, l,
802 op, latex);
803 first = 1;
804 } else {
805 op = constraint_op(s, strict, latex);
806 p = print_constraint(p, space, div, c->el, l,
807 op, latex);
808 first = 0;
812 isl_basic_map_free(bmap);
813 isl_vec_free(c);
815 return p;
816 error:
817 isl_basic_map_free(bmap);
818 isl_vec_free(c);
819 isl_printer_free(p);
820 return NULL;
823 static __isl_give isl_printer *print_div(__isl_keep isl_space *dim,
824 __isl_keep isl_mat *div, int pos, __isl_take isl_printer *p)
826 int c;
828 if (!p || !div)
829 return isl_printer_free(p);
831 c = p->output_format == ISL_FORMAT_C;
832 p = isl_printer_print_str(p, c ? "floord(" : "floor((");
833 p = print_affine_of_len(dim, div, p,
834 div->row[pos] + 1, div->n_col - 1);
835 p = isl_printer_print_str(p, c ? ", " : ")/");
836 p = isl_printer_print_isl_int(p, div->row[pos][0]);
837 p = isl_printer_print_str(p, ")");
838 return p;
841 /* Print a comma separated list of div names, except those that have
842 * a definition that can be printed.
843 * If "print_defined_divs" is set, then those div names are printed
844 * as well, along with their definitions.
846 static __isl_give isl_printer *print_div_list(__isl_take isl_printer *p,
847 __isl_keep isl_space *space, __isl_keep isl_mat *div, int latex,
848 int print_defined_divs)
850 int i;
851 int first = 1;
852 unsigned n_div;
854 if (!p || !space || !div)
855 return isl_printer_free(p);
857 n_div = isl_mat_rows(div);
859 for (i = 0; i < n_div; ++i) {
860 if (!print_defined_divs && can_print_div_expr(p, div, i))
861 continue;
862 if (!first)
863 p = isl_printer_print_str(p, ", ");
864 p = print_name(space, p, isl_dim_div, i, latex);
865 first = 0;
866 if (!can_print_div_expr(p, div, i))
867 continue;
868 p = isl_printer_print_str(p, " = ");
869 p = print_div(space, div, i, p);
872 return p;
875 /* Does printing an object with local variables described by "div"
876 * require an "exists" clause?
877 * That is, are there any local variables without an explicit representation?
878 * An exists clause is also needed in "dump" mode because
879 * explicit div representations are not printed inline in that case.
881 static isl_bool need_exists(__isl_keep isl_printer *p, __isl_keep isl_mat *div)
883 int i, n;
885 if (!p || !div)
886 return isl_bool_error;
887 n = isl_mat_rows(div);
888 if (n == 0)
889 return isl_bool_false;
890 if (p->dump)
891 return isl_bool_true;
892 for (i = 0; i < n; ++i)
893 if (!can_print_div_expr(p, div, i))
894 return isl_bool_true;
895 return isl_bool_false;
898 /* Print the start of an exists clause, i.e.,
900 * (exists variables:
902 * In dump mode, local variables with an explicit definition are printed
903 * as well because they will not be printed inline.
905 static __isl_give isl_printer *open_exists(__isl_take isl_printer *p,
906 __isl_keep isl_space *space, __isl_keep isl_mat *div, int latex)
908 int dump;
910 if (!p)
911 return NULL;
913 dump = p->dump;
914 p = isl_printer_print_str(p, s_open_exists[latex]);
915 p = print_div_list(p, space, div, latex, dump);
916 p = isl_printer_print_str(p, ": ");
918 return p;
921 /* Remove the explicit representations of all local variables in "div".
923 static __isl_give isl_mat *mark_all_unknown(__isl_take isl_mat *div)
925 int i, n_div;
927 if (!div)
928 return NULL;
930 n_div = isl_mat_rows(div);
931 for (i = 0; i < n_div; ++i)
932 div = isl_mat_set_element_si(div, i, 0, 0);
933 return div;
936 /* Print the constraints of "bmap" to "p".
937 * The names of the variables are taken from "space".
938 * "latex" is set if the constraints should be printed in LaTeX format.
939 * Do not print inline explicit div representations in "dump" mode.
941 static __isl_give isl_printer *print_disjunct(__isl_keep isl_basic_map *bmap,
942 __isl_keep isl_space *space, __isl_take isl_printer *p, int latex)
944 int dump;
945 isl_mat *div;
946 isl_bool exists;
948 if (!p)
949 return NULL;
950 dump = p->dump;
951 div = isl_basic_map_get_divs(bmap);
952 exists = need_exists(p, div);
953 if (exists >= 0 && exists)
954 p = open_exists(p, space, div, latex);
956 if (dump)
957 div = mark_all_unknown(div);
958 p = print_constraints(bmap, space, div, p, latex);
959 isl_mat_free(div);
961 if (exists >= 0 && exists)
962 p = isl_printer_print_str(p, s_close_exists[latex]);
963 return p;
966 /* Print a colon followed by the constraints of "bmap"
967 * to "p", provided there are any constraints.
968 * The names of the variables are taken from "space".
969 * "latex" is set if the constraints should be printed in LaTeX format.
971 static __isl_give isl_printer *print_optional_disjunct(
972 __isl_keep isl_basic_map *bmap, __isl_keep isl_space *space,
973 __isl_take isl_printer *p, int latex)
975 if (isl_basic_map_plain_is_universe(bmap))
976 return p;
978 p = isl_printer_print_str(p, ": ");
979 p = print_disjunct(bmap, space, p, latex);
981 return p;
984 static __isl_give isl_printer *basic_map_print_omega(
985 __isl_keep isl_basic_map *bmap, __isl_take isl_printer *p)
987 p = isl_printer_print_str(p, "{ [");
988 p = print_var_list(p, bmap->dim, isl_dim_in);
989 p = isl_printer_print_str(p, "] -> [");
990 p = print_var_list(p, bmap->dim, isl_dim_out);
991 p = isl_printer_print_str(p, "] ");
992 p = print_optional_disjunct(bmap, bmap->dim, p, 0);
993 p = isl_printer_print_str(p, " }");
994 return p;
997 static __isl_give isl_printer *basic_set_print_omega(
998 __isl_keep isl_basic_set *bset, __isl_take isl_printer *p)
1000 p = isl_printer_print_str(p, "{ [");
1001 p = print_var_list(p, bset->dim, isl_dim_set);
1002 p = isl_printer_print_str(p, "] ");
1003 p = print_optional_disjunct(bset, bset->dim, p, 0);
1004 p = isl_printer_print_str(p, " }");
1005 return p;
1008 static __isl_give isl_printer *isl_map_print_omega(__isl_keep isl_map *map,
1009 __isl_take isl_printer *p)
1011 int i;
1013 for (i = 0; i < map->n; ++i) {
1014 if (i)
1015 p = isl_printer_print_str(p, " union ");
1016 p = basic_map_print_omega(map->p[i], p);
1018 return p;
1021 static __isl_give isl_printer *isl_set_print_omega(__isl_keep isl_set *set,
1022 __isl_take isl_printer *p)
1024 int i;
1026 for (i = 0; i < set->n; ++i) {
1027 if (i)
1028 p = isl_printer_print_str(p, " union ");
1029 p = basic_set_print_omega(set->p[i], p);
1031 return p;
1034 /* Print the list of parameters in "space", followed by an arrow, to "p",
1035 * if there are any parameters.
1037 static __isl_give isl_printer *print_param_tuple(__isl_take isl_printer *p,
1038 __isl_keep isl_space *space, struct isl_print_space_data *data)
1040 if (!p || !space)
1041 return isl_printer_free(p);
1042 if (isl_space_dim(space, isl_dim_param) == 0)
1043 return p;
1045 p = print_tuple(space, p, isl_dim_param, data);
1046 p = isl_printer_print_str(p, s_to[data->latex]);
1048 return p;
1051 static __isl_give isl_printer *isl_basic_map_print_isl(
1052 __isl_keep isl_basic_map *bmap, __isl_take isl_printer *p,
1053 int latex)
1055 struct isl_print_space_data data = { .latex = latex };
1056 int rational = ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL);
1058 p = print_param_tuple(p, bmap->dim, &data);
1059 p = isl_printer_print_str(p, "{ ");
1060 p = isl_print_space(bmap->dim, p, rational, &data);
1061 p = isl_printer_print_str(p, " : ");
1062 p = print_disjunct(bmap, bmap->dim, p, latex);
1063 p = isl_printer_print_str(p, " }");
1064 return p;
1067 /* Print the disjuncts of a map (or set) "map" to "p".
1068 * The names of the variables are taken from "space".
1069 * "latex" is set if the constraints should be printed in LaTeX format.
1071 static __isl_give isl_printer *print_disjuncts_core(__isl_keep isl_map *map,
1072 __isl_keep isl_space *space, __isl_take isl_printer *p, int latex)
1074 int i;
1076 if (map->n == 0)
1077 p = isl_printer_print_str(p, "false");
1078 for (i = 0; i < map->n; ++i) {
1079 if (i)
1080 p = isl_printer_print_str(p, s_or[latex]);
1081 if (map->n > 1 && map->p[i]->n_eq + map->p[i]->n_ineq > 1)
1082 p = isl_printer_print_str(p, "(");
1083 p = print_disjunct(map->p[i], space, p, latex);
1084 if (map->n > 1 && map->p[i]->n_eq + map->p[i]->n_ineq > 1)
1085 p = isl_printer_print_str(p, ")");
1087 return p;
1090 /* Print the disjuncts of a map (or set) "map" to "p".
1091 * The names of the variables are taken from "space".
1092 * "hull" describes constraints shared by all disjuncts of "map".
1093 * "latex" is set if the constraints should be printed in LaTeX format.
1095 * Print the disjuncts as a conjunction of "hull" and
1096 * the result of removing the constraints of "hull" from "map".
1097 * If this result turns out to be the universe, then simply print "hull".
1099 static __isl_give isl_printer *print_disjuncts_in_hull(__isl_keep isl_map *map,
1100 __isl_keep isl_space *space, __isl_take isl_basic_map *hull,
1101 __isl_take isl_printer *p, int latex)
1103 isl_bool is_universe;
1105 p = print_disjunct(hull, space, p, latex);
1106 map = isl_map_plain_gist_basic_map(isl_map_copy(map), hull);
1107 is_universe = isl_map_plain_is_universe(map);
1108 if (is_universe < 0)
1109 goto error;
1110 if (!is_universe) {
1111 p = isl_printer_print_str(p, s_and[latex]);
1112 p = isl_printer_print_str(p, "(");
1113 p = print_disjuncts_core(map, space, p, latex);
1114 p = isl_printer_print_str(p, ")");
1116 isl_map_free(map);
1118 return p;
1119 error:
1120 isl_map_free(map);
1121 isl_printer_free(p);
1122 return NULL;
1125 /* Print the disjuncts of a map (or set) "map" to "p".
1126 * The names of the variables are taken from "space".
1127 * "latex" is set if the constraints should be printed in LaTeX format.
1129 * If there are at least two disjuncts and "dump" mode is not turned out,
1130 * check for any shared constraints among all disjuncts.
1131 * If there are any, then print them separately in print_disjuncts_in_hull.
1133 static __isl_give isl_printer *print_disjuncts(__isl_keep isl_map *map,
1134 __isl_keep isl_space *space, __isl_take isl_printer *p, int latex)
1136 if (isl_map_plain_is_universe(map))
1137 return p;
1139 p = isl_printer_print_str(p, s_such_that[latex]);
1140 if (!p)
1141 return NULL;
1143 if (!p->dump && map->n >= 2) {
1144 isl_basic_map *hull;
1145 isl_bool is_universe;
1147 hull = isl_map_plain_unshifted_simple_hull(isl_map_copy(map));
1148 is_universe = isl_basic_map_plain_is_universe(hull);
1149 if (is_universe < 0)
1150 p = isl_printer_free(p);
1151 else if (!is_universe)
1152 return print_disjuncts_in_hull(map, space, hull,
1153 p, latex);
1154 isl_basic_map_free(hull);
1157 return print_disjuncts_core(map, space, p, latex);
1160 /* Print the disjuncts of a map (or set).
1161 * The names of the variables are taken from "space".
1162 * "latex" is set if the constraints should be printed in LaTeX format.
1164 * If the map turns out to be a universal parameter domain, then
1165 * we need to print the colon. Otherwise, the output looks identical
1166 * to the empty set.
1168 static __isl_give isl_printer *print_disjuncts_map(__isl_keep isl_map *map,
1169 __isl_keep isl_space *space, __isl_take isl_printer *p, int latex)
1171 if (isl_map_plain_is_universe(map) && isl_space_is_params(map->dim))
1172 return isl_printer_print_str(p, s_such_that[latex]);
1173 else
1174 return print_disjuncts(map, space, p, latex);
1177 struct isl_aff_split {
1178 isl_basic_map *aff;
1179 isl_map *map;
1182 static void free_split(__isl_take struct isl_aff_split *split, int n)
1184 int i;
1186 if (!split)
1187 return;
1189 for (i = 0; i < n; ++i) {
1190 isl_basic_map_free(split[i].aff);
1191 isl_map_free(split[i].map);
1194 free(split);
1197 static __isl_give isl_basic_map *get_aff(__isl_take isl_basic_map *bmap)
1199 int i, j;
1200 unsigned nparam, n_in, n_out, total;
1202 bmap = isl_basic_map_cow(bmap);
1203 if (!bmap)
1204 return NULL;
1205 if (isl_basic_map_free_inequality(bmap, bmap->n_ineq) < 0)
1206 goto error;
1208 nparam = isl_basic_map_dim(bmap, isl_dim_param);
1209 n_in = isl_basic_map_dim(bmap, isl_dim_in);
1210 n_out = isl_basic_map_dim(bmap, isl_dim_out);
1211 total = isl_basic_map_dim(bmap, isl_dim_all);
1212 for (i = bmap->n_eq - 1; i >= 0; --i) {
1213 j = isl_seq_last_non_zero(bmap->eq[i] + 1, total);
1214 if (j >= nparam && j < nparam + n_in + n_out &&
1215 (isl_int_is_one(bmap->eq[i][1 + j]) ||
1216 isl_int_is_negone(bmap->eq[i][1 + j])))
1217 continue;
1218 if (isl_basic_map_drop_equality(bmap, i) < 0)
1219 goto error;
1222 bmap = isl_basic_map_finalize(bmap);
1224 return bmap;
1225 error:
1226 isl_basic_map_free(bmap);
1227 return NULL;
1230 static int aff_split_cmp(const void *p1, const void *p2, void *user)
1232 const struct isl_aff_split *s1, *s2;
1233 s1 = (const struct isl_aff_split *) p1;
1234 s2 = (const struct isl_aff_split *) p2;
1236 return isl_basic_map_plain_cmp(s1->aff, s2->aff);
1239 static __isl_give isl_basic_map *drop_aff(__isl_take isl_basic_map *bmap,
1240 __isl_keep isl_basic_map *aff)
1242 int i, j;
1243 unsigned total;
1245 if (!bmap || !aff)
1246 goto error;
1248 total = isl_space_dim(bmap->dim, isl_dim_all);
1250 for (i = bmap->n_eq - 1; i >= 0; --i) {
1251 if (isl_seq_first_non_zero(bmap->eq[i] + 1 + total,
1252 bmap->n_div) != -1)
1253 continue;
1254 for (j = 0; j < aff->n_eq; ++j) {
1255 if (!isl_seq_eq(bmap->eq[i], aff->eq[j], 1 + total) &&
1256 !isl_seq_is_neg(bmap->eq[i], aff->eq[j], 1 + total))
1257 continue;
1258 if (isl_basic_map_drop_equality(bmap, i) < 0)
1259 goto error;
1260 break;
1264 return bmap;
1265 error:
1266 isl_basic_map_free(bmap);
1267 return NULL;
1270 static __isl_give struct isl_aff_split *split_aff(__isl_keep isl_map *map)
1272 int i, n;
1273 struct isl_aff_split *split;
1274 isl_ctx *ctx;
1276 ctx = isl_map_get_ctx(map);
1277 split = isl_calloc_array(ctx, struct isl_aff_split, map->n);
1278 if (!split)
1279 return NULL;
1281 for (i = 0; i < map->n; ++i) {
1282 isl_basic_map *bmap;
1283 split[i].aff = get_aff(isl_basic_map_copy(map->p[i]));
1284 bmap = isl_basic_map_copy(map->p[i]);
1285 bmap = isl_basic_map_cow(bmap);
1286 bmap = drop_aff(bmap, split[i].aff);
1287 split[i].map = isl_map_from_basic_map(bmap);
1288 if (!split[i].aff || !split[i].map)
1289 goto error;
1292 if (isl_sort(split, map->n, sizeof(struct isl_aff_split),
1293 &aff_split_cmp, NULL) < 0)
1294 goto error;
1296 n = map->n;
1297 for (i = n - 1; i >= 1; --i) {
1298 if (!isl_basic_map_plain_is_equal(split[i - 1].aff,
1299 split[i].aff))
1300 continue;
1301 isl_basic_map_free(split[i].aff);
1302 split[i - 1].map = isl_map_union(split[i - 1].map,
1303 split[i].map);
1304 if (i != n - 1)
1305 split[i] = split[n - 1];
1306 split[n - 1].aff = NULL;
1307 split[n - 1].map = NULL;
1308 --n;
1311 return split;
1312 error:
1313 free_split(split, map->n);
1314 return NULL;
1317 static int defining_equality(__isl_keep isl_basic_map *eq,
1318 __isl_keep isl_space *dim, enum isl_dim_type type, int pos)
1320 int i;
1321 unsigned total;
1323 if (!eq)
1324 return -1;
1326 pos += isl_space_offset(dim, type);
1327 total = isl_basic_map_total_dim(eq);
1329 for (i = 0; i < eq->n_eq; ++i) {
1330 if (isl_seq_last_non_zero(eq->eq[i] + 1, total) != pos)
1331 continue;
1332 if (isl_int_is_one(eq->eq[i][1 + pos]))
1333 isl_seq_neg(eq->eq[i], eq->eq[i], 1 + total);
1334 return i;
1337 return -1;
1340 /* Print dimension "pos" of data->space to "p".
1342 * data->user is assumed to be an isl_basic_map keeping track of equalities.
1344 * If the current dimension is defined by these equalities, then print
1345 * the corresponding expression, assigned to the name of the dimension
1346 * if there is any. Otherwise, print the name of the dimension.
1348 static __isl_give isl_printer *print_dim_eq(__isl_take isl_printer *p,
1349 struct isl_print_space_data *data, unsigned pos)
1351 isl_basic_map *eq = data->user;
1352 int j;
1354 j = defining_equality(eq, data->space, data->type, pos);
1355 if (j >= 0) {
1356 if (isl_space_has_dim_name(data->space, data->type, pos)) {
1357 p = print_name(data->space, p, data->type, pos,
1358 data->latex);
1359 p = isl_printer_print_str(p, " = ");
1361 pos += 1 + isl_space_offset(data->space, data->type);
1362 p = print_affine_of_len(data->space, NULL, p, eq->eq[j], pos);
1363 } else {
1364 p = print_name(data->space, p, data->type, pos, data->latex);
1367 return p;
1370 static __isl_give isl_printer *print_split_map(__isl_take isl_printer *p,
1371 struct isl_aff_split *split, int n, __isl_keep isl_space *space)
1373 struct isl_print_space_data data = { 0 };
1374 int i;
1375 int rational;
1377 data.print_dim = &print_dim_eq;
1378 for (i = 0; i < n; ++i) {
1379 if (!split[i].map)
1380 break;
1381 rational = split[i].map->n > 0 &&
1382 ISL_F_ISSET(split[i].map->p[0], ISL_BASIC_MAP_RATIONAL);
1383 if (i)
1384 p = isl_printer_print_str(p, "; ");
1385 data.user = split[i].aff;
1386 p = isl_print_space(space, p, rational, &data);
1387 p = print_disjuncts_map(split[i].map, space, p, 0);
1390 return p;
1393 static __isl_give isl_printer *isl_map_print_isl_body(__isl_keep isl_map *map,
1394 __isl_take isl_printer *p)
1396 struct isl_print_space_data data = { 0 };
1397 struct isl_aff_split *split = NULL;
1398 int rational;
1400 if (!p || !map)
1401 return isl_printer_free(p);
1402 if (!p->dump && map->n > 0)
1403 split = split_aff(map);
1404 if (split) {
1405 p = print_split_map(p, split, map->n, map->dim);
1406 } else {
1407 rational = map->n > 0 &&
1408 ISL_F_ISSET(map->p[0], ISL_BASIC_MAP_RATIONAL);
1409 p = isl_print_space(map->dim, p, rational, &data);
1410 p = print_disjuncts_map(map, map->dim, p, 0);
1412 free_split(split, map->n);
1413 return p;
1416 static __isl_give isl_printer *isl_map_print_isl(__isl_keep isl_map *map,
1417 __isl_take isl_printer *p)
1419 struct isl_print_space_data data = { 0 };
1421 p = print_param_tuple(p, map->dim, &data);
1422 p = isl_printer_print_str(p, s_open_set[0]);
1423 p = isl_map_print_isl_body(map, p);
1424 p = isl_printer_print_str(p, s_close_set[0]);
1425 return p;
1428 static __isl_give isl_printer *print_latex_map(__isl_keep isl_map *map,
1429 __isl_take isl_printer *p, __isl_keep isl_basic_map *aff)
1431 struct isl_print_space_data data = { 0 };
1433 data.latex = 1;
1434 p = print_param_tuple(p, map->dim, &data);
1435 p = isl_printer_print_str(p, s_open_set[1]);
1436 data.print_dim = &print_dim_eq;
1437 data.user = aff;
1438 p = isl_print_space(map->dim, p, 0, &data);
1439 p = print_disjuncts_map(map, map->dim, p, 1);
1440 p = isl_printer_print_str(p, s_close_set[1]);
1442 return p;
1445 static __isl_give isl_printer *isl_map_print_latex(__isl_keep isl_map *map,
1446 __isl_take isl_printer *p)
1448 int i;
1449 struct isl_aff_split *split = NULL;
1451 if (map->n > 0)
1452 split = split_aff(map);
1454 if (!split)
1455 return print_latex_map(map, p, NULL);
1457 for (i = 0; i < map->n; ++i) {
1458 if (!split[i].map)
1459 break;
1460 if (i)
1461 p = isl_printer_print_str(p, " \\cup ");
1462 p = print_latex_map(split[i].map, p, split[i].aff);
1465 free_split(split, map->n);
1466 return p;
1469 __isl_give isl_printer *isl_printer_print_basic_map(__isl_take isl_printer *p,
1470 __isl_keep isl_basic_map *bmap)
1472 if (!p || !bmap)
1473 goto error;
1474 if (p->output_format == ISL_FORMAT_ISL)
1475 return isl_basic_map_print_isl(bmap, p, 0);
1476 else if (p->output_format == ISL_FORMAT_OMEGA)
1477 return basic_map_print_omega(bmap, p);
1478 isl_assert(bmap->ctx, 0, goto error);
1479 error:
1480 isl_printer_free(p);
1481 return NULL;
1484 __isl_give isl_printer *isl_printer_print_basic_set(__isl_take isl_printer *p,
1485 __isl_keep isl_basic_set *bset)
1487 if (!p || !bset)
1488 goto error;
1490 if (p->output_format == ISL_FORMAT_ISL)
1491 return isl_basic_map_print_isl(bset, p, 0);
1492 else if (p->output_format == ISL_FORMAT_POLYLIB)
1493 return isl_basic_set_print_polylib(bset, p, 0);
1494 else if (p->output_format == ISL_FORMAT_EXT_POLYLIB)
1495 return isl_basic_set_print_polylib(bset, p, 1);
1496 else if (p->output_format == ISL_FORMAT_POLYLIB_CONSTRAINTS)
1497 return bset_print_constraints_polylib(bset, p);
1498 else if (p->output_format == ISL_FORMAT_OMEGA)
1499 return basic_set_print_omega(bset, p);
1500 isl_assert(p->ctx, 0, goto error);
1501 error:
1502 isl_printer_free(p);
1503 return NULL;
1506 __isl_give isl_printer *isl_printer_print_set(__isl_take isl_printer *p,
1507 __isl_keep isl_set *set)
1509 if (!p || !set)
1510 goto error;
1511 if (p->output_format == ISL_FORMAT_ISL)
1512 return isl_map_print_isl(set_to_map(set), p);
1513 else if (p->output_format == ISL_FORMAT_POLYLIB)
1514 return isl_set_print_polylib(set, p, 0);
1515 else if (p->output_format == ISL_FORMAT_EXT_POLYLIB)
1516 return isl_set_print_polylib(set, p, 1);
1517 else if (p->output_format == ISL_FORMAT_OMEGA)
1518 return isl_set_print_omega(set, p);
1519 else if (p->output_format == ISL_FORMAT_LATEX)
1520 return isl_map_print_latex(set_to_map(set), p);
1521 isl_assert(set->ctx, 0, goto error);
1522 error:
1523 isl_printer_free(p);
1524 return NULL;
1527 __isl_give isl_printer *isl_printer_print_map(__isl_take isl_printer *p,
1528 __isl_keep isl_map *map)
1530 if (!p || !map)
1531 goto error;
1533 if (p->output_format == ISL_FORMAT_ISL)
1534 return isl_map_print_isl(map, p);
1535 else if (p->output_format == ISL_FORMAT_POLYLIB)
1536 return isl_map_print_polylib(map, p, 0);
1537 else if (p->output_format == ISL_FORMAT_EXT_POLYLIB)
1538 return isl_map_print_polylib(map, p, 1);
1539 else if (p->output_format == ISL_FORMAT_OMEGA)
1540 return isl_map_print_omega(map, p);
1541 else if (p->output_format == ISL_FORMAT_LATEX)
1542 return isl_map_print_latex(map, p);
1543 isl_assert(map->ctx, 0, goto error);
1544 error:
1545 isl_printer_free(p);
1546 return NULL;
1549 struct isl_union_print_data {
1550 isl_printer *p;
1551 int first;
1554 static isl_stat print_map_body(__isl_take isl_map *map, void *user)
1556 struct isl_union_print_data *data;
1557 data = (struct isl_union_print_data *)user;
1559 if (!data->first)
1560 data->p = isl_printer_print_str(data->p, "; ");
1561 data->first = 0;
1563 data->p = isl_map_print_isl_body(map, data->p);
1564 isl_map_free(map);
1566 return isl_stat_ok;
1569 static __isl_give isl_printer *isl_union_map_print_isl(
1570 __isl_keep isl_union_map *umap, __isl_take isl_printer *p)
1572 struct isl_union_print_data data;
1573 struct isl_print_space_data space_data = { 0 };
1574 isl_space *space;
1576 space = isl_union_map_get_space(umap);
1577 p = print_param_tuple(p, space, &space_data);
1578 isl_space_free(space);
1579 p = isl_printer_print_str(p, s_open_set[0]);
1580 data.p = p;
1581 data.first = 1;
1582 isl_union_map_foreach_map(umap, &print_map_body, &data);
1583 p = data.p;
1584 p = isl_printer_print_str(p, s_close_set[0]);
1585 return p;
1588 static isl_stat print_latex_map_body(__isl_take isl_map *map, void *user)
1590 struct isl_union_print_data *data;
1591 data = (struct isl_union_print_data *)user;
1593 if (!data->first)
1594 data->p = isl_printer_print_str(data->p, " \\cup ");
1595 data->first = 0;
1597 data->p = isl_map_print_latex(map, data->p);
1598 isl_map_free(map);
1600 return isl_stat_ok;
1603 static __isl_give isl_printer *isl_union_map_print_latex(
1604 __isl_keep isl_union_map *umap, __isl_take isl_printer *p)
1606 struct isl_union_print_data data = { p, 1 };
1607 isl_union_map_foreach_map(umap, &print_latex_map_body, &data);
1608 p = data.p;
1609 return p;
1612 __isl_give isl_printer *isl_printer_print_union_map(__isl_take isl_printer *p,
1613 __isl_keep isl_union_map *umap)
1615 if (!p || !umap)
1616 goto error;
1618 if (p->output_format == ISL_FORMAT_ISL)
1619 return isl_union_map_print_isl(umap, p);
1620 if (p->output_format == ISL_FORMAT_LATEX)
1621 return isl_union_map_print_latex(umap, p);
1623 isl_die(p->ctx, isl_error_invalid,
1624 "invalid output format for isl_union_map", goto error);
1625 error:
1626 isl_printer_free(p);
1627 return NULL;
1630 __isl_give isl_printer *isl_printer_print_union_set(__isl_take isl_printer *p,
1631 __isl_keep isl_union_set *uset)
1633 if (!p || !uset)
1634 goto error;
1636 if (p->output_format == ISL_FORMAT_ISL)
1637 return isl_union_map_print_isl((isl_union_map *)uset, p);
1638 if (p->output_format == ISL_FORMAT_LATEX)
1639 return isl_union_map_print_latex((isl_union_map *)uset, p);
1641 isl_die(p->ctx, isl_error_invalid,
1642 "invalid output format for isl_union_set", goto error);
1643 error:
1644 isl_printer_free(p);
1645 return NULL;
1648 static int upoly_rec_n_non_zero(__isl_keep struct isl_upoly_rec *rec)
1650 int i;
1651 int n;
1653 for (i = 0, n = 0; i < rec->n; ++i)
1654 if (!isl_upoly_is_zero(rec->p[i]))
1655 ++n;
1657 return n;
1660 static __isl_give isl_printer *upoly_print_cst(__isl_keep struct isl_upoly *up,
1661 __isl_take isl_printer *p, int first)
1663 struct isl_upoly_cst *cst;
1664 int neg;
1666 cst = isl_upoly_as_cst(up);
1667 if (!cst)
1668 goto error;
1669 neg = !first && isl_int_is_neg(cst->n);
1670 if (!first)
1671 p = isl_printer_print_str(p, neg ? " - " : " + ");
1672 if (neg)
1673 isl_int_neg(cst->n, cst->n);
1674 if (isl_int_is_zero(cst->d)) {
1675 int sgn = isl_int_sgn(cst->n);
1676 p = isl_printer_print_str(p, sgn < 0 ? "-infty" :
1677 sgn == 0 ? "NaN" : "infty");
1678 } else
1679 p = isl_printer_print_isl_int(p, cst->n);
1680 if (neg)
1681 isl_int_neg(cst->n, cst->n);
1682 if (!isl_int_is_zero(cst->d) && !isl_int_is_one(cst->d)) {
1683 p = isl_printer_print_str(p, "/");
1684 p = isl_printer_print_isl_int(p, cst->d);
1686 return p;
1687 error:
1688 isl_printer_free(p);
1689 return NULL;
1692 static __isl_give isl_printer *print_base(__isl_take isl_printer *p,
1693 __isl_keep isl_space *dim, __isl_keep isl_mat *div, int var)
1695 unsigned total;
1697 total = isl_space_dim(dim, isl_dim_all);
1698 if (var < total)
1699 p = print_term(dim, NULL, dim->ctx->one, 1 + var, p, 0);
1700 else
1701 p = print_div(dim, div, var - total, p);
1702 return p;
1705 static __isl_give isl_printer *print_pow(__isl_take isl_printer *p,
1706 __isl_keep isl_space *dim, __isl_keep isl_mat *div, int var, int exp)
1708 p = print_base(p, dim, div, var);
1709 if (exp == 1)
1710 return p;
1711 if (p->output_format == ISL_FORMAT_C) {
1712 int i;
1713 for (i = 1; i < exp; ++i) {
1714 p = isl_printer_print_str(p, "*");
1715 p = print_base(p, dim, div, var);
1717 } else {
1718 p = isl_printer_print_str(p, "^");
1719 p = isl_printer_print_int(p, exp);
1721 return p;
1724 /* Print the polynomial "up" defined over the domain space "space" and
1725 * local variables defined by "div" to "p".
1727 static __isl_give isl_printer *upoly_print(__isl_keep struct isl_upoly *up,
1728 __isl_keep isl_space *space, __isl_keep isl_mat *div,
1729 __isl_take isl_printer *p)
1731 int i, n, first, print_parens;
1732 struct isl_upoly_rec *rec;
1734 if (!p || !up || !space || !div)
1735 goto error;
1737 if (isl_upoly_is_cst(up))
1738 return upoly_print_cst(up, p, 1);
1740 rec = isl_upoly_as_rec(up);
1741 if (!rec)
1742 goto error;
1743 n = upoly_rec_n_non_zero(rec);
1744 print_parens = n > 1;
1745 if (print_parens)
1746 p = isl_printer_print_str(p, "(");
1747 for (i = 0, first = 1; i < rec->n; ++i) {
1748 if (isl_upoly_is_zero(rec->p[i]))
1749 continue;
1750 if (isl_upoly_is_negone(rec->p[i])) {
1751 if (!i)
1752 p = isl_printer_print_str(p, "-1");
1753 else if (first)
1754 p = isl_printer_print_str(p, "-");
1755 else
1756 p = isl_printer_print_str(p, " - ");
1757 } else if (isl_upoly_is_cst(rec->p[i]) &&
1758 !isl_upoly_is_one(rec->p[i]))
1759 p = upoly_print_cst(rec->p[i], p, first);
1760 else {
1761 if (!first)
1762 p = isl_printer_print_str(p, " + ");
1763 if (i == 0 || !isl_upoly_is_one(rec->p[i]))
1764 p = upoly_print(rec->p[i], space, div, p);
1766 first = 0;
1767 if (i == 0)
1768 continue;
1769 if (!isl_upoly_is_one(rec->p[i]) &&
1770 !isl_upoly_is_negone(rec->p[i]))
1771 p = isl_printer_print_str(p, " * ");
1772 p = print_pow(p, space, div, rec->up.var, i);
1774 if (print_parens)
1775 p = isl_printer_print_str(p, ")");
1776 return p;
1777 error:
1778 isl_printer_free(p);
1779 return NULL;
1782 static __isl_give isl_printer *print_qpolynomial(__isl_take isl_printer *p,
1783 __isl_keep isl_qpolynomial *qp)
1785 if (!p || !qp)
1786 goto error;
1787 p = upoly_print(qp->upoly, qp->dim, qp->div, p);
1788 return p;
1789 error:
1790 isl_printer_free(p);
1791 return NULL;
1794 static __isl_give isl_printer *print_qpolynomial_isl(__isl_take isl_printer *p,
1795 __isl_keep isl_qpolynomial *qp)
1797 struct isl_print_space_data data = { 0 };
1799 if (!p || !qp)
1800 goto error;
1802 p = print_param_tuple(p, qp->dim, &data);
1803 p = isl_printer_print_str(p, "{ ");
1804 if (!isl_space_is_params(qp->dim)) {
1805 p = isl_print_space(qp->dim, p, 0, &data);
1806 p = isl_printer_print_str(p, " -> ");
1808 p = print_qpolynomial(p, qp);
1809 p = isl_printer_print_str(p, " }");
1810 return p;
1811 error:
1812 isl_printer_free(p);
1813 return NULL;
1816 /* Print the quasi-polynomial "qp" to "p" in C format, with the variable names
1817 * taken from the domain space "space".
1819 static __isl_give isl_printer *print_qpolynomial_c(__isl_take isl_printer *p,
1820 __isl_keep isl_space *space, __isl_keep isl_qpolynomial *qp)
1822 isl_int den;
1824 isl_int_init(den);
1825 isl_qpolynomial_get_den(qp, &den);
1826 if (!isl_int_is_one(den)) {
1827 isl_qpolynomial *f;
1828 p = isl_printer_print_str(p, "(");
1829 qp = isl_qpolynomial_copy(qp);
1830 f = isl_qpolynomial_rat_cst_on_domain(isl_space_copy(qp->dim),
1831 den, qp->dim->ctx->one);
1832 qp = isl_qpolynomial_mul(qp, f);
1834 if (qp)
1835 p = upoly_print(qp->upoly, space, qp->div, p);
1836 else
1837 p = isl_printer_free(p);
1838 if (!isl_int_is_one(den)) {
1839 p = isl_printer_print_str(p, ")/");
1840 p = isl_printer_print_isl_int(p, den);
1841 isl_qpolynomial_free(qp);
1843 isl_int_clear(den);
1844 return p;
1847 __isl_give isl_printer *isl_printer_print_qpolynomial(
1848 __isl_take isl_printer *p, __isl_keep isl_qpolynomial *qp)
1850 if (!p || !qp)
1851 goto error;
1853 if (p->output_format == ISL_FORMAT_ISL)
1854 return print_qpolynomial_isl(p, qp);
1855 else if (p->output_format == ISL_FORMAT_C)
1856 return print_qpolynomial_c(p, qp->dim, qp);
1857 else
1858 isl_die(qp->dim->ctx, isl_error_unsupported,
1859 "output format not supported for isl_qpolynomials",
1860 goto error);
1861 error:
1862 isl_printer_free(p);
1863 return NULL;
1866 void isl_qpolynomial_print(__isl_keep isl_qpolynomial *qp, FILE *out,
1867 unsigned output_format)
1869 isl_printer *p;
1871 if (!qp)
1872 return;
1874 isl_assert(qp->dim->ctx, output_format == ISL_FORMAT_ISL, return);
1875 p = isl_printer_to_file(qp->dim->ctx, out);
1876 p = isl_printer_print_qpolynomial(p, qp);
1877 isl_printer_free(p);
1880 static __isl_give isl_printer *qpolynomial_fold_print(
1881 __isl_keep isl_qpolynomial_fold *fold, __isl_take isl_printer *p)
1883 int i;
1885 if (fold->type == isl_fold_min)
1886 p = isl_printer_print_str(p, "min");
1887 else if (fold->type == isl_fold_max)
1888 p = isl_printer_print_str(p, "max");
1889 p = isl_printer_print_str(p, "(");
1890 for (i = 0; i < fold->n; ++i) {
1891 if (i)
1892 p = isl_printer_print_str(p, ", ");
1893 p = print_qpolynomial(p, fold->qp[i]);
1895 p = isl_printer_print_str(p, ")");
1896 return p;
1899 void isl_qpolynomial_fold_print(__isl_keep isl_qpolynomial_fold *fold,
1900 FILE *out, unsigned output_format)
1902 isl_printer *p;
1904 if (!fold)
1905 return;
1907 isl_assert(fold->dim->ctx, output_format == ISL_FORMAT_ISL, return);
1909 p = isl_printer_to_file(fold->dim->ctx, out);
1910 p = isl_printer_print_qpolynomial_fold(p, fold);
1912 isl_printer_free(p);
1915 static __isl_give isl_printer *isl_pwqp_print_isl_body(
1916 __isl_take isl_printer *p, __isl_keep isl_pw_qpolynomial *pwqp)
1918 struct isl_print_space_data data = { 0 };
1919 int i = 0;
1921 for (i = 0; i < pwqp->n; ++i) {
1922 isl_space *space;
1924 if (i)
1925 p = isl_printer_print_str(p, "; ");
1926 space = isl_qpolynomial_get_domain_space(pwqp->p[i].qp);
1927 if (!isl_space_is_params(space)) {
1928 p = isl_print_space(space, p, 0, &data);
1929 p = isl_printer_print_str(p, " -> ");
1931 p = print_qpolynomial(p, pwqp->p[i].qp);
1932 p = print_disjuncts(set_to_map(pwqp->p[i].set), space, p, 0);
1933 isl_space_free(space);
1936 return p;
1939 static __isl_give isl_printer *print_pw_qpolynomial_isl(
1940 __isl_take isl_printer *p, __isl_keep isl_pw_qpolynomial *pwqp)
1942 struct isl_print_space_data data = { 0 };
1944 if (!p || !pwqp)
1945 goto error;
1947 p = print_param_tuple(p, pwqp->dim, &data);
1948 p = isl_printer_print_str(p, "{ ");
1949 if (pwqp->n == 0) {
1950 if (!isl_space_is_set(pwqp->dim)) {
1951 p = print_tuple(pwqp->dim, p, isl_dim_in, &data);
1952 p = isl_printer_print_str(p, " -> ");
1954 p = isl_printer_print_str(p, "0");
1956 p = isl_pwqp_print_isl_body(p, pwqp);
1957 p = isl_printer_print_str(p, " }");
1958 return p;
1959 error:
1960 isl_printer_free(p);
1961 return NULL;
1964 void isl_pw_qpolynomial_print(__isl_keep isl_pw_qpolynomial *pwqp, FILE *out,
1965 unsigned output_format)
1967 isl_printer *p;
1969 if (!pwqp)
1970 return;
1972 p = isl_printer_to_file(pwqp->dim->ctx, out);
1973 p = isl_printer_set_output_format(p, output_format);
1974 p = isl_printer_print_pw_qpolynomial(p, pwqp);
1976 isl_printer_free(p);
1979 static __isl_give isl_printer *isl_pwf_print_isl_body(
1980 __isl_take isl_printer *p, __isl_keep isl_pw_qpolynomial_fold *pwf)
1982 struct isl_print_space_data data = { 0 };
1983 int i = 0;
1985 for (i = 0; i < pwf->n; ++i) {
1986 isl_space *space;
1988 if (i)
1989 p = isl_printer_print_str(p, "; ");
1990 space = isl_qpolynomial_fold_get_domain_space(pwf->p[i].fold);
1991 if (!isl_space_is_params(space)) {
1992 p = isl_print_space(space, p, 0, &data);
1993 p = isl_printer_print_str(p, " -> ");
1995 p = qpolynomial_fold_print(pwf->p[i].fold, p);
1996 p = print_disjuncts(set_to_map(pwf->p[i].set), space, p, 0);
1997 isl_space_free(space);
2000 return p;
2003 static __isl_give isl_printer *print_pw_qpolynomial_fold_isl(
2004 __isl_take isl_printer *p, __isl_keep isl_pw_qpolynomial_fold *pwf)
2006 struct isl_print_space_data data = { 0 };
2008 p = print_param_tuple(p, pwf->dim, &data);
2009 p = isl_printer_print_str(p, "{ ");
2010 if (pwf->n == 0) {
2011 if (!isl_space_is_set(pwf->dim)) {
2012 p = print_tuple(pwf->dim, p, isl_dim_in, &data);
2013 p = isl_printer_print_str(p, " -> ");
2015 p = isl_printer_print_str(p, "0");
2017 p = isl_pwf_print_isl_body(p, pwf);
2018 p = isl_printer_print_str(p, " }");
2019 return p;
2022 static __isl_give isl_printer *print_affine_c(__isl_take isl_printer *p,
2023 __isl_keep isl_space *dim, __isl_keep isl_basic_set *bset, isl_int *c);
2025 static __isl_give isl_printer *print_name_c(__isl_take isl_printer *p,
2026 __isl_keep isl_space *dim,
2027 __isl_keep isl_basic_set *bset, enum isl_dim_type type, unsigned pos)
2029 if (type == isl_dim_div) {
2030 p = isl_printer_print_str(p, "floord(");
2031 p = print_affine_c(p, dim, bset, bset->div[pos] + 1);
2032 p = isl_printer_print_str(p, ", ");
2033 p = isl_printer_print_isl_int(p, bset->div[pos][0]);
2034 p = isl_printer_print_str(p, ")");
2035 } else {
2036 const char *name;
2038 name = isl_space_get_dim_name(dim, type, pos);
2039 if (!name)
2040 name = "UNNAMED";
2041 p = isl_printer_print_str(p, name);
2043 return p;
2046 static __isl_give isl_printer *print_term_c(__isl_take isl_printer *p,
2047 __isl_keep isl_space *dim,
2048 __isl_keep isl_basic_set *bset, isl_int c, unsigned pos)
2050 enum isl_dim_type type;
2052 if (pos == 0)
2053 return isl_printer_print_isl_int(p, c);
2055 if (isl_int_is_one(c))
2057 else if (isl_int_is_negone(c))
2058 p = isl_printer_print_str(p, "-");
2059 else {
2060 p = isl_printer_print_isl_int(p, c);
2061 p = isl_printer_print_str(p, "*");
2063 type = pos2type(dim, &pos);
2064 p = print_name_c(p, dim, bset, type, pos);
2065 return p;
2068 static __isl_give isl_printer *print_partial_affine_c(__isl_take isl_printer *p,
2069 __isl_keep isl_space *dim,
2070 __isl_keep isl_basic_set *bset, isl_int *c, unsigned len)
2072 int i;
2073 int first;
2075 for (i = 0, first = 1; i < len; ++i) {
2076 int flip = 0;
2077 if (isl_int_is_zero(c[i]))
2078 continue;
2079 if (!first) {
2080 if (isl_int_is_neg(c[i])) {
2081 flip = 1;
2082 isl_int_neg(c[i], c[i]);
2083 p = isl_printer_print_str(p, " - ");
2084 } else
2085 p = isl_printer_print_str(p, " + ");
2087 first = 0;
2088 p = print_term_c(p, dim, bset, c[i], i);
2089 if (flip)
2090 isl_int_neg(c[i], c[i]);
2092 if (first)
2093 p = isl_printer_print_str(p, "0");
2094 return p;
2097 static __isl_give isl_printer *print_affine_c(__isl_take isl_printer *p,
2098 __isl_keep isl_space *dim, __isl_keep isl_basic_set *bset, isl_int *c)
2100 unsigned len = 1 + isl_basic_set_total_dim(bset);
2101 return print_partial_affine_c(p, dim, bset, c, len);
2104 /* We skip the constraint if it is implied by the div expression.
2106 * *first indicates whether this is the first constraint in the conjunction and
2107 * is updated if the constraint is actually printed.
2109 static __isl_give isl_printer *print_constraint_c(__isl_take isl_printer *p,
2110 __isl_keep isl_space *dim,
2111 __isl_keep isl_basic_set *bset, isl_int *c, const char *op, int *first)
2113 unsigned o_div;
2114 unsigned n_div;
2115 int div;
2117 o_div = isl_basic_set_offset(bset, isl_dim_div);
2118 n_div = isl_basic_set_dim(bset, isl_dim_div);
2119 div = isl_seq_last_non_zero(c + o_div, n_div);
2120 if (div >= 0) {
2121 isl_bool is_div = isl_basic_set_is_div_constraint(bset, c, div);
2122 if (is_div < 0)
2123 return isl_printer_free(p);
2124 if (is_div)
2125 return p;
2128 if (!*first)
2129 p = isl_printer_print_str(p, " && ");
2131 p = print_affine_c(p, dim, bset, c);
2132 p = isl_printer_print_str(p, " ");
2133 p = isl_printer_print_str(p, op);
2134 p = isl_printer_print_str(p, " 0");
2136 *first = 0;
2138 return p;
2141 static __isl_give isl_printer *print_basic_set_c(__isl_take isl_printer *p,
2142 __isl_keep isl_space *dim, __isl_keep isl_basic_set *bset)
2144 int i, j;
2145 int first = 1;
2146 unsigned n_div = isl_basic_set_dim(bset, isl_dim_div);
2147 unsigned total = isl_basic_set_total_dim(bset) - n_div;
2149 for (i = 0; i < bset->n_eq; ++i) {
2150 j = isl_seq_last_non_zero(bset->eq[i] + 1 + total, n_div);
2151 if (j < 0)
2152 p = print_constraint_c(p, dim, bset,
2153 bset->eq[i], "==", &first);
2154 else {
2155 if (i)
2156 p = isl_printer_print_str(p, " && ");
2157 p = isl_printer_print_str(p, "(");
2158 p = print_partial_affine_c(p, dim, bset, bset->eq[i],
2159 1 + total + j);
2160 p = isl_printer_print_str(p, ") % ");
2161 p = isl_printer_print_isl_int(p,
2162 bset->eq[i][1 + total + j]);
2163 p = isl_printer_print_str(p, " == 0");
2164 first = 0;
2167 for (i = 0; i < bset->n_ineq; ++i)
2168 p = print_constraint_c(p, dim, bset, bset->ineq[i], ">=",
2169 &first);
2170 return p;
2173 static __isl_give isl_printer *print_set_c(__isl_take isl_printer *p,
2174 __isl_keep isl_space *dim, __isl_keep isl_set *set)
2176 int i;
2178 if (!set)
2179 return isl_printer_free(p);
2181 if (set->n == 0)
2182 p = isl_printer_print_str(p, "0");
2184 for (i = 0; i < set->n; ++i) {
2185 if (i)
2186 p = isl_printer_print_str(p, " || ");
2187 if (set->n > 1)
2188 p = isl_printer_print_str(p, "(");
2189 p = print_basic_set_c(p, dim, set->p[i]);
2190 if (set->n > 1)
2191 p = isl_printer_print_str(p, ")");
2193 return p;
2196 /* Print the piecewise quasi-polynomial "pwqp" to "p" in C format.
2198 static __isl_give isl_printer *print_pw_qpolynomial_c(
2199 __isl_take isl_printer *p, __isl_keep isl_pw_qpolynomial *pwqp)
2201 int i;
2202 isl_space *space;
2204 space = isl_pw_qpolynomial_get_domain_space(pwqp);
2205 if (pwqp->n == 1 && isl_set_plain_is_universe(pwqp->p[0].set)) {
2206 p = print_qpolynomial_c(p, space, pwqp->p[0].qp);
2207 isl_space_free(space);
2208 return p;
2211 for (i = 0; i < pwqp->n; ++i) {
2212 p = isl_printer_print_str(p, "(");
2213 p = print_set_c(p, space, pwqp->p[i].set);
2214 p = isl_printer_print_str(p, ") ? (");
2215 p = print_qpolynomial_c(p, space, pwqp->p[i].qp);
2216 p = isl_printer_print_str(p, ") : ");
2219 isl_space_free(space);
2220 p = isl_printer_print_str(p, "0");
2221 return p;
2224 __isl_give isl_printer *isl_printer_print_pw_qpolynomial(
2225 __isl_take isl_printer *p, __isl_keep isl_pw_qpolynomial *pwqp)
2227 if (!p || !pwqp)
2228 goto error;
2230 if (p->output_format == ISL_FORMAT_ISL)
2231 return print_pw_qpolynomial_isl(p, pwqp);
2232 else if (p->output_format == ISL_FORMAT_C)
2233 return print_pw_qpolynomial_c(p, pwqp);
2234 isl_assert(p->ctx, 0, goto error);
2235 error:
2236 isl_printer_free(p);
2237 return NULL;
2240 static isl_stat print_pwqp_body(__isl_take isl_pw_qpolynomial *pwqp, void *user)
2242 struct isl_union_print_data *data;
2243 data = (struct isl_union_print_data *)user;
2245 if (!data->first)
2246 data->p = isl_printer_print_str(data->p, "; ");
2247 data->first = 0;
2249 data->p = isl_pwqp_print_isl_body(data->p, pwqp);
2250 isl_pw_qpolynomial_free(pwqp);
2252 return isl_stat_ok;
2255 static __isl_give isl_printer *print_union_pw_qpolynomial_isl(
2256 __isl_take isl_printer *p, __isl_keep isl_union_pw_qpolynomial *upwqp)
2258 struct isl_union_print_data data;
2259 struct isl_print_space_data space_data = { 0 };
2260 isl_space *space;
2262 space = isl_union_pw_qpolynomial_get_space(upwqp);
2263 p = print_param_tuple(p, space, &space_data);
2264 isl_space_free(space);
2265 p = isl_printer_print_str(p, "{ ");
2266 data.p = p;
2267 data.first = 1;
2268 isl_union_pw_qpolynomial_foreach_pw_qpolynomial(upwqp, &print_pwqp_body,
2269 &data);
2270 p = data.p;
2271 p = isl_printer_print_str(p, " }");
2272 return p;
2275 __isl_give isl_printer *isl_printer_print_union_pw_qpolynomial(
2276 __isl_take isl_printer *p, __isl_keep isl_union_pw_qpolynomial *upwqp)
2278 if (!p || !upwqp)
2279 goto error;
2281 if (p->output_format == ISL_FORMAT_ISL)
2282 return print_union_pw_qpolynomial_isl(p, upwqp);
2283 isl_die(p->ctx, isl_error_invalid,
2284 "invalid output format for isl_union_pw_qpolynomial",
2285 goto error);
2286 error:
2287 isl_printer_free(p);
2288 return NULL;
2291 /* Print the quasi-polynomial reduction "fold" to "p" in C format,
2292 * with the variable names taken from the domain space "space".
2294 static __isl_give isl_printer *print_qpolynomial_fold_c(
2295 __isl_take isl_printer *p, __isl_keep isl_space *space,
2296 __isl_keep isl_qpolynomial_fold *fold)
2298 int i;
2300 for (i = 0; i < fold->n - 1; ++i)
2301 if (fold->type == isl_fold_min)
2302 p = isl_printer_print_str(p, "min(");
2303 else if (fold->type == isl_fold_max)
2304 p = isl_printer_print_str(p, "max(");
2306 for (i = 0; i < fold->n; ++i) {
2307 if (i)
2308 p = isl_printer_print_str(p, ", ");
2309 p = print_qpolynomial_c(p, space, fold->qp[i]);
2310 if (i)
2311 p = isl_printer_print_str(p, ")");
2313 return p;
2316 __isl_give isl_printer *isl_printer_print_qpolynomial_fold(
2317 __isl_take isl_printer *p, __isl_keep isl_qpolynomial_fold *fold)
2319 if (!p || !fold)
2320 goto error;
2321 if (p->output_format == ISL_FORMAT_ISL)
2322 return qpolynomial_fold_print(fold, p);
2323 else if (p->output_format == ISL_FORMAT_C)
2324 return print_qpolynomial_fold_c(p, fold->dim, fold);
2325 isl_die(p->ctx, isl_error_unsupported, "unsupported output format",
2326 goto error);
2327 error:
2328 isl_printer_free(p);
2329 return NULL;
2332 /* Print the piecewise quasi-polynomial reduction "pwf" to "p" in C format.
2334 static __isl_give isl_printer *print_pw_qpolynomial_fold_c(
2335 __isl_take isl_printer *p, __isl_keep isl_pw_qpolynomial_fold *pwf)
2337 int i;
2338 isl_space *space;
2340 space = isl_pw_qpolynomial_fold_get_domain_space(pwf);
2341 if (pwf->n == 1 && isl_set_plain_is_universe(pwf->p[0].set)) {
2342 p = print_qpolynomial_fold_c(p, space, pwf->p[0].fold);
2343 isl_space_free(space);
2344 return p;
2347 for (i = 0; i < pwf->n; ++i) {
2348 p = isl_printer_print_str(p, "(");
2349 p = print_set_c(p, space, pwf->p[i].set);
2350 p = isl_printer_print_str(p, ") ? (");
2351 p = print_qpolynomial_fold_c(p, space, pwf->p[i].fold);
2352 p = isl_printer_print_str(p, ") : ");
2355 isl_space_free(space);
2356 p = isl_printer_print_str(p, "0");
2357 return p;
2360 __isl_give isl_printer *isl_printer_print_pw_qpolynomial_fold(
2361 __isl_take isl_printer *p, __isl_keep isl_pw_qpolynomial_fold *pwf)
2363 if (!p || !pwf)
2364 goto error;
2366 if (p->output_format == ISL_FORMAT_ISL)
2367 return print_pw_qpolynomial_fold_isl(p, pwf);
2368 else if (p->output_format == ISL_FORMAT_C)
2369 return print_pw_qpolynomial_fold_c(p, pwf);
2370 isl_assert(p->ctx, 0, goto error);
2371 error:
2372 isl_printer_free(p);
2373 return NULL;
2376 void isl_pw_qpolynomial_fold_print(__isl_keep isl_pw_qpolynomial_fold *pwf,
2377 FILE *out, unsigned output_format)
2379 isl_printer *p;
2381 if (!pwf)
2382 return;
2384 p = isl_printer_to_file(pwf->dim->ctx, out);
2385 p = isl_printer_set_output_format(p, output_format);
2386 p = isl_printer_print_pw_qpolynomial_fold(p, pwf);
2388 isl_printer_free(p);
2391 static isl_stat print_pwf_body(__isl_take isl_pw_qpolynomial_fold *pwf,
2392 void *user)
2394 struct isl_union_print_data *data;
2395 data = (struct isl_union_print_data *)user;
2397 if (!data->first)
2398 data->p = isl_printer_print_str(data->p, "; ");
2399 data->first = 0;
2401 data->p = isl_pwf_print_isl_body(data->p, pwf);
2402 isl_pw_qpolynomial_fold_free(pwf);
2404 return isl_stat_ok;
2407 static __isl_give isl_printer *print_union_pw_qpolynomial_fold_isl(
2408 __isl_take isl_printer *p,
2409 __isl_keep isl_union_pw_qpolynomial_fold *upwf)
2411 struct isl_union_print_data data;
2412 struct isl_print_space_data space_data = { 0 };
2413 isl_space *space;
2415 space = isl_union_pw_qpolynomial_fold_get_space(upwf);
2416 p = print_param_tuple(p, space, &space_data);
2417 isl_space_free(space);
2418 p = isl_printer_print_str(p, "{ ");
2419 data.p = p;
2420 data.first = 1;
2421 isl_union_pw_qpolynomial_fold_foreach_pw_qpolynomial_fold(upwf,
2422 &print_pwf_body, &data);
2423 p = data.p;
2424 p = isl_printer_print_str(p, " }");
2425 return p;
2428 __isl_give isl_printer *isl_printer_print_union_pw_qpolynomial_fold(
2429 __isl_take isl_printer *p,
2430 __isl_keep isl_union_pw_qpolynomial_fold *upwf)
2432 if (!p || !upwf)
2433 goto error;
2435 if (p->output_format == ISL_FORMAT_ISL)
2436 return print_union_pw_qpolynomial_fold_isl(p, upwf);
2437 isl_die(p->ctx, isl_error_invalid,
2438 "invalid output format for isl_union_pw_qpolynomial_fold",
2439 goto error);
2440 error:
2441 isl_printer_free(p);
2442 return NULL;
2445 /* Print the isl_constraint "c" to "p".
2447 __isl_give isl_printer *isl_printer_print_constraint(__isl_take isl_printer *p,
2448 __isl_keep isl_constraint *c)
2450 struct isl_print_space_data data = { 0 };
2451 isl_local_space *ls;
2452 isl_space *space;
2453 isl_bool exists;
2455 if (!p || !c)
2456 goto error;
2458 ls = isl_constraint_get_local_space(c);
2459 if (!ls)
2460 return isl_printer_free(p);
2461 space = isl_local_space_get_space(ls);
2462 p = print_param_tuple(p, space, &data);
2463 p = isl_printer_print_str(p, "{ ");
2464 p = isl_print_space(space, p, 0, &data);
2465 p = isl_printer_print_str(p, " : ");
2466 exists = need_exists(p, ls->div);
2467 if (exists < 0)
2468 p = isl_printer_free(p);
2469 if (exists >= 0 && exists)
2470 p = open_exists(p, space, ls->div, 0);
2471 p = print_affine_of_len(space, ls->div, p, c->v->el, c->v->size);
2472 if (isl_constraint_is_equality(c))
2473 p = isl_printer_print_str(p, " = 0");
2474 else
2475 p = isl_printer_print_str(p, " >= 0");
2476 if (exists >= 0 && exists)
2477 p = isl_printer_print_str(p, s_close_exists[0]);
2478 p = isl_printer_print_str(p, " }");
2479 isl_space_free(space);
2480 isl_local_space_free(ls);
2482 return p;
2483 error:
2484 isl_printer_free(p);
2485 return NULL;
2488 static __isl_give isl_printer *isl_printer_print_space_isl(
2489 __isl_take isl_printer *p, __isl_keep isl_space *space)
2491 struct isl_print_space_data data = { 0 };
2493 if (!space)
2494 goto error;
2496 p = print_param_tuple(p, space, &data);
2498 p = isl_printer_print_str(p, "{ ");
2499 if (isl_space_is_params(space))
2500 p = isl_printer_print_str(p, s_such_that[0]);
2501 else
2502 p = isl_print_space(space, p, 0, &data);
2503 p = isl_printer_print_str(p, " }");
2505 return p;
2506 error:
2507 isl_printer_free(p);
2508 return NULL;
2511 __isl_give isl_printer *isl_printer_print_space(__isl_take isl_printer *p,
2512 __isl_keep isl_space *space)
2514 if (!p || !space)
2515 return isl_printer_free(p);
2516 if (p->output_format == ISL_FORMAT_ISL)
2517 return isl_printer_print_space_isl(p, space);
2518 else if (p->output_format == ISL_FORMAT_OMEGA)
2519 return print_omega_parameters(space, p);
2521 isl_die(isl_space_get_ctx(space), isl_error_unsupported,
2522 "output format not supported for space",
2523 return isl_printer_free(p));
2526 __isl_give isl_printer *isl_printer_print_local_space(__isl_take isl_printer *p,
2527 __isl_keep isl_local_space *ls)
2529 struct isl_print_space_data data = { 0 };
2530 unsigned n_div;
2532 if (!ls)
2533 goto error;
2535 p = print_param_tuple(p, ls->dim, &data);
2536 p = isl_printer_print_str(p, "{ ");
2537 p = isl_print_space(ls->dim, p, 0, &data);
2538 n_div = isl_local_space_dim(ls, isl_dim_div);
2539 if (n_div > 0) {
2540 p = isl_printer_print_str(p, " : ");
2541 p = isl_printer_print_str(p, s_open_exists[0]);
2542 p = print_div_list(p, ls->dim, ls->div, 0, 1);
2543 p = isl_printer_print_str(p, s_close_exists[0]);
2544 } else if (isl_space_is_params(ls->dim))
2545 p = isl_printer_print_str(p, s_such_that[0]);
2546 p = isl_printer_print_str(p, " }");
2547 return p;
2548 error:
2549 isl_printer_free(p);
2550 return NULL;
2553 static __isl_give isl_printer *print_aff_body(__isl_take isl_printer *p,
2554 __isl_keep isl_aff *aff)
2556 unsigned total;
2558 if (isl_aff_is_nan(aff))
2559 return isl_printer_print_str(p, "NaN");
2561 total = isl_local_space_dim(aff->ls, isl_dim_all);
2562 p = isl_printer_print_str(p, "(");
2563 p = print_affine_of_len(aff->ls->dim, aff->ls->div, p,
2564 aff->v->el + 1, 1 + total);
2565 if (isl_int_is_one(aff->v->el[0]))
2566 p = isl_printer_print_str(p, ")");
2567 else {
2568 p = isl_printer_print_str(p, ")/");
2569 p = isl_printer_print_isl_int(p, aff->v->el[0]);
2572 return p;
2575 static __isl_give isl_printer *print_aff(__isl_take isl_printer *p,
2576 __isl_keep isl_aff *aff)
2578 struct isl_print_space_data data = { 0 };
2580 if (isl_space_is_params(aff->ls->dim))
2582 else {
2583 p = print_tuple(aff->ls->dim, p, isl_dim_set, &data);
2584 p = isl_printer_print_str(p, " -> ");
2586 p = isl_printer_print_str(p, "[");
2587 p = print_aff_body(p, aff);
2588 p = isl_printer_print_str(p, "]");
2590 return p;
2593 static __isl_give isl_printer *print_aff_isl(__isl_take isl_printer *p,
2594 __isl_keep isl_aff *aff)
2596 struct isl_print_space_data data = { 0 };
2598 if (!aff)
2599 goto error;
2601 p = print_param_tuple(p, aff->ls->dim, &data);
2602 p = isl_printer_print_str(p, "{ ");
2603 p = print_aff(p, aff);
2604 p = isl_printer_print_str(p, " }");
2605 return p;
2606 error:
2607 isl_printer_free(p);
2608 return NULL;
2611 /* Print the body of an isl_pw_aff, i.e., a semicolon delimited
2612 * sequence of affine expressions, each followed by constraints.
2614 static __isl_give isl_printer *print_pw_aff_body(
2615 __isl_take isl_printer *p, __isl_keep isl_pw_aff *pa)
2617 int i;
2619 if (!pa)
2620 return isl_printer_free(p);
2622 for (i = 0; i < pa->n; ++i) {
2623 isl_space *space;
2625 if (i)
2626 p = isl_printer_print_str(p, "; ");
2627 p = print_aff(p, pa->p[i].aff);
2628 space = isl_aff_get_domain_space(pa->p[i].aff);
2629 p = print_disjuncts(set_to_map(pa->p[i].set), space, p, 0);
2630 isl_space_free(space);
2633 return p;
2636 static __isl_give isl_printer *print_pw_aff_isl(__isl_take isl_printer *p,
2637 __isl_keep isl_pw_aff *pwaff)
2639 struct isl_print_space_data data = { 0 };
2641 if (!pwaff)
2642 goto error;
2644 p = print_param_tuple(p, pwaff->dim, &data);
2645 p = isl_printer_print_str(p, "{ ");
2646 p = print_pw_aff_body(p, pwaff);
2647 p = isl_printer_print_str(p, " }");
2648 return p;
2649 error:
2650 isl_printer_free(p);
2651 return NULL;
2654 static __isl_give isl_printer *print_ls_affine_c(__isl_take isl_printer *p,
2655 __isl_keep isl_local_space *ls, isl_int *c);
2657 static __isl_give isl_printer *print_ls_name_c(__isl_take isl_printer *p,
2658 __isl_keep isl_local_space *ls, enum isl_dim_type type, unsigned pos)
2660 if (type == isl_dim_div) {
2661 p = isl_printer_print_str(p, "floord(");
2662 p = print_ls_affine_c(p, ls, ls->div->row[pos] + 1);
2663 p = isl_printer_print_str(p, ", ");
2664 p = isl_printer_print_isl_int(p, ls->div->row[pos][0]);
2665 p = isl_printer_print_str(p, ")");
2666 } else {
2667 const char *name;
2669 name = isl_space_get_dim_name(ls->dim, type, pos);
2670 if (!name)
2671 name = "UNNAMED";
2672 p = isl_printer_print_str(p, name);
2674 return p;
2677 static __isl_give isl_printer *print_ls_term_c(__isl_take isl_printer *p,
2678 __isl_keep isl_local_space *ls, isl_int c, unsigned pos)
2680 enum isl_dim_type type;
2682 if (pos == 0)
2683 return isl_printer_print_isl_int(p, c);
2685 if (isl_int_is_one(c))
2687 else if (isl_int_is_negone(c))
2688 p = isl_printer_print_str(p, "-");
2689 else {
2690 p = isl_printer_print_isl_int(p, c);
2691 p = isl_printer_print_str(p, "*");
2693 type = pos2type(ls->dim, &pos);
2694 p = print_ls_name_c(p, ls, type, pos);
2695 return p;
2698 static __isl_give isl_printer *print_ls_partial_affine_c(
2699 __isl_take isl_printer *p, __isl_keep isl_local_space *ls,
2700 isl_int *c, unsigned len)
2702 int i;
2703 int first;
2705 for (i = 0, first = 1; i < len; ++i) {
2706 int flip = 0;
2707 if (isl_int_is_zero(c[i]))
2708 continue;
2709 if (!first) {
2710 if (isl_int_is_neg(c[i])) {
2711 flip = 1;
2712 isl_int_neg(c[i], c[i]);
2713 p = isl_printer_print_str(p, " - ");
2714 } else
2715 p = isl_printer_print_str(p, " + ");
2717 first = 0;
2718 p = print_ls_term_c(p, ls, c[i], i);
2719 if (flip)
2720 isl_int_neg(c[i], c[i]);
2722 if (first)
2723 p = isl_printer_print_str(p, "0");
2724 return p;
2727 static __isl_give isl_printer *print_ls_affine_c(__isl_take isl_printer *p,
2728 __isl_keep isl_local_space *ls, isl_int *c)
2730 unsigned len = 1 + isl_local_space_dim(ls, isl_dim_all);
2731 return print_ls_partial_affine_c(p, ls, c, len);
2734 static __isl_give isl_printer *print_aff_c(__isl_take isl_printer *p,
2735 __isl_keep isl_aff *aff)
2737 unsigned total;
2739 total = isl_local_space_dim(aff->ls, isl_dim_all);
2740 if (!isl_int_is_one(aff->v->el[0]))
2741 p = isl_printer_print_str(p, "(");
2742 p = print_ls_partial_affine_c(p, aff->ls, aff->v->el + 1, 1 + total);
2743 if (!isl_int_is_one(aff->v->el[0])) {
2744 p = isl_printer_print_str(p, ")/");
2745 p = isl_printer_print_isl_int(p, aff->v->el[0]);
2747 return p;
2750 /* In the C format, we cannot express that "pwaff" may be undefined
2751 * on parts of the domain space. We therefore assume that the expression
2752 * will only be evaluated on its definition domain and compute the gist
2753 * of each cell with respect to this domain.
2755 static __isl_give isl_printer *print_pw_aff_c(__isl_take isl_printer *p,
2756 __isl_keep isl_pw_aff *pwaff)
2758 isl_set *domain;
2759 isl_ast_build *build;
2760 isl_ast_expr *expr;
2762 if (pwaff->n < 1)
2763 isl_die(p->ctx, isl_error_unsupported,
2764 "cannot print empty isl_pw_aff in C format",
2765 return isl_printer_free(p));
2767 domain = isl_pw_aff_domain(isl_pw_aff_copy(pwaff));
2768 build = isl_ast_build_from_context(domain);
2769 expr = isl_ast_build_expr_from_pw_aff(build, isl_pw_aff_copy(pwaff));
2770 p = isl_printer_print_ast_expr(p, expr);
2771 isl_ast_expr_free(expr);
2772 isl_ast_build_free(build);
2774 return p;
2777 __isl_give isl_printer *isl_printer_print_aff(__isl_take isl_printer *p,
2778 __isl_keep isl_aff *aff)
2780 if (!p || !aff)
2781 goto error;
2783 if (p->output_format == ISL_FORMAT_ISL)
2784 return print_aff_isl(p, aff);
2785 else if (p->output_format == ISL_FORMAT_C)
2786 return print_aff_c(p, aff);
2787 isl_die(p->ctx, isl_error_unsupported, "unsupported output format",
2788 goto error);
2789 error:
2790 isl_printer_free(p);
2791 return NULL;
2794 __isl_give isl_printer *isl_printer_print_pw_aff(__isl_take isl_printer *p,
2795 __isl_keep isl_pw_aff *pwaff)
2797 if (!p || !pwaff)
2798 goto error;
2800 if (p->output_format == ISL_FORMAT_ISL)
2801 return print_pw_aff_isl(p, pwaff);
2802 else if (p->output_format == ISL_FORMAT_C)
2803 return print_pw_aff_c(p, pwaff);
2804 isl_die(p->ctx, isl_error_unsupported, "unsupported output format",
2805 goto error);
2806 error:
2807 isl_printer_free(p);
2808 return NULL;
2811 /* Print "pa" in a sequence of isl_pw_affs delimited by semicolons.
2812 * Each isl_pw_aff itself is also printed as semicolon delimited
2813 * sequence of pieces.
2814 * If data->first = 1, then this is the first in the sequence.
2815 * Update data->first to tell the next element that it is not the first.
2817 static isl_stat print_pw_aff_body_wrap(__isl_take isl_pw_aff *pa,
2818 void *user)
2820 struct isl_union_print_data *data;
2821 data = (struct isl_union_print_data *) user;
2823 if (!data->first)
2824 data->p = isl_printer_print_str(data->p, "; ");
2825 data->first = 0;
2827 data->p = print_pw_aff_body(data->p, pa);
2828 isl_pw_aff_free(pa);
2830 return data->p ? isl_stat_ok : isl_stat_error;
2833 /* Print the body of an isl_union_pw_aff, i.e., a semicolon delimited
2834 * sequence of affine expressions, each followed by constraints,
2835 * with the sequence enclosed in braces.
2837 static __isl_give isl_printer *print_union_pw_aff_body(
2838 __isl_take isl_printer *p, __isl_keep isl_union_pw_aff *upa)
2840 struct isl_union_print_data data = { p, 1 };
2842 p = isl_printer_print_str(p, s_open_set[0]);
2843 data.p = p;
2844 if (isl_union_pw_aff_foreach_pw_aff(upa,
2845 &print_pw_aff_body_wrap, &data) < 0)
2846 data.p = isl_printer_free(p);
2847 p = data.p;
2848 p = isl_printer_print_str(p, s_close_set[0]);
2850 return p;
2853 /* Print the isl_union_pw_aff "upa" to "p" in isl format.
2855 * The individual isl_pw_affs are delimited by a semicolon.
2857 static __isl_give isl_printer *print_union_pw_aff_isl(
2858 __isl_take isl_printer *p, __isl_keep isl_union_pw_aff *upa)
2860 struct isl_print_space_data data = { 0 };
2861 isl_space *space;
2863 space = isl_union_pw_aff_get_space(upa);
2864 p = print_param_tuple(p, space, &data);
2865 isl_space_free(space);
2866 p = print_union_pw_aff_body(p, upa);
2867 return p;
2870 /* Print the isl_union_pw_aff "upa" to "p".
2872 * We currently only support an isl format.
2874 __isl_give isl_printer *isl_printer_print_union_pw_aff(
2875 __isl_take isl_printer *p, __isl_keep isl_union_pw_aff *upa)
2877 if (!p || !upa)
2878 return isl_printer_free(p);
2880 if (p->output_format == ISL_FORMAT_ISL)
2881 return print_union_pw_aff_isl(p, upa);
2882 isl_die(isl_printer_get_ctx(p), isl_error_unsupported,
2883 "unsupported output format", return isl_printer_free(p));
2886 /* Print dimension "pos" of data->space to "p".
2888 * data->user is assumed to be an isl_multi_aff.
2890 * If the current dimension is an output dimension, then print
2891 * the corresponding expression. Otherwise, print the name of the dimension.
2893 static __isl_give isl_printer *print_dim_ma(__isl_take isl_printer *p,
2894 struct isl_print_space_data *data, unsigned pos)
2896 isl_multi_aff *ma = data->user;
2898 if (data->type == isl_dim_out)
2899 p = print_aff_body(p, ma->p[pos]);
2900 else
2901 p = print_name(data->space, p, data->type, pos, data->latex);
2903 return p;
2906 static __isl_give isl_printer *print_multi_aff(__isl_take isl_printer *p,
2907 __isl_keep isl_multi_aff *maff)
2909 struct isl_print_space_data data = { 0 };
2911 data.print_dim = &print_dim_ma;
2912 data.user = maff;
2913 return isl_print_space(maff->space, p, 0, &data);
2916 static __isl_give isl_printer *print_multi_aff_isl(__isl_take isl_printer *p,
2917 __isl_keep isl_multi_aff *maff)
2919 struct isl_print_space_data data = { 0 };
2921 if (!maff)
2922 goto error;
2924 p = print_param_tuple(p, maff->space, &data);
2925 p = isl_printer_print_str(p, "{ ");
2926 p = print_multi_aff(p, maff);
2927 p = isl_printer_print_str(p, " }");
2928 return p;
2929 error:
2930 isl_printer_free(p);
2931 return NULL;
2934 __isl_give isl_printer *isl_printer_print_multi_aff(__isl_take isl_printer *p,
2935 __isl_keep isl_multi_aff *maff)
2937 if (!p || !maff)
2938 goto error;
2940 if (p->output_format == ISL_FORMAT_ISL)
2941 return print_multi_aff_isl(p, maff);
2942 isl_die(p->ctx, isl_error_unsupported, "unsupported output format",
2943 goto error);
2944 error:
2945 isl_printer_free(p);
2946 return NULL;
2949 static __isl_give isl_printer *print_pw_multi_aff_body(
2950 __isl_take isl_printer *p, __isl_keep isl_pw_multi_aff *pma)
2952 int i;
2954 if (!pma)
2955 goto error;
2957 for (i = 0; i < pma->n; ++i) {
2958 isl_space *space;
2960 if (i)
2961 p = isl_printer_print_str(p, "; ");
2962 p = print_multi_aff(p, pma->p[i].maff);
2963 space = isl_multi_aff_get_domain_space(pma->p[i].maff);
2964 p = print_disjuncts(set_to_map(pma->p[i].set), space, p, 0);
2965 isl_space_free(space);
2967 return p;
2968 error:
2969 isl_printer_free(p);
2970 return NULL;
2973 static __isl_give isl_printer *print_pw_multi_aff_isl(__isl_take isl_printer *p,
2974 __isl_keep isl_pw_multi_aff *pma)
2976 struct isl_print_space_data data = { 0 };
2978 if (!pma)
2979 goto error;
2981 p = print_param_tuple(p, pma->dim, &data);
2982 p = isl_printer_print_str(p, "{ ");
2983 p = print_pw_multi_aff_body(p, pma);
2984 p = isl_printer_print_str(p, " }");
2985 return p;
2986 error:
2987 isl_printer_free(p);
2988 return NULL;
2991 /* Print the unnamed, single-dimensional piecewise multi affine expression "pma"
2992 * to "p".
2994 static __isl_give isl_printer *print_unnamed_pw_multi_aff_c(
2995 __isl_take isl_printer *p, __isl_keep isl_pw_multi_aff *pma)
2997 int i;
2998 isl_space *space;
3000 space = isl_pw_multi_aff_get_domain_space(pma);
3001 for (i = 0; i < pma->n - 1; ++i) {
3002 p = isl_printer_print_str(p, "(");
3003 p = print_set_c(p, space, pma->p[i].set);
3004 p = isl_printer_print_str(p, ") ? (");
3005 p = print_aff_c(p, pma->p[i].maff->p[0]);
3006 p = isl_printer_print_str(p, ") : ");
3008 isl_space_free(space);
3010 return print_aff_c(p, pma->p[pma->n - 1].maff->p[0]);
3013 static __isl_give isl_printer *print_pw_multi_aff_c(__isl_take isl_printer *p,
3014 __isl_keep isl_pw_multi_aff *pma)
3016 int n;
3017 const char *name;
3019 if (!pma)
3020 goto error;
3021 if (pma->n < 1)
3022 isl_die(p->ctx, isl_error_unsupported,
3023 "cannot print empty isl_pw_multi_aff in C format",
3024 goto error);
3025 name = isl_pw_multi_aff_get_tuple_name(pma, isl_dim_out);
3026 if (!name && isl_pw_multi_aff_dim(pma, isl_dim_out) == 1)
3027 return print_unnamed_pw_multi_aff_c(p, pma);
3028 if (!name)
3029 isl_die(p->ctx, isl_error_unsupported,
3030 "cannot print unnamed isl_pw_multi_aff in C format",
3031 goto error);
3033 p = isl_printer_print_str(p, name);
3034 n = isl_pw_multi_aff_dim(pma, isl_dim_out);
3035 if (n != 0)
3036 isl_die(p->ctx, isl_error_unsupported,
3037 "not supported yet", goto error);
3039 return p;
3040 error:
3041 isl_printer_free(p);
3042 return NULL;
3045 __isl_give isl_printer *isl_printer_print_pw_multi_aff(
3046 __isl_take isl_printer *p, __isl_keep isl_pw_multi_aff *pma)
3048 if (!p || !pma)
3049 goto error;
3051 if (p->output_format == ISL_FORMAT_ISL)
3052 return print_pw_multi_aff_isl(p, pma);
3053 if (p->output_format == ISL_FORMAT_C)
3054 return print_pw_multi_aff_c(p, pma);
3055 isl_die(p->ctx, isl_error_unsupported, "unsupported output format",
3056 goto error);
3057 error:
3058 isl_printer_free(p);
3059 return NULL;
3062 static isl_stat print_pw_multi_aff_body_wrap(__isl_take isl_pw_multi_aff *pma,
3063 void *user)
3065 struct isl_union_print_data *data;
3066 data = (struct isl_union_print_data *) user;
3068 if (!data->first)
3069 data->p = isl_printer_print_str(data->p, "; ");
3070 data->first = 0;
3072 data->p = print_pw_multi_aff_body(data->p, pma);
3073 isl_pw_multi_aff_free(pma);
3075 return isl_stat_ok;
3078 static __isl_give isl_printer *print_union_pw_multi_aff_isl(
3079 __isl_take isl_printer *p, __isl_keep isl_union_pw_multi_aff *upma)
3081 struct isl_union_print_data data;
3082 struct isl_print_space_data space_data = { 0 };
3083 isl_space *space;
3085 space = isl_union_pw_multi_aff_get_space(upma);
3086 p = print_param_tuple(p, space, &space_data);
3087 isl_space_free(space);
3088 p = isl_printer_print_str(p, s_open_set[0]);
3089 data.p = p;
3090 data.first = 1;
3091 isl_union_pw_multi_aff_foreach_pw_multi_aff(upma,
3092 &print_pw_multi_aff_body_wrap, &data);
3093 p = data.p;
3094 p = isl_printer_print_str(p, s_close_set[0]);
3095 return p;
3098 __isl_give isl_printer *isl_printer_print_union_pw_multi_aff(
3099 __isl_take isl_printer *p, __isl_keep isl_union_pw_multi_aff *upma)
3101 if (!p || !upma)
3102 goto error;
3104 if (p->output_format == ISL_FORMAT_ISL)
3105 return print_union_pw_multi_aff_isl(p, upma);
3106 isl_die(p->ctx, isl_error_unsupported, "unsupported output format",
3107 goto error);
3108 error:
3109 isl_printer_free(p);
3110 return NULL;
3113 /* Print dimension "pos" of data->space to "p".
3115 * data->user is assumed to be an isl_multi_pw_aff.
3117 * If the current dimension is an output dimension, then print
3118 * the corresponding piecewise affine expression.
3119 * Otherwise, print the name of the dimension.
3121 static __isl_give isl_printer *print_dim_mpa(__isl_take isl_printer *p,
3122 struct isl_print_space_data *data, unsigned pos)
3124 int i;
3125 int need_parens;
3126 isl_multi_pw_aff *mpa = data->user;
3127 isl_pw_aff *pa;
3129 if (data->type != isl_dim_out)
3130 return print_name(data->space, p, data->type, pos, data->latex);
3132 pa = mpa->p[pos];
3133 if (pa->n == 0)
3134 return isl_printer_print_str(p, "(0 : false)");
3136 need_parens = pa->n != 1 || !isl_set_plain_is_universe(pa->p[0].set);
3137 if (need_parens)
3138 p = isl_printer_print_str(p, "(");
3139 for (i = 0; i < pa->n; ++i) {
3140 isl_space *space;
3142 if (i)
3143 p = isl_printer_print_str(p, "; ");
3144 p = print_aff_body(p, pa->p[i].aff);
3145 space = isl_aff_get_domain_space(pa->p[i].aff);
3146 p = print_disjuncts(pa->p[i].set, space, p, 0);
3147 isl_space_free(space);
3149 if (need_parens)
3150 p = isl_printer_print_str(p, ")");
3152 return p;
3155 /* Print "mpa" to "p" in isl format.
3157 static __isl_give isl_printer *print_multi_pw_aff_isl(__isl_take isl_printer *p,
3158 __isl_keep isl_multi_pw_aff *mpa)
3160 struct isl_print_space_data data = { 0 };
3162 if (!mpa)
3163 return isl_printer_free(p);
3165 p = print_param_tuple(p, mpa->space, &data);
3166 p = isl_printer_print_str(p, "{ ");
3167 data.print_dim = &print_dim_mpa;
3168 data.user = mpa;
3169 p = isl_print_space(mpa->space, p, 0, &data);
3170 p = isl_printer_print_str(p, " }");
3171 return p;
3174 __isl_give isl_printer *isl_printer_print_multi_pw_aff(
3175 __isl_take isl_printer *p, __isl_keep isl_multi_pw_aff *mpa)
3177 if (!p || !mpa)
3178 return isl_printer_free(p);
3180 if (p->output_format == ISL_FORMAT_ISL)
3181 return print_multi_pw_aff_isl(p, mpa);
3182 isl_die(p->ctx, isl_error_unsupported, "unsupported output format",
3183 return isl_printer_free(p));
3186 /* Print dimension "pos" of data->space to "p".
3188 * data->user is assumed to be an isl_multi_val.
3190 * If the current dimension is an output dimension, then print
3191 * the corresponding value. Otherwise, print the name of the dimension.
3193 static __isl_give isl_printer *print_dim_mv(__isl_take isl_printer *p,
3194 struct isl_print_space_data *data, unsigned pos)
3196 isl_multi_val *mv = data->user;
3198 if (data->type == isl_dim_out)
3199 return isl_printer_print_val(p, mv->p[pos]);
3200 else
3201 return print_name(data->space, p, data->type, pos, data->latex);
3204 /* Print the isl_multi_val "mv" to "p" in isl format.
3206 static __isl_give isl_printer *print_multi_val_isl(__isl_take isl_printer *p,
3207 __isl_keep isl_multi_val *mv)
3209 struct isl_print_space_data data = { 0 };
3211 if (!mv)
3212 return isl_printer_free(p);
3214 p = print_param_tuple(p, mv->space, &data);
3215 p = isl_printer_print_str(p, "{ ");
3216 data.print_dim = &print_dim_mv;
3217 data.user = mv;
3218 p = isl_print_space(mv->space, p, 0, &data);
3219 p = isl_printer_print_str(p, " }");
3220 return p;
3223 /* Print the isl_multi_val "mv" to "p".
3225 * Currently only supported in isl format.
3227 __isl_give isl_printer *isl_printer_print_multi_val(
3228 __isl_take isl_printer *p, __isl_keep isl_multi_val *mv)
3230 if (!p || !mv)
3231 return isl_printer_free(p);
3233 if (p->output_format == ISL_FORMAT_ISL)
3234 return print_multi_val_isl(p, mv);
3235 isl_die(p->ctx, isl_error_unsupported, "unsupported output format",
3236 return isl_printer_free(p));
3239 /* Print dimension "pos" of data->space to "p".
3241 * data->user is assumed to be an isl_multi_union_pw_aff.
3243 * The current dimension is necessarily a set dimension, so
3244 * we print the corresponding isl_union_pw_aff, including
3245 * the braces.
3247 static __isl_give isl_printer *print_union_pw_aff_dim(__isl_take isl_printer *p,
3248 struct isl_print_space_data *data, unsigned pos)
3250 isl_multi_union_pw_aff *mupa = data->user;
3251 isl_union_pw_aff *upa;
3253 upa = isl_multi_union_pw_aff_get_union_pw_aff(mupa, pos);
3254 p = print_union_pw_aff_body(p, upa);
3255 isl_union_pw_aff_free(upa);
3257 return p;
3260 /* Print the isl_multi_union_pw_aff "mupa" to "p" in isl format.
3262 static __isl_give isl_printer *print_multi_union_pw_aff_isl(
3263 __isl_take isl_printer *p, __isl_keep isl_multi_union_pw_aff *mupa)
3265 struct isl_print_space_data data = { 0 };
3266 isl_space *space;
3268 space = isl_multi_union_pw_aff_get_space(mupa);
3269 p = print_param_tuple(p, space, &data);
3271 data.print_dim = &print_union_pw_aff_dim;
3272 data.user = mupa;
3274 p = isl_print_space(space, p, 0, &data);
3275 isl_space_free(space);
3277 return p;
3280 /* Print the isl_multi_union_pw_aff "mupa" to "p" in isl format.
3282 * We currently only support an isl format.
3284 __isl_give isl_printer *isl_printer_print_multi_union_pw_aff(
3285 __isl_take isl_printer *p, __isl_keep isl_multi_union_pw_aff *mupa)
3287 if (!p || !mupa)
3288 return isl_printer_free(p);
3290 if (p->output_format == ISL_FORMAT_ISL)
3291 return print_multi_union_pw_aff_isl(p, mupa);
3292 isl_die(isl_printer_get_ctx(p), isl_error_unsupported,
3293 "unsupported output format", return isl_printer_free(p));