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