1/*
2 * Copyright 2008-2009 Katholieke Universiteit Leuven
3 * Copyright 2010      INRIA Saclay
4 *
5 * Use of this software is governed by the MIT license
6 *
7 * Written by Sven Verdoolaege, K.U.Leuven, Departement
8 * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
9 * and INRIA Saclay - Ile-de-France, Parc Club Orsay Universite,
10 * ZAC des vignes, 4 rue Jacques Monod, 91893 Orsay, France
11 */
12
13#include <stdlib.h>
14#include <string.h>
15#include <isl_ctx_private.h>
16#include <isl_map_private.h>
17#include <isl/set.h>
18#include <isl/seq.h>
19#include <isl_polynomial_private.h>
20#include <isl_printer_private.h>
21#include <isl_space_private.h>
22#include <isl_mat_private.h>
23#include <isl/union_map.h>
24#include <isl/constraint.h>
25#include <isl_local_space_private.h>
26#include <isl_aff_private.h>
27#include <isl_ast_build_expr.h>
28#include <isl_sort.h>
29
30static const char *s_to[2] = { " -> ", " \\to " };
31static const char *s_and[2] = { " and ", " \\wedge " };
32static const char *s_or[2] = { " or ", " \\vee " };
33static const char *s_le[2] = { "<=", "\\le" };
34static const char *s_ge[2] = { ">=", "\\ge" };
35static const char *s_open_set[2] = { "{ ", "\\{\\, " };
36static const char *s_close_set[2] = { " }", " \\,\\}" };
37static const char *s_open_list[2] = { "[", "(" };
38static const char *s_close_list[2] = { "]", ")" };
39static const char *s_such_that[2] = { " : ", " \\mid " };
40static const char *s_open_exists[2] = { "exists (", "\\exists \\, " };
41static const char *s_close_exists[2] = { ")", "" };
42static const char *s_div_prefix[2] = { "e", "\\alpha_" };
43static const char *s_param_prefix[2] = { "p", "p_" };
44static const char *s_input_prefix[2] = { "i", "i_" };
45static const char *s_output_prefix[2] = { "o", "o_" };
46
47static __isl_give isl_printer *print_constraint_polylib(
48	struct isl_basic_map *bmap, int ineq, int n, __isl_take isl_printer *p)
49{
50	int i;
51	unsigned n_in = isl_basic_map_dim(bmap, isl_dim_in);
52	unsigned n_out = isl_basic_map_dim(bmap, isl_dim_out);
53	unsigned nparam = isl_basic_map_dim(bmap, isl_dim_param);
54	isl_int *c = ineq ? bmap->ineq[n] : bmap->eq[n];
55
56	p = isl_printer_start_line(p);
57	p = isl_printer_print_int(p, ineq);
58	for (i = 0; i < n_out; ++i) {
59		p = isl_printer_print_str(p, " ");
60		p = isl_printer_print_isl_int(p, c[1+nparam+n_in+i]);
61	}
62	for (i = 0; i < n_in; ++i) {
63		p = isl_printer_print_str(p, " ");
64		p = isl_printer_print_isl_int(p, c[1+nparam+i]);
65	}
66	for (i = 0; i < bmap->n_div; ++i) {
67		p = isl_printer_print_str(p, " ");
68		p = isl_printer_print_isl_int(p, c[1+nparam+n_in+n_out+i]);
69	}
70	for (i = 0; i < nparam; ++i) {
71		p = isl_printer_print_str(p, " ");
72		p = isl_printer_print_isl_int(p, c[1+i]);
73	}
74	p = isl_printer_print_str(p, " ");
75	p = isl_printer_print_isl_int(p, c[0]);
76	p = isl_printer_end_line(p);
77	return p;
78}
79
80static __isl_give isl_printer *print_constraints_polylib(
81	struct isl_basic_map *bmap, __isl_take isl_printer *p)
82{
83	int i;
84
85	p = isl_printer_set_isl_int_width(p, 5);
86
87	for (i = 0; i < bmap->n_eq; ++i)
88		p = print_constraint_polylib(bmap, 0, i, p);
89	for (i = 0; i < bmap->n_ineq; ++i)
90		p = print_constraint_polylib(bmap, 1, i, p);
91
92	return p;
93}
94
95static __isl_give isl_printer *bset_print_constraints_polylib(
96	struct isl_basic_set *bset, __isl_take isl_printer *p)
97{
98	return print_constraints_polylib((struct isl_basic_map *)bset, p);
99}
100
101static __isl_give isl_printer *isl_basic_map_print_polylib(
102	__isl_keep isl_basic_map *bmap, __isl_take isl_printer *p, int ext)
103{
104	unsigned total = isl_basic_map_total_dim(bmap);
105	p = isl_printer_start_line(p);
106	p = isl_printer_print_int(p, bmap->n_eq + bmap->n_ineq);
107	p = isl_printer_print_str(p, " ");
108	p = isl_printer_print_int(p, 1 + total + 1);
109	if (ext) {
110		p = isl_printer_print_str(p, " ");
111		p = isl_printer_print_int(p,
112				    isl_basic_map_dim(bmap, isl_dim_out));
113		p = isl_printer_print_str(p, " ");
114		p = isl_printer_print_int(p,
115				    isl_basic_map_dim(bmap, isl_dim_in));
116		p = isl_printer_print_str(p, " ");
117		p = isl_printer_print_int(p,
118				    isl_basic_map_dim(bmap, isl_dim_div));
119		p = isl_printer_print_str(p, " ");
120		p = isl_printer_print_int(p,
121				    isl_basic_map_dim(bmap, isl_dim_param));
122	}
123	p = isl_printer_end_line(p);
124	return print_constraints_polylib(bmap, p);
125}
126
127static __isl_give isl_printer *isl_basic_set_print_polylib(
128	__isl_keep isl_basic_set *bset, __isl_take isl_printer *p, int ext)
129{
130	return isl_basic_map_print_polylib((struct isl_basic_map *)bset, p, ext);
131}
132
133static __isl_give isl_printer *isl_map_print_polylib(__isl_keep isl_map *map,
134	__isl_take isl_printer *p, int ext)
135{
136	int i;
137
138	p = isl_printer_start_line(p);
139	p = isl_printer_print_int(p, map->n);
140	p = isl_printer_end_line(p);
141	for (i = 0; i < map->n; ++i) {
142		p = isl_printer_start_line(p);
143		p = isl_printer_end_line(p);
144		p = isl_basic_map_print_polylib(map->p[i], p, ext);
145	}
146	return p;
147}
148
149static __isl_give isl_printer *isl_set_print_polylib(__isl_keep isl_set *set,
150	__isl_take isl_printer *p, int ext)
151{
152	return isl_map_print_polylib((struct isl_map *)set, p, ext);
153}
154
155static int count_same_name(__isl_keep isl_space *dim,
156	enum isl_dim_type type, unsigned pos, const char *name)
157{
158	enum isl_dim_type t;
159	unsigned p, s;
160	int count = 0;
161
162	for (t = isl_dim_param; t <= type && t <= isl_dim_out; ++t) {
163		s = t == type ? pos : isl_space_dim(dim, t);
164		for (p = 0; p < s; ++p) {
165			const char *n = isl_space_get_dim_name(dim, t, p);
166			if (n && !strcmp(n, name))
167				count++;
168		}
169	}
170	return count;
171}
172
173static __isl_give isl_printer *print_name(__isl_keep isl_space *dim,
174	__isl_take isl_printer *p, enum isl_dim_type type, unsigned pos,
175	int latex)
176{
177	const char *name;
178	char buffer[20];
179	int primes;
180
181	name = type == isl_dim_div ? NULL : isl_space_get_dim_name(dim, type, pos);
182
183	if (!name) {
184		const char *prefix;
185		if (type == isl_dim_param)
186			prefix = s_param_prefix[latex];
187		else if (type == isl_dim_div)
188			prefix = s_div_prefix[latex];
189		else if (isl_space_is_set(dim) || type == isl_dim_in)
190			prefix = s_input_prefix[latex];
191		else
192			prefix = s_output_prefix[latex];
193		snprintf(buffer, sizeof(buffer), "%s%d", prefix, pos);
194		name = buffer;
195	}
196	primes = count_same_name(dim, name == buffer ? isl_dim_div : type,
197				 pos, name);
198	p = isl_printer_print_str(p, name);
199	while (primes-- > 0)
200		p = isl_printer_print_str(p, "'");
201	return p;
202}
203
204static enum isl_dim_type pos2type(__isl_keep isl_space *dim, unsigned *pos)
205{
206	enum isl_dim_type type;
207	unsigned n_in = isl_space_dim(dim, isl_dim_in);
208	unsigned n_out = isl_space_dim(dim, isl_dim_out);
209	unsigned nparam = isl_space_dim(dim, isl_dim_param);
210
211	if (*pos < 1 + nparam) {
212		type = isl_dim_param;
213		*pos -= 1;
214	} else if (*pos < 1 + nparam + n_in) {
215		type = isl_dim_in;
216		*pos -= 1 + nparam;
217	} else if (*pos < 1 + nparam + n_in + n_out) {
218		type = isl_dim_out;
219		*pos -= 1 + nparam + n_in;
220	} else {
221		type = isl_dim_div;
222		*pos -= 1 + nparam + n_in + n_out;
223	}
224
225	return type;
226}
227
228static __isl_give isl_printer *print_div(__isl_keep isl_space *dim,
229	__isl_keep isl_mat *div, int pos, __isl_take isl_printer *p);
230
231static __isl_give isl_printer *print_term(__isl_keep isl_space *dim,
232	__isl_keep isl_mat *div,
233	isl_int c, unsigned pos, __isl_take isl_printer *p, int latex)
234{
235	enum isl_dim_type type;
236	int print_div_def;
237
238	if (pos == 0)
239		return isl_printer_print_isl_int(p, c);
240
241	type = pos2type(dim, &pos);
242	print_div_def = type == isl_dim_div && div &&
243			!isl_int_is_zero(div->row[pos][0]);
244
245	if (isl_int_is_one(c))
246		;
247	else if (isl_int_is_negone(c))
248		p = isl_printer_print_str(p, "-");
249	else {
250		p = isl_printer_print_isl_int(p, c);
251		if (p->output_format == ISL_FORMAT_C || print_div_def)
252			p = isl_printer_print_str(p, "*");
253	}
254	if (print_div_def)
255		p = print_div(dim, div, pos, p);
256	else
257		p = print_name(dim, p, type, pos, latex);
258	return p;
259}
260
261static __isl_give isl_printer *print_affine_of_len(__isl_keep isl_space *dim,
262	__isl_keep isl_mat *div,
263	__isl_take isl_printer *p, isl_int *c, int len)
264{
265	int i;
266	int first;
267
268	for (i = 0, first = 1; i < len; ++i) {
269		int flip = 0;
270		if (isl_int_is_zero(c[i]))
271			continue;
272		if (!first) {
273			if (isl_int_is_neg(c[i])) {
274				flip = 1;
275				isl_int_neg(c[i], c[i]);
276				p = isl_printer_print_str(p, " - ");
277			} else
278				p = isl_printer_print_str(p, " + ");
279		}
280		first = 0;
281		p = print_term(dim, div, c[i], i, p, 0);
282		if (flip)
283			isl_int_neg(c[i], c[i]);
284	}
285	if (first)
286		p = isl_printer_print_str(p, "0");
287	return p;
288}
289
290static __isl_give isl_printer *print_affine(__isl_keep isl_basic_map *bmap,
291	__isl_keep isl_space *dim, __isl_take isl_printer *p, isl_int *c)
292{
293	unsigned len = 1 + isl_basic_map_total_dim(bmap);
294	return print_affine_of_len(dim, NULL, p, c, len);
295}
296
297static int defining_equality(__isl_keep isl_basic_map *eq,
298	__isl_keep isl_space *dim, enum isl_dim_type type, int pos)
299{
300	int i;
301	unsigned total;
302
303	if (!eq)
304		return -1;
305
306	pos += isl_space_offset(dim, type);
307	total = isl_basic_map_total_dim(eq);
308
309	for (i = 0; i < eq->n_eq; ++i) {
310		if (isl_seq_last_non_zero(eq->eq[i] + 1, total) != pos)
311			continue;
312		if (isl_int_is_one(eq->eq[i][1 + pos]))
313			isl_seq_neg(eq->eq[i], eq->eq[i], 1 + total);
314		return i;
315	}
316
317	return -1;
318}
319
320static __isl_give isl_printer *print_aff_body(__isl_take isl_printer *p,
321	__isl_keep isl_aff *aff);
322
323/* offset is the offset of local_dim inside global_type of global_dim.
324 */
325static __isl_give isl_printer *print_nested_var_list(__isl_take isl_printer *p,
326	__isl_keep isl_space *global_dim, enum isl_dim_type global_type,
327	__isl_keep isl_space *local_dim, enum isl_dim_type local_type,
328	int latex, __isl_keep isl_basic_map *eq,
329	__isl_keep isl_multi_aff *maff, int offset)
330{
331	int i, j;
332
333	if (global_dim != local_dim && local_type == isl_dim_out)
334		offset += local_dim->n_in;
335
336	for (i = 0; i < isl_space_dim(local_dim, local_type); ++i) {
337		if (i)
338			p = isl_printer_print_str(p, ", ");
339		if (maff && global_type == isl_dim_out) {
340			p = print_aff_body(p, maff->p[offset + i]);
341			continue;
342		}
343		j = defining_equality(eq, global_dim, global_type, offset + i);
344		if (j >= 0) {
345			int pos = 1 + isl_space_offset(global_dim, global_type)
346				    + offset + i;
347			p = print_affine_of_len(eq->dim, NULL,
348						p, eq->eq[j], pos);
349		} else {
350			p = print_name(global_dim, p, global_type, offset + i,
351					latex);
352		}
353	}
354	return p;
355}
356
357static __isl_give isl_printer *print_var_list(__isl_keep isl_space *dim,
358	__isl_take isl_printer *p, enum isl_dim_type type,
359	int latex, __isl_keep isl_basic_map *eq, __isl_keep isl_multi_aff *maff)
360{
361	return print_nested_var_list(p, dim, type, dim, type, latex,
362					eq, maff, 0);
363}
364
365static __isl_give isl_printer *print_nested_map_dim(__isl_take isl_printer *p,
366	__isl_keep isl_space *global_dim, enum isl_dim_type global_type,
367	__isl_keep isl_space *local_dim,
368	int latex, __isl_keep isl_basic_map *eq,
369	__isl_keep isl_multi_aff *maff, int offset);
370
371static __isl_give isl_printer *print_nested_tuple(__isl_take isl_printer *p,
372	__isl_keep isl_space *global_dim, enum isl_dim_type global_type,
373	__isl_keep isl_space *local_dim, enum isl_dim_type local_type,
374	int latex, __isl_keep isl_basic_map *eq,
375	__isl_keep isl_multi_aff *maff, int offset)
376{
377	const char *name = NULL;
378	unsigned n = isl_space_dim(local_dim, local_type);
379	if ((local_type == isl_dim_in || local_type == isl_dim_out)) {
380		name = isl_space_get_tuple_name(local_dim, local_type);
381		if (name) {
382			if (latex)
383				p = isl_printer_print_str(p, "\\mathrm{");
384			p = isl_printer_print_str(p, name);
385			if (latex)
386				p = isl_printer_print_str(p, "}");
387		}
388	}
389	if (!latex || n != 1 || name)
390		p = isl_printer_print_str(p, s_open_list[latex]);
391	if ((local_type == isl_dim_in || local_type == isl_dim_out) &&
392	    local_dim->nested[local_type - isl_dim_in]) {
393		if (global_dim != local_dim && local_type == isl_dim_out)
394			offset += local_dim->n_in;
395		p = print_nested_map_dim(p, global_dim, global_type,
396				local_dim->nested[local_type - isl_dim_in],
397				latex, eq, maff, offset);
398	} else
399		p = print_nested_var_list(p, global_dim, global_type,
400					  local_dim, local_type, latex,
401					  eq, maff, offset);
402	if (!latex || n != 1 || name)
403		p = isl_printer_print_str(p, s_close_list[latex]);
404	return p;
405}
406
407static __isl_give isl_printer *print_tuple(__isl_keep isl_space *dim,
408	__isl_take isl_printer *p, enum isl_dim_type type,
409	int latex, __isl_keep isl_basic_map *eq, __isl_keep isl_multi_aff *maff)
410{
411	return print_nested_tuple(p, dim, type, dim, type, latex, eq, maff, 0);
412}
413
414static __isl_give isl_printer *print_nested_map_dim(__isl_take isl_printer *p,
415	__isl_keep isl_space *global_dim, enum isl_dim_type global_type,
416	__isl_keep isl_space *local_dim,
417	int latex, __isl_keep isl_basic_map *eq,
418	__isl_keep isl_multi_aff *maff, int offset)
419{
420	p = print_nested_tuple(p, global_dim, global_type,
421			local_dim, isl_dim_in, latex, eq, maff, offset);
422	p = isl_printer_print_str(p, s_to[latex]);
423	p = print_nested_tuple(p, global_dim, global_type,
424			local_dim, isl_dim_out, latex, eq, maff, offset);
425
426	return p;
427}
428
429static __isl_give isl_printer *print_space(__isl_keep isl_space *dim,
430	__isl_take isl_printer *p, int latex, int rational,
431	__isl_keep isl_basic_map *eq, __isl_keep isl_multi_aff *maff)
432{
433	if (rational && !latex)
434		p = isl_printer_print_str(p, "rat: ");
435	if (isl_space_is_params(dim))
436		;
437	else if (isl_space_is_set(dim))
438		p = print_tuple(dim, p, isl_dim_set, latex, eq, maff);
439	else {
440		p = print_tuple(dim, p, isl_dim_in, latex, eq, maff);
441		p = isl_printer_print_str(p, s_to[latex]);
442		p = print_tuple(dim, p, isl_dim_out, latex, eq, maff);
443	}
444
445	return p;
446}
447
448static __isl_give isl_printer *print_omega_parameters(__isl_keep isl_space *dim,
449	__isl_take isl_printer *p)
450{
451	if (isl_space_dim(dim, isl_dim_param) == 0)
452		return p;
453
454	p = isl_printer_start_line(p);
455	p = isl_printer_print_str(p, "symbolic ");
456	p = print_var_list(dim, p, isl_dim_param, 0, NULL, NULL);
457	p = isl_printer_print_str(p, ";");
458	p = isl_printer_end_line(p);
459	return p;
460}
461
462static __isl_give isl_printer *print_constraint(struct isl_basic_map *bmap,
463	__isl_keep isl_space *dim, __isl_take isl_printer *p,
464	isl_int *c, int last, const char *op, int first_constraint, int latex)
465{
466	if (!first_constraint)
467		p = isl_printer_print_str(p, s_and[latex]);
468
469	isl_int_abs(c[last], c[last]);
470
471	p = print_term(dim, NULL, c[last], last, p, latex);
472
473	p = isl_printer_print_str(p, " ");
474	p = isl_printer_print_str(p, op);
475	p = isl_printer_print_str(p, " ");
476
477	isl_int_set_si(c[last], 0);
478	p = print_affine(bmap, dim, p, c);
479
480	return p;
481}
482
483static __isl_give isl_printer *print_constraints(__isl_keep isl_basic_map *bmap,
484	__isl_keep isl_space *dim, __isl_take isl_printer *p, int latex)
485{
486	int i;
487	struct isl_vec *c;
488	unsigned total = isl_basic_map_total_dim(bmap);
489
490	c = isl_vec_alloc(bmap->ctx, 1 + total);
491	if (!c)
492		goto error;
493
494	for (i = bmap->n_eq - 1; i >= 0; --i) {
495		int l = isl_seq_last_non_zero(bmap->eq[i], 1 + total);
496		if (l < 0) {
497			if (i != bmap->n_eq - 1)
498				p = isl_printer_print_str(p, s_and[latex]);
499			p = isl_printer_print_str(p, "0 = 0");
500			continue;
501		}
502		if (isl_int_is_neg(bmap->eq[i][l]))
503			isl_seq_cpy(c->el, bmap->eq[i], 1 + total);
504		else
505			isl_seq_neg(c->el, bmap->eq[i], 1 + total);
506		p = print_constraint(bmap, dim, p, c->el, l,
507				    "=", i == bmap->n_eq - 1, latex);
508	}
509	for (i = 0; i < bmap->n_ineq; ++i) {
510		int l = isl_seq_last_non_zero(bmap->ineq[i], 1 + total);
511		int s;
512		const char *op;
513		if (l < 0)
514			continue;
515		s = isl_int_sgn(bmap->ineq[i][l]);
516		if (s < 0)
517			isl_seq_cpy(c->el, bmap->ineq[i], 1 + total);
518		else
519			isl_seq_neg(c->el, bmap->ineq[i], 1 + total);
520		op = s < 0 ? s_le[latex] : s_ge[latex];
521		p = print_constraint(bmap, dim, p, c->el, l,
522					op, !bmap->n_eq && !i, latex);
523	}
524
525	isl_vec_free(c);
526
527	return p;
528error:
529	isl_vec_free(c);
530	isl_printer_free(p);
531	return NULL;
532}
533
534static __isl_give isl_printer *print_omega_constraints(
535	__isl_keep isl_basic_map *bmap, __isl_take isl_printer *p)
536{
537	if (bmap->n_eq + bmap->n_ineq == 0)
538		return p;
539
540	p = isl_printer_print_str(p, ": ");
541	if (bmap->n_div > 0) {
542		int i;
543		p = isl_printer_print_str(p, "exists (");
544		for (i = 0; i < bmap->n_div; ++i) {
545			if (i)
546				p = isl_printer_print_str(p, ", ");
547			p = print_name(bmap->dim, p, isl_dim_div, i, 0);
548		}
549		p = isl_printer_print_str(p, ": ");
550	}
551	p = print_constraints(bmap, bmap->dim, p, 0);
552	if (bmap->n_div > 0)
553		p = isl_printer_print_str(p, ")");
554	return p;
555}
556
557static __isl_give isl_printer *basic_map_print_omega(
558	__isl_keep isl_basic_map *bmap, __isl_take isl_printer *p)
559{
560	p = isl_printer_print_str(p, "{ [");
561	p = print_var_list(bmap->dim, p, isl_dim_in, 0, NULL, NULL);
562	p = isl_printer_print_str(p, "] -> [");
563	p = print_var_list(bmap->dim, p, isl_dim_out, 0, NULL, NULL);
564	p = isl_printer_print_str(p, "] ");
565	p = print_omega_constraints(bmap, p);
566	p = isl_printer_print_str(p, " }");
567	return p;
568}
569
570static __isl_give isl_printer *basic_set_print_omega(
571	__isl_keep isl_basic_set *bset, __isl_take isl_printer *p)
572{
573	p = isl_printer_print_str(p, "{ [");
574	p = print_var_list(bset->dim, p, isl_dim_set, 0, NULL, NULL);
575	p = isl_printer_print_str(p, "] ");
576	p = print_omega_constraints((isl_basic_map *)bset, p);
577	p = isl_printer_print_str(p, " }");
578	return p;
579}
580
581static __isl_give isl_printer *isl_map_print_omega(__isl_keep isl_map *map,
582	__isl_take isl_printer *p)
583{
584	int i;
585
586	for (i = 0; i < map->n; ++i) {
587		if (i)
588			p = isl_printer_print_str(p, " union ");
589		p = basic_map_print_omega(map->p[i], p);
590	}
591	return p;
592}
593
594static __isl_give isl_printer *isl_set_print_omega(__isl_keep isl_set *set,
595	__isl_take isl_printer *p)
596{
597	int i;
598
599	for (i = 0; i < set->n; ++i) {
600		if (i)
601			p = isl_printer_print_str(p, " union ");
602		p = basic_set_print_omega(set->p[i], p);
603	}
604	return p;
605}
606
607static __isl_give isl_printer *print_disjunct(__isl_keep isl_basic_map *bmap,
608	__isl_keep isl_space *dim, __isl_take isl_printer *p, int latex)
609{
610	if (bmap->n_div > 0) {
611		int i;
612		p = isl_printer_print_str(p, s_open_exists[latex]);
613		for (i = 0; i < bmap->n_div; ++i) {
614			if (i)
615				p = isl_printer_print_str(p, ", ");
616			p = print_name(dim, p, isl_dim_div, i, latex);
617			if (latex || isl_int_is_zero(bmap->div[i][0]))
618				continue;
619			p = isl_printer_print_str(p, " = [(");
620			p = print_affine(bmap, dim, p, bmap->div[i] + 1);
621			p = isl_printer_print_str(p, ")/");
622			p = isl_printer_print_isl_int(p, bmap->div[i][0]);
623			p = isl_printer_print_str(p, "]");
624		}
625		p = isl_printer_print_str(p, ": ");
626	}
627
628	p = print_constraints(bmap, dim, p, latex);
629
630	if (bmap->n_div > 0)
631		p = isl_printer_print_str(p, s_close_exists[latex]);
632	return p;
633}
634
635static __isl_give isl_printer *isl_basic_map_print_isl(
636	__isl_keep isl_basic_map *bmap, __isl_take isl_printer *p,
637	int latex)
638{
639	int rational = ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL);
640	if (isl_basic_map_dim(bmap, isl_dim_param) > 0) {
641		p = print_tuple(bmap->dim, p, isl_dim_param, latex, NULL, NULL);
642		p = isl_printer_print_str(p, " -> ");
643	}
644	p = isl_printer_print_str(p, "{ ");
645	p = print_space(bmap->dim, p, latex, rational, NULL, NULL);
646	p = isl_printer_print_str(p, " : ");
647	p = print_disjunct(bmap, bmap->dim, p, latex);
648	p = isl_printer_print_str(p, " }");
649	return p;
650}
651
652static __isl_give isl_printer *print_disjuncts(__isl_keep isl_map *map,
653	__isl_take isl_printer *p, int latex)
654{
655	int i;
656
657	if (isl_map_plain_is_universe(map))
658		return p;
659
660	p = isl_printer_print_str(p, s_such_that[latex]);
661	if (map->n == 0)
662		p = isl_printer_print_str(p, "1 = 0");
663	for (i = 0; i < map->n; ++i) {
664		if (i)
665			p = isl_printer_print_str(p, s_or[latex]);
666		if (map->n > 1 && map->p[i]->n_eq + map->p[i]->n_ineq > 1)
667			p = isl_printer_print_str(p, "(");
668		p = print_disjunct(map->p[i], map->dim, p, latex);
669		if (map->n > 1 && map->p[i]->n_eq + map->p[i]->n_ineq > 1)
670			p = isl_printer_print_str(p, ")");
671	}
672	return p;
673}
674
675/* Print the disjuncts of a map (or set).
676 * If the map turns out to be a universal parameter domain, then
677 * we need to print the colon.  Otherwise, the output looks identical
678 * to the empty set.
679 */
680static __isl_give isl_printer *print_disjuncts_map(__isl_keep isl_map *map,
681	__isl_take isl_printer *p, int latex)
682{
683	if (isl_map_plain_is_universe(map) && isl_space_is_params(map->dim))
684		return isl_printer_print_str(p, s_such_that[latex]);
685	else
686		return print_disjuncts(map, p, latex);
687}
688
689struct isl_aff_split {
690	isl_basic_map *aff;
691	isl_map *map;
692};
693
694static void free_split(__isl_take struct isl_aff_split *split, int n)
695{
696	int i;
697
698	if (!split)
699		return;
700
701	for (i = 0; i < n; ++i) {
702		isl_basic_map_free(split[i].aff);
703		isl_map_free(split[i].map);
704	}
705
706	free(split);
707}
708
709static __isl_give isl_basic_map *get_aff(__isl_take isl_basic_map *bmap)
710{
711	int i, j;
712	unsigned nparam, n_in, n_out, total;
713
714	bmap = isl_basic_map_cow(bmap);
715	if (!bmap)
716		return NULL;
717	if (isl_basic_map_free_inequality(bmap, bmap->n_ineq) < 0)
718		goto error;
719
720	nparam = isl_basic_map_dim(bmap, isl_dim_param);
721	n_in = isl_basic_map_dim(bmap, isl_dim_in);
722	n_out = isl_basic_map_dim(bmap, isl_dim_out);
723	total = isl_basic_map_dim(bmap, isl_dim_all);
724	for (i = bmap->n_eq - 1; i >= 0; --i) {
725		j = isl_seq_last_non_zero(bmap->eq[i] + 1, total);
726		if (j >= nparam && j < nparam + n_in + n_out &&
727		    (isl_int_is_one(bmap->eq[i][1 + j]) ||
728		     isl_int_is_negone(bmap->eq[i][1 + j])))
729			continue;
730		if (isl_basic_map_drop_equality(bmap, i) < 0)
731			goto error;
732	}
733
734	bmap = isl_basic_map_finalize(bmap);
735
736	return bmap;
737error:
738	isl_basic_map_free(bmap);
739	return NULL;
740}
741
742static int aff_split_cmp(const void *p1, const void *p2, void *user)
743{
744	const struct isl_aff_split *s1, *s2;
745	s1 = (const struct isl_aff_split *) p1;
746	s2 = (const struct isl_aff_split *) p2;
747
748	return isl_basic_map_plain_cmp(s1->aff, s2->aff);
749}
750
751static __isl_give isl_basic_map *drop_aff(__isl_take isl_basic_map *bmap,
752	__isl_keep isl_basic_map *aff)
753{
754	int i, j;
755	unsigned total;
756
757	if (!bmap || !aff)
758		goto error;
759
760	total = isl_space_dim(bmap->dim, isl_dim_all);
761
762	for (i = bmap->n_eq - 1; i >= 0; --i) {
763		if (isl_seq_first_non_zero(bmap->eq[i] + 1 + total,
764					    bmap->n_div) != -1)
765			continue;
766		for (j = 0; j < aff->n_eq; ++j) {
767			if (!isl_seq_eq(bmap->eq[i], aff->eq[j], 1 + total) &&
768			    !isl_seq_is_neg(bmap->eq[i], aff->eq[j], 1 + total))
769				continue;
770			if (isl_basic_map_drop_equality(bmap, i) < 0)
771				goto error;
772			break;
773		}
774	}
775
776	return bmap;
777error:
778	isl_basic_map_free(bmap);
779	return NULL;
780}
781
782static __isl_give struct isl_aff_split *split_aff(__isl_keep isl_map *map)
783{
784	int i, n;
785	struct isl_aff_split *split;
786	isl_ctx *ctx;
787
788	ctx = isl_map_get_ctx(map);
789	split = isl_calloc_array(ctx, struct isl_aff_split, map->n);
790	if (!split)
791		return NULL;
792
793	for (i = 0; i < map->n; ++i) {
794		isl_basic_map *bmap;
795		split[i].aff = get_aff(isl_basic_map_copy(map->p[i]));
796		bmap = isl_basic_map_copy(map->p[i]);
797		bmap = isl_basic_map_cow(bmap);
798		bmap = drop_aff(bmap, split[i].aff);
799		split[i].map = isl_map_from_basic_map(bmap);
800		if (!split[i].aff || !split[i].map)
801			goto error;
802	}
803
804	if (isl_sort(split, map->n, sizeof(struct isl_aff_split),
805			&aff_split_cmp, NULL) < 0)
806		goto error;
807
808	n = map->n;
809	for (i = n - 1; i >= 1; --i) {
810		if (!isl_basic_map_plain_is_equal(split[i - 1].aff,
811						 split[i].aff))
812			continue;
813		isl_basic_map_free(split[i].aff);
814		split[i - 1].map = isl_map_union(split[i - 1].map,
815						 split[i].map);
816		if (i != n - 1)
817			split[i] = split[n - 1];
818		split[n - 1].aff = NULL;
819		split[n - 1].map = NULL;
820		--n;
821	}
822
823	return split;
824error:
825	free_split(split, map->n);
826	return NULL;
827}
828
829static __isl_give isl_printer *print_split_map(__isl_take isl_printer *p,
830	struct isl_aff_split *split, int n)
831{
832	int i;
833	int rational;
834
835	for (i = 0; i < n; ++i) {
836		isl_space *dim;
837
838		if (!split[i].map)
839			break;
840		dim = split[i].map->dim;
841		rational = split[i].map->n > 0 &&
842		    ISL_F_ISSET(split[i].map->p[0], ISL_BASIC_MAP_RATIONAL);
843		if (i)
844			p = isl_printer_print_str(p, "; ");
845		p = print_space(dim, p, 0, rational, split[i].aff, NULL);
846		p = print_disjuncts_map(split[i].map, p, 0);
847	}
848
849	return p;
850}
851
852static __isl_give isl_printer *isl_map_print_isl_body(__isl_keep isl_map *map,
853	__isl_take isl_printer *p)
854{
855	struct isl_aff_split *split = NULL;
856	int rational;
857
858	if (map->n > 0)
859		split = split_aff(map);
860	if (split) {
861		p = print_split_map(p, split, map->n);
862	} else {
863		rational = map->n > 0 &&
864		    ISL_F_ISSET(map->p[0], ISL_BASIC_MAP_RATIONAL);
865		p = print_space(map->dim, p, 0, rational, NULL, NULL);
866		p = print_disjuncts_map(map, p, 0);
867	}
868	free_split(split, map->n);
869	return p;
870}
871
872static __isl_give isl_printer *isl_map_print_isl(__isl_keep isl_map *map,
873	__isl_take isl_printer *p)
874{
875	if (isl_map_dim(map, isl_dim_param) > 0) {
876		p = print_tuple(map->dim, p, isl_dim_param, 0, NULL, NULL);
877		p = isl_printer_print_str(p, s_to[0]);
878	}
879	p = isl_printer_print_str(p, s_open_set[0]);
880	p = isl_map_print_isl_body(map, p);
881	p = isl_printer_print_str(p, s_close_set[0]);
882	return p;
883}
884
885static __isl_give isl_printer *print_latex_map(__isl_keep isl_map *map,
886	__isl_take isl_printer *p, __isl_keep isl_basic_map *aff)
887{
888	if (isl_map_dim(map, isl_dim_param) > 0) {
889		p = print_tuple(map->dim, p, isl_dim_param, 1, NULL, NULL);
890		p = isl_printer_print_str(p, s_to[1]);
891	}
892	p = isl_printer_print_str(p, s_open_set[1]);
893	p = print_space(map->dim, p, 1, 0, aff, NULL);
894	p = print_disjuncts_map(map, p, 1);
895	p = isl_printer_print_str(p, s_close_set[1]);
896
897	return p;
898}
899
900static __isl_give isl_printer *isl_map_print_latex(__isl_keep isl_map *map,
901	__isl_take isl_printer *p)
902{
903	int i;
904	struct isl_aff_split *split = NULL;
905
906	if (map->n > 0)
907		split = split_aff(map);
908
909	if (!split)
910		return print_latex_map(map, p, NULL);
911
912	for (i = 0; i < map->n; ++i) {
913		if (!split[i].map)
914			break;
915		if (i)
916			p = isl_printer_print_str(p, " \\cup ");
917		p = print_latex_map(split[i].map, p, split[i].aff);
918	}
919
920	free_split(split, map->n);
921	return p;
922}
923
924__isl_give isl_printer *isl_printer_print_basic_map(__isl_take isl_printer *p,
925	__isl_keep isl_basic_map *bmap)
926{
927	if (!p || !bmap)
928		goto error;
929	if (p->output_format == ISL_FORMAT_ISL)
930		return isl_basic_map_print_isl(bmap, p, 0);
931	else if (p->output_format == ISL_FORMAT_OMEGA)
932		return basic_map_print_omega(bmap, p);
933	isl_assert(bmap->ctx, 0, goto error);
934error:
935	isl_printer_free(p);
936	return NULL;
937}
938
939void isl_basic_map_print(__isl_keep isl_basic_map *bmap, FILE *out, int indent,
940	const char *prefix, const char *suffix, unsigned output_format)
941{
942	isl_printer *printer;
943
944	if (!bmap)
945		return;
946
947	printer = isl_printer_to_file(bmap->ctx, out);
948	printer = isl_printer_set_indent(printer, indent);
949	printer = isl_printer_set_prefix(printer, prefix);
950	printer = isl_printer_set_suffix(printer, suffix);
951	printer = isl_printer_set_output_format(printer, output_format);
952	isl_printer_print_basic_map(printer, bmap);
953
954	isl_printer_free(printer);
955}
956
957__isl_give isl_printer *isl_printer_print_basic_set(__isl_take isl_printer *p,
958	__isl_keep isl_basic_set *bset)
959{
960	if (!p || !bset)
961		goto error;
962
963	if (p->output_format == ISL_FORMAT_ISL)
964		return isl_basic_map_print_isl(bset, p, 0);
965	else if (p->output_format == ISL_FORMAT_POLYLIB)
966		return isl_basic_set_print_polylib(bset, p, 0);
967	else if (p->output_format == ISL_FORMAT_EXT_POLYLIB)
968		return isl_basic_set_print_polylib(bset, p, 1);
969	else if (p->output_format == ISL_FORMAT_POLYLIB_CONSTRAINTS)
970		return bset_print_constraints_polylib(bset, p);
971	else if (p->output_format == ISL_FORMAT_OMEGA)
972		return basic_set_print_omega(bset, p);
973	isl_assert(p->ctx, 0, goto error);
974error:
975	isl_printer_free(p);
976	return NULL;
977}
978
979void isl_basic_set_print(struct isl_basic_set *bset, FILE *out, int indent,
980	const char *prefix, const char *suffix, unsigned output_format)
981{
982	isl_printer *printer;
983
984	if (!bset)
985		return;
986
987	printer = isl_printer_to_file(bset->ctx, out);
988	printer = isl_printer_set_indent(printer, indent);
989	printer = isl_printer_set_prefix(printer, prefix);
990	printer = isl_printer_set_suffix(printer, suffix);
991	printer = isl_printer_set_output_format(printer, output_format);
992	isl_printer_print_basic_set(printer, bset);
993
994	isl_printer_free(printer);
995}
996
997__isl_give isl_printer *isl_printer_print_set(__isl_take isl_printer *p,
998	__isl_keep isl_set *set)
999{
1000	if (!p || !set)
1001		goto error;
1002	if (p->output_format == ISL_FORMAT_ISL)
1003		return isl_map_print_isl((isl_map *)set, p);
1004	else if (p->output_format == ISL_FORMAT_POLYLIB)
1005		return isl_set_print_polylib(set, p, 0);
1006	else if (p->output_format == ISL_FORMAT_EXT_POLYLIB)
1007		return isl_set_print_polylib(set, p, 1);
1008	else if (p->output_format == ISL_FORMAT_OMEGA)
1009		return isl_set_print_omega(set, p);
1010	else if (p->output_format == ISL_FORMAT_LATEX)
1011		return isl_map_print_latex((isl_map *)set, p);
1012	isl_assert(set->ctx, 0, goto error);
1013error:
1014	isl_printer_free(p);
1015	return NULL;
1016}
1017
1018void isl_set_print(struct isl_set *set, FILE *out, int indent,
1019	unsigned output_format)
1020{
1021	isl_printer *printer;
1022
1023	if (!set)
1024		return;
1025
1026	printer = isl_printer_to_file(set->ctx, out);
1027	printer = isl_printer_set_indent(printer, indent);
1028	printer = isl_printer_set_output_format(printer, output_format);
1029	printer = isl_printer_print_set(printer, set);
1030
1031	isl_printer_free(printer);
1032}
1033
1034__isl_give isl_printer *isl_printer_print_map(__isl_take isl_printer *p,
1035	__isl_keep isl_map *map)
1036{
1037	if (!p || !map)
1038		goto error;
1039
1040	if (p->output_format == ISL_FORMAT_ISL)
1041		return isl_map_print_isl(map, p);
1042	else if (p->output_format == ISL_FORMAT_POLYLIB)
1043		return isl_map_print_polylib(map, p, 0);
1044	else if (p->output_format == ISL_FORMAT_EXT_POLYLIB)
1045		return isl_map_print_polylib(map, p, 1);
1046	else if (p->output_format == ISL_FORMAT_OMEGA)
1047		return isl_map_print_omega(map, p);
1048	else if (p->output_format == ISL_FORMAT_LATEX)
1049		return isl_map_print_latex(map, p);
1050	isl_assert(map->ctx, 0, goto error);
1051error:
1052	isl_printer_free(p);
1053	return NULL;
1054}
1055
1056struct isl_union_print_data {
1057	isl_printer *p;
1058	int first;
1059};
1060
1061static int print_map_body(__isl_take isl_map *map, void *user)
1062{
1063	struct isl_union_print_data *data;
1064	data = (struct isl_union_print_data *)user;
1065
1066	if (!data->first)
1067		data->p = isl_printer_print_str(data->p, "; ");
1068	data->first = 0;
1069
1070	data->p = isl_map_print_isl_body(map, data->p);
1071	isl_map_free(map);
1072
1073	return 0;
1074}
1075
1076static __isl_give isl_printer *isl_union_map_print_isl(
1077	__isl_keep isl_union_map *umap, __isl_take isl_printer *p)
1078{
1079	struct isl_union_print_data data = { p, 1 };
1080	isl_space *dim;
1081	dim = isl_union_map_get_space(umap);
1082	if (isl_space_dim(dim, isl_dim_param) > 0) {
1083		p = print_tuple(dim, p, isl_dim_param, 0, NULL, NULL);
1084		p = isl_printer_print_str(p, s_to[0]);
1085	}
1086	isl_space_free(dim);
1087	p = isl_printer_print_str(p, s_open_set[0]);
1088	isl_union_map_foreach_map(umap, &print_map_body, &data);
1089	p = data.p;
1090	p = isl_printer_print_str(p, s_close_set[0]);
1091	return p;
1092}
1093
1094static int print_latex_map_body(__isl_take isl_map *map, void *user)
1095{
1096	struct isl_union_print_data *data;
1097	data = (struct isl_union_print_data *)user;
1098
1099	if (!data->first)
1100		data->p = isl_printer_print_str(data->p, " \\cup ");
1101	data->first = 0;
1102
1103	data->p = isl_map_print_latex(map, data->p);
1104	isl_map_free(map);
1105
1106	return 0;
1107}
1108
1109static __isl_give isl_printer *isl_union_map_print_latex(
1110	__isl_keep isl_union_map *umap, __isl_take isl_printer *p)
1111{
1112	struct isl_union_print_data data = { p, 1 };
1113	isl_union_map_foreach_map(umap, &print_latex_map_body, &data);
1114	p = data.p;
1115	return p;
1116}
1117
1118__isl_give isl_printer *isl_printer_print_union_map(__isl_take isl_printer *p,
1119	__isl_keep isl_union_map *umap)
1120{
1121	if (!p || !umap)
1122		goto error;
1123
1124	if (p->output_format == ISL_FORMAT_ISL)
1125		return isl_union_map_print_isl(umap, p);
1126	if (p->output_format == ISL_FORMAT_LATEX)
1127		return isl_union_map_print_latex(umap, p);
1128
1129	isl_die(p->ctx, isl_error_invalid,
1130		"invalid output format for isl_union_map", goto error);
1131error:
1132	isl_printer_free(p);
1133	return NULL;
1134}
1135
1136__isl_give isl_printer *isl_printer_print_union_set(__isl_take isl_printer *p,
1137	__isl_keep isl_union_set *uset)
1138{
1139	if (!p || !uset)
1140		goto error;
1141
1142	if (p->output_format == ISL_FORMAT_ISL)
1143		return isl_union_map_print_isl((isl_union_map *)uset, p);
1144	if (p->output_format == ISL_FORMAT_LATEX)
1145		return isl_union_map_print_latex((isl_union_map *)uset, p);
1146
1147	isl_die(p->ctx, isl_error_invalid,
1148		"invalid output format for isl_union_set", goto error);
1149error:
1150	isl_printer_free(p);
1151	return NULL;
1152}
1153
1154void isl_map_print(__isl_keep isl_map *map, FILE *out, int indent,
1155	unsigned output_format)
1156{
1157	isl_printer *printer;
1158
1159	if (!map)
1160		return;
1161
1162	printer = isl_printer_to_file(map->ctx, out);
1163	printer = isl_printer_set_indent(printer, indent);
1164	printer = isl_printer_set_output_format(printer, output_format);
1165	printer = isl_printer_print_map(printer, map);
1166
1167	isl_printer_free(printer);
1168}
1169
1170static int upoly_rec_n_non_zero(__isl_keep struct isl_upoly_rec *rec)
1171{
1172	int i;
1173	int n;
1174
1175	for (i = 0, n = 0; i < rec->n; ++i)
1176		if (!isl_upoly_is_zero(rec->p[i]))
1177			++n;
1178
1179	return n;
1180}
1181
1182static __isl_give isl_printer *print_div(__isl_keep isl_space *dim,
1183	__isl_keep isl_mat *div, int pos, __isl_take isl_printer *p)
1184{
1185	int c = p->output_format == ISL_FORMAT_C;
1186	p = isl_printer_print_str(p, c ? "floord(" : "[(");
1187	p = print_affine_of_len(dim, div, p,
1188				div->row[pos] + 1, div->n_col - 1);
1189	p = isl_printer_print_str(p, c ? ", " : ")/");
1190	p = isl_printer_print_isl_int(p, div->row[pos][0]);
1191	p = isl_printer_print_str(p, c ? ")" : "]");
1192	return p;
1193}
1194
1195static __isl_give isl_printer *upoly_print_cst(__isl_keep struct isl_upoly *up,
1196	__isl_take isl_printer *p, int first)
1197{
1198	struct isl_upoly_cst *cst;
1199	int neg;
1200
1201	cst = isl_upoly_as_cst(up);
1202	if (!cst)
1203		goto error;
1204	neg = !first && isl_int_is_neg(cst->n);
1205	if (!first)
1206		p = isl_printer_print_str(p, neg ? " - " :  " + ");
1207	if (neg)
1208		isl_int_neg(cst->n, cst->n);
1209	if (isl_int_is_zero(cst->d)) {
1210		int sgn = isl_int_sgn(cst->n);
1211		p = isl_printer_print_str(p, sgn < 0 ? "-infty" :
1212					    sgn == 0 ? "NaN" : "infty");
1213	} else
1214		p = isl_printer_print_isl_int(p, cst->n);
1215	if (neg)
1216		isl_int_neg(cst->n, cst->n);
1217	if (!isl_int_is_zero(cst->d) && !isl_int_is_one(cst->d)) {
1218		p = isl_printer_print_str(p, "/");
1219		p = isl_printer_print_isl_int(p, cst->d);
1220	}
1221	return p;
1222error:
1223	isl_printer_free(p);
1224	return NULL;
1225}
1226
1227static __isl_give isl_printer *print_base(__isl_take isl_printer *p,
1228	__isl_keep isl_space *dim, __isl_keep isl_mat *div, int var)
1229{
1230	unsigned total;
1231
1232	total = isl_space_dim(dim, isl_dim_all);
1233	if (var < total)
1234		p = print_term(dim, NULL, dim->ctx->one, 1 + var, p, 0);
1235	else
1236		p = print_div(dim, div, var - total, p);
1237	return p;
1238}
1239
1240static __isl_give isl_printer *print_pow(__isl_take isl_printer *p,
1241	__isl_keep isl_space *dim, __isl_keep isl_mat *div, int var, int exp)
1242{
1243	p = print_base(p, dim, div, var);
1244	if (exp == 1)
1245		return p;
1246	if (p->output_format == ISL_FORMAT_C) {
1247		int i;
1248		for (i = 1; i < exp; ++i) {
1249			p = isl_printer_print_str(p, "*");
1250			p = print_base(p, dim, div, var);
1251		}
1252	} else {
1253		p = isl_printer_print_str(p, "^");
1254		p = isl_printer_print_int(p, exp);
1255	}
1256	return p;
1257}
1258
1259static __isl_give isl_printer *upoly_print(__isl_keep struct isl_upoly *up,
1260	__isl_keep isl_space *dim, __isl_keep isl_mat *div,
1261	__isl_take isl_printer *p, int outer)
1262{
1263	int i, n, first, print_parens;
1264	struct isl_upoly_rec *rec;
1265
1266	if (!p || !up || !dim || !div)
1267		goto error;
1268
1269	if (isl_upoly_is_cst(up))
1270		return upoly_print_cst(up, p, 1);
1271
1272	rec = isl_upoly_as_rec(up);
1273	if (!rec)
1274		goto error;
1275	n = upoly_rec_n_non_zero(rec);
1276	print_parens = n > 1 ||
1277		    (outer && rec->up.var >= isl_space_dim(dim, isl_dim_all));
1278	if (print_parens)
1279		p = isl_printer_print_str(p, "(");
1280	for (i = 0, first = 1; i < rec->n; ++i) {
1281		if (isl_upoly_is_zero(rec->p[i]))
1282			continue;
1283		if (isl_upoly_is_negone(rec->p[i])) {
1284			if (!i)
1285				p = isl_printer_print_str(p, "-1");
1286			else if (first)
1287				p = isl_printer_print_str(p, "-");
1288			else
1289				p = isl_printer_print_str(p, " - ");
1290		} else if (isl_upoly_is_cst(rec->p[i]) &&
1291				!isl_upoly_is_one(rec->p[i]))
1292			p = upoly_print_cst(rec->p[i], p, first);
1293		else {
1294			if (!first)
1295				p = isl_printer_print_str(p, " + ");
1296			if (i == 0 || !isl_upoly_is_one(rec->p[i]))
1297				p = upoly_print(rec->p[i], dim, div, p, 0);
1298		}
1299		first = 0;
1300		if (i == 0)
1301			continue;
1302		if (!isl_upoly_is_one(rec->p[i]) &&
1303		    !isl_upoly_is_negone(rec->p[i]))
1304			p = isl_printer_print_str(p, " * ");
1305		p = print_pow(p, dim, div, rec->up.var, i);
1306	}
1307	if (print_parens)
1308		p = isl_printer_print_str(p, ")");
1309	return p;
1310error:
1311	isl_printer_free(p);
1312	return NULL;
1313}
1314
1315static __isl_give isl_printer *print_qpolynomial(__isl_take isl_printer *p,
1316	__isl_keep isl_qpolynomial *qp)
1317{
1318	if (!p || !qp)
1319		goto error;
1320	p = upoly_print(qp->upoly, qp->dim, qp->div, p, 1);
1321	return p;
1322error:
1323	isl_printer_free(p);
1324	return NULL;
1325}
1326
1327static __isl_give isl_printer *print_qpolynomial_isl(__isl_take isl_printer *p,
1328	__isl_keep isl_qpolynomial *qp)
1329{
1330	if (!p || !qp)
1331		goto error;
1332
1333	if (isl_space_dim(qp->dim, isl_dim_param) > 0) {
1334		p = print_tuple(qp->dim, p, isl_dim_param, 0, NULL, NULL);
1335		p = isl_printer_print_str(p, " -> ");
1336	}
1337	p = isl_printer_print_str(p, "{ ");
1338	if (!isl_space_is_params(qp->dim)) {
1339		p = print_space(qp->dim, p, 0, 0, NULL, NULL);
1340		p = isl_printer_print_str(p, " -> ");
1341	}
1342	p = print_qpolynomial(p, qp);
1343	p = isl_printer_print_str(p, " }");
1344	return p;
1345error:
1346	isl_printer_free(p);
1347	return NULL;
1348}
1349
1350static __isl_give isl_printer *print_qpolynomial_c(__isl_take isl_printer *p,
1351	__isl_keep isl_space *dim, __isl_keep isl_qpolynomial *qp)
1352{
1353	isl_int den;
1354
1355	isl_int_init(den);
1356	isl_qpolynomial_get_den(qp, &den);
1357	if (!isl_int_is_one(den)) {
1358		isl_qpolynomial *f;
1359		p = isl_printer_print_str(p, "(");
1360		qp = isl_qpolynomial_copy(qp);
1361		f = isl_qpolynomial_rat_cst_on_domain(isl_space_copy(qp->dim),
1362						den, qp->dim->ctx->one);
1363		qp = isl_qpolynomial_mul(qp, f);
1364	}
1365	if (qp)
1366		p = upoly_print(qp->upoly, dim, qp->div, p, 0);
1367	else
1368		p = isl_printer_free(p);
1369	if (!isl_int_is_one(den)) {
1370		p = isl_printer_print_str(p, ")/");
1371		p = isl_printer_print_isl_int(p, den);
1372		isl_qpolynomial_free(qp);
1373	}
1374	isl_int_clear(den);
1375	return p;
1376}
1377
1378__isl_give isl_printer *isl_printer_print_qpolynomial(
1379	__isl_take isl_printer *p, __isl_keep isl_qpolynomial *qp)
1380{
1381	if (!p || !qp)
1382		goto error;
1383
1384	if (p->output_format == ISL_FORMAT_ISL)
1385		return print_qpolynomial_isl(p, qp);
1386	else if (p->output_format == ISL_FORMAT_C)
1387		return print_qpolynomial_c(p, qp->dim, qp);
1388	else
1389		isl_die(qp->dim->ctx, isl_error_unsupported,
1390			"output format not supported for isl_qpolynomials",
1391			goto error);
1392error:
1393	isl_printer_free(p);
1394	return NULL;
1395}
1396
1397void isl_qpolynomial_print(__isl_keep isl_qpolynomial *qp, FILE *out,
1398	unsigned output_format)
1399{
1400	isl_printer *p;
1401
1402	if  (!qp)
1403		return;
1404
1405	isl_assert(qp->dim->ctx, output_format == ISL_FORMAT_ISL, return);
1406	p = isl_printer_to_file(qp->dim->ctx, out);
1407	p = isl_printer_print_qpolynomial(p, qp);
1408	isl_printer_free(p);
1409}
1410
1411static __isl_give isl_printer *qpolynomial_fold_print(
1412	__isl_keep isl_qpolynomial_fold *fold, __isl_take isl_printer *p)
1413{
1414	int i;
1415
1416	if (fold->type == isl_fold_min)
1417		p = isl_printer_print_str(p, "min");
1418	else if (fold->type == isl_fold_max)
1419		p = isl_printer_print_str(p, "max");
1420	p = isl_printer_print_str(p, "(");
1421	for (i = 0; i < fold->n; ++i) {
1422		if (i)
1423			p = isl_printer_print_str(p, ", ");
1424		p = print_qpolynomial(p, fold->qp[i]);
1425	}
1426	p = isl_printer_print_str(p, ")");
1427	return p;
1428}
1429
1430void isl_qpolynomial_fold_print(__isl_keep isl_qpolynomial_fold *fold,
1431	FILE *out, unsigned output_format)
1432{
1433	isl_printer *p;
1434
1435	if (!fold)
1436		return;
1437
1438	isl_assert(fold->dim->ctx, output_format == ISL_FORMAT_ISL, return);
1439
1440	p = isl_printer_to_file(fold->dim->ctx, out);
1441	p = isl_printer_print_qpolynomial_fold(p, fold);
1442
1443	isl_printer_free(p);
1444}
1445
1446static __isl_give isl_printer *isl_pwqp_print_isl_body(
1447	__isl_take isl_printer *p, __isl_keep isl_pw_qpolynomial *pwqp)
1448{
1449	int i = 0;
1450
1451	for (i = 0; i < pwqp->n; ++i) {
1452		if (i)
1453			p = isl_printer_print_str(p, "; ");
1454		if (!isl_space_is_params(pwqp->p[i].set->dim)) {
1455			p = print_space(pwqp->p[i].set->dim, p, 0, 0, NULL, NULL);
1456			p = isl_printer_print_str(p, " -> ");
1457		}
1458		p = print_qpolynomial(p, pwqp->p[i].qp);
1459		p = print_disjuncts((isl_map *)pwqp->p[i].set, p, 0);
1460	}
1461
1462	return p;
1463}
1464
1465static __isl_give isl_printer *print_pw_qpolynomial_isl(
1466	__isl_take isl_printer *p, __isl_keep isl_pw_qpolynomial *pwqp)
1467{
1468	if (!p || !pwqp)
1469		goto error;
1470
1471	if (isl_space_dim(pwqp->dim, isl_dim_param) > 0) {
1472		p = print_tuple(pwqp->dim, p, isl_dim_param, 0, NULL, NULL);
1473		p = isl_printer_print_str(p, " -> ");
1474	}
1475	p = isl_printer_print_str(p, "{ ");
1476	if (pwqp->n == 0) {
1477		if (!isl_space_is_set(pwqp->dim)) {
1478			p = print_tuple(pwqp->dim, p, isl_dim_in, 0, NULL, NULL);
1479			p = isl_printer_print_str(p, " -> ");
1480		}
1481		p = isl_printer_print_str(p, "0");
1482	}
1483	p = isl_pwqp_print_isl_body(p, pwqp);
1484	p = isl_printer_print_str(p, " }");
1485	return p;
1486error:
1487	isl_printer_free(p);
1488	return NULL;
1489}
1490
1491void isl_pw_qpolynomial_print(__isl_keep isl_pw_qpolynomial *pwqp, FILE *out,
1492	unsigned output_format)
1493{
1494	isl_printer *p;
1495
1496	if (!pwqp)
1497		return;
1498
1499	p = isl_printer_to_file(pwqp->dim->ctx, out);
1500	p = isl_printer_set_output_format(p, output_format);
1501	p = isl_printer_print_pw_qpolynomial(p, pwqp);
1502
1503	isl_printer_free(p);
1504}
1505
1506static __isl_give isl_printer *isl_pwf_print_isl_body(
1507	__isl_take isl_printer *p, __isl_keep isl_pw_qpolynomial_fold *pwf)
1508{
1509	int i = 0;
1510
1511	for (i = 0; i < pwf->n; ++i) {
1512		if (i)
1513			p = isl_printer_print_str(p, "; ");
1514		if (!isl_space_is_params(pwf->p[i].set->dim)) {
1515			p = print_space(pwf->p[i].set->dim, p, 0, 0, NULL, NULL);
1516			p = isl_printer_print_str(p, " -> ");
1517		}
1518		p = qpolynomial_fold_print(pwf->p[i].fold, p);
1519		p = print_disjuncts((isl_map *)pwf->p[i].set, p, 0);
1520	}
1521
1522	return p;
1523}
1524
1525static __isl_give isl_printer *print_pw_qpolynomial_fold_isl(
1526	__isl_take isl_printer *p, __isl_keep isl_pw_qpolynomial_fold *pwf)
1527{
1528	if (isl_space_dim(pwf->dim, isl_dim_param) > 0) {
1529		p = print_tuple(pwf->dim, p, isl_dim_param, 0, NULL, NULL);
1530		p = isl_printer_print_str(p, " -> ");
1531	}
1532	p = isl_printer_print_str(p, "{ ");
1533	if (pwf->n == 0) {
1534		if (!isl_space_is_set(pwf->dim)) {
1535			p = print_tuple(pwf->dim, p, isl_dim_in, 0, NULL, NULL);
1536			p = isl_printer_print_str(p, " -> ");
1537		}
1538		p = isl_printer_print_str(p, "0");
1539	}
1540	p = isl_pwf_print_isl_body(p, pwf);
1541	p = isl_printer_print_str(p, " }");
1542	return p;
1543}
1544
1545static __isl_give isl_printer *print_affine_c(__isl_take isl_printer *p,
1546	__isl_keep isl_space *dim, __isl_keep isl_basic_set *bset, isl_int *c);
1547
1548static __isl_give isl_printer *print_name_c(__isl_take isl_printer *p,
1549	__isl_keep isl_space *dim,
1550	__isl_keep isl_basic_set *bset, enum isl_dim_type type, unsigned pos)
1551{
1552	if (type == isl_dim_div) {
1553		p = isl_printer_print_str(p, "floord(");
1554		p = print_affine_c(p, dim, bset, bset->div[pos] + 1);
1555		p = isl_printer_print_str(p, ", ");
1556		p = isl_printer_print_isl_int(p, bset->div[pos][0]);
1557		p = isl_printer_print_str(p, ")");
1558	} else {
1559		const char *name;
1560
1561		name = isl_space_get_dim_name(dim, type, pos);
1562		if (!name)
1563			name = "UNNAMED";
1564		p = isl_printer_print_str(p, name);
1565	}
1566	return p;
1567}
1568
1569static __isl_give isl_printer *print_term_c(__isl_take isl_printer *p,
1570	__isl_keep isl_space *dim,
1571	__isl_keep isl_basic_set *bset, isl_int c, unsigned pos)
1572{
1573	enum isl_dim_type type;
1574
1575	if (pos == 0)
1576		return isl_printer_print_isl_int(p, c);
1577
1578	if (isl_int_is_one(c))
1579		;
1580	else if (isl_int_is_negone(c))
1581		p = isl_printer_print_str(p, "-");
1582	else {
1583		p = isl_printer_print_isl_int(p, c);
1584		p = isl_printer_print_str(p, "*");
1585	}
1586	type = pos2type(dim, &pos);
1587	p = print_name_c(p, dim, bset, type, pos);
1588	return p;
1589}
1590
1591static __isl_give isl_printer *print_partial_affine_c(__isl_take isl_printer *p,
1592	__isl_keep isl_space *dim,
1593	__isl_keep isl_basic_set *bset, isl_int *c, unsigned len)
1594{
1595	int i;
1596	int first;
1597
1598	for (i = 0, first = 1; i < len; ++i) {
1599		int flip = 0;
1600		if (isl_int_is_zero(c[i]))
1601			continue;
1602		if (!first) {
1603			if (isl_int_is_neg(c[i])) {
1604				flip = 1;
1605				isl_int_neg(c[i], c[i]);
1606				p = isl_printer_print_str(p, " - ");
1607			} else
1608				p = isl_printer_print_str(p, " + ");
1609		}
1610		first = 0;
1611		p = print_term_c(p, dim, bset, c[i], i);
1612		if (flip)
1613			isl_int_neg(c[i], c[i]);
1614	}
1615	if (first)
1616		p = isl_printer_print_str(p, "0");
1617	return p;
1618}
1619
1620static __isl_give isl_printer *print_affine_c(__isl_take isl_printer *p,
1621	__isl_keep isl_space *dim, __isl_keep isl_basic_set *bset, isl_int *c)
1622{
1623	unsigned len = 1 + isl_basic_set_total_dim(bset);
1624	return print_partial_affine_c(p, dim, bset, c, len);
1625}
1626
1627/* We skip the constraint if it is implied by the div expression.
1628 */
1629static __isl_give isl_printer *print_constraint_c(__isl_take isl_printer *p,
1630	__isl_keep isl_space *dim,
1631	__isl_keep isl_basic_set *bset, isl_int *c, const char *op, int first)
1632{
1633	unsigned o_div;
1634	unsigned n_div;
1635	int div;
1636
1637	o_div = isl_basic_set_offset(bset, isl_dim_div);
1638	n_div = isl_basic_set_dim(bset, isl_dim_div);
1639	div = isl_seq_last_non_zero(c + o_div, n_div);
1640	if (div >= 0 && isl_basic_set_is_div_constraint(bset, c, div))
1641		return p;
1642
1643	if (!first)
1644		p = isl_printer_print_str(p, " && ");
1645
1646	p = print_affine_c(p, dim, bset, c);
1647	p = isl_printer_print_str(p, " ");
1648	p = isl_printer_print_str(p, op);
1649	p = isl_printer_print_str(p, " 0");
1650	return p;
1651}
1652
1653static __isl_give isl_printer *print_basic_set_c(__isl_take isl_printer *p,
1654	__isl_keep isl_space *dim, __isl_keep isl_basic_set *bset)
1655{
1656	int i, j;
1657	unsigned n_div = isl_basic_set_dim(bset, isl_dim_div);
1658	unsigned total = isl_basic_set_total_dim(bset) - n_div;
1659
1660	for (i = 0; i < bset->n_eq; ++i) {
1661		j = isl_seq_last_non_zero(bset->eq[i] + 1 + total, n_div);
1662		if (j < 0)
1663			p = print_constraint_c(p, dim, bset,
1664						bset->eq[i], "==", !i);
1665		else {
1666			if (i)
1667				p = isl_printer_print_str(p, " && ");
1668			p = isl_printer_print_str(p, "(");
1669			p = print_partial_affine_c(p, dim, bset, bset->eq[i],
1670						   1 + total + j);
1671			p = isl_printer_print_str(p, ") % ");
1672			p = isl_printer_print_isl_int(p,
1673						bset->eq[i][1 + total + j]);
1674			p = isl_printer_print_str(p, " == 0");
1675		}
1676	}
1677	for (i = 0; i < bset->n_ineq; ++i)
1678		p = print_constraint_c(p, dim, bset, bset->ineq[i], ">=",
1679					!bset->n_eq && !i);
1680	return p;
1681}
1682
1683static __isl_give isl_printer *print_set_c(__isl_take isl_printer *p,
1684	__isl_keep isl_space *dim, __isl_keep isl_set *set)
1685{
1686	int i;
1687
1688	if (!set)
1689		return isl_printer_free(p);
1690
1691	if (set->n == 0)
1692		p = isl_printer_print_str(p, "0");
1693
1694	for (i = 0; i < set->n; ++i) {
1695		if (i)
1696			p = isl_printer_print_str(p, " || ");
1697		if (set->n > 1)
1698			p = isl_printer_print_str(p, "(");
1699		p = print_basic_set_c(p, dim, set->p[i]);
1700		if (set->n > 1)
1701			p = isl_printer_print_str(p, ")");
1702	}
1703	return p;
1704}
1705
1706static __isl_give isl_printer *print_pw_qpolynomial_c(
1707	__isl_take isl_printer *p, __isl_keep isl_pw_qpolynomial *pwqp)
1708{
1709	int i;
1710
1711	if (pwqp->n == 1 && isl_set_plain_is_universe(pwqp->p[0].set))
1712		return print_qpolynomial_c(p, pwqp->dim, pwqp->p[0].qp);
1713
1714	for (i = 0; i < pwqp->n; ++i) {
1715		p = isl_printer_print_str(p, "(");
1716		p = print_set_c(p, pwqp->dim, pwqp->p[i].set);
1717		p = isl_printer_print_str(p, ") ? (");
1718		p = print_qpolynomial_c(p, pwqp->dim, pwqp->p[i].qp);
1719		p = isl_printer_print_str(p, ") : ");
1720	}
1721
1722	p = isl_printer_print_str(p, "0");
1723	return p;
1724}
1725
1726__isl_give isl_printer *isl_printer_print_pw_qpolynomial(
1727	__isl_take isl_printer *p, __isl_keep isl_pw_qpolynomial *pwqp)
1728{
1729	if (!p || !pwqp)
1730		goto error;
1731
1732	if (p->output_format == ISL_FORMAT_ISL)
1733		return print_pw_qpolynomial_isl(p, pwqp);
1734	else if (p->output_format == ISL_FORMAT_C)
1735		return print_pw_qpolynomial_c(p, pwqp);
1736	isl_assert(p->ctx, 0, goto error);
1737error:
1738	isl_printer_free(p);
1739	return NULL;
1740}
1741
1742static int print_pwqp_body(__isl_take isl_pw_qpolynomial *pwqp, void *user)
1743{
1744	struct isl_union_print_data *data;
1745	data = (struct isl_union_print_data *)user;
1746
1747	if (!data->first)
1748		data->p = isl_printer_print_str(data->p, "; ");
1749	data->first = 0;
1750
1751	data->p = isl_pwqp_print_isl_body(data->p, pwqp);
1752	isl_pw_qpolynomial_free(pwqp);
1753
1754	return 0;
1755}
1756
1757static __isl_give isl_printer *print_union_pw_qpolynomial_isl(
1758	__isl_take isl_printer *p, __isl_keep isl_union_pw_qpolynomial *upwqp)
1759{
1760	struct isl_union_print_data data = { p, 1 };
1761	isl_space *dim;
1762	dim = isl_union_pw_qpolynomial_get_space(upwqp);
1763	if (isl_space_dim(dim, isl_dim_param) > 0) {
1764		p = print_tuple(dim, p, isl_dim_param, 0, NULL, NULL);
1765		p = isl_printer_print_str(p, " -> ");
1766	}
1767	isl_space_free(dim);
1768	p = isl_printer_print_str(p, "{ ");
1769	isl_union_pw_qpolynomial_foreach_pw_qpolynomial(upwqp, &print_pwqp_body,
1770							&data);
1771	p = data.p;
1772	p = isl_printer_print_str(p, " }");
1773	return p;
1774}
1775
1776__isl_give isl_printer *isl_printer_print_union_pw_qpolynomial(
1777	__isl_take isl_printer *p, __isl_keep isl_union_pw_qpolynomial *upwqp)
1778{
1779	if (!p || !upwqp)
1780		goto error;
1781
1782	if (p->output_format == ISL_FORMAT_ISL)
1783		return print_union_pw_qpolynomial_isl(p, upwqp);
1784	isl_die(p->ctx, isl_error_invalid,
1785		"invalid output format for isl_union_pw_qpolynomial",
1786		goto error);
1787error:
1788	isl_printer_free(p);
1789	return NULL;
1790}
1791
1792static __isl_give isl_printer *print_qpolynomial_fold_c(
1793	__isl_take isl_printer *p, __isl_keep isl_space *dim,
1794	__isl_keep isl_qpolynomial_fold *fold)
1795{
1796	int i;
1797
1798	for (i = 0; i < fold->n - 1; ++i)
1799		if (fold->type == isl_fold_min)
1800			p = isl_printer_print_str(p, "min(");
1801		else if (fold->type == isl_fold_max)
1802			p = isl_printer_print_str(p, "max(");
1803
1804	for (i = 0; i < fold->n; ++i) {
1805		if (i)
1806			p = isl_printer_print_str(p, ", ");
1807		p = print_qpolynomial_c(p, dim, fold->qp[i]);
1808		if (i)
1809			p = isl_printer_print_str(p, ")");
1810	}
1811	return p;
1812}
1813
1814__isl_give isl_printer *isl_printer_print_qpolynomial_fold(
1815	__isl_take isl_printer *p, __isl_keep isl_qpolynomial_fold *fold)
1816{
1817	if  (!p || !fold)
1818		goto error;
1819	if (p->output_format == ISL_FORMAT_ISL)
1820		return qpolynomial_fold_print(fold, p);
1821	else if (p->output_format == ISL_FORMAT_C)
1822		return print_qpolynomial_fold_c(p, fold->dim, fold);
1823	isl_die(p->ctx, isl_error_unsupported, "unsupported output format",
1824		goto error);
1825error:
1826	isl_printer_free(p);
1827	return NULL;
1828}
1829
1830static __isl_give isl_printer *print_pw_qpolynomial_fold_c(
1831	__isl_take isl_printer *p, __isl_keep isl_pw_qpolynomial_fold *pwf)
1832{
1833	int i;
1834
1835	if (pwf->n == 1 && isl_set_plain_is_universe(pwf->p[0].set))
1836		return print_qpolynomial_fold_c(p, pwf->dim, pwf->p[0].fold);
1837
1838	for (i = 0; i < pwf->n; ++i) {
1839		p = isl_printer_print_str(p, "(");
1840		p = print_set_c(p, pwf->dim, pwf->p[i].set);
1841		p = isl_printer_print_str(p, ") ? (");
1842		p = print_qpolynomial_fold_c(p, pwf->dim, pwf->p[i].fold);
1843		p = isl_printer_print_str(p, ") : ");
1844	}
1845
1846	p = isl_printer_print_str(p, "0");
1847	return p;
1848}
1849
1850__isl_give isl_printer *isl_printer_print_pw_qpolynomial_fold(
1851	__isl_take isl_printer *p, __isl_keep isl_pw_qpolynomial_fold *pwf)
1852{
1853	if (!p || !pwf)
1854		goto error;
1855
1856	if (p->output_format == ISL_FORMAT_ISL)
1857		return print_pw_qpolynomial_fold_isl(p, pwf);
1858	else if (p->output_format == ISL_FORMAT_C)
1859		return print_pw_qpolynomial_fold_c(p, pwf);
1860	isl_assert(p->ctx, 0, goto error);
1861error:
1862	isl_printer_free(p);
1863	return NULL;
1864}
1865
1866void isl_pw_qpolynomial_fold_print(__isl_keep isl_pw_qpolynomial_fold *pwf,
1867	FILE *out, unsigned output_format)
1868{
1869	isl_printer *p;
1870
1871	if (!pwf)
1872		return;
1873
1874	p = isl_printer_to_file(pwf->dim->ctx, out);
1875	p = isl_printer_set_output_format(p, output_format);
1876	p = isl_printer_print_pw_qpolynomial_fold(p, pwf);
1877
1878	isl_printer_free(p);
1879}
1880
1881static int print_pwf_body(__isl_take isl_pw_qpolynomial_fold *pwf, void *user)
1882{
1883	struct isl_union_print_data *data;
1884	data = (struct isl_union_print_data *)user;
1885
1886	if (!data->first)
1887		data->p = isl_printer_print_str(data->p, "; ");
1888	data->first = 0;
1889
1890	data->p = isl_pwf_print_isl_body(data->p, pwf);
1891	isl_pw_qpolynomial_fold_free(pwf);
1892
1893	return 0;
1894}
1895
1896static __isl_give isl_printer *print_union_pw_qpolynomial_fold_isl(
1897	__isl_take isl_printer *p,
1898	__isl_keep isl_union_pw_qpolynomial_fold *upwf)
1899{
1900	struct isl_union_print_data data = { p, 1 };
1901	isl_space *dim;
1902	dim = isl_union_pw_qpolynomial_fold_get_space(upwf);
1903	if (isl_space_dim(dim, isl_dim_param) > 0) {
1904		p = print_tuple(dim, p, isl_dim_param, 0, NULL, NULL);
1905		p = isl_printer_print_str(p, " -> ");
1906	}
1907	isl_space_free(dim);
1908	p = isl_printer_print_str(p, "{ ");
1909	isl_union_pw_qpolynomial_fold_foreach_pw_qpolynomial_fold(upwf,
1910							&print_pwf_body, &data);
1911	p = data.p;
1912	p = isl_printer_print_str(p, " }");
1913	return p;
1914}
1915
1916__isl_give isl_printer *isl_printer_print_union_pw_qpolynomial_fold(
1917	__isl_take isl_printer *p,
1918	__isl_keep isl_union_pw_qpolynomial_fold *upwf)
1919{
1920	if (!p || !upwf)
1921		goto error;
1922
1923	if (p->output_format == ISL_FORMAT_ISL)
1924		return print_union_pw_qpolynomial_fold_isl(p, upwf);
1925	isl_die(p->ctx, isl_error_invalid,
1926		"invalid output format for isl_union_pw_qpolynomial_fold",
1927		goto error);
1928error:
1929	isl_printer_free(p);
1930	return NULL;
1931}
1932
1933__isl_give isl_printer *isl_printer_print_constraint(__isl_take isl_printer *p,
1934	__isl_keep isl_constraint *c)
1935{
1936	isl_basic_map *bmap;
1937
1938	if (!p || !c)
1939		goto error;
1940
1941	bmap = isl_basic_map_from_constraint(isl_constraint_copy(c));
1942	p = isl_printer_print_basic_map(p, bmap);
1943	isl_basic_map_free(bmap);
1944	return p;
1945error:
1946	isl_printer_free(p);
1947	return NULL;
1948}
1949
1950static __isl_give isl_printer *isl_printer_print_space_isl(
1951	__isl_take isl_printer *p, __isl_keep isl_space *dim)
1952{
1953	if (!dim)
1954		goto error;
1955
1956	if (isl_space_dim(dim, isl_dim_param) > 0) {
1957		p = print_tuple(dim, p, isl_dim_param, 0, NULL, NULL);
1958		p = isl_printer_print_str(p, " -> ");
1959	}
1960
1961	p = isl_printer_print_str(p, "{ ");
1962	if (isl_space_is_params(dim))
1963		p = isl_printer_print_str(p, s_such_that[0]);
1964	else
1965		p = print_space(dim, p, 0, 0, NULL, NULL);
1966	p = isl_printer_print_str(p, " }");
1967
1968	return p;
1969error:
1970	isl_printer_free(p);
1971	return NULL;
1972}
1973
1974__isl_give isl_printer *isl_printer_print_space(__isl_take isl_printer *p,
1975	__isl_keep isl_space *space)
1976{
1977	if (!p || !space)
1978		return isl_printer_free(p);
1979	if (p->output_format == ISL_FORMAT_ISL)
1980		return isl_printer_print_space_isl(p, space);
1981	else if (p->output_format == ISL_FORMAT_OMEGA)
1982		return print_omega_parameters(space, p);
1983
1984	isl_die(isl_space_get_ctx(space), isl_error_unsupported,
1985		"output format not supported for space",
1986		return isl_printer_free(p));
1987}
1988
1989__isl_give isl_printer *isl_printer_print_local_space(__isl_take isl_printer *p,
1990	__isl_keep isl_local_space *ls)
1991{
1992	unsigned total;
1993	unsigned n_div;
1994
1995	if (!ls)
1996		goto error;
1997
1998	total = isl_local_space_dim(ls, isl_dim_all);
1999	if (isl_local_space_dim(ls, isl_dim_param) > 0) {
2000		p = print_tuple(ls->dim, p, isl_dim_param, 0, NULL, NULL);
2001		p = isl_printer_print_str(p, " -> ");
2002	}
2003	p = isl_printer_print_str(p, "{ ");
2004	p = print_space(ls->dim, p, 0, 0, NULL, NULL);
2005	n_div = isl_local_space_dim(ls, isl_dim_div);
2006	if (n_div > 0) {
2007		int i;
2008		p = isl_printer_print_str(p, " : ");
2009		p = isl_printer_print_str(p, s_open_exists[0]);
2010		for (i = 0; i < n_div; ++i) {
2011			if (i)
2012				p = isl_printer_print_str(p, ", ");
2013			p = print_name(ls->dim, p, isl_dim_div, i, 0);
2014			if (isl_int_is_zero(ls->div->row[i][0]))
2015				continue;
2016			p = isl_printer_print_str(p, " = [(");
2017			p = print_affine_of_len(ls->dim, ls->div, p,
2018					    ls->div->row[i] + 1, 1 + total);
2019			p = isl_printer_print_str(p, ")/");
2020			p = isl_printer_print_isl_int(p, ls->div->row[i][0]);
2021			p = isl_printer_print_str(p, "]");
2022		}
2023	} else if (isl_space_is_params(ls->dim))
2024		p = isl_printer_print_str(p, s_such_that[0]);
2025	p = isl_printer_print_str(p, " }");
2026	return p;
2027error:
2028	isl_printer_free(p);
2029	return NULL;
2030}
2031
2032static __isl_give isl_printer *print_aff_body(__isl_take isl_printer *p,
2033	__isl_keep isl_aff *aff)
2034{
2035	unsigned total;
2036
2037	total = isl_local_space_dim(aff->ls, isl_dim_all);
2038	p = isl_printer_print_str(p, "(");
2039	p = print_affine_of_len(aff->ls->dim, aff->ls->div, p,
2040				aff->v->el + 1, 1 + total);
2041	if (isl_int_is_one(aff->v->el[0]))
2042		p = isl_printer_print_str(p, ")");
2043	else {
2044		p = isl_printer_print_str(p, ")/");
2045		p = isl_printer_print_isl_int(p, aff->v->el[0]);
2046	}
2047
2048	return p;
2049}
2050
2051static __isl_give isl_printer *print_aff(__isl_take isl_printer *p,
2052	__isl_keep isl_aff *aff)
2053{
2054	if (isl_space_is_params(aff->ls->dim))
2055		;
2056	else {
2057		p = print_tuple(aff->ls->dim, p, isl_dim_set, 0, NULL, NULL);
2058		p = isl_printer_print_str(p, " -> ");
2059	}
2060	p = isl_printer_print_str(p, "[");
2061	p = print_aff_body(p, aff);
2062	p = isl_printer_print_str(p, "]");
2063
2064	return p;
2065}
2066
2067static __isl_give isl_printer *print_aff_isl(__isl_take isl_printer *p,
2068	__isl_keep isl_aff *aff)
2069{
2070	if (!aff)
2071		goto error;
2072
2073	if (isl_local_space_dim(aff->ls, isl_dim_param) > 0) {
2074		p = print_tuple(aff->ls->dim, p, isl_dim_param, 0, NULL, NULL);
2075		p = isl_printer_print_str(p, " -> ");
2076	}
2077	p = isl_printer_print_str(p, "{ ");
2078	p = print_aff(p, aff);
2079	p = isl_printer_print_str(p, " }");
2080	return p;
2081error:
2082	isl_printer_free(p);
2083	return NULL;
2084}
2085
2086static __isl_give isl_printer *print_pw_aff_isl(__isl_take isl_printer *p,
2087	__isl_keep isl_pw_aff *pwaff)
2088{
2089	int i;
2090
2091	if (!pwaff)
2092		goto error;
2093
2094	if (isl_space_dim(pwaff->dim, isl_dim_param) > 0) {
2095		p = print_tuple(pwaff->dim, p, isl_dim_param, 0, NULL, NULL);
2096		p = isl_printer_print_str(p, " -> ");
2097	}
2098	p = isl_printer_print_str(p, "{ ");
2099	for (i = 0; i < pwaff->n; ++i) {
2100		if (i)
2101			p = isl_printer_print_str(p, "; ");
2102		p = print_aff(p, pwaff->p[i].aff);
2103		p = print_disjuncts((isl_map *)pwaff->p[i].set, p, 0);
2104	}
2105	p = isl_printer_print_str(p, " }");
2106	return p;
2107error:
2108	isl_printer_free(p);
2109	return NULL;
2110}
2111
2112static __isl_give isl_printer *print_ls_affine_c(__isl_take isl_printer *p,
2113	__isl_keep isl_local_space *ls, isl_int *c);
2114
2115static __isl_give isl_printer *print_ls_name_c(__isl_take isl_printer *p,
2116	__isl_keep isl_local_space *ls, enum isl_dim_type type, unsigned pos)
2117{
2118	if (type == isl_dim_div) {
2119		p = isl_printer_print_str(p, "floord(");
2120		p = print_ls_affine_c(p, ls, ls->div->row[pos] + 1);
2121		p = isl_printer_print_str(p, ", ");
2122		p = isl_printer_print_isl_int(p, ls->div->row[pos][0]);
2123		p = isl_printer_print_str(p, ")");
2124	} else {
2125		const char *name;
2126
2127		name = isl_space_get_dim_name(ls->dim, type, pos);
2128		if (!name)
2129			name = "UNNAMED";
2130		p = isl_printer_print_str(p, name);
2131	}
2132	return p;
2133}
2134
2135static __isl_give isl_printer *print_ls_term_c(__isl_take isl_printer *p,
2136	__isl_keep isl_local_space *ls, isl_int c, unsigned pos)
2137{
2138	enum isl_dim_type type;
2139
2140	if (pos == 0)
2141		return isl_printer_print_isl_int(p, c);
2142
2143	if (isl_int_is_one(c))
2144		;
2145	else if (isl_int_is_negone(c))
2146		p = isl_printer_print_str(p, "-");
2147	else {
2148		p = isl_printer_print_isl_int(p, c);
2149		p = isl_printer_print_str(p, "*");
2150	}
2151	type = pos2type(ls->dim, &pos);
2152	p = print_ls_name_c(p, ls, type, pos);
2153	return p;
2154}
2155
2156static __isl_give isl_printer *print_ls_partial_affine_c(
2157	__isl_take isl_printer *p, __isl_keep isl_local_space *ls,
2158	isl_int *c, unsigned len)
2159{
2160	int i;
2161	int first;
2162
2163	for (i = 0, first = 1; i < len; ++i) {
2164		int flip = 0;
2165		if (isl_int_is_zero(c[i]))
2166			continue;
2167		if (!first) {
2168			if (isl_int_is_neg(c[i])) {
2169				flip = 1;
2170				isl_int_neg(c[i], c[i]);
2171				p = isl_printer_print_str(p, " - ");
2172			} else
2173				p = isl_printer_print_str(p, " + ");
2174		}
2175		first = 0;
2176		p = print_ls_term_c(p, ls, c[i], i);
2177		if (flip)
2178			isl_int_neg(c[i], c[i]);
2179	}
2180	if (first)
2181		p = isl_printer_print_str(p, "0");
2182	return p;
2183}
2184
2185static __isl_give isl_printer *print_ls_affine_c(__isl_take isl_printer *p,
2186	__isl_keep isl_local_space *ls, isl_int *c)
2187{
2188	unsigned len = 1 + isl_local_space_dim(ls, isl_dim_all);
2189	return print_ls_partial_affine_c(p, ls, c, len);
2190}
2191
2192static __isl_give isl_printer *print_aff_c(__isl_take isl_printer *p,
2193	__isl_keep isl_aff *aff)
2194{
2195	unsigned total;
2196
2197	total = isl_local_space_dim(aff->ls, isl_dim_all);
2198	if (!isl_int_is_one(aff->v->el[0]))
2199		p = isl_printer_print_str(p, "(");
2200	p = print_ls_partial_affine_c(p, aff->ls, aff->v->el + 1, 1 + total);
2201	if (!isl_int_is_one(aff->v->el[0])) {
2202		p = isl_printer_print_str(p, ")/");
2203		p = isl_printer_print_isl_int(p, aff->v->el[0]);
2204	}
2205	return p;
2206}
2207
2208/* Print the affine expression "aff" in C format to "p".
2209 * The dimension names are taken from "space"
2210 * "set" represents the domain of the affine expression.
2211 */
2212static __isl_give isl_printer *print_aff_on_domain_c(__isl_take isl_printer *p,
2213	__isl_keep isl_space *space, __isl_keep isl_aff *aff,
2214	__isl_keep isl_set *set)
2215{
2216	isl_set *u;
2217	isl_ast_build *build;
2218	isl_ast_expr *expr;
2219
2220	u = isl_set_universe(isl_space_copy(space));
2221	build = isl_ast_build_from_context(u);
2222	build = isl_ast_build_restrict(build, isl_set_copy(set));
2223	expr = isl_ast_expr_from_aff(isl_aff_copy(aff), build);
2224	p = isl_printer_print_ast_expr(p, expr);
2225	isl_ast_expr_free(expr);
2226	isl_ast_build_free(build);
2227
2228	return p;
2229}
2230
2231/* In the C format, we cannot express that "pwaff" may be undefined
2232 * on parts of the domain space.  We therefore assume that the expression
2233 * will only be evaluated on its definition domain and compute the gist
2234 * of each cell with respect to this domain.
2235 */
2236static __isl_give isl_printer *print_pw_aff_c(__isl_take isl_printer *p,
2237	__isl_keep isl_pw_aff *pwaff)
2238{
2239	int i;
2240	isl_set *domain;
2241	isl_space *space;
2242
2243	if (pwaff->n < 1)
2244		isl_die(p->ctx, isl_error_unsupported,
2245			"cannot print empty isl_pw_aff in C format", goto error);
2246	space = isl_pw_aff_get_domain_space(pwaff);
2247	if (!space)
2248		goto error;
2249
2250	domain = isl_pw_aff_domain(isl_pw_aff_copy(pwaff));
2251
2252	for (i = 0; i < pwaff->n - 1; ++i) {
2253		isl_set *set_i;
2254
2255		p = isl_printer_print_str(p, "(");
2256
2257		set_i = isl_set_copy(pwaff->p[i].set);
2258		set_i = isl_set_gist(set_i, isl_set_copy(domain));
2259		p = print_set_c(p, space, set_i);
2260		isl_set_free(set_i);
2261
2262		p = isl_printer_print_str(p, ") ? (");
2263		p = print_aff_on_domain_c(p, space,
2264					pwaff->p[i].aff, pwaff->p[i].set);
2265		p = isl_printer_print_str(p, ") : ");
2266	}
2267
2268	isl_set_free(domain);
2269
2270	p = print_aff_on_domain_c(p, space, pwaff->p[pwaff->n - 1].aff,
2271					pwaff->p[pwaff->n - 1].set);
2272	isl_space_free(space);
2273	return p;
2274error:
2275	isl_printer_free(p);
2276	return NULL;
2277}
2278
2279__isl_give isl_printer *isl_printer_print_aff(__isl_take isl_printer *p,
2280	__isl_keep isl_aff *aff)
2281{
2282	if (!p || !aff)
2283		goto error;
2284
2285	if (p->output_format == ISL_FORMAT_ISL)
2286		return print_aff_isl(p, aff);
2287	else if (p->output_format == ISL_FORMAT_C)
2288		return print_aff_c(p, aff);
2289	isl_die(p->ctx, isl_error_unsupported, "unsupported output format",
2290		goto error);
2291error:
2292	isl_printer_free(p);
2293	return NULL;
2294}
2295
2296__isl_give isl_printer *isl_printer_print_pw_aff(__isl_take isl_printer *p,
2297	__isl_keep isl_pw_aff *pwaff)
2298{
2299	if (!p || !pwaff)
2300		goto error;
2301
2302	if (p->output_format == ISL_FORMAT_ISL)
2303		return print_pw_aff_isl(p, pwaff);
2304	else if (p->output_format == ISL_FORMAT_C)
2305		return print_pw_aff_c(p, pwaff);
2306	isl_die(p->ctx, isl_error_unsupported, "unsupported output format",
2307		goto error);
2308error:
2309	isl_printer_free(p);
2310	return NULL;
2311}
2312
2313static __isl_give isl_printer *print_multi_aff(__isl_take isl_printer *p,
2314	__isl_keep isl_multi_aff *maff)
2315{
2316	return print_space(maff->space, p, 0, 0, NULL, maff);
2317}
2318
2319static __isl_give isl_printer *print_multi_aff_isl(__isl_take isl_printer *p,
2320	__isl_keep isl_multi_aff *maff)
2321{
2322	if (!maff)
2323		goto error;
2324
2325	if (isl_space_dim(maff->space, isl_dim_param) > 0) {
2326		p = print_tuple(maff->space, p, isl_dim_param, 0, NULL, NULL);
2327		p = isl_printer_print_str(p, " -> ");
2328	}
2329	p = isl_printer_print_str(p, "{ ");
2330	p = print_multi_aff(p, maff);
2331	p = isl_printer_print_str(p, " }");
2332	return p;
2333error:
2334	isl_printer_free(p);
2335	return NULL;
2336}
2337
2338__isl_give isl_printer *isl_printer_print_multi_aff(__isl_take isl_printer *p,
2339	__isl_keep isl_multi_aff *maff)
2340{
2341	if (!p || !maff)
2342		goto error;
2343
2344	if (p->output_format == ISL_FORMAT_ISL)
2345		return print_multi_aff_isl(p, maff);
2346	isl_die(p->ctx, isl_error_unsupported, "unsupported output format",
2347		goto error);
2348error:
2349	isl_printer_free(p);
2350	return NULL;
2351}
2352
2353static __isl_give isl_printer *print_pw_multi_aff_body(
2354	__isl_take isl_printer *p, __isl_keep isl_pw_multi_aff *pma)
2355{
2356	int i;
2357
2358	if (!pma)
2359		goto error;
2360
2361	for (i = 0; i < pma->n; ++i) {
2362		if (i)
2363			p = isl_printer_print_str(p, "; ");
2364		p = print_multi_aff(p, pma->p[i].maff);
2365		p = print_disjuncts((isl_map *)pma->p[i].set, p, 0);
2366	}
2367	return p;
2368error:
2369	isl_printer_free(p);
2370	return NULL;
2371}
2372
2373static __isl_give isl_printer *print_pw_multi_aff_isl(__isl_take isl_printer *p,
2374	__isl_keep isl_pw_multi_aff *pma)
2375{
2376	if (!pma)
2377		goto error;
2378
2379	if (isl_space_dim(pma->dim, isl_dim_param) > 0) {
2380		p = print_tuple(pma->dim, p, isl_dim_param, 0, NULL, NULL);
2381		p = isl_printer_print_str(p, " -> ");
2382	}
2383	p = isl_printer_print_str(p, "{ ");
2384	p = print_pw_multi_aff_body(p, pma);
2385	p = isl_printer_print_str(p, " }");
2386	return p;
2387error:
2388	isl_printer_free(p);
2389	return NULL;
2390}
2391
2392static __isl_give isl_printer *print_unnamed_pw_multi_aff_c(
2393	__isl_take isl_printer *p, __isl_keep isl_pw_multi_aff *pma)
2394{
2395	int i;
2396
2397	for (i = 0; i < pma->n - 1; ++i) {
2398		p = isl_printer_print_str(p, "(");
2399		p = print_set_c(p, pma->dim, pma->p[i].set);
2400		p = isl_printer_print_str(p, ") ? (");
2401		p = print_aff_c(p, pma->p[i].maff->p[0]);
2402		p = isl_printer_print_str(p, ") : ");
2403	}
2404
2405	return print_aff_c(p, pma->p[pma->n - 1].maff->p[0]);
2406}
2407
2408static __isl_give isl_printer *print_pw_multi_aff_c(__isl_take isl_printer *p,
2409	__isl_keep isl_pw_multi_aff *pma)
2410{
2411	int n;
2412	const char *name;
2413
2414	if (!pma)
2415		goto error;
2416	if (pma->n < 1)
2417		isl_die(p->ctx, isl_error_unsupported,
2418			"cannot print empty isl_pw_multi_aff in C format",
2419			goto error);
2420	name = isl_pw_multi_aff_get_tuple_name(pma, isl_dim_out);
2421	if (!name && isl_pw_multi_aff_dim(pma, isl_dim_out) == 1)
2422		return print_unnamed_pw_multi_aff_c(p, pma);
2423	if (!name)
2424		isl_die(p->ctx, isl_error_unsupported,
2425			"cannot print unnamed isl_pw_multi_aff in C format",
2426			goto error);
2427
2428	p = isl_printer_print_str(p, name);
2429	n = isl_pw_multi_aff_dim(pma, isl_dim_out);
2430	if (n != 0)
2431		isl_die(p->ctx, isl_error_unsupported,
2432			"not supported yet", goto error);
2433
2434	return p;
2435error:
2436	isl_printer_free(p);
2437	return NULL;
2438}
2439
2440__isl_give isl_printer *isl_printer_print_pw_multi_aff(
2441	__isl_take isl_printer *p, __isl_keep isl_pw_multi_aff *pma)
2442{
2443	if (!p || !pma)
2444		goto error;
2445
2446	if (p->output_format == ISL_FORMAT_ISL)
2447		return print_pw_multi_aff_isl(p, pma);
2448	if (p->output_format == ISL_FORMAT_C)
2449		return print_pw_multi_aff_c(p, pma);
2450	isl_die(p->ctx, isl_error_unsupported, "unsupported output format",
2451		goto error);
2452error:
2453	isl_printer_free(p);
2454	return NULL;
2455}
2456
2457static int print_pw_multi_aff_body_wrap(__isl_take isl_pw_multi_aff *pma,
2458	void *user)
2459{
2460	struct isl_union_print_data *data;
2461	data = (struct isl_union_print_data *) user;
2462
2463	if (!data->first)
2464		data->p = isl_printer_print_str(data->p, "; ");
2465	data->first = 0;
2466
2467	data->p = print_pw_multi_aff_body(data->p, pma);
2468	isl_pw_multi_aff_free(pma);
2469
2470	return 0;
2471}
2472
2473static __isl_give isl_printer *print_union_pw_multi_aff_isl(
2474	__isl_take isl_printer *p, __isl_keep isl_union_pw_multi_aff *upma)
2475{
2476	struct isl_union_print_data data = { p, 1 };
2477	isl_space *space;
2478
2479	space = isl_union_pw_multi_aff_get_space(upma);
2480	if (isl_space_dim(space, isl_dim_param) > 0) {
2481		p = print_tuple(space, p, isl_dim_param, 0, NULL, NULL);
2482		p = isl_printer_print_str(p, s_to[0]);
2483	}
2484	isl_space_free(space);
2485	p = isl_printer_print_str(p, s_open_set[0]);
2486	isl_union_pw_multi_aff_foreach_pw_multi_aff(upma,
2487					&print_pw_multi_aff_body_wrap, &data);
2488	p = data.p;
2489	p = isl_printer_print_str(p, s_close_set[0]);
2490	return p;
2491}
2492
2493__isl_give isl_printer *isl_printer_print_union_pw_multi_aff(
2494	__isl_take isl_printer *p, __isl_keep isl_union_pw_multi_aff *upma)
2495{
2496	if (!p || !upma)
2497		goto error;
2498
2499	if (p->output_format == ISL_FORMAT_ISL)
2500		return print_union_pw_multi_aff_isl(p, upma);
2501	isl_die(p->ctx, isl_error_unsupported, "unsupported output format",
2502		goto error);
2503error:
2504	isl_printer_free(p);
2505	return NULL;
2506}
2507
2508static __isl_give isl_printer *print_multi_pw_aff_isl(__isl_take isl_printer *p,
2509	__isl_keep isl_multi_pw_aff *mpa)
2510{
2511	int i;
2512
2513	if (!mpa)
2514		return isl_printer_free(p);
2515
2516	p = isl_printer_print_str(p, "(");
2517	for (i = 0; i < mpa->n; ++i) {
2518		if (i)
2519			p = isl_printer_print_str(p, ",");
2520		p = isl_printer_print_pw_aff(p, mpa->p[i]);
2521	}
2522	p = isl_printer_print_str(p, ")");
2523	return p;
2524}
2525
2526__isl_give isl_printer *isl_printer_print_multi_pw_aff(
2527	__isl_take isl_printer *p, __isl_keep isl_multi_pw_aff *mpa)
2528{
2529	if (!p || !mpa)
2530		return isl_printer_free(p);
2531
2532	if (p->output_format == ISL_FORMAT_ISL)
2533		return print_multi_pw_aff_isl(p, mpa);
2534	isl_die(p->ctx, isl_error_unsupported, "unsupported output format",
2535		return isl_printer_free(p));
2536}
2537