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, type: isl_dim_in); |
68 | isl_size n_out = isl_basic_map_dim(bmap, type: isl_dim_out); |
69 | isl_size nparam = isl_basic_map_dim(bmap, type: 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(printer: p); |
74 | |
75 | p = isl_printer_start_line(p); |
76 | p = isl_printer_print_int(p, i: ineq); |
77 | for (i = 0; i < n_out; ++i) { |
78 | p = isl_printer_print_str(p, s: " " ); |
79 | p = isl_printer_print_isl_int(p, i: c[1+nparam+n_in+i]); |
80 | } |
81 | for (i = 0; i < n_in; ++i) { |
82 | p = isl_printer_print_str(p, s: " " ); |
83 | p = isl_printer_print_isl_int(p, i: c[1+nparam+i]); |
84 | } |
85 | for (i = 0; i < bmap->n_div; ++i) { |
86 | p = isl_printer_print_str(p, s: " " ); |
87 | p = isl_printer_print_isl_int(p, i: c[1+nparam+n_in+n_out+i]); |
88 | } |
89 | for (i = 0; i < nparam; ++i) { |
90 | p = isl_printer_print_str(p, s: " " ); |
91 | p = isl_printer_print_isl_int(p, i: c[1+i]); |
92 | } |
93 | p = isl_printer_print_str(p, s: " " ); |
94 | p = isl_printer_print_isl_int(p, i: 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, width: 5); |
105 | |
106 | for (i = 0; i < bmap->n_eq; ++i) |
107 | p = print_constraint_polylib(bmap, ineq: 0, n: i, p); |
108 | for (i = 0; i < bmap->n_ineq; ++i) |
109 | p = print_constraint_polylib(bmap, ineq: 1, n: 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(bmap: 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, type: isl_dim_all); |
126 | if (total < 0) |
127 | return isl_printer_free(printer: p); |
128 | p = isl_printer_start_line(p); |
129 | p = isl_printer_print_int(p, i: bmap->n_eq + bmap->n_ineq); |
130 | p = isl_printer_print_str(p, s: " " ); |
131 | p = isl_printer_print_int(p, i: 1 + total + 1); |
132 | if (ext) { |
133 | isl_size n_in = isl_basic_map_dim(bmap, type: isl_dim_in); |
134 | isl_size n_out = isl_basic_map_dim(bmap, type: isl_dim_out); |
135 | isl_size n_div = isl_basic_map_dim(bmap, type: isl_dim_div); |
136 | isl_size nparam = isl_basic_map_dim(bmap, type: isl_dim_param); |
137 | |
138 | if (n_in < 0 || n_out < 0 || n_div < 0 || nparam < 0) |
139 | return isl_printer_free(printer: p); |
140 | |
141 | p = isl_printer_print_str(p, s: " " ); |
142 | p = isl_printer_print_int(p, i: n_out); |
143 | p = isl_printer_print_str(p, s: " " ); |
144 | p = isl_printer_print_int(p, i: n_in); |
145 | p = isl_printer_print_str(p, s: " " ); |
146 | p = isl_printer_print_int(p, i: n_div); |
147 | p = isl_printer_print_str(p, s: " " ); |
148 | p = isl_printer_print_int(p, i: 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(bmap: 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, i: 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(bmap: 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(map: 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, type: 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, type: t, pos: p); |
196 | if (n && !strcmp(s1: n, s2: 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(s: buffer, maxlen: sizeof(buffer), format: "%s%d" , prefix, pos); |
228 | name = buffer; |
229 | } |
230 | primes = count_same_name(space, type: name == buffer ? isl_dim_div : type, |
231 | pos, name); |
232 | if (primes < 0) |
233 | return isl_printer_free(printer: p); |
234 | p = isl_printer_print_str(p, s: name); |
235 | while (primes-- > 0) |
236 | p = isl_printer_print_str(p, s: "'" ); |
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, type: isl_dim_in); |
244 | isl_size n_out = isl_space_dim(space, type: isl_dim_out); |
245 | isl_size nparam = isl_space_dim(space, type: 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(b: isl_local_div_is_marked_unknown(local: 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(printer: p); |
296 | |
297 | if (pos == 0) |
298 | return isl_printer_print_isl_int(p, i: c); |
299 | |
300 | if (pos2type(space, type: &type, pos: &pos) < 0) |
301 | return isl_printer_free(printer: 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, s: "-" ); |
308 | else { |
309 | p = isl_printer_print_isl_int(p, i: c); |
310 | if (p->output_format == ISL_FORMAT_C || print_div_def) |
311 | p = isl_printer_print_str(p, s: "*" ); |
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, s: " - " ); |
336 | } else |
337 | p = isl_printer_print_str(p, s: " + " ); |
338 | } |
339 | first = 0; |
340 | p = print_term(space, div, c: c[i], pos: i, p, latex: 0); |
341 | if (flip) |
342 | isl_int_neg(c[i], c[i]); |
343 | } |
344 | if (first) |
345 | p = isl_printer_print_str(p, s: "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, type: isl_dim_all); |
360 | n_div = isl_mat_rows(mat: div); |
361 | if (total < 0 || n_div < 0) |
362 | return isl_printer_free(printer: 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(space: local_space, type: local_type); |
380 | if (dim < 0) |
381 | return isl_printer_free(printer: p); |
382 | for (i = 0; i < dim; ++i) { |
383 | if (i) |
384 | p = isl_printer_print_str(p, s: ", " ); |
385 | if (data->print_dim) |
386 | p = data->print_dim(p, data, offset + i); |
387 | else |
388 | p = print_name(space: data->space, p, type: data->type, pos: offset + i, |
389 | latex: 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, local_space: space, local_type: type, data: &data, offset: 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(space: local_space, type: local_type); |
412 | |
413 | if (n < 0) |
414 | return isl_printer_free(printer: p); |
415 | if ((local_type == isl_dim_in || local_type == isl_dim_out)) { |
416 | name = isl_space_get_tuple_name(space: local_space, type: local_type); |
417 | if (name) { |
418 | if (data->latex) |
419 | p = isl_printer_print_str(p, s: "\\mathrm{" ); |
420 | p = isl_printer_print_str(p, s: name); |
421 | if (data->latex) |
422 | p = isl_printer_print_str(p, s: "}" ); |
423 | } |
424 | } |
425 | if (!data->latex || n != 1 || name) |
426 | p = isl_printer_print_str(p, s: 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_dim: 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: 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, local_space: space, local_type: type, data, offset: 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_space: local_dim, local_type: isl_dim_in, data, offset); |
456 | p = isl_printer_print_str(p, s: s_to[data->latex]); |
457 | p = print_nested_tuple(p, local_space: local_dim, local_type: 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, s: "rat: " ); |
468 | if (isl_space_is_params(space)) |
469 | ; |
470 | else if (isl_space_is_set(space)) |
471 | p = print_tuple(space, p, type: isl_dim_set, data); |
472 | else { |
473 | p = print_tuple(space, p, type: isl_dim_in, data); |
474 | p = isl_printer_print_str(p, s: s_to[data->latex]); |
475 | p = print_tuple(space, p, type: 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, type: isl_dim_param); |
485 | |
486 | if (nparam < 0) |
487 | return isl_printer_free(printer: p); |
488 | if (nparam == 0) |
489 | return p; |
490 | |
491 | p = isl_printer_start_line(p); |
492 | p = isl_printer_print_str(p, s: "symbolic " ); |
493 | p = print_var_list(p, space, type: isl_dim_param); |
494 | p = isl_printer_print_str(p, s: ";" ); |
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, type: isl_dim_all); |
510 | unsigned o_div = isl_basic_map_offset(bmap, type: 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(p: bmap->ineq[i + 1], len: 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 | constraint: bmap->ineq[i + 1], div: 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(b: 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, s: " " ); |
567 | p = isl_printer_print_str(p, s: op); |
568 | p = isl_printer_print_str(p, s: " " ); |
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: c[last], pos: last, p, latex); |
589 | |
590 | p = isl_printer_print_str(p, s: " " ); |
591 | p = isl_printer_print_str(p, s: op); |
592 | p = isl_printer_print_str(p, s: " " ); |
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(printer: p); |
617 | |
618 | p = isl_printer_print_str(p, s: "(" ); |
619 | p = print_affine_of_len(space, div, p, |
620 | c: div->row[pos] + 1, len: div->n_col - 1); |
621 | p = isl_printer_print_str(p, s: ") " ); |
622 | p = isl_printer_print_str(p, s: s_mod[latex]); |
623 | p = isl_printer_print_str(p, s: " " ); |
624 | p = isl_printer_print_isl_int(p, i: 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(mat: 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: &type, pos: &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(printer: 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, i: c[last]); |
700 | p = isl_printer_print_str(p, s: "*(" ); |
701 | } |
702 | p = print_mod(p, space, div, pos: div_pos, latex); |
703 | if (multiple) |
704 | p = isl_printer_print_str(p, s: ")" ); |
705 | p = isl_printer_print_str(p, s: " = " ); |
706 | isl_seq_combine(dst: c, m1: ctx->negone, src1: c, |
707 | m2: c[last], src2: div->row[div_pos] + 1, len: 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(mat: div); |
728 | div_pos = print_as_modulo_pos(p, space, div, pos: last, c: c[last]); |
729 | if (n_div < 0 || div_pos < 0) |
730 | return isl_printer_free(printer: 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, op: "=" , 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, type: isl_dim_all); |
785 | unsigned o_div = isl_basic_map_offset(bmap, type: isl_dim_div); |
786 | int first = 1; |
787 | int dump; |
788 | |
789 | if (total < 0 || !p) |
790 | return isl_printer_free(printer: 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(ctx: bmap->ctx, size: 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(p: bmap->eq[i], len: 1 + total); |
804 | if (l < 0) { |
805 | if (i != bmap->n_eq - 1) |
806 | p = isl_printer_print_str(p, s: s_and[latex]); |
807 | p = isl_printer_print_str(p, s: "0 = 0" ); |
808 | continue; |
809 | } |
810 | if (!first) |
811 | p = isl_printer_print_str(p, s: s_and[latex]); |
812 | if (isl_int_is_neg(bmap->eq[i][l])) |
813 | isl_seq_cpy(dst: c->el, src: bmap->eq[i], len: 1 + total); |
814 | else |
815 | isl_seq_neg(dst: c->el, src: bmap->eq[i], len: 1 + total); |
816 | p = print_eq_constraint(p, space, div, c: c->el, last: 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(p: bmap->ineq[i], len: 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, pos: l - o_div)) { |
829 | isl_bool is_div; |
830 | is_div = isl_basic_map_is_div_constraint(bmap, |
831 | constraint: bmap->ineq[i], div: 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: 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(dst: c->el, src: bmap->ineq[i], len: 1 + total); |
843 | else |
844 | isl_seq_neg(dst: c->el, src: bmap->ineq[i], len: 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, last: l); |
848 | if (combine < 0) |
849 | goto error; |
850 | if (combine) { |
851 | op = constraint_op(sign: -s, strict, latex); |
852 | p = print_half_constraint(p, space, div, c: c->el, last: l, |
853 | op, latex); |
854 | first = 1; |
855 | } else { |
856 | op = constraint_op(sign: s, strict, latex); |
857 | p = print_constraint(p, space, div, c: c->el, last: l, |
858 | op, latex); |
859 | first = 0; |
860 | } |
861 | } |
862 | |
863 | isl_basic_map_free(bmap); |
864 | isl_vec_free(vec: c); |
865 | |
866 | return p; |
867 | error: |
868 | isl_basic_map_free(bmap); |
869 | isl_vec_free(vec: c); |
870 | isl_printer_free(printer: 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(printer: p); |
881 | |
882 | c = p->output_format == ISL_FORMAT_C; |
883 | p = isl_printer_print_str(p, s: c ? "floord(" : "floor((" ); |
884 | p = print_affine_of_len(space, div, p, |
885 | c: div->row[pos] + 1, len: div->n_col - 1); |
886 | p = isl_printer_print_str(p, s: c ? ", " : ")/" ); |
887 | p = isl_printer_print_isl_int(p, i: div->row[pos][0]); |
888 | p = isl_printer_print_str(p, s: ")" ); |
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(mat: div); |
906 | if (!p || !space || n_div < 0) |
907 | return isl_printer_free(printer: p); |
908 | |
909 | for (i = 0; i < n_div; ++i) { |
910 | if (!print_defined_divs && can_print_div_expr(p, div, pos: i)) |
911 | continue; |
912 | if (!first) |
913 | p = isl_printer_print_str(p, s: ", " ); |
914 | p = print_name(space, p, type: isl_dim_div, pos: i, latex); |
915 | first = 0; |
916 | if (!can_print_div_expr(p, div, pos: i)) |
917 | continue; |
918 | p = isl_printer_print_str(p, s: " = " ); |
919 | p = print_div(space, div, pos: 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(mat: 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, pos: 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: s_open_exists[latex]); |
966 | p = print_div_list(p, space, div, latex, print_defined_divs: dump); |
967 | p = isl_printer_print_str(p, s: ": " ); |
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(mat: div); |
980 | if (n_div < 0) |
981 | return isl_mat_free(mat: div); |
982 | |
983 | for (i = 0; i < n_div; ++i) |
984 | div = isl_mat_set_element_si(mat: div, row: i, col: 0, v: 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(mat: div); |
1012 | |
1013 | if (exists >= 0 && exists) |
1014 | p = isl_printer_print_str(p, s: 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, s: ": " ); |
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, s: "{ [" ); |
1040 | p = print_var_list(p, space: bmap->dim, type: isl_dim_in); |
1041 | p = isl_printer_print_str(p, s: "] -> [" ); |
1042 | p = print_var_list(p, space: bmap->dim, type: isl_dim_out); |
1043 | p = isl_printer_print_str(p, s: "] " ); |
1044 | p = print_optional_disjunct(bmap, space: bmap->dim, p, latex: 0); |
1045 | p = isl_printer_print_str(p, s: " }" ); |
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, s: "{ [" ); |
1053 | p = print_var_list(p, space: bset->dim, type: isl_dim_set); |
1054 | p = isl_printer_print_str(p, s: "] " ); |
1055 | p = print_optional_disjunct(bmap: bset, space: bset->dim, p, latex: 0); |
1056 | p = isl_printer_print_str(p, s: " }" ); |
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, s: " union " ); |
1068 | p = basic_map_print_omega(bmap: 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, s: " union " ); |
1081 | p = basic_set_print_omega(bset: 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, type: isl_dim_param); |
1095 | if (!p || nparam < 0) |
1096 | return isl_printer_free(printer: p); |
1097 | if (nparam == 0) |
1098 | return p; |
1099 | |
1100 | p = print_tuple(space, p, type: isl_dim_param, data); |
1101 | p = isl_printer_print_str(p, s: 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, space: bmap->dim, data: &data); |
1114 | p = isl_printer_print_str(p, s: "{ " ); |
1115 | p = isl_print_space(space: bmap->dim, p, rational, data: &data); |
1116 | p = isl_printer_print_str(p, s: " : " ); |
1117 | p = print_disjunct(bmap, space: bmap->dim, p, latex); |
1118 | p = isl_printer_print_str(p, s: " }" ); |
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, s: "false" ); |
1133 | for (i = 0; i < map->n; ++i) { |
1134 | if (i) |
1135 | p = isl_printer_print_str(p, s: 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, s: "(" ); |
1138 | p = print_disjunct(bmap: 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, s: ")" ); |
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(bmap: hull, space, p, latex); |
1161 | map = isl_map_plain_gist_basic_map(map: isl_map_copy(map), context: 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: s_and[latex]); |
1167 | p = isl_printer_print_str(p, s: "(" ); |
1168 | p = print_disjuncts_core(map, space, p, latex); |
1169 | p = isl_printer_print_str(p, s: ")" ); |
1170 | } |
1171 | isl_map_free(map); |
1172 | |
1173 | return p; |
1174 | error: |
1175 | isl_map_free(map); |
1176 | isl_printer_free(printer: 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: 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(map: isl_map_copy(map)); |
1203 | is_universe = isl_basic_map_plain_is_universe(bmap: hull); |
1204 | if (is_universe < 0) |
1205 | p = isl_printer_free(printer: p); |
1206 | else if (!is_universe) |
1207 | return print_disjuncts_in_hull(map, space, hull, |
1208 | p, latex); |
1209 | isl_basic_map_free(bmap: 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(space: map->dim)) |
1227 | return isl_printer_print_str(p, s: 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(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(bmap: split[i].aff); |
1256 | isl_map_free(map: split[i].map); |
1257 | } |
1258 | |
1259 | free(ptr: 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, n: bmap->n_ineq); |
1271 | |
1272 | nparam = isl_basic_map_dim(bmap, type: isl_dim_param); |
1273 | n_in = isl_basic_map_dim(bmap, type: isl_dim_in); |
1274 | n_out = isl_basic_map_dim(bmap, type: isl_dim_out); |
1275 | total = isl_basic_map_dim(bmap, type: 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(p: bmap->eq[i] + 1, len: 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, pos: 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(bmap1: s1->aff, bmap2: 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, type: 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(p: bmap->eq[i] + 1 + v_div, |
1318 | len: bmap->n_div) != -1) |
1319 | continue; |
1320 | for (j = 0; j < aff->n_eq; ++j) { |
1321 | if (!isl_seq_eq(p1: bmap->eq[i], p2: aff->eq[j], len: 1 + v_div) && |
1322 | !isl_seq_is_neg(p1: bmap->eq[i], p2: aff->eq[j], len: 1 + v_div)) |
1323 | continue; |
1324 | if (isl_basic_map_drop_equality(bmap, pos: 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(bmap: isl_basic_map_copy(bmap: map->p[i])); |
1350 | bmap = isl_basic_map_copy(bmap: map->p[i]); |
1351 | bmap = isl_basic_map_cow(bmap); |
1352 | bmap = drop_aff(bmap, aff: 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(pbase: split, total_elems: map->n, size: sizeof(struct isl_aff_split), |
1359 | cmp: &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(bmap1: split[i - 1].aff, |
1365 | bmap2: split[i].aff)) |
1366 | continue; |
1367 | isl_basic_map_free(bmap: split[i].aff); |
1368 | split[i - 1].map = isl_map_union(map1: split[i - 1].map, |
1369 | map2: 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, n: map->n); |
1380 | return NULL; |
1381 | } |
1382 | |
1383 | static int defining_equality(__isl_keep isl_basic_map *eq, |
1384 | __isl_keep isl_space *space, enum isl_dim_type type, int pos) |
1385 | { |
1386 | int i; |
1387 | isl_size total; |
1388 | |
1389 | total = isl_basic_map_dim(bmap: eq, type: isl_dim_all); |
1390 | if (total < 0) |
1391 | return -1; |
1392 | |
1393 | pos += isl_space_offset(space, type); |
1394 | |
1395 | for (i = 0; i < eq->n_eq; ++i) { |
1396 | if (isl_seq_last_non_zero(p: eq->eq[i] + 1, len: total) != pos) |
1397 | continue; |
1398 | if (isl_int_is_one(eq->eq[i][1 + pos])) |
1399 | isl_seq_neg(dst: eq->eq[i], src: eq->eq[i], len: 1 + total); |
1400 | return i; |
1401 | } |
1402 | |
1403 | return -1; |
1404 | } |
1405 | |
1406 | /* Print dimension "pos" of data->space to "p". |
1407 | * |
1408 | * data->user is assumed to be an isl_basic_map keeping track of equalities. |
1409 | * |
1410 | * If the current dimension is defined by these equalities, then print |
1411 | * the corresponding expression, assigned to the name of the dimension |
1412 | * if there is any. Otherwise, print the name of the dimension. |
1413 | */ |
1414 | static __isl_give isl_printer *print_dim_eq(__isl_take isl_printer *p, |
1415 | struct isl_print_space_data *data, unsigned pos) |
1416 | { |
1417 | isl_basic_map *eq = data->user; |
1418 | int j; |
1419 | |
1420 | j = defining_equality(eq, space: data->space, type: data->type, pos); |
1421 | if (j >= 0) { |
1422 | if (isl_space_has_dim_name(space: data->space, type: data->type, pos)) { |
1423 | p = print_name(space: data->space, p, type: data->type, pos, |
1424 | latex: data->latex); |
1425 | p = isl_printer_print_str(p, s: " = " ); |
1426 | } |
1427 | pos += 1 + isl_space_offset(space: data->space, type: data->type); |
1428 | p = print_affine_of_len(space: data->space, NULL, p, c: eq->eq[j], len: pos); |
1429 | } else { |
1430 | p = print_name(space: data->space, p, type: data->type, pos, latex: data->latex); |
1431 | } |
1432 | |
1433 | return p; |
1434 | } |
1435 | |
1436 | static __isl_give isl_printer *print_split_map(__isl_take isl_printer *p, |
1437 | struct isl_aff_split *split, int n, __isl_keep isl_space *space) |
1438 | { |
1439 | struct isl_print_space_data data = { 0 }; |
1440 | int i; |
1441 | int rational; |
1442 | |
1443 | data.print_dim = &print_dim_eq; |
1444 | for (i = 0; i < n; ++i) { |
1445 | if (!split[i].map) |
1446 | break; |
1447 | rational = split[i].map->n > 0 && |
1448 | ISL_F_ISSET(split[i].map->p[0], ISL_BASIC_MAP_RATIONAL); |
1449 | if (i) |
1450 | p = isl_printer_print_str(p, s: "; " ); |
1451 | data.user = split[i].aff; |
1452 | p = isl_print_space(space, p, rational, data: &data); |
1453 | p = print_disjuncts_map(map: split[i].map, space, p, latex: 0); |
1454 | } |
1455 | |
1456 | return p; |
1457 | } |
1458 | |
1459 | static __isl_give isl_printer *print_body_map(__isl_take isl_printer *p, |
1460 | __isl_keep isl_map *map) |
1461 | { |
1462 | struct isl_print_space_data data = { 0 }; |
1463 | struct isl_aff_split *split = NULL; |
1464 | int rational; |
1465 | |
1466 | if (!p || !map) |
1467 | return isl_printer_free(printer: p); |
1468 | if (!p->dump && map->n > 0) |
1469 | split = split_aff(map); |
1470 | if (split) { |
1471 | p = print_split_map(p, split, n: map->n, space: map->dim); |
1472 | } else { |
1473 | rational = map->n > 0 && |
1474 | ISL_F_ISSET(map->p[0], ISL_BASIC_MAP_RATIONAL); |
1475 | p = isl_print_space(space: map->dim, p, rational, data: &data); |
1476 | p = print_disjuncts_map(map, space: map->dim, p, latex: 0); |
1477 | } |
1478 | free_split(split, n: map->n); |
1479 | return p; |
1480 | } |
1481 | |
1482 | static __isl_give isl_printer *isl_map_print_isl(__isl_keep isl_map *map, |
1483 | __isl_take isl_printer *p) |
1484 | { |
1485 | struct isl_print_space_data data = { 0 }; |
1486 | |
1487 | p = print_param_tuple(p, space: map->dim, data: &data); |
1488 | p = isl_printer_print_str(p, s: s_open_set[0]); |
1489 | p = print_body_map(p, map); |
1490 | p = isl_printer_print_str(p, s: s_close_set[0]); |
1491 | return p; |
1492 | } |
1493 | |
1494 | static __isl_give isl_printer *print_latex_map(__isl_keep isl_map *map, |
1495 | __isl_take isl_printer *p, __isl_keep isl_basic_map *aff) |
1496 | { |
1497 | struct isl_print_space_data data = { 0 }; |
1498 | |
1499 | data.latex = 1; |
1500 | p = print_param_tuple(p, space: map->dim, data: &data); |
1501 | p = isl_printer_print_str(p, s: s_open_set[1]); |
1502 | data.print_dim = &print_dim_eq; |
1503 | data.user = aff; |
1504 | p = isl_print_space(space: map->dim, p, rational: 0, data: &data); |
1505 | p = print_disjuncts_map(map, space: map->dim, p, latex: 1); |
1506 | p = isl_printer_print_str(p, s: s_close_set[1]); |
1507 | |
1508 | return p; |
1509 | } |
1510 | |
1511 | static __isl_give isl_printer *isl_map_print_latex(__isl_keep isl_map *map, |
1512 | __isl_take isl_printer *p) |
1513 | { |
1514 | int i; |
1515 | struct isl_aff_split *split = NULL; |
1516 | |
1517 | if (map->n > 0) |
1518 | split = split_aff(map); |
1519 | |
1520 | if (!split) |
1521 | return print_latex_map(map, p, NULL); |
1522 | |
1523 | for (i = 0; i < map->n; ++i) { |
1524 | if (!split[i].map) |
1525 | break; |
1526 | if (i) |
1527 | p = isl_printer_print_str(p, s: " \\cup " ); |
1528 | p = print_latex_map(map: split[i].map, p, aff: split[i].aff); |
1529 | } |
1530 | |
1531 | free_split(split, n: map->n); |
1532 | return p; |
1533 | } |
1534 | |
1535 | __isl_give isl_printer *isl_printer_print_basic_map(__isl_take isl_printer *p, |
1536 | __isl_keep isl_basic_map *bmap) |
1537 | { |
1538 | if (!p || !bmap) |
1539 | goto error; |
1540 | if (p->output_format == ISL_FORMAT_ISL) |
1541 | return isl_basic_map_print_isl(bmap, p, latex: 0); |
1542 | else if (p->output_format == ISL_FORMAT_OMEGA) |
1543 | return basic_map_print_omega(bmap, p); |
1544 | isl_assert(bmap->ctx, 0, goto error); |
1545 | error: |
1546 | isl_printer_free(printer: p); |
1547 | return NULL; |
1548 | } |
1549 | |
1550 | __isl_give isl_printer *isl_printer_print_basic_set(__isl_take isl_printer *p, |
1551 | __isl_keep isl_basic_set *bset) |
1552 | { |
1553 | if (!p || !bset) |
1554 | goto error; |
1555 | |
1556 | if (p->output_format == ISL_FORMAT_ISL) |
1557 | return isl_basic_map_print_isl(bmap: bset, p, latex: 0); |
1558 | else if (p->output_format == ISL_FORMAT_POLYLIB) |
1559 | return isl_basic_set_print_polylib(bset, p, ext: 0); |
1560 | else if (p->output_format == ISL_FORMAT_EXT_POLYLIB) |
1561 | return isl_basic_set_print_polylib(bset, p, ext: 1); |
1562 | else if (p->output_format == ISL_FORMAT_POLYLIB_CONSTRAINTS) |
1563 | return bset_print_constraints_polylib(bset, p); |
1564 | else if (p->output_format == ISL_FORMAT_OMEGA) |
1565 | return basic_set_print_omega(bset, p); |
1566 | isl_assert(p->ctx, 0, goto error); |
1567 | error: |
1568 | isl_printer_free(printer: p); |
1569 | return NULL; |
1570 | } |
1571 | |
1572 | __isl_give isl_printer *isl_printer_print_set(__isl_take isl_printer *p, |
1573 | __isl_keep isl_set *set) |
1574 | { |
1575 | if (!p || !set) |
1576 | goto error; |
1577 | if (p->output_format == ISL_FORMAT_ISL) |
1578 | return isl_map_print_isl(map: set_to_map(set), p); |
1579 | else if (p->output_format == ISL_FORMAT_POLYLIB) |
1580 | return isl_set_print_polylib(set, p, ext: 0); |
1581 | else if (p->output_format == ISL_FORMAT_EXT_POLYLIB) |
1582 | return isl_set_print_polylib(set, p, ext: 1); |
1583 | else if (p->output_format == ISL_FORMAT_OMEGA) |
1584 | return isl_set_print_omega(set, p); |
1585 | else if (p->output_format == ISL_FORMAT_LATEX) |
1586 | return isl_map_print_latex(map: set_to_map(set), p); |
1587 | isl_assert(set->ctx, 0, goto error); |
1588 | error: |
1589 | isl_printer_free(printer: p); |
1590 | return NULL; |
1591 | } |
1592 | |
1593 | __isl_give isl_printer *isl_printer_print_map(__isl_take isl_printer *p, |
1594 | __isl_keep isl_map *map) |
1595 | { |
1596 | if (!p || !map) |
1597 | goto error; |
1598 | |
1599 | if (p->output_format == ISL_FORMAT_ISL) |
1600 | return isl_map_print_isl(map, p); |
1601 | else if (p->output_format == ISL_FORMAT_POLYLIB) |
1602 | return isl_map_print_polylib(map, p, ext: 0); |
1603 | else if (p->output_format == ISL_FORMAT_EXT_POLYLIB) |
1604 | return isl_map_print_polylib(map, p, ext: 1); |
1605 | else if (p->output_format == ISL_FORMAT_OMEGA) |
1606 | return isl_map_print_omega(map, p); |
1607 | else if (p->output_format == ISL_FORMAT_LATEX) |
1608 | return isl_map_print_latex(map, p); |
1609 | isl_assert(map->ctx, 0, goto error); |
1610 | error: |
1611 | isl_printer_free(printer: p); |
1612 | return NULL; |
1613 | } |
1614 | |
1615 | struct isl_union_print_data { |
1616 | isl_printer *p; |
1617 | int first; |
1618 | }; |
1619 | |
1620 | #undef BASE |
1621 | #define BASE map |
1622 | #include "isl_union_print_templ.c" |
1623 | |
1624 | /* Print the body of "uset" (everything except the parameter declarations) |
1625 | * to "p" in isl format. |
1626 | */ |
1627 | static __isl_give isl_printer *isl_printer_print_union_set_isl_body( |
1628 | __isl_take isl_printer *p, __isl_keep isl_union_set *uset) |
1629 | { |
1630 | return print_body_union_map(p, u: uset_to_umap(uset)); |
1631 | } |
1632 | |
1633 | static isl_stat print_latex_map_body(__isl_take isl_map *map, void *user) |
1634 | { |
1635 | struct isl_union_print_data *data; |
1636 | data = (struct isl_union_print_data *)user; |
1637 | |
1638 | if (!data->first) |
1639 | data->p = isl_printer_print_str(p: data->p, s: " \\cup " ); |
1640 | data->first = 0; |
1641 | |
1642 | data->p = isl_map_print_latex(map, p: data->p); |
1643 | isl_map_free(map); |
1644 | |
1645 | return isl_stat_ok; |
1646 | } |
1647 | |
1648 | static __isl_give isl_printer *isl_union_map_print_latex( |
1649 | __isl_keep isl_union_map *umap, __isl_take isl_printer *p) |
1650 | { |
1651 | struct isl_union_print_data data = { p, 1 }; |
1652 | isl_union_map_foreach_map(umap, fn: &print_latex_map_body, user: &data); |
1653 | p = data.p; |
1654 | return p; |
1655 | } |
1656 | |
1657 | __isl_give isl_printer *isl_printer_print_union_map(__isl_take isl_printer *p, |
1658 | __isl_keep isl_union_map *umap) |
1659 | { |
1660 | if (!p || !umap) |
1661 | goto error; |
1662 | |
1663 | if (p->output_format == ISL_FORMAT_ISL) |
1664 | return print_union_map_isl(p, u: umap); |
1665 | if (p->output_format == ISL_FORMAT_LATEX) |
1666 | return isl_union_map_print_latex(umap, p); |
1667 | |
1668 | isl_die(p->ctx, isl_error_invalid, |
1669 | "invalid output format for isl_union_map" , goto error); |
1670 | error: |
1671 | isl_printer_free(printer: p); |
1672 | return NULL; |
1673 | } |
1674 | |
1675 | __isl_give isl_printer *isl_printer_print_union_set(__isl_take isl_printer *p, |
1676 | __isl_keep isl_union_set *uset) |
1677 | { |
1678 | if (!p || !uset) |
1679 | goto error; |
1680 | |
1681 | if (p->output_format == ISL_FORMAT_ISL) |
1682 | return print_union_map_isl(p, u: uset_to_umap(uset)); |
1683 | if (p->output_format == ISL_FORMAT_LATEX) |
1684 | return isl_union_map_print_latex(umap: uset_to_umap(uset), p); |
1685 | |
1686 | isl_die(p->ctx, isl_error_invalid, |
1687 | "invalid output format for isl_union_set" , goto error); |
1688 | error: |
1689 | isl_printer_free(printer: p); |
1690 | return NULL; |
1691 | } |
1692 | |
1693 | static isl_size poly_rec_n_non_zero(__isl_keep isl_poly_rec *rec) |
1694 | { |
1695 | int i; |
1696 | int n; |
1697 | |
1698 | if (!rec) |
1699 | return isl_size_error; |
1700 | |
1701 | for (i = 0, n = 0; i < rec->n; ++i) { |
1702 | isl_bool is_zero = isl_poly_is_zero(poly: rec->p[i]); |
1703 | |
1704 | if (is_zero < 0) |
1705 | return isl_size_error; |
1706 | if (!is_zero) |
1707 | ++n; |
1708 | } |
1709 | |
1710 | return n; |
1711 | } |
1712 | |
1713 | static __isl_give isl_printer *poly_print_cst(__isl_keep isl_poly *poly, |
1714 | __isl_take isl_printer *p, int first) |
1715 | { |
1716 | isl_poly_cst *cst; |
1717 | int neg; |
1718 | |
1719 | cst = isl_poly_as_cst(poly); |
1720 | if (!cst) |
1721 | goto error; |
1722 | neg = !first && isl_int_is_neg(cst->n); |
1723 | if (!first) |
1724 | p = isl_printer_print_str(p, s: neg ? " - " : " + " ); |
1725 | if (neg) |
1726 | isl_int_neg(cst->n, cst->n); |
1727 | if (isl_int_is_zero(cst->d)) { |
1728 | int sgn = isl_int_sgn(cst->n); |
1729 | p = isl_printer_print_str(p, s: sgn < 0 ? "-infty" : |
1730 | sgn == 0 ? "NaN" : "infty" ); |
1731 | } else |
1732 | p = isl_printer_print_isl_int(p, i: cst->n); |
1733 | if (neg) |
1734 | isl_int_neg(cst->n, cst->n); |
1735 | if (!isl_int_is_zero(cst->d) && !isl_int_is_one(cst->d)) { |
1736 | p = isl_printer_print_str(p, s: "/" ); |
1737 | p = isl_printer_print_isl_int(p, i: cst->d); |
1738 | } |
1739 | return p; |
1740 | error: |
1741 | isl_printer_free(printer: p); |
1742 | return NULL; |
1743 | } |
1744 | |
1745 | static __isl_give isl_printer *print_base(__isl_take isl_printer *p, |
1746 | __isl_keep isl_space *space, __isl_keep isl_mat *div, int var) |
1747 | { |
1748 | isl_size total; |
1749 | |
1750 | total = isl_space_dim(space, type: isl_dim_all); |
1751 | if (total < 0) |
1752 | return isl_printer_free(printer: p); |
1753 | if (var < total) |
1754 | p = print_term(space, NULL, c: space->ctx->one, pos: 1 + var, p, latex: 0); |
1755 | else |
1756 | p = print_div(space, div, pos: var - total, p); |
1757 | return p; |
1758 | } |
1759 | |
1760 | static __isl_give isl_printer *print_pow(__isl_take isl_printer *p, |
1761 | __isl_keep isl_space *space, __isl_keep isl_mat *div, int var, int exp) |
1762 | { |
1763 | p = print_base(p, space, div, var); |
1764 | if (exp == 1) |
1765 | return p; |
1766 | if (p->output_format == ISL_FORMAT_C) { |
1767 | int i; |
1768 | for (i = 1; i < exp; ++i) { |
1769 | p = isl_printer_print_str(p, s: "*" ); |
1770 | p = print_base(p, space, div, var); |
1771 | } |
1772 | } else { |
1773 | p = isl_printer_print_str(p, s: "^" ); |
1774 | p = isl_printer_print_int(p, i: exp); |
1775 | } |
1776 | return p; |
1777 | } |
1778 | |
1779 | /* Print the polynomial "poly" defined over the domain space "space" and |
1780 | * local variables defined by "div" to "p". |
1781 | */ |
1782 | static __isl_give isl_printer *poly_print(__isl_keep isl_poly *poly, |
1783 | __isl_keep isl_space *space, __isl_keep isl_mat *div, |
1784 | __isl_take isl_printer *p) |
1785 | { |
1786 | int i, first, print_parens; |
1787 | isl_size n; |
1788 | isl_bool is_cst; |
1789 | isl_poly_rec *rec; |
1790 | |
1791 | is_cst = isl_poly_is_cst(poly); |
1792 | if (!p || is_cst < 0 || !space || !div) |
1793 | goto error; |
1794 | |
1795 | if (is_cst) |
1796 | return poly_print_cst(poly, p, first: 1); |
1797 | |
1798 | rec = isl_poly_as_rec(poly); |
1799 | n = poly_rec_n_non_zero(rec); |
1800 | if (n < 0) |
1801 | return isl_printer_free(printer: p); |
1802 | print_parens = n > 1; |
1803 | if (print_parens) |
1804 | p = isl_printer_print_str(p, s: "(" ); |
1805 | for (i = 0, first = 1; i < rec->n; ++i) { |
1806 | isl_bool is_zero = isl_poly_is_zero(poly: rec->p[i]); |
1807 | isl_bool is_one = isl_poly_is_one(poly: rec->p[i]); |
1808 | isl_bool is_negone = isl_poly_is_negone(poly: rec->p[i]); |
1809 | isl_bool is_cst = isl_poly_is_cst(poly: rec->p[i]); |
1810 | |
1811 | if (is_zero < 0 || is_one < 0 || is_negone < 0) |
1812 | return isl_printer_free(printer: p); |
1813 | if (is_zero) |
1814 | continue; |
1815 | if (is_negone) { |
1816 | if (!i) |
1817 | p = isl_printer_print_str(p, s: "-1" ); |
1818 | else if (first) |
1819 | p = isl_printer_print_str(p, s: "-" ); |
1820 | else |
1821 | p = isl_printer_print_str(p, s: " - " ); |
1822 | } else if (is_cst && !is_one) |
1823 | p = poly_print_cst(poly: rec->p[i], p, first); |
1824 | else { |
1825 | if (!first) |
1826 | p = isl_printer_print_str(p, s: " + " ); |
1827 | if (i == 0 || !is_one) |
1828 | p = poly_print(poly: rec->p[i], space, div, p); |
1829 | } |
1830 | first = 0; |
1831 | if (i == 0) |
1832 | continue; |
1833 | if (!is_one && !is_negone) |
1834 | p = isl_printer_print_str(p, s: " * " ); |
1835 | p = print_pow(p, space, div, var: rec->poly.var, exp: i); |
1836 | } |
1837 | if (print_parens) |
1838 | p = isl_printer_print_str(p, s: ")" ); |
1839 | return p; |
1840 | error: |
1841 | isl_printer_free(printer: p); |
1842 | return NULL; |
1843 | } |
1844 | |
1845 | static __isl_give isl_printer *print_qpolynomial(__isl_take isl_printer *p, |
1846 | __isl_keep isl_qpolynomial *qp) |
1847 | { |
1848 | if (!p || !qp) |
1849 | goto error; |
1850 | p = poly_print(poly: qp->poly, space: qp->dim, div: qp->div, p); |
1851 | return p; |
1852 | error: |
1853 | isl_printer_free(printer: p); |
1854 | return NULL; |
1855 | } |
1856 | |
1857 | static __isl_give isl_printer *print_qpolynomial_isl(__isl_take isl_printer *p, |
1858 | __isl_keep isl_qpolynomial *qp) |
1859 | { |
1860 | struct isl_print_space_data data = { 0 }; |
1861 | |
1862 | if (!p || !qp) |
1863 | goto error; |
1864 | |
1865 | p = print_param_tuple(p, space: qp->dim, data: &data); |
1866 | p = isl_printer_print_str(p, s: "{ " ); |
1867 | if (!isl_space_is_params(space: qp->dim)) { |
1868 | p = isl_print_space(space: qp->dim, p, rational: 0, data: &data); |
1869 | p = isl_printer_print_str(p, s: " -> " ); |
1870 | } |
1871 | p = print_qpolynomial(p, qp); |
1872 | p = isl_printer_print_str(p, s: " }" ); |
1873 | return p; |
1874 | error: |
1875 | isl_printer_free(printer: p); |
1876 | return NULL; |
1877 | } |
1878 | |
1879 | /* Print the quasi-polynomial "qp" to "p" in C format, with the variable names |
1880 | * taken from the domain space "space". |
1881 | */ |
1882 | static __isl_give isl_printer *print_qpolynomial_c(__isl_take isl_printer *p, |
1883 | __isl_keep isl_space *space, __isl_keep isl_qpolynomial *qp) |
1884 | { |
1885 | isl_bool is_one; |
1886 | isl_val *den; |
1887 | |
1888 | den = isl_qpolynomial_get_den(qp); |
1889 | qp = isl_qpolynomial_copy(qp); |
1890 | qp = isl_qpolynomial_scale_val(qp, v: isl_val_copy(v: den)); |
1891 | is_one = isl_val_is_one(v: den); |
1892 | if (is_one < 0) |
1893 | p = isl_printer_free(printer: p); |
1894 | if (!is_one) |
1895 | p = isl_printer_print_str(p, s: "(" ); |
1896 | if (qp) |
1897 | p = poly_print(poly: qp->poly, space, div: qp->div, p); |
1898 | else |
1899 | p = isl_printer_free(printer: p); |
1900 | if (!is_one) { |
1901 | p = isl_printer_print_str(p, s: ")/" ); |
1902 | p = isl_printer_print_val(p, v: den); |
1903 | } |
1904 | isl_qpolynomial_free(qp); |
1905 | isl_val_free(v: den); |
1906 | return p; |
1907 | } |
1908 | |
1909 | __isl_give isl_printer *isl_printer_print_qpolynomial( |
1910 | __isl_take isl_printer *p, __isl_keep isl_qpolynomial *qp) |
1911 | { |
1912 | if (!p || !qp) |
1913 | goto error; |
1914 | |
1915 | if (p->output_format == ISL_FORMAT_ISL) |
1916 | return print_qpolynomial_isl(p, qp); |
1917 | else if (p->output_format == ISL_FORMAT_C) |
1918 | return print_qpolynomial_c(p, space: qp->dim, qp); |
1919 | else |
1920 | isl_die(qp->dim->ctx, isl_error_unsupported, |
1921 | "output format not supported for isl_qpolynomials" , |
1922 | goto error); |
1923 | error: |
1924 | isl_printer_free(printer: p); |
1925 | return NULL; |
1926 | } |
1927 | |
1928 | void isl_qpolynomial_print(__isl_keep isl_qpolynomial *qp, FILE *out, |
1929 | unsigned output_format) |
1930 | { |
1931 | isl_printer *p; |
1932 | |
1933 | if (!qp) |
1934 | return; |
1935 | |
1936 | isl_assert(qp->dim->ctx, output_format == ISL_FORMAT_ISL, return); |
1937 | p = isl_printer_to_file(ctx: qp->dim->ctx, file: out); |
1938 | p = isl_printer_print_qpolynomial(p, qp); |
1939 | isl_printer_free(printer: p); |
1940 | } |
1941 | |
1942 | static __isl_give isl_printer *qpolynomial_fold_print( |
1943 | __isl_keep isl_qpolynomial_fold *fold, __isl_take isl_printer *p) |
1944 | { |
1945 | int i; |
1946 | isl_qpolynomial_list *list; |
1947 | isl_size n; |
1948 | |
1949 | list = isl_qpolynomial_fold_peek_list(fold); |
1950 | n = isl_qpolynomial_list_size(list); |
1951 | if (n < 0) |
1952 | return isl_printer_free(printer: p); |
1953 | if (fold->type == isl_fold_min) |
1954 | p = isl_printer_print_str(p, s: "min" ); |
1955 | else if (fold->type == isl_fold_max) |
1956 | p = isl_printer_print_str(p, s: "max" ); |
1957 | p = isl_printer_print_str(p, s: "(" ); |
1958 | for (i = 0; i < n; ++i) { |
1959 | isl_qpolynomial *qp; |
1960 | |
1961 | if (i) |
1962 | p = isl_printer_print_str(p, s: ", " ); |
1963 | qp = isl_qpolynomial_list_peek(list, index: i); |
1964 | p = print_qpolynomial(p, qp); |
1965 | } |
1966 | p = isl_printer_print_str(p, s: ")" ); |
1967 | return p; |
1968 | } |
1969 | |
1970 | void isl_qpolynomial_fold_print(__isl_keep isl_qpolynomial_fold *fold, |
1971 | FILE *out, unsigned output_format) |
1972 | { |
1973 | isl_printer *p; |
1974 | |
1975 | if (!fold) |
1976 | return; |
1977 | |
1978 | isl_assert(fold->dim->ctx, output_format == ISL_FORMAT_ISL, return); |
1979 | |
1980 | p = isl_printer_to_file(ctx: fold->dim->ctx, file: out); |
1981 | p = isl_printer_print_qpolynomial_fold(p, fold); |
1982 | |
1983 | isl_printer_free(printer: p); |
1984 | } |
1985 | |
1986 | static __isl_give isl_printer *print_body_pw_qpolynomial( |
1987 | __isl_take isl_printer *p, __isl_keep isl_pw_qpolynomial *pwqp) |
1988 | { |
1989 | struct isl_print_space_data data = { 0 }; |
1990 | int i = 0; |
1991 | |
1992 | for (i = 0; i < pwqp->n; ++i) { |
1993 | isl_space *space; |
1994 | |
1995 | if (i) |
1996 | p = isl_printer_print_str(p, s: "; " ); |
1997 | space = isl_qpolynomial_get_domain_space(qp: pwqp->p[i].qp); |
1998 | if (!isl_space_is_params(space)) { |
1999 | p = isl_print_space(space, p, rational: 0, data: &data); |
2000 | p = isl_printer_print_str(p, s: " -> " ); |
2001 | } |
2002 | p = print_qpolynomial(p, qp: pwqp->p[i].qp); |
2003 | p = print_disjuncts(map: set_to_map(pwqp->p[i].set), space, p, latex: 0); |
2004 | isl_space_free(space); |
2005 | } |
2006 | |
2007 | return p; |
2008 | } |
2009 | |
2010 | static __isl_give isl_printer *print_pw_qpolynomial_isl( |
2011 | __isl_take isl_printer *p, __isl_keep isl_pw_qpolynomial *pwqp) |
2012 | { |
2013 | struct isl_print_space_data data = { 0 }; |
2014 | |
2015 | if (!p || !pwqp) |
2016 | goto error; |
2017 | |
2018 | p = print_param_tuple(p, space: pwqp->dim, data: &data); |
2019 | p = isl_printer_print_str(p, s: "{ " ); |
2020 | if (pwqp->n == 0) { |
2021 | if (!isl_space_is_set(space: pwqp->dim)) { |
2022 | p = print_tuple(space: pwqp->dim, p, type: isl_dim_in, data: &data); |
2023 | p = isl_printer_print_str(p, s: " -> " ); |
2024 | } |
2025 | p = isl_printer_print_str(p, s: "0" ); |
2026 | } |
2027 | p = print_body_pw_qpolynomial(p, pwqp); |
2028 | p = isl_printer_print_str(p, s: " }" ); |
2029 | return p; |
2030 | error: |
2031 | isl_printer_free(printer: p); |
2032 | return NULL; |
2033 | } |
2034 | |
2035 | void isl_pw_qpolynomial_print(__isl_keep isl_pw_qpolynomial *pwqp, FILE *out, |
2036 | unsigned output_format) |
2037 | { |
2038 | isl_printer *p; |
2039 | |
2040 | if (!pwqp) |
2041 | return; |
2042 | |
2043 | p = isl_printer_to_file(ctx: pwqp->dim->ctx, file: out); |
2044 | p = isl_printer_set_output_format(p, output_format); |
2045 | p = isl_printer_print_pw_qpolynomial(p, pwqp); |
2046 | |
2047 | isl_printer_free(printer: p); |
2048 | } |
2049 | |
2050 | static __isl_give isl_printer *print_body_pw_qpolynomial_fold( |
2051 | __isl_take isl_printer *p, __isl_keep isl_pw_qpolynomial_fold *pwf) |
2052 | { |
2053 | struct isl_print_space_data data = { 0 }; |
2054 | int i = 0; |
2055 | |
2056 | for (i = 0; i < pwf->n; ++i) { |
2057 | isl_space *space; |
2058 | |
2059 | if (i) |
2060 | p = isl_printer_print_str(p, s: "; " ); |
2061 | space = isl_qpolynomial_fold_get_domain_space(fold: pwf->p[i].fold); |
2062 | if (!isl_space_is_params(space)) { |
2063 | p = isl_print_space(space, p, rational: 0, data: &data); |
2064 | p = isl_printer_print_str(p, s: " -> " ); |
2065 | } |
2066 | p = qpolynomial_fold_print(fold: pwf->p[i].fold, p); |
2067 | p = print_disjuncts(map: set_to_map(pwf->p[i].set), space, p, latex: 0); |
2068 | isl_space_free(space); |
2069 | } |
2070 | |
2071 | return p; |
2072 | } |
2073 | |
2074 | static __isl_give isl_printer *print_pw_qpolynomial_fold_isl( |
2075 | __isl_take isl_printer *p, __isl_keep isl_pw_qpolynomial_fold *pwf) |
2076 | { |
2077 | struct isl_print_space_data data = { 0 }; |
2078 | |
2079 | p = print_param_tuple(p, space: pwf->dim, data: &data); |
2080 | p = isl_printer_print_str(p, s: "{ " ); |
2081 | if (pwf->n == 0) { |
2082 | if (!isl_space_is_set(space: pwf->dim)) { |
2083 | p = print_tuple(space: pwf->dim, p, type: isl_dim_in, data: &data); |
2084 | p = isl_printer_print_str(p, s: " -> " ); |
2085 | } |
2086 | p = isl_printer_print_str(p, s: "0" ); |
2087 | } |
2088 | p = print_body_pw_qpolynomial_fold(p, pwf); |
2089 | p = isl_printer_print_str(p, s: " }" ); |
2090 | return p; |
2091 | } |
2092 | |
2093 | static __isl_give isl_printer *print_ls_affine_c(__isl_take isl_printer *p, |
2094 | __isl_keep isl_local_space *ls, isl_int *c); |
2095 | |
2096 | /* We skip the constraint if it is implied by the div expression. |
2097 | * |
2098 | * *first indicates whether this is the first constraint in the conjunction and |
2099 | * is updated if the constraint is actually printed. |
2100 | */ |
2101 | static __isl_give isl_printer *print_constraint_c(__isl_take isl_printer *p, |
2102 | __isl_keep isl_local_space *ls, isl_int *c, const char *op, int *first) |
2103 | { |
2104 | unsigned o_div; |
2105 | isl_size n_div; |
2106 | int div; |
2107 | |
2108 | o_div = isl_local_space_offset(ls, type: isl_dim_div); |
2109 | n_div = isl_local_space_dim(ls, type: isl_dim_div); |
2110 | if (n_div < 0) |
2111 | return isl_printer_free(printer: p); |
2112 | div = isl_seq_last_non_zero(p: c + o_div, len: n_div); |
2113 | if (div >= 0) { |
2114 | isl_bool is_div = isl_local_space_is_div_constraint(ls, constraint: c, div); |
2115 | if (is_div < 0) |
2116 | return isl_printer_free(printer: p); |
2117 | if (is_div) |
2118 | return p; |
2119 | } |
2120 | |
2121 | if (!*first) |
2122 | p = isl_printer_print_str(p, s: " && " ); |
2123 | |
2124 | p = print_ls_affine_c(p, ls, c); |
2125 | p = isl_printer_print_str(p, s: " " ); |
2126 | p = isl_printer_print_str(p, s: op); |
2127 | p = isl_printer_print_str(p, s: " 0" ); |
2128 | |
2129 | *first = 0; |
2130 | |
2131 | return p; |
2132 | } |
2133 | |
2134 | static __isl_give isl_printer *print_ls_partial_affine_c( |
2135 | __isl_take isl_printer *p, __isl_keep isl_local_space *ls, |
2136 | isl_int *c, unsigned len); |
2137 | |
2138 | static __isl_give isl_printer *print_basic_set_c(__isl_take isl_printer *p, |
2139 | __isl_keep isl_space *space, __isl_keep isl_basic_set *bset) |
2140 | { |
2141 | int i, j; |
2142 | int first = 1; |
2143 | isl_size n_div = isl_basic_set_dim(bset, type: isl_dim_div); |
2144 | isl_size total = isl_basic_set_dim(bset, type: isl_dim_all); |
2145 | isl_mat *div; |
2146 | isl_local_space *ls; |
2147 | |
2148 | if (n_div < 0 || total < 0) |
2149 | return isl_printer_free(printer: p); |
2150 | |
2151 | total -= n_div; |
2152 | div = isl_basic_set_get_divs(bset); |
2153 | ls = isl_local_space_alloc_div(space: isl_space_copy(space), div); |
2154 | for (i = 0; i < bset->n_eq; ++i) { |
2155 | j = isl_seq_last_non_zero(p: bset->eq[i] + 1 + total, len: n_div); |
2156 | if (j < 0) |
2157 | p = print_constraint_c(p, ls, |
2158 | c: bset->eq[i], op: "==" , first: &first); |
2159 | else { |
2160 | if (i) |
2161 | p = isl_printer_print_str(p, s: " && " ); |
2162 | p = isl_printer_print_str(p, s: "(" ); |
2163 | p = print_ls_partial_affine_c(p, ls, c: bset->eq[i], |
2164 | len: 1 + total + j); |
2165 | p = isl_printer_print_str(p, s: ") % " ); |
2166 | p = isl_printer_print_isl_int(p, |
2167 | i: bset->eq[i][1 + total + j]); |
2168 | p = isl_printer_print_str(p, s: " == 0" ); |
2169 | first = 0; |
2170 | } |
2171 | } |
2172 | for (i = 0; i < bset->n_ineq; ++i) |
2173 | p = print_constraint_c(p, ls, c: bset->ineq[i], op: ">=" , first: &first); |
2174 | isl_local_space_free(ls); |
2175 | return p; |
2176 | } |
2177 | |
2178 | static __isl_give isl_printer *print_set_c(__isl_take isl_printer *p, |
2179 | __isl_keep isl_space *space, __isl_keep isl_set *set) |
2180 | { |
2181 | int i; |
2182 | |
2183 | if (!set) |
2184 | return isl_printer_free(printer: p); |
2185 | |
2186 | if (set->n == 0) |
2187 | p = isl_printer_print_str(p, s: "0" ); |
2188 | |
2189 | for (i = 0; i < set->n; ++i) { |
2190 | if (i) |
2191 | p = isl_printer_print_str(p, s: " || " ); |
2192 | if (set->n > 1) |
2193 | p = isl_printer_print_str(p, s: "(" ); |
2194 | p = print_basic_set_c(p, space, bset: set->p[i]); |
2195 | if (set->n > 1) |
2196 | p = isl_printer_print_str(p, s: ")" ); |
2197 | } |
2198 | return p; |
2199 | } |
2200 | |
2201 | /* Print the piecewise quasi-polynomial "pwqp" to "p" in C format. |
2202 | */ |
2203 | static __isl_give isl_printer *print_pw_qpolynomial_c( |
2204 | __isl_take isl_printer *p, __isl_keep isl_pw_qpolynomial *pwqp) |
2205 | { |
2206 | int i; |
2207 | isl_space *space; |
2208 | |
2209 | space = isl_pw_qpolynomial_get_domain_space(pwqp); |
2210 | if (pwqp->n == 1 && isl_set_plain_is_universe(set: pwqp->p[0].set)) { |
2211 | p = print_qpolynomial_c(p, space, qp: pwqp->p[0].qp); |
2212 | isl_space_free(space); |
2213 | return p; |
2214 | } |
2215 | |
2216 | for (i = 0; i < pwqp->n; ++i) { |
2217 | p = isl_printer_print_str(p, s: "(" ); |
2218 | p = print_set_c(p, space, set: pwqp->p[i].set); |
2219 | p = isl_printer_print_str(p, s: ") ? (" ); |
2220 | p = print_qpolynomial_c(p, space, qp: pwqp->p[i].qp); |
2221 | p = isl_printer_print_str(p, s: ") : " ); |
2222 | } |
2223 | |
2224 | isl_space_free(space); |
2225 | p = isl_printer_print_str(p, s: "0" ); |
2226 | return p; |
2227 | } |
2228 | |
2229 | __isl_give isl_printer *isl_printer_print_pw_qpolynomial( |
2230 | __isl_take isl_printer *p, __isl_keep isl_pw_qpolynomial *pwqp) |
2231 | { |
2232 | if (!p || !pwqp) |
2233 | goto error; |
2234 | |
2235 | if (p->output_format == ISL_FORMAT_ISL) |
2236 | return print_pw_qpolynomial_isl(p, pwqp); |
2237 | else if (p->output_format == ISL_FORMAT_C) |
2238 | return print_pw_qpolynomial_c(p, pwqp); |
2239 | isl_assert(p->ctx, 0, goto error); |
2240 | error: |
2241 | isl_printer_free(printer: p); |
2242 | return NULL; |
2243 | } |
2244 | |
2245 | #undef BASE |
2246 | #define BASE pw_qpolynomial |
2247 | #include "isl_union_print_templ.c" |
2248 | |
2249 | __isl_give isl_printer *isl_printer_print_union_pw_qpolynomial( |
2250 | __isl_take isl_printer *p, __isl_keep isl_union_pw_qpolynomial *upwqp) |
2251 | { |
2252 | if (!p || !upwqp) |
2253 | goto error; |
2254 | |
2255 | if (p->output_format == ISL_FORMAT_ISL) |
2256 | return print_union_pw_qpolynomial_isl(p, u: upwqp); |
2257 | isl_die(p->ctx, isl_error_invalid, |
2258 | "invalid output format for isl_union_pw_qpolynomial" , |
2259 | goto error); |
2260 | error: |
2261 | isl_printer_free(printer: p); |
2262 | return NULL; |
2263 | } |
2264 | |
2265 | /* Print the quasi-polynomial reduction "fold" to "p" in C format, |
2266 | * with the variable names taken from the domain space "space". |
2267 | */ |
2268 | static __isl_give isl_printer *print_qpolynomial_fold_c( |
2269 | __isl_take isl_printer *p, __isl_keep isl_space *space, |
2270 | __isl_keep isl_qpolynomial_fold *fold) |
2271 | { |
2272 | int i; |
2273 | isl_qpolynomial_list *list; |
2274 | isl_size n; |
2275 | |
2276 | list = isl_qpolynomial_fold_peek_list(fold); |
2277 | n = isl_qpolynomial_list_size(list); |
2278 | if (n < 0) |
2279 | return isl_printer_free(printer: p); |
2280 | for (i = 0; i < n - 1; ++i) |
2281 | if (fold->type == isl_fold_min) |
2282 | p = isl_printer_print_str(p, s: "min(" ); |
2283 | else if (fold->type == isl_fold_max) |
2284 | p = isl_printer_print_str(p, s: "max(" ); |
2285 | |
2286 | for (i = 0; i < n; ++i) { |
2287 | isl_qpolynomial *qp; |
2288 | |
2289 | if (i) |
2290 | p = isl_printer_print_str(p, s: ", " ); |
2291 | qp = isl_qpolynomial_list_peek(list, index: i); |
2292 | p = print_qpolynomial_c(p, space, qp); |
2293 | if (i) |
2294 | p = isl_printer_print_str(p, s: ")" ); |
2295 | } |
2296 | return p; |
2297 | } |
2298 | |
2299 | __isl_give isl_printer *isl_printer_print_qpolynomial_fold( |
2300 | __isl_take isl_printer *p, __isl_keep isl_qpolynomial_fold *fold) |
2301 | { |
2302 | if (!p || !fold) |
2303 | goto error; |
2304 | if (p->output_format == ISL_FORMAT_ISL) |
2305 | return qpolynomial_fold_print(fold, p); |
2306 | else if (p->output_format == ISL_FORMAT_C) |
2307 | return print_qpolynomial_fold_c(p, space: fold->dim, fold); |
2308 | isl_die(p->ctx, isl_error_unsupported, "unsupported output format" , |
2309 | goto error); |
2310 | error: |
2311 | isl_printer_free(printer: p); |
2312 | return NULL; |
2313 | } |
2314 | |
2315 | /* Print the piecewise quasi-polynomial reduction "pwf" to "p" in C format. |
2316 | */ |
2317 | static __isl_give isl_printer *print_pw_qpolynomial_fold_c( |
2318 | __isl_take isl_printer *p, __isl_keep isl_pw_qpolynomial_fold *pwf) |
2319 | { |
2320 | int i; |
2321 | isl_space *space; |
2322 | |
2323 | space = isl_pw_qpolynomial_fold_get_domain_space(pwf); |
2324 | if (pwf->n == 1 && isl_set_plain_is_universe(set: pwf->p[0].set)) { |
2325 | p = print_qpolynomial_fold_c(p, space, fold: pwf->p[0].fold); |
2326 | isl_space_free(space); |
2327 | return p; |
2328 | } |
2329 | |
2330 | for (i = 0; i < pwf->n; ++i) { |
2331 | p = isl_printer_print_str(p, s: "(" ); |
2332 | p = print_set_c(p, space, set: pwf->p[i].set); |
2333 | p = isl_printer_print_str(p, s: ") ? (" ); |
2334 | p = print_qpolynomial_fold_c(p, space, fold: pwf->p[i].fold); |
2335 | p = isl_printer_print_str(p, s: ") : " ); |
2336 | } |
2337 | |
2338 | isl_space_free(space); |
2339 | p = isl_printer_print_str(p, s: "0" ); |
2340 | return p; |
2341 | } |
2342 | |
2343 | __isl_give isl_printer *isl_printer_print_pw_qpolynomial_fold( |
2344 | __isl_take isl_printer *p, __isl_keep isl_pw_qpolynomial_fold *pwf) |
2345 | { |
2346 | if (!p || !pwf) |
2347 | goto error; |
2348 | |
2349 | if (p->output_format == ISL_FORMAT_ISL) |
2350 | return print_pw_qpolynomial_fold_isl(p, pwf); |
2351 | else if (p->output_format == ISL_FORMAT_C) |
2352 | return print_pw_qpolynomial_fold_c(p, pwf); |
2353 | isl_assert(p->ctx, 0, goto error); |
2354 | error: |
2355 | isl_printer_free(printer: p); |
2356 | return NULL; |
2357 | } |
2358 | |
2359 | void isl_pw_qpolynomial_fold_print(__isl_keep isl_pw_qpolynomial_fold *pwf, |
2360 | FILE *out, unsigned output_format) |
2361 | { |
2362 | isl_printer *p; |
2363 | |
2364 | if (!pwf) |
2365 | return; |
2366 | |
2367 | p = isl_printer_to_file(ctx: pwf->dim->ctx, file: out); |
2368 | p = isl_printer_set_output_format(p, output_format); |
2369 | p = isl_printer_print_pw_qpolynomial_fold(p, pwf); |
2370 | |
2371 | isl_printer_free(printer: p); |
2372 | } |
2373 | |
2374 | #undef BASE |
2375 | #define BASE pw_qpolynomial_fold |
2376 | #include "isl_union_print_templ.c" |
2377 | |
2378 | __isl_give isl_printer *isl_printer_print_union_pw_qpolynomial_fold( |
2379 | __isl_take isl_printer *p, |
2380 | __isl_keep isl_union_pw_qpolynomial_fold *upwf) |
2381 | { |
2382 | if (!p || !upwf) |
2383 | goto error; |
2384 | |
2385 | if (p->output_format == ISL_FORMAT_ISL) |
2386 | return print_union_pw_qpolynomial_fold_isl(p, u: upwf); |
2387 | isl_die(p->ctx, isl_error_invalid, |
2388 | "invalid output format for isl_union_pw_qpolynomial_fold" , |
2389 | goto error); |
2390 | error: |
2391 | isl_printer_free(printer: p); |
2392 | return NULL; |
2393 | } |
2394 | |
2395 | /* Print the isl_constraint "c" to "p". |
2396 | */ |
2397 | __isl_give isl_printer *isl_printer_print_constraint(__isl_take isl_printer *p, |
2398 | __isl_keep isl_constraint *c) |
2399 | { |
2400 | struct isl_print_space_data data = { 0 }; |
2401 | isl_local_space *ls; |
2402 | isl_space *space; |
2403 | isl_bool exists; |
2404 | |
2405 | if (!p || !c) |
2406 | goto error; |
2407 | |
2408 | ls = isl_constraint_get_local_space(constraint: c); |
2409 | if (!ls) |
2410 | return isl_printer_free(printer: p); |
2411 | space = isl_local_space_get_space(ls); |
2412 | p = print_param_tuple(p, space, data: &data); |
2413 | p = isl_printer_print_str(p, s: "{ " ); |
2414 | p = isl_print_space(space, p, rational: 0, data: &data); |
2415 | p = isl_printer_print_str(p, s: " : " ); |
2416 | exists = need_exists(p, div: ls->div); |
2417 | if (exists < 0) |
2418 | p = isl_printer_free(printer: p); |
2419 | if (exists >= 0 && exists) |
2420 | p = open_exists(p, space, div: ls->div, latex: 0); |
2421 | p = print_affine_of_len(space, div: ls->div, p, c: c->v->el, len: c->v->size); |
2422 | if (isl_constraint_is_equality(constraint: c)) |
2423 | p = isl_printer_print_str(p, s: " = 0" ); |
2424 | else |
2425 | p = isl_printer_print_str(p, s: " >= 0" ); |
2426 | if (exists >= 0 && exists) |
2427 | p = isl_printer_print_str(p, s: s_close_exists[0]); |
2428 | p = isl_printer_print_str(p, s: " }" ); |
2429 | isl_space_free(space); |
2430 | isl_local_space_free(ls); |
2431 | |
2432 | return p; |
2433 | error: |
2434 | isl_printer_free(printer: p); |
2435 | return NULL; |
2436 | } |
2437 | |
2438 | static __isl_give isl_printer *isl_printer_print_space_isl( |
2439 | __isl_take isl_printer *p, __isl_keep isl_space *space) |
2440 | { |
2441 | struct isl_print_space_data data = { 0 }; |
2442 | |
2443 | if (!space) |
2444 | goto error; |
2445 | |
2446 | p = print_param_tuple(p, space, data: &data); |
2447 | |
2448 | p = isl_printer_print_str(p, s: "{ " ); |
2449 | if (isl_space_is_params(space)) |
2450 | p = isl_printer_print_str(p, s: s_such_that[0]); |
2451 | else |
2452 | p = isl_print_space(space, p, rational: 0, data: &data); |
2453 | p = isl_printer_print_str(p, s: " }" ); |
2454 | |
2455 | return p; |
2456 | error: |
2457 | isl_printer_free(printer: p); |
2458 | return NULL; |
2459 | } |
2460 | |
2461 | __isl_give isl_printer *isl_printer_print_space(__isl_take isl_printer *p, |
2462 | __isl_keep isl_space *space) |
2463 | { |
2464 | if (!p || !space) |
2465 | return isl_printer_free(printer: p); |
2466 | if (p->output_format == ISL_FORMAT_ISL) |
2467 | return isl_printer_print_space_isl(p, space); |
2468 | else if (p->output_format == ISL_FORMAT_OMEGA) |
2469 | return print_omega_parameters(space, p); |
2470 | |
2471 | isl_die(isl_space_get_ctx(space), isl_error_unsupported, |
2472 | "output format not supported for space" , |
2473 | return isl_printer_free(p)); |
2474 | } |
2475 | |
2476 | __isl_give isl_printer *isl_printer_print_local_space(__isl_take isl_printer *p, |
2477 | __isl_keep isl_local_space *ls) |
2478 | { |
2479 | struct isl_print_space_data data = { 0 }; |
2480 | isl_size n_div; |
2481 | |
2482 | n_div = isl_local_space_dim(ls, type: isl_dim_div); |
2483 | if (n_div < 0) |
2484 | goto error; |
2485 | |
2486 | p = print_param_tuple(p, space: ls->dim, data: &data); |
2487 | p = isl_printer_print_str(p, s: "{ " ); |
2488 | p = isl_print_space(space: ls->dim, p, rational: 0, data: &data); |
2489 | if (n_div > 0) { |
2490 | p = isl_printer_print_str(p, s: " : " ); |
2491 | p = isl_printer_print_str(p, s: s_open_exists[0]); |
2492 | p = print_div_list(p, space: ls->dim, div: ls->div, latex: 0, print_defined_divs: 1); |
2493 | p = isl_printer_print_str(p, s: s_close_exists[0]); |
2494 | } else if (isl_space_is_params(space: ls->dim)) |
2495 | p = isl_printer_print_str(p, s: s_such_that[0]); |
2496 | p = isl_printer_print_str(p, s: " }" ); |
2497 | return p; |
2498 | error: |
2499 | isl_printer_free(printer: p); |
2500 | return NULL; |
2501 | } |
2502 | |
2503 | /* Look for the last of the "n" integer divisions that is used in "aff" and |
2504 | * that can be printed as a modulo and |
2505 | * return the position of this integer division. |
2506 | * Return "n" if no such integer division can be found. |
2507 | * Return isl_size_error on error. |
2508 | * |
2509 | * In particular, look for an integer division that appears in "aff" |
2510 | * with a coefficient that is a multiple of the denominator |
2511 | * of the integer division. |
2512 | * That is, check if the numerator of "aff" is of the form |
2513 | * |
2514 | * f(...) + a m floor(g/m) |
2515 | * |
2516 | * and return the position of "floor(g/m)". |
2517 | * |
2518 | * Note that, unlike print_as_modulo_pos, no check needs to be made |
2519 | * for whether the integer division can be printed, since it will |
2520 | * need to be printed as an integer division anyway if it is not printed |
2521 | * as a modulo. |
2522 | */ |
2523 | static isl_size last_modulo(__isl_keep isl_printer *p, __isl_keep isl_aff *aff, |
2524 | unsigned n) |
2525 | { |
2526 | isl_size o_div; |
2527 | int i; |
2528 | |
2529 | if (n == 0) |
2530 | return n; |
2531 | o_div = isl_aff_domain_offset(aff, type: isl_dim_div); |
2532 | if (o_div < 0) |
2533 | return isl_size_error; |
2534 | for (i = n - 1; i >= 0; --i) { |
2535 | if (isl_int_is_zero(aff->v->el[1 + o_div + i])) |
2536 | continue; |
2537 | if (isl_int_is_divisible_by(aff->v->el[1 + o_div + i], |
2538 | aff->ls->div->row[i][0])) |
2539 | return i; |
2540 | } |
2541 | |
2542 | return n; |
2543 | } |
2544 | |
2545 | /* Print the numerator of the affine expression "aff" to "p", |
2546 | * with the variable names taken from "space". |
2547 | */ |
2548 | static __isl_give isl_printer *print_aff_num_base(__isl_take isl_printer *p, |
2549 | __isl_keep isl_space *space, __isl_keep isl_aff *aff) |
2550 | { |
2551 | isl_size total; |
2552 | |
2553 | total = isl_aff_domain_dim(aff, type: isl_dim_all); |
2554 | if (total < 0) |
2555 | return isl_printer_free(printer: p); |
2556 | p = print_affine_of_len(space, div: aff->ls->div, p, |
2557 | c: aff->v->el + 1, len: 1 + total); |
2558 | |
2559 | return p; |
2560 | } |
2561 | |
2562 | static __isl_give isl_printer *print_aff_num(__isl_take isl_printer *p, |
2563 | __isl_keep isl_space *space, __isl_keep isl_aff *aff); |
2564 | |
2565 | /* Print the modulo term "c" * ("aff" mod "mod") to "p", |
2566 | * with the variable names taken from "space". |
2567 | * If "first" is set, then this is the first term of an expression. |
2568 | */ |
2569 | static __isl_give isl_printer *print_mod_term(__isl_take isl_printer *p, |
2570 | __isl_keep isl_space *space, __isl_keep isl_aff *aff, int first, |
2571 | __isl_take isl_val *c, __isl_keep isl_val *mod) |
2572 | { |
2573 | isl_bool is_one, is_neg; |
2574 | |
2575 | is_neg = isl_val_is_neg(v: c); |
2576 | if (is_neg < 0) |
2577 | p = isl_printer_free(printer: p); |
2578 | if (!first) { |
2579 | if (is_neg) |
2580 | c = isl_val_neg(v: c); |
2581 | p = isl_printer_print_str(p, s: is_neg ? " - " : " + " ); |
2582 | } |
2583 | is_one = isl_val_is_one(v: c); |
2584 | if (is_one < 0) |
2585 | p = isl_printer_free(printer: p); |
2586 | if (!is_one) { |
2587 | p = isl_printer_print_val(p, v: c); |
2588 | p = isl_printer_print_str(p, s: "*(" ); |
2589 | } |
2590 | p = isl_printer_print_str(p, s: "(" ); |
2591 | p = print_aff_num(p, space, aff); |
2592 | p = isl_printer_print_str(p, s: ")" ); |
2593 | p = isl_printer_print_str(p, s: " mod " ); |
2594 | p = isl_printer_print_val(p, v: mod); |
2595 | if (!is_one) |
2596 | p = isl_printer_print_str(p, s: ")" ); |
2597 | |
2598 | isl_val_free(v: c); |
2599 | |
2600 | return p; |
2601 | } |
2602 | |
2603 | /* Print the numerator of the affine expression "aff" to "p", |
2604 | * with the variable names taken from "space", |
2605 | * given that the numerator of "aff" is of the form |
2606 | * |
2607 | * f(...) + a m floor(g/m) |
2608 | * |
2609 | * with "floor(g/m)" the integer division at position "last". |
2610 | * |
2611 | * First replace "aff" by its numerator and rewrite it as |
2612 | * |
2613 | * f(...) + a g - a (g mod m) |
2614 | * |
2615 | * Recursively write out (the numerator of) "f(...) + a g" |
2616 | * (which may involve other modulo expressions) and |
2617 | * then write out "- a (g mod m)". |
2618 | */ |
2619 | static __isl_give isl_printer *print_aff_num_mod(__isl_take isl_printer *p, |
2620 | __isl_keep isl_space *space, __isl_keep isl_aff *aff, unsigned last) |
2621 | { |
2622 | isl_bool is_zero; |
2623 | isl_val *a, *m; |
2624 | isl_aff *div, *term; |
2625 | |
2626 | aff = isl_aff_copy(aff); |
2627 | aff = isl_aff_scale_val(aff, v: isl_aff_get_denominator_val(aff)); |
2628 | a = isl_aff_get_coefficient_val(aff, type: isl_dim_div, pos: last); |
2629 | aff = isl_aff_set_coefficient_si(aff, type: isl_dim_div, pos: last, v: 0); |
2630 | div = isl_aff_get_div(aff, pos: last); |
2631 | m = isl_aff_get_denominator_val(aff: div); |
2632 | a = isl_val_div(v1: a, v2: isl_val_copy(v: m)); |
2633 | div = isl_aff_scale_val(aff: div, v: isl_val_copy(v: m)); |
2634 | term = isl_aff_scale_val(aff: isl_aff_copy(aff: div), v: isl_val_copy(v: a)); |
2635 | aff = isl_aff_add(aff1: aff, aff2: term); |
2636 | |
2637 | is_zero = isl_aff_plain_is_zero(aff); |
2638 | if (is_zero < 0) { |
2639 | p = isl_printer_free(printer: p); |
2640 | } else { |
2641 | if (!is_zero) |
2642 | p = print_aff_num(p, space, aff); |
2643 | a = isl_val_neg(v: a); |
2644 | p = print_mod_term(p, space, aff: div, first: is_zero, c: isl_val_copy(v: a), mod: m); |
2645 | } |
2646 | |
2647 | isl_val_free(v: a); |
2648 | isl_val_free(v: m); |
2649 | isl_aff_free(aff); |
2650 | isl_aff_free(aff: div); |
2651 | |
2652 | return p; |
2653 | } |
2654 | |
2655 | /* Print the numerator of the affine expression "aff" to "p", |
2656 | * with the variable names taken from "space", |
2657 | * separating out any (obvious) modulo expressions. |
2658 | * |
2659 | * In particular, look for modulo expressions in "aff", |
2660 | * separating them out if found and simply printing out "aff" otherwise. |
2661 | */ |
2662 | static __isl_give isl_printer *print_aff_num(__isl_take isl_printer *p, |
2663 | __isl_keep isl_space *space, __isl_keep isl_aff *aff) |
2664 | { |
2665 | isl_size n_div, mod; |
2666 | |
2667 | n_div = isl_aff_dim(aff, type: isl_dim_div); |
2668 | if (n_div < 0) |
2669 | return isl_printer_free(printer: p); |
2670 | mod = last_modulo(p, aff, n: n_div); |
2671 | if (mod < 0) |
2672 | return isl_printer_free(printer: p); |
2673 | if (mod < n_div) |
2674 | return print_aff_num_mod(p, space, aff, last: mod); |
2675 | else |
2676 | return print_aff_num_base(p, space, aff); |
2677 | } |
2678 | |
2679 | /* Print the (potentially rational) affine expression "aff" to "p", |
2680 | * with the variable names taken from "space". |
2681 | */ |
2682 | static __isl_give isl_printer *print_aff_body(__isl_take isl_printer *p, |
2683 | __isl_keep isl_space *space, __isl_keep isl_aff *aff) |
2684 | { |
2685 | if (isl_aff_is_nan(aff)) |
2686 | return isl_printer_print_str(p, s: "NaN" ); |
2687 | |
2688 | p = isl_printer_print_str(p, s: "(" ); |
2689 | p = print_aff_num(p, space, aff); |
2690 | if (isl_int_is_one(aff->v->el[0])) |
2691 | p = isl_printer_print_str(p, s: ")" ); |
2692 | else { |
2693 | p = isl_printer_print_str(p, s: ")/" ); |
2694 | p = isl_printer_print_isl_int(p, i: aff->v->el[0]); |
2695 | } |
2696 | |
2697 | return p; |
2698 | } |
2699 | |
2700 | static __isl_give isl_printer *print_body_aff(__isl_take isl_printer *p, |
2701 | __isl_keep isl_aff *aff) |
2702 | { |
2703 | struct isl_print_space_data data = { 0 }; |
2704 | |
2705 | if (isl_space_is_params(space: aff->ls->dim)) |
2706 | ; |
2707 | else { |
2708 | p = print_tuple(space: aff->ls->dim, p, type: isl_dim_set, data: &data); |
2709 | p = isl_printer_print_str(p, s: " -> " ); |
2710 | } |
2711 | p = isl_printer_print_str(p, s: "[" ); |
2712 | p = print_aff_body(p, space: aff->ls->dim, aff); |
2713 | p = isl_printer_print_str(p, s: "]" ); |
2714 | |
2715 | return p; |
2716 | } |
2717 | |
2718 | static __isl_give isl_printer *print_aff_isl(__isl_take isl_printer *p, |
2719 | __isl_keep isl_aff *aff) |
2720 | { |
2721 | struct isl_print_space_data data = { 0 }; |
2722 | |
2723 | if (!aff) |
2724 | goto error; |
2725 | |
2726 | p = print_param_tuple(p, space: aff->ls->dim, data: &data); |
2727 | p = isl_printer_print_str(p, s: "{ " ); |
2728 | p = print_body_aff(p, aff); |
2729 | p = isl_printer_print_str(p, s: " }" ); |
2730 | return p; |
2731 | error: |
2732 | isl_printer_free(printer: p); |
2733 | return NULL; |
2734 | } |
2735 | |
2736 | #undef BASE |
2737 | #define BASE aff |
2738 | #include "isl_pw_print_templ.c" |
2739 | |
2740 | static __isl_give isl_printer *print_ls_name_c(__isl_take isl_printer *p, |
2741 | __isl_keep isl_local_space *ls, enum isl_dim_type type, unsigned pos) |
2742 | { |
2743 | if (type == isl_dim_div) { |
2744 | p = isl_printer_print_str(p, s: "floord(" ); |
2745 | p = print_ls_affine_c(p, ls, c: ls->div->row[pos] + 1); |
2746 | p = isl_printer_print_str(p, s: ", " ); |
2747 | p = isl_printer_print_isl_int(p, i: ls->div->row[pos][0]); |
2748 | p = isl_printer_print_str(p, s: ")" ); |
2749 | } else { |
2750 | const char *name; |
2751 | |
2752 | name = isl_space_get_dim_name(space: ls->dim, type, pos); |
2753 | if (!name) |
2754 | name = "UNNAMED" ; |
2755 | p = isl_printer_print_str(p, s: name); |
2756 | } |
2757 | return p; |
2758 | } |
2759 | |
2760 | static __isl_give isl_printer *print_ls_term_c(__isl_take isl_printer *p, |
2761 | __isl_keep isl_local_space *ls, isl_int c, unsigned pos) |
2762 | { |
2763 | enum isl_dim_type type; |
2764 | |
2765 | if (!p || !ls) |
2766 | return isl_printer_free(printer: p); |
2767 | |
2768 | if (pos == 0) |
2769 | return isl_printer_print_isl_int(p, i: c); |
2770 | |
2771 | if (isl_int_is_one(c)) |
2772 | ; |
2773 | else if (isl_int_is_negone(c)) |
2774 | p = isl_printer_print_str(p, s: "-" ); |
2775 | else { |
2776 | p = isl_printer_print_isl_int(p, i: c); |
2777 | p = isl_printer_print_str(p, s: "*" ); |
2778 | } |
2779 | if (pos2type(space: ls->dim, type: &type, pos: &pos) < 0) |
2780 | return isl_printer_free(printer: p); |
2781 | p = print_ls_name_c(p, ls, type, pos); |
2782 | return p; |
2783 | } |
2784 | |
2785 | static __isl_give isl_printer *print_ls_partial_affine_c( |
2786 | __isl_take isl_printer *p, __isl_keep isl_local_space *ls, |
2787 | isl_int *c, unsigned len) |
2788 | { |
2789 | int i; |
2790 | int first; |
2791 | |
2792 | for (i = 0, first = 1; i < len; ++i) { |
2793 | int flip = 0; |
2794 | if (isl_int_is_zero(c[i])) |
2795 | continue; |
2796 | if (!first) { |
2797 | if (isl_int_is_neg(c[i])) { |
2798 | flip = 1; |
2799 | isl_int_neg(c[i], c[i]); |
2800 | p = isl_printer_print_str(p, s: " - " ); |
2801 | } else |
2802 | p = isl_printer_print_str(p, s: " + " ); |
2803 | } |
2804 | first = 0; |
2805 | p = print_ls_term_c(p, ls, c: c[i], pos: i); |
2806 | if (flip) |
2807 | isl_int_neg(c[i], c[i]); |
2808 | } |
2809 | if (first) |
2810 | p = isl_printer_print_str(p, s: "0" ); |
2811 | return p; |
2812 | } |
2813 | |
2814 | static __isl_give isl_printer *print_ls_affine_c(__isl_take isl_printer *p, |
2815 | __isl_keep isl_local_space *ls, isl_int *c) |
2816 | { |
2817 | isl_size total = isl_local_space_dim(ls, type: isl_dim_all); |
2818 | |
2819 | if (total < 0) |
2820 | return isl_printer_free(printer: p); |
2821 | return print_ls_partial_affine_c(p, ls, c, len: 1 + total); |
2822 | } |
2823 | |
2824 | static __isl_give isl_printer *print_aff_c(__isl_take isl_printer *p, |
2825 | __isl_keep isl_aff *aff) |
2826 | { |
2827 | isl_size total; |
2828 | |
2829 | total = isl_aff_domain_dim(aff, type: isl_dim_all); |
2830 | if (total < 0) |
2831 | return isl_printer_free(printer: p); |
2832 | if (!isl_int_is_one(aff->v->el[0])) |
2833 | p = isl_printer_print_str(p, s: "(" ); |
2834 | p = print_ls_partial_affine_c(p, ls: aff->ls, c: aff->v->el + 1, len: 1 + total); |
2835 | if (!isl_int_is_one(aff->v->el[0])) { |
2836 | p = isl_printer_print_str(p, s: ")/" ); |
2837 | p = isl_printer_print_isl_int(p, i: aff->v->el[0]); |
2838 | } |
2839 | return p; |
2840 | } |
2841 | |
2842 | /* In the C format, we cannot express that "pwaff" may be undefined |
2843 | * on parts of the domain space. We therefore assume that the expression |
2844 | * will only be evaluated on its definition domain and compute the gist |
2845 | * of each cell with respect to this domain. |
2846 | */ |
2847 | static __isl_give isl_printer *print_pw_aff_c(__isl_take isl_printer *p, |
2848 | __isl_keep isl_pw_aff *pwaff) |
2849 | { |
2850 | isl_set *domain; |
2851 | isl_ast_build *build; |
2852 | isl_ast_expr *expr; |
2853 | |
2854 | if (pwaff->n < 1) |
2855 | isl_die(p->ctx, isl_error_unsupported, |
2856 | "cannot print empty isl_pw_aff in C format" , |
2857 | return isl_printer_free(p)); |
2858 | |
2859 | domain = isl_pw_aff_domain(pwaff: isl_pw_aff_copy(pwaff)); |
2860 | build = isl_ast_build_from_context(set: domain); |
2861 | expr = isl_ast_build_expr_from_pw_aff(build, pa: isl_pw_aff_copy(pwaff)); |
2862 | p = isl_printer_print_ast_expr(p, expr); |
2863 | isl_ast_expr_free(expr); |
2864 | isl_ast_build_free(build); |
2865 | |
2866 | return p; |
2867 | } |
2868 | |
2869 | __isl_give isl_printer *isl_printer_print_aff(__isl_take isl_printer *p, |
2870 | __isl_keep isl_aff *aff) |
2871 | { |
2872 | if (!p || !aff) |
2873 | goto error; |
2874 | |
2875 | if (p->output_format == ISL_FORMAT_ISL) |
2876 | return print_aff_isl(p, aff); |
2877 | else if (p->output_format == ISL_FORMAT_C) |
2878 | return print_aff_c(p, aff); |
2879 | isl_die(p->ctx, isl_error_unsupported, "unsupported output format" , |
2880 | goto error); |
2881 | error: |
2882 | isl_printer_free(printer: p); |
2883 | return NULL; |
2884 | } |
2885 | |
2886 | __isl_give isl_printer *isl_printer_print_pw_aff(__isl_take isl_printer *p, |
2887 | __isl_keep isl_pw_aff *pwaff) |
2888 | { |
2889 | if (!p || !pwaff) |
2890 | goto error; |
2891 | |
2892 | if (p->output_format == ISL_FORMAT_ISL) |
2893 | return print_pw_aff_isl(p, pw: pwaff); |
2894 | else if (p->output_format == ISL_FORMAT_C) |
2895 | return print_pw_aff_c(p, pwaff); |
2896 | isl_die(p->ctx, isl_error_unsupported, "unsupported output format" , |
2897 | goto error); |
2898 | error: |
2899 | isl_printer_free(printer: p); |
2900 | return NULL; |
2901 | } |
2902 | |
2903 | #undef BASE |
2904 | #define BASE pw_aff |
2905 | #include "isl_union_print_templ.c" |
2906 | |
2907 | /* Print the isl_union_pw_aff "upa" to "p". |
2908 | * |
2909 | * We currently only support an isl format. |
2910 | */ |
2911 | __isl_give isl_printer *isl_printer_print_union_pw_aff( |
2912 | __isl_take isl_printer *p, __isl_keep isl_union_pw_aff *upa) |
2913 | { |
2914 | if (!p || !upa) |
2915 | return isl_printer_free(printer: p); |
2916 | |
2917 | if (p->output_format == ISL_FORMAT_ISL) |
2918 | return print_union_pw_aff_isl(p, u: upa); |
2919 | isl_die(isl_printer_get_ctx(p), isl_error_unsupported, |
2920 | "unsupported output format" , return isl_printer_free(p)); |
2921 | } |
2922 | |
2923 | /* Print dimension "pos" of data->space to "p". |
2924 | * |
2925 | * data->user is assumed to be an isl_multi_aff. |
2926 | * |
2927 | * If the current dimension is an output dimension, then print |
2928 | * the corresponding expression. Otherwise, print the name of the dimension. |
2929 | * Make sure to use the domain space for printing names as |
2930 | * that is the space that will be used for printing constraints (if any). |
2931 | */ |
2932 | static __isl_give isl_printer *print_dim_ma(__isl_take isl_printer *p, |
2933 | struct isl_print_space_data *data, unsigned pos) |
2934 | { |
2935 | isl_multi_aff *ma = data->user; |
2936 | isl_space *space; |
2937 | |
2938 | space = isl_multi_aff_get_domain_space(multi: ma); |
2939 | if (data->type == isl_dim_out) { |
2940 | p = print_aff_body(p, space, aff: ma->u.p[pos]); |
2941 | } else { |
2942 | enum isl_dim_type type = data->type; |
2943 | |
2944 | if (type == isl_dim_in) |
2945 | type = isl_dim_set; |
2946 | p = print_name(space, p, type, pos, latex: data->latex); |
2947 | } |
2948 | isl_space_free(space); |
2949 | |
2950 | return p; |
2951 | } |
2952 | |
2953 | static __isl_give isl_printer *print_body_multi_aff(__isl_take isl_printer *p, |
2954 | __isl_keep isl_multi_aff *maff) |
2955 | { |
2956 | struct isl_print_space_data data = { 0 }; |
2957 | |
2958 | data.print_dim = &print_dim_ma; |
2959 | data.user = maff; |
2960 | return isl_print_space(space: maff->space, p, rational: 0, data: &data); |
2961 | } |
2962 | |
2963 | static __isl_give isl_printer *print_multi_aff_isl(__isl_take isl_printer *p, |
2964 | __isl_keep isl_multi_aff *maff) |
2965 | { |
2966 | struct isl_print_space_data data = { 0 }; |
2967 | |
2968 | if (!maff) |
2969 | goto error; |
2970 | |
2971 | p = print_param_tuple(p, space: maff->space, data: &data); |
2972 | p = isl_printer_print_str(p, s: "{ " ); |
2973 | p = print_body_multi_aff(p, maff); |
2974 | p = isl_printer_print_str(p, s: " }" ); |
2975 | return p; |
2976 | error: |
2977 | isl_printer_free(printer: p); |
2978 | return NULL; |
2979 | } |
2980 | |
2981 | __isl_give isl_printer *isl_printer_print_multi_aff(__isl_take isl_printer *p, |
2982 | __isl_keep isl_multi_aff *maff) |
2983 | { |
2984 | if (!p || !maff) |
2985 | goto error; |
2986 | |
2987 | if (p->output_format == ISL_FORMAT_ISL) |
2988 | return print_multi_aff_isl(p, maff); |
2989 | isl_die(p->ctx, isl_error_unsupported, "unsupported output format" , |
2990 | goto error); |
2991 | error: |
2992 | isl_printer_free(printer: p); |
2993 | return NULL; |
2994 | } |
2995 | |
2996 | #undef BASE |
2997 | #define BASE multi_aff |
2998 | #include "isl_pw_print_templ.c" |
2999 | |
3000 | /* Print the unnamed, single-dimensional piecewise multi affine expression "pma" |
3001 | * to "p". |
3002 | */ |
3003 | static __isl_give isl_printer *print_unnamed_pw_multi_aff_c( |
3004 | __isl_take isl_printer *p, __isl_keep isl_pw_multi_aff *pma) |
3005 | { |
3006 | int i; |
3007 | isl_space *space; |
3008 | |
3009 | space = isl_pw_multi_aff_get_domain_space(pma); |
3010 | for (i = 0; i < pma->n - 1; ++i) { |
3011 | p = isl_printer_print_str(p, s: "(" ); |
3012 | p = print_set_c(p, space, set: pma->p[i].set); |
3013 | p = isl_printer_print_str(p, s: ") ? (" ); |
3014 | p = print_aff_c(p, aff: pma->p[i].maff->u.p[0]); |
3015 | p = isl_printer_print_str(p, s: ") : " ); |
3016 | } |
3017 | isl_space_free(space); |
3018 | |
3019 | return print_aff_c(p, aff: pma->p[pma->n - 1].maff->u.p[0]); |
3020 | } |
3021 | |
3022 | static __isl_give isl_printer *print_pw_multi_aff_c(__isl_take isl_printer *p, |
3023 | __isl_keep isl_pw_multi_aff *pma) |
3024 | { |
3025 | isl_size n; |
3026 | const char *name; |
3027 | |
3028 | if (!pma) |
3029 | goto error; |
3030 | if (pma->n < 1) |
3031 | isl_die(p->ctx, isl_error_unsupported, |
3032 | "cannot print empty isl_pw_multi_aff in C format" , |
3033 | goto error); |
3034 | n = isl_pw_multi_aff_dim(pma, type: isl_dim_out); |
3035 | if (n < 0) |
3036 | return isl_printer_free(printer: p); |
3037 | name = isl_pw_multi_aff_get_tuple_name(pma, type: isl_dim_out); |
3038 | if (!name && n == 1) |
3039 | return print_unnamed_pw_multi_aff_c(p, pma); |
3040 | if (!name) |
3041 | isl_die(p->ctx, isl_error_unsupported, |
3042 | "cannot print unnamed isl_pw_multi_aff in C format" , |
3043 | goto error); |
3044 | |
3045 | p = isl_printer_print_str(p, s: name); |
3046 | if (n != 0) |
3047 | isl_die(p->ctx, isl_error_unsupported, |
3048 | "not supported yet" , goto error); |
3049 | |
3050 | return p; |
3051 | error: |
3052 | isl_printer_free(printer: p); |
3053 | return NULL; |
3054 | } |
3055 | |
3056 | __isl_give isl_printer *isl_printer_print_pw_multi_aff( |
3057 | __isl_take isl_printer *p, __isl_keep isl_pw_multi_aff *pma) |
3058 | { |
3059 | if (!p || !pma) |
3060 | goto error; |
3061 | |
3062 | if (p->output_format == ISL_FORMAT_ISL) |
3063 | return print_pw_multi_aff_isl(p, pw: pma); |
3064 | if (p->output_format == ISL_FORMAT_C) |
3065 | return print_pw_multi_aff_c(p, pma); |
3066 | isl_die(p->ctx, isl_error_unsupported, "unsupported output format" , |
3067 | goto error); |
3068 | error: |
3069 | isl_printer_free(printer: p); |
3070 | return NULL; |
3071 | } |
3072 | |
3073 | #undef BASE |
3074 | #define BASE pw_multi_aff |
3075 | #include "isl_union_print_templ.c" |
3076 | |
3077 | __isl_give isl_printer *isl_printer_print_union_pw_multi_aff( |
3078 | __isl_take isl_printer *p, __isl_keep isl_union_pw_multi_aff *upma) |
3079 | { |
3080 | if (!p || !upma) |
3081 | goto error; |
3082 | |
3083 | if (p->output_format == ISL_FORMAT_ISL) |
3084 | return print_union_pw_multi_aff_isl(p, u: upma); |
3085 | isl_die(p->ctx, isl_error_unsupported, "unsupported output format" , |
3086 | goto error); |
3087 | error: |
3088 | isl_printer_free(printer: p); |
3089 | return NULL; |
3090 | } |
3091 | |
3092 | /* Print dimension "pos" of data->space to "p". |
3093 | * |
3094 | * data->user is assumed to be an isl_multi_pw_aff. |
3095 | * |
3096 | * If the current dimension is an output dimension, then print |
3097 | * the corresponding piecewise affine expression. |
3098 | * Otherwise, print the name of the dimension. |
3099 | * Make sure to use the same space in both cases. |
3100 | * In particular, use the domain space for printing names as |
3101 | * that is the space that is used for printing constraints. |
3102 | */ |
3103 | static __isl_give isl_printer *print_dim_mpa(__isl_take isl_printer *p, |
3104 | struct isl_print_space_data *data, unsigned pos) |
3105 | { |
3106 | int i; |
3107 | int need_parens; |
3108 | isl_space *space; |
3109 | isl_multi_pw_aff *mpa = data->user; |
3110 | isl_pw_aff *pa; |
3111 | |
3112 | if (data->type != isl_dim_out) { |
3113 | enum isl_dim_type type = data->type; |
3114 | |
3115 | if (type == isl_dim_in) |
3116 | type = isl_dim_set; |
3117 | space = isl_multi_pw_aff_get_domain_space(multi: mpa); |
3118 | p = print_name(space, p, type, pos, latex: data->latex); |
3119 | isl_space_free(space); |
3120 | return p; |
3121 | } |
3122 | |
3123 | pa = mpa->u.p[pos]; |
3124 | if (pa->n == 0) |
3125 | return isl_printer_print_str(p, s: "(0 : false)" ); |
3126 | |
3127 | need_parens = pa->n != 1 || !isl_set_plain_is_universe(set: pa->p[0].set); |
3128 | if (need_parens) |
3129 | p = isl_printer_print_str(p, s: "(" ); |
3130 | space = isl_multi_pw_aff_get_domain_space(multi: mpa); |
3131 | for (i = 0; i < pa->n; ++i) { |
3132 | |
3133 | if (i) |
3134 | p = isl_printer_print_str(p, s: "; " ); |
3135 | p = print_aff_body(p, space, aff: pa->p[i].aff); |
3136 | p = print_disjuncts(map: pa->p[i].set, space, p, latex: 0); |
3137 | } |
3138 | isl_space_free(space); |
3139 | if (need_parens) |
3140 | p = isl_printer_print_str(p, s: ")" ); |
3141 | |
3142 | return p; |
3143 | } |
3144 | |
3145 | /* Print "mpa" to "p" in isl format. |
3146 | * |
3147 | * If "mpa" is zero-dimensional and has a non-trivial explicit domain, |
3148 | * then it is printed after the tuple of affine expressions. |
3149 | */ |
3150 | static __isl_give isl_printer *print_multi_pw_aff_isl(__isl_take isl_printer *p, |
3151 | __isl_keep isl_multi_pw_aff *mpa) |
3152 | { |
3153 | struct isl_print_space_data data = { 0 }; |
3154 | isl_bool has_domain; |
3155 | |
3156 | if (!mpa) |
3157 | return isl_printer_free(printer: p); |
3158 | |
3159 | p = print_param_tuple(p, space: mpa->space, data: &data); |
3160 | p = isl_printer_print_str(p, s: "{ " ); |
3161 | data.print_dim = &print_dim_mpa; |
3162 | data.user = mpa; |
3163 | p = isl_print_space(space: mpa->space, p, rational: 0, data: &data); |
3164 | has_domain = isl_multi_pw_aff_has_non_trivial_domain(multi: mpa); |
3165 | if (has_domain < 0) |
3166 | return isl_printer_free(printer: p); |
3167 | if (has_domain) { |
3168 | isl_space *space; |
3169 | |
3170 | space = isl_space_domain(space: isl_space_copy(space: mpa->space)); |
3171 | p = print_disjuncts_set(set: mpa->u.dom, space, p, latex: 0); |
3172 | isl_space_free(space); |
3173 | } |
3174 | p = isl_printer_print_str(p, s: " }" ); |
3175 | return p; |
3176 | } |
3177 | |
3178 | __isl_give isl_printer *isl_printer_print_multi_pw_aff( |
3179 | __isl_take isl_printer *p, __isl_keep isl_multi_pw_aff *mpa) |
3180 | { |
3181 | if (!p || !mpa) |
3182 | return isl_printer_free(printer: p); |
3183 | |
3184 | if (p->output_format == ISL_FORMAT_ISL) |
3185 | return print_multi_pw_aff_isl(p, mpa); |
3186 | isl_die(p->ctx, isl_error_unsupported, "unsupported output format" , |
3187 | return isl_printer_free(p)); |
3188 | } |
3189 | |
3190 | /* Print dimension "pos" of data->space to "p". |
3191 | * |
3192 | * data->user is assumed to be an isl_multi_val. |
3193 | * |
3194 | * If the current dimension is an output dimension, then print |
3195 | * the corresponding value. Otherwise, print the name of the dimension. |
3196 | */ |
3197 | static __isl_give isl_printer *print_dim_mv(__isl_take isl_printer *p, |
3198 | struct isl_print_space_data *data, unsigned pos) |
3199 | { |
3200 | isl_multi_val *mv = data->user; |
3201 | |
3202 | if (data->type == isl_dim_out) |
3203 | return isl_printer_print_val(p, v: mv->u.p[pos]); |
3204 | else |
3205 | return print_name(space: data->space, p, type: data->type, pos, latex: data->latex); |
3206 | } |
3207 | |
3208 | /* Print the isl_multi_val "mv" to "p" in isl format. |
3209 | */ |
3210 | static __isl_give isl_printer *print_multi_val_isl(__isl_take isl_printer *p, |
3211 | __isl_keep isl_multi_val *mv) |
3212 | { |
3213 | struct isl_print_space_data data = { 0 }; |
3214 | |
3215 | if (!mv) |
3216 | return isl_printer_free(printer: p); |
3217 | |
3218 | p = print_param_tuple(p, space: mv->space, data: &data); |
3219 | p = isl_printer_print_str(p, s: "{ " ); |
3220 | data.print_dim = &print_dim_mv; |
3221 | data.user = mv; |
3222 | p = isl_print_space(space: mv->space, p, rational: 0, data: &data); |
3223 | p = isl_printer_print_str(p, s: " }" ); |
3224 | return p; |
3225 | } |
3226 | |
3227 | /* Print the isl_multi_val "mv" to "p". |
3228 | * |
3229 | * Currently only supported in isl format. |
3230 | */ |
3231 | __isl_give isl_printer *isl_printer_print_multi_val( |
3232 | __isl_take isl_printer *p, __isl_keep isl_multi_val *mv) |
3233 | { |
3234 | if (!p || !mv) |
3235 | return isl_printer_free(printer: p); |
3236 | |
3237 | if (p->output_format == ISL_FORMAT_ISL) |
3238 | return print_multi_val_isl(p, mv); |
3239 | isl_die(p->ctx, isl_error_unsupported, "unsupported output format" , |
3240 | return isl_printer_free(p)); |
3241 | } |
3242 | |
3243 | /* Print dimension "pos" of data->space to "p". |
3244 | * |
3245 | * data->user is assumed to be an isl_multi_id. |
3246 | * |
3247 | * If the current dimension is an output dimension, then print |
3248 | * the corresponding identifier. Otherwise, print the name of the dimension. |
3249 | */ |
3250 | static __isl_give isl_printer *print_dim_mi(__isl_take isl_printer *p, |
3251 | struct isl_print_space_data *data, unsigned pos) |
3252 | { |
3253 | isl_multi_id *mi = data->user; |
3254 | |
3255 | if (data->type == isl_dim_out) |
3256 | return isl_printer_print_id(p, id: mi->u.p[pos]); |
3257 | else |
3258 | return print_name(space: data->space, p, type: data->type, pos, latex: data->latex); |
3259 | } |
3260 | |
3261 | /* Print the isl_multi_id "mi" to "p" in isl format. |
3262 | */ |
3263 | static __isl_give isl_printer *print_multi_id_isl(__isl_take isl_printer *p, |
3264 | __isl_keep isl_multi_id *mi) |
3265 | { |
3266 | isl_space *space; |
3267 | struct isl_print_space_data data = { 0 }; |
3268 | |
3269 | space = isl_multi_id_peek_space(multi: mi); |
3270 | p = print_param_tuple(p, space, data: &data); |
3271 | p = isl_printer_print_str(p, s: "{ " ); |
3272 | data.print_dim = &print_dim_mi; |
3273 | data.user = mi; |
3274 | p = isl_print_space(space, p, rational: 0, data: &data); |
3275 | p = isl_printer_print_str(p, s: " }" ); |
3276 | return p; |
3277 | } |
3278 | |
3279 | /* Print the isl_multi_id "mi" to "p". |
3280 | * |
3281 | * Currently only supported in isl format. |
3282 | */ |
3283 | __isl_give isl_printer *isl_printer_print_multi_id( |
3284 | __isl_take isl_printer *p, __isl_keep isl_multi_id *mi) |
3285 | { |
3286 | if (!p || !mi) |
3287 | return isl_printer_free(printer: p); |
3288 | |
3289 | if (p->output_format == ISL_FORMAT_ISL) |
3290 | return print_multi_id_isl(p, mi); |
3291 | isl_die(isl_printer_get_ctx(p), isl_error_unsupported, |
3292 | "unsupported output format" , return isl_printer_free(p)); |
3293 | } |
3294 | |
3295 | /* Print dimension "pos" of data->space to "p". |
3296 | * |
3297 | * data->user is assumed to be an isl_multi_union_pw_aff. |
3298 | * |
3299 | * The current dimension is necessarily a set dimension, so |
3300 | * we print the corresponding isl_union_pw_aff, including |
3301 | * the braces. |
3302 | */ |
3303 | static __isl_give isl_printer *print_union_pw_aff_dim(__isl_take isl_printer *p, |
3304 | struct isl_print_space_data *data, unsigned pos) |
3305 | { |
3306 | isl_multi_union_pw_aff *mupa = data->user; |
3307 | isl_union_pw_aff *upa; |
3308 | |
3309 | upa = isl_multi_union_pw_aff_get_union_pw_aff(multi: mupa, pos); |
3310 | p = print_body_union_pw_aff(p, u: upa); |
3311 | isl_union_pw_aff_free(upa); |
3312 | |
3313 | return p; |
3314 | } |
3315 | |
3316 | /* Print the isl_multi_union_pw_aff "mupa" to "p" in isl format. |
3317 | * |
3318 | * If "mupa" is zero-dimensional and has a non-trivial explicit domain, |
3319 | * then it is printed after the tuple of affine expressions. |
3320 | * In order to clarify that this domain belongs to the expression, |
3321 | * the tuple along with the domain are placed inside parentheses. |
3322 | * If "mupa" has any parameters, then the opening parenthesis |
3323 | * appears after the parameter declarations. |
3324 | */ |
3325 | static __isl_give isl_printer *print_multi_union_pw_aff_isl( |
3326 | __isl_take isl_printer *p, __isl_keep isl_multi_union_pw_aff *mupa) |
3327 | { |
3328 | struct isl_print_space_data data = { 0 }; |
3329 | isl_bool has_domain; |
3330 | isl_space *space; |
3331 | |
3332 | if (!mupa) |
3333 | return isl_printer_free(printer: p); |
3334 | has_domain = isl_multi_union_pw_aff_has_non_trivial_domain(multi: mupa); |
3335 | if (has_domain < 0) |
3336 | return isl_printer_free(printer: p); |
3337 | |
3338 | space = isl_multi_union_pw_aff_get_space(multi: mupa); |
3339 | p = print_param_tuple(p, space, data: &data); |
3340 | |
3341 | if (has_domain) |
3342 | p = isl_printer_print_str(p, s: "(" ); |
3343 | |
3344 | data.print_dim = &print_union_pw_aff_dim; |
3345 | data.user = mupa; |
3346 | |
3347 | p = isl_print_space(space, p, rational: 0, data: &data); |
3348 | isl_space_free(space); |
3349 | |
3350 | if (has_domain) { |
3351 | p = isl_printer_print_str(p, s: " : " ); |
3352 | p = isl_printer_print_union_set_isl_body(p, uset: mupa->u.dom); |
3353 | p = isl_printer_print_str(p, s: ")" ); |
3354 | } |
3355 | |
3356 | return p; |
3357 | } |
3358 | |
3359 | /* Print the isl_multi_union_pw_aff "mupa" to "p" in isl format. |
3360 | * |
3361 | * We currently only support an isl format. |
3362 | */ |
3363 | __isl_give isl_printer *isl_printer_print_multi_union_pw_aff( |
3364 | __isl_take isl_printer *p, __isl_keep isl_multi_union_pw_aff *mupa) |
3365 | { |
3366 | if (!p || !mupa) |
3367 | return isl_printer_free(printer: p); |
3368 | |
3369 | if (p->output_format == ISL_FORMAT_ISL) |
3370 | return print_multi_union_pw_aff_isl(p, mupa); |
3371 | isl_die(isl_printer_get_ctx(p), isl_error_unsupported, |
3372 | "unsupported output format" , return isl_printer_free(p)); |
3373 | } |
3374 | |