Line data Source code
1 : /*
2 : * Copyright 2008-2009 Katholieke Universiteit Leuven
3 : * Copyright 2011 INRIA Saclay
4 : * Copyright 2012-2013 Ecole Normale Superieure
5 : * Copyright 2017 Sven Verdoolaege
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 : */
15 :
16 : #include <isl_sort.h>
17 : #include <isl_tarjan.h>
18 : #include <isl/printer.h>
19 :
20 : #define xCAT(A,B) A ## B
21 : #define CAT(A,B) xCAT(A,B)
22 : #undef EL
23 : #define EL CAT(isl_,BASE)
24 : #define xFN(TYPE,NAME) TYPE ## _ ## NAME
25 : #define FN(TYPE,NAME) xFN(TYPE,NAME)
26 : #define xLIST(EL) EL ## _list
27 : #define LIST(EL) xLIST(EL)
28 : #define xS(TYPE,NAME) struct TYPE ## _ ## NAME
29 : #define S(TYPE,NAME) xS(TYPE,NAME)
30 :
31 0 : isl_ctx *FN(LIST(EL),get_ctx)(__isl_keep LIST(EL) *list)
32 : {
33 0 : return list ? list->ctx : NULL;
34 : }
35 :
36 0 : __isl_give LIST(EL) *FN(LIST(EL),alloc)(isl_ctx *ctx, int n)
37 : {
38 : LIST(EL) *list;
39 :
40 0 : if (n < 0)
41 0 : isl_die(ctx, isl_error_invalid,
42 : "cannot create list of negative length",
43 : return NULL);
44 0 : list = isl_alloc(ctx, LIST(EL),
45 : sizeof(LIST(EL)) + (n - 1) * sizeof(struct EL *));
46 0 : if (!list)
47 0 : return NULL;
48 :
49 0 : list->ctx = ctx;
50 0 : isl_ctx_ref(ctx);
51 0 : list->ref = 1;
52 0 : list->size = n;
53 0 : list->n = 0;
54 0 : return list;
55 : }
56 :
57 0 : __isl_give LIST(EL) *FN(LIST(EL),copy)(__isl_keep LIST(EL) *list)
58 : {
59 0 : if (!list)
60 0 : return NULL;
61 :
62 0 : list->ref++;
63 0 : return list;
64 : }
65 :
66 0 : __isl_give LIST(EL) *FN(LIST(EL),dup)(__isl_keep LIST(EL) *list)
67 : {
68 : int i;
69 : LIST(EL) *dup;
70 :
71 0 : if (!list)
72 0 : return NULL;
73 :
74 0 : dup = FN(LIST(EL),alloc)(FN(LIST(EL),get_ctx)(list), list->n);
75 0 : if (!dup)
76 0 : return NULL;
77 0 : for (i = 0; i < list->n; ++i)
78 0 : dup = FN(LIST(EL),add)(dup, FN(EL,copy)(list->p[i]));
79 0 : return dup;
80 : }
81 :
82 0 : __isl_give LIST(EL) *FN(LIST(EL),cow)(__isl_take LIST(EL) *list)
83 : {
84 0 : if (!list)
85 0 : return NULL;
86 :
87 0 : if (list->ref == 1)
88 0 : return list;
89 0 : list->ref--;
90 0 : return FN(LIST(EL),dup)(list);
91 : }
92 :
93 : /* Make sure "list" has room for at least "n" more pieces.
94 : * Always return a list with a single reference.
95 : *
96 : * If there is only one reference to list, we extend it in place.
97 : * Otherwise, we create a new LIST(EL) and copy the elements.
98 : */
99 0 : static __isl_give LIST(EL) *FN(LIST(EL),grow)(__isl_take LIST(EL) *list, int n)
100 : {
101 : isl_ctx *ctx;
102 : int i, new_size;
103 : LIST(EL) *res;
104 :
105 0 : if (!list)
106 0 : return NULL;
107 0 : if (list->ref == 1 && list->n + n <= list->size)
108 0 : return list;
109 :
110 0 : ctx = FN(LIST(EL),get_ctx)(list);
111 0 : new_size = ((list->n + n + 1) * 3) / 2;
112 0 : if (list->ref == 1) {
113 0 : res = isl_realloc(ctx, list, LIST(EL),
114 : sizeof(LIST(EL)) + (new_size - 1) * sizeof(EL *));
115 0 : if (!res)
116 0 : return FN(LIST(EL),free)(list);
117 0 : res->size = new_size;
118 0 : return res;
119 : }
120 :
121 0 : if (list->n + n <= list->size && list->size < new_size)
122 0 : new_size = list->size;
123 :
124 0 : res = FN(LIST(EL),alloc)(ctx, new_size);
125 0 : if (!res)
126 0 : return FN(LIST(EL),free)(list);
127 :
128 0 : for (i = 0; i < list->n; ++i)
129 0 : res = FN(LIST(EL),add)(res, FN(EL,copy)(list->p[i]));
130 :
131 0 : FN(LIST(EL),free)(list);
132 0 : return res;
133 : }
134 :
135 : /* Check that "index" is a valid position in "list".
136 : */
137 0 : static isl_stat FN(LIST(EL),check_index)(__isl_keep LIST(EL) *list, int index)
138 : {
139 0 : if (!list)
140 0 : return isl_stat_error;
141 0 : if (index < 0 || index >= list->n)
142 0 : isl_die(FN(LIST(EL),get_ctx)(list), isl_error_invalid,
143 : "index out of bounds", return isl_stat_error);
144 0 : return isl_stat_ok;
145 : }
146 :
147 0 : __isl_give LIST(EL) *FN(LIST(EL),add)(__isl_take LIST(EL) *list,
148 : __isl_take struct EL *el)
149 : {
150 0 : list = FN(LIST(EL),grow)(list, 1);
151 0 : if (!list || !el)
152 : goto error;
153 0 : list->p[list->n] = el;
154 0 : list->n++;
155 0 : return list;
156 : error:
157 0 : FN(EL,free)(el);
158 0 : FN(LIST(EL),free)(list);
159 0 : return NULL;
160 : }
161 :
162 : /* Remove the "n" elements starting at "first" from "list".
163 : */
164 0 : __isl_give LIST(EL) *FN(LIST(EL),drop)(__isl_take LIST(EL) *list,
165 : unsigned first, unsigned n)
166 : {
167 : int i;
168 :
169 0 : if (!list)
170 0 : return NULL;
171 0 : if (first + n > list->n || first + n < first)
172 0 : isl_die(list->ctx, isl_error_invalid,
173 : "index out of bounds", return FN(LIST(EL),free)(list));
174 0 : if (n == 0)
175 0 : return list;
176 0 : list = FN(LIST(EL),cow)(list);
177 0 : if (!list)
178 0 : return NULL;
179 0 : for (i = 0; i < n; ++i)
180 0 : FN(EL,free)(list->p[first + i]);
181 0 : for (i = first; i + n < list->n; ++i)
182 0 : list->p[i] = list->p[i + n];
183 0 : list->n -= n;
184 0 : return list;
185 : }
186 :
187 : /* Insert "el" at position "pos" in "list".
188 : *
189 : * If there is only one reference to "list" and if it already has space
190 : * for one extra element, we insert it directly into "list".
191 : * Otherwise, we create a new list consisting of "el" and copied
192 : * elements from "list".
193 : */
194 0 : __isl_give LIST(EL) *FN(LIST(EL),insert)(__isl_take LIST(EL) *list,
195 : unsigned pos, __isl_take struct EL *el)
196 : {
197 : int i;
198 : isl_ctx *ctx;
199 : LIST(EL) *res;
200 :
201 0 : if (!list || !el)
202 : goto error;
203 0 : ctx = FN(LIST(EL),get_ctx)(list);
204 0 : if (pos > list->n)
205 0 : isl_die(ctx, isl_error_invalid,
206 : "index out of bounds", goto error);
207 :
208 0 : if (list->ref == 1 && list->size > list->n) {
209 0 : for (i = list->n; i > pos; --i)
210 0 : list->p[i] = list->p[i - 1];
211 0 : list->n++;
212 0 : list->p[pos] = el;
213 0 : return list;
214 : }
215 :
216 0 : res = FN(LIST(EL),alloc)(ctx, list->n + 1);
217 0 : for (i = 0; i < pos; ++i)
218 0 : res = FN(LIST(EL),add)(res, FN(EL,copy)(list->p[i]));
219 0 : res = FN(LIST(EL),add)(res, el);
220 0 : for (i = pos; i < list->n; ++i)
221 0 : res = FN(LIST(EL),add)(res, FN(EL,copy)(list->p[i]));
222 0 : FN(LIST(EL),free)(list);
223 :
224 0 : return res;
225 : error:
226 0 : FN(EL,free)(el);
227 0 : FN(LIST(EL),free)(list);
228 0 : return NULL;
229 : }
230 :
231 0 : __isl_null LIST(EL) *FN(LIST(EL),free)(__isl_take LIST(EL) *list)
232 : {
233 : int i;
234 :
235 0 : if (!list)
236 0 : return NULL;
237 :
238 0 : if (--list->ref > 0)
239 0 : return NULL;
240 :
241 0 : isl_ctx_deref(list->ctx);
242 0 : for (i = 0; i < list->n; ++i)
243 0 : FN(EL,free)(list->p[i]);
244 0 : free(list);
245 :
246 0 : return NULL;
247 : }
248 :
249 : /* Return the number of elements in "list".
250 : */
251 0 : int FN(LIST(EL),size)(__isl_keep LIST(EL) *list)
252 : {
253 0 : return list ? list->n : 0;
254 : }
255 :
256 : /* This is an alternative name for the function above.
257 : */
258 0 : int FN(FN(LIST(EL),n),BASE)(__isl_keep LIST(EL) *list)
259 : {
260 0 : return FN(LIST(EL),size)(list);
261 : }
262 :
263 : /* Return the element at position "index" in "list".
264 : */
265 0 : static __isl_keep EL *FN(LIST(EL),peek)(__isl_keep LIST(EL) *list, int index)
266 : {
267 0 : if (FN(LIST(EL),check_index)(list, index) < 0)
268 0 : return NULL;
269 0 : return list->p[index];
270 : }
271 :
272 : /* Return a copy of the element at position "index" in "list".
273 : */
274 0 : __isl_give EL *FN(LIST(EL),get_at)(__isl_keep LIST(EL) *list, int index)
275 : {
276 0 : return FN(EL,copy)(FN(LIST(EL),peek)(list, index));
277 : }
278 :
279 : /* This is an alternative name for the function above.
280 : */
281 0 : __isl_give EL *FN(FN(LIST(EL),get),BASE)(__isl_keep LIST(EL) *list, int index)
282 : {
283 0 : return FN(LIST(EL),get_at)(list, index);
284 : }
285 :
286 : /* Replace the element at position "index" in "list" by "el".
287 : */
288 0 : __isl_give LIST(EL) *FN(FN(LIST(EL),set),BASE)(__isl_take LIST(EL) *list,
289 : int index, __isl_take EL *el)
290 : {
291 0 : if (!list || !el)
292 : goto error;
293 0 : if (FN(LIST(EL),check_index)(list, index) < 0)
294 0 : goto error;
295 0 : if (list->p[index] == el) {
296 0 : FN(EL,free)(el);
297 0 : return list;
298 : }
299 0 : list = FN(LIST(EL),cow)(list);
300 0 : if (!list)
301 0 : goto error;
302 0 : FN(EL,free)(list->p[index]);
303 0 : list->p[index] = el;
304 0 : return list;
305 : error:
306 0 : FN(EL,free)(el);
307 0 : FN(LIST(EL),free)(list);
308 0 : return NULL;
309 : }
310 :
311 : /* Return the element at position "index" of "list".
312 : * This may be either a copy or the element itself
313 : * if there is only one reference to "list".
314 : * This allows the element to be modified inplace
315 : * if both the list and the element have only a single reference.
316 : * The caller is not allowed to modify "list" between
317 : * this call to isl_list_*_take_* and a subsequent call
318 : * to isl_list_*_restore_*.
319 : * The only exception is that isl_list_*_free can be called instead.
320 : */
321 0 : static __isl_give EL *FN(FN(LIST(EL),take),BASE)(__isl_keep LIST(EL) *list,
322 : int index)
323 : {
324 : EL *el;
325 :
326 0 : if (FN(LIST(EL),check_index)(list, index) < 0)
327 0 : return NULL;
328 0 : if (list->ref != 1)
329 0 : return FN(FN(LIST(EL),get),BASE)(list, index);
330 0 : el = list->p[index];
331 0 : list->p[index] = NULL;
332 0 : return el;
333 : }
334 :
335 : /* Set the element at position "index" of "list" to "el",
336 : * where the position may be empty due to a previous call
337 : * to isl_list_*_take_*.
338 : */
339 0 : static __isl_give LIST(EL) *FN(FN(LIST(EL),restore),BASE)(
340 : __isl_take LIST(EL) *list, int index, __isl_take EL *el)
341 : {
342 0 : return FN(FN(LIST(EL),set),BASE)(list, index, el);
343 : }
344 :
345 : /* Swap the elements of "list" in positions "pos1" and "pos2".
346 : */
347 0 : __isl_give LIST(EL) *FN(LIST(EL),swap)(__isl_take LIST(EL) *list,
348 : unsigned pos1, unsigned pos2)
349 : {
350 : EL *el1, *el2;
351 :
352 0 : if (pos1 == pos2)
353 0 : return list;
354 0 : el1 = FN(FN(LIST(EL),take),BASE)(list, pos1);
355 0 : el2 = FN(FN(LIST(EL),take),BASE)(list, pos2);
356 0 : list = FN(FN(LIST(EL),restore),BASE)(list, pos1, el2);
357 0 : list = FN(FN(LIST(EL),restore),BASE)(list, pos2, el1);
358 0 : return list;
359 : }
360 :
361 : /* Reverse the elements of "list".
362 : */
363 0 : __isl_give LIST(EL) *FN(LIST(EL),reverse)(__isl_take LIST(EL) *list)
364 : {
365 : int i, n;
366 :
367 0 : n = FN(LIST(EL),size)(list);
368 0 : for (i = 0; i < n - 1 - i; ++i)
369 0 : list = FN(LIST(EL),swap)(list, i, n - 1 - i);
370 0 : return list;
371 : }
372 :
373 0 : isl_stat FN(LIST(EL),foreach)(__isl_keep LIST(EL) *list,
374 : isl_stat (*fn)(__isl_take EL *el, void *user), void *user)
375 : {
376 : int i;
377 :
378 0 : if (!list)
379 0 : return isl_stat_error;
380 :
381 0 : for (i = 0; i < list->n; ++i) {
382 0 : EL *el = FN(EL,copy)(list->p[i]);
383 0 : if (!el)
384 0 : return isl_stat_error;
385 0 : if (fn(el, user) < 0)
386 0 : return isl_stat_error;
387 : }
388 :
389 0 : return isl_stat_ok;
390 : }
391 :
392 : /* Replace each element in "list" by the result of calling "fn"
393 : * on the element.
394 : */
395 0 : __isl_give LIST(EL) *FN(LIST(EL),map)(__isl_keep LIST(EL) *list,
396 : __isl_give EL *(*fn)(__isl_take EL *el, void *user), void *user)
397 : {
398 : int i, n;
399 :
400 0 : if (!list)
401 0 : return NULL;
402 :
403 0 : n = list->n;
404 0 : for (i = 0; i < n; ++i) {
405 0 : EL *el = FN(FN(LIST(EL),take),BASE)(list, i);
406 0 : if (!el)
407 0 : return FN(LIST(EL),free)(list);
408 0 : el = fn(el, user);
409 0 : list = FN(FN(LIST(EL),restore),BASE)(list, i, el);
410 : }
411 :
412 0 : return list;
413 : }
414 :
415 : /* Internal data structure for isl_*_list_sort.
416 : *
417 : * "cmp" is the original comparison function.
418 : * "user" is a user provided pointer that should be passed to "cmp".
419 : */
420 : S(LIST(EL),sort_data) {
421 : int (*cmp)(__isl_keep EL *a, __isl_keep EL *b, void *user);
422 : void *user;
423 : };
424 :
425 : /* Compare two entries of an isl_*_list based on the user provided
426 : * comparison function on pairs of isl_* objects.
427 : */
428 0 : static int FN(LIST(EL),cmp)(const void *a, const void *b, void *user)
429 : {
430 0 : S(LIST(EL),sort_data) *data = user;
431 0 : EL * const *el1 = a;
432 0 : EL * const *el2 = b;
433 :
434 0 : return data->cmp(*el1, *el2, data->user);
435 : }
436 :
437 : /* Sort the elements of "list" in ascending order according to
438 : * comparison function "cmp".
439 : */
440 0 : __isl_give LIST(EL) *FN(LIST(EL),sort)(__isl_take LIST(EL) *list,
441 : int (*cmp)(__isl_keep EL *a, __isl_keep EL *b, void *user), void *user)
442 : {
443 0 : S(LIST(EL),sort_data) data = { cmp, user };
444 :
445 0 : if (!list)
446 0 : return NULL;
447 0 : if (list->n <= 1)
448 0 : return list;
449 0 : list = FN(LIST(EL),cow)(list);
450 0 : if (!list)
451 0 : return NULL;
452 :
453 0 : if (isl_sort(list->p, list->n, sizeof(list->p[0]),
454 : &FN(LIST(EL),cmp), &data) < 0)
455 0 : return FN(LIST(EL),free)(list);
456 :
457 0 : return list;
458 : }
459 :
460 : /* Internal data structure for isl_*_list_foreach_scc.
461 : *
462 : * "list" is the original list.
463 : * "follows" is the user provided callback that defines the edges of the graph.
464 : */
465 : S(LIST(EL),foreach_scc_data) {
466 : LIST(EL) *list;
467 : isl_bool (*follows)(__isl_keep EL *a, __isl_keep EL *b, void *user);
468 : void *follows_user;
469 : };
470 :
471 : /* Does element i of data->list follow element j?
472 : *
473 : * Use the user provided callback to find out.
474 : */
475 0 : static isl_bool FN(LIST(EL),follows)(int i, int j, void *user)
476 : {
477 0 : S(LIST(EL),foreach_scc_data) *data = user;
478 :
479 0 : return data->follows(data->list->p[i], data->list->p[j],
480 : data->follows_user);
481 : }
482 :
483 : /* Call "fn" on the sublist of "list" that consists of the elements
484 : * with indices specified by the "n" elements of "pos".
485 : */
486 0 : static isl_stat FN(LIST(EL),call_on_scc)(__isl_keep LIST(EL) *list, int *pos,
487 : int n, isl_stat (*fn)(__isl_take LIST(EL) *scc, void *user), void *user)
488 : {
489 : int i;
490 : isl_ctx *ctx;
491 : LIST(EL) *slice;
492 :
493 0 : ctx = FN(LIST(EL),get_ctx)(list);
494 0 : slice = FN(LIST(EL),alloc)(ctx, n);
495 0 : for (i = 0; i < n; ++i) {
496 : EL *el;
497 :
498 0 : el = FN(EL,copy)(list->p[pos[i]]);
499 0 : slice = FN(LIST(EL),add)(slice, el);
500 : }
501 :
502 0 : return fn(slice, user);
503 : }
504 :
505 : /* Call "fn" on each of the strongly connected components (SCCs) of
506 : * the graph with as vertices the elements of "list" and
507 : * a directed edge from node b to node a iff follows(a, b)
508 : * returns 1. follows should return -1 on error.
509 : *
510 : * If SCC a contains a node i that follows a node j in another SCC b
511 : * (i.e., follows(i, j, user) returns 1), then fn will be called on SCC a
512 : * after being called on SCC b.
513 : *
514 : * We simply call isl_tarjan_graph_init, extract the SCCs from the result and
515 : * call fn on each of them.
516 : */
517 0 : isl_stat FN(LIST(EL),foreach_scc)(__isl_keep LIST(EL) *list,
518 : isl_bool (*follows)(__isl_keep EL *a, __isl_keep EL *b, void *user),
519 : void *follows_user,
520 : isl_stat (*fn)(__isl_take LIST(EL) *scc, void *user), void *fn_user)
521 : {
522 0 : S(LIST(EL),foreach_scc_data) data = { list, follows, follows_user };
523 : int i, n;
524 : isl_ctx *ctx;
525 : struct isl_tarjan_graph *g;
526 :
527 0 : if (!list)
528 0 : return isl_stat_error;
529 0 : if (list->n == 0)
530 0 : return isl_stat_ok;
531 0 : if (list->n == 1)
532 0 : return fn(FN(LIST(EL),copy)(list), fn_user);
533 :
534 0 : ctx = FN(LIST(EL),get_ctx)(list);
535 0 : n = list->n;
536 0 : g = isl_tarjan_graph_init(ctx, n, &FN(LIST(EL),follows), &data);
537 0 : if (!g)
538 0 : return isl_stat_error;
539 :
540 0 : i = 0;
541 : do {
542 : int first;
543 :
544 0 : if (g->order[i] == -1)
545 0 : isl_die(ctx, isl_error_internal, "cannot happen",
546 : break);
547 0 : first = i;
548 0 : while (g->order[i] != -1) {
549 0 : ++i; --n;
550 : }
551 0 : if (first == 0 && n == 0) {
552 0 : isl_tarjan_graph_free(g);
553 0 : return fn(FN(LIST(EL),copy)(list), fn_user);
554 : }
555 0 : if (FN(LIST(EL),call_on_scc)(list, g->order + first, i - first,
556 : fn, fn_user) < 0)
557 0 : break;
558 0 : ++i;
559 0 : } while (n);
560 :
561 0 : isl_tarjan_graph_free(g);
562 :
563 0 : return n > 0 ? isl_stat_error : isl_stat_ok;
564 : }
565 :
566 0 : __isl_give LIST(EL) *FN(FN(LIST(EL),from),BASE)(__isl_take EL *el)
567 : {
568 : isl_ctx *ctx;
569 : LIST(EL) *list;
570 :
571 0 : if (!el)
572 0 : return NULL;
573 0 : ctx = FN(EL,get_ctx)(el);
574 0 : list = FN(LIST(EL),alloc)(ctx, 1);
575 0 : if (!list)
576 0 : goto error;
577 0 : list = FN(LIST(EL),add)(list, el);
578 0 : return list;
579 : error:
580 0 : FN(EL,free)(el);
581 0 : return NULL;
582 : }
583 :
584 : /* Append the elements of "list2" to "list1", where "list1" is known
585 : * to have only a single reference and enough room to hold
586 : * the extra elements.
587 : */
588 0 : static __isl_give LIST(EL) *FN(LIST(EL),concat_inplace)(
589 : __isl_take LIST(EL) *list1, __isl_take LIST(EL) *list2)
590 : {
591 : int i;
592 :
593 0 : for (i = 0; i < list2->n; ++i)
594 0 : list1 = FN(LIST(EL),add)(list1, FN(EL,copy)(list2->p[i]));
595 0 : FN(LIST(EL),free)(list2);
596 0 : return list1;
597 : }
598 :
599 : /* Concatenate "list1" and "list2".
600 : * If "list1" has only one reference and has enough room
601 : * for the elements of "list2", the add the elements to "list1" itself.
602 : * Otherwise, create a new list to store the result.
603 : */
604 0 : __isl_give LIST(EL) *FN(LIST(EL),concat)(__isl_take LIST(EL) *list1,
605 : __isl_take LIST(EL) *list2)
606 : {
607 : int i;
608 : isl_ctx *ctx;
609 : LIST(EL) *res;
610 :
611 0 : if (!list1 || !list2)
612 : goto error;
613 :
614 0 : if (list1->ref == 1 && list1->n + list2->n <= list1->size)
615 0 : return FN(LIST(EL),concat_inplace)(list1, list2);
616 :
617 0 : ctx = FN(LIST(EL),get_ctx)(list1);
618 0 : res = FN(LIST(EL),alloc)(ctx, list1->n + list2->n);
619 0 : for (i = 0; i < list1->n; ++i)
620 0 : res = FN(LIST(EL),add)(res, FN(EL,copy)(list1->p[i]));
621 0 : for (i = 0; i < list2->n; ++i)
622 0 : res = FN(LIST(EL),add)(res, FN(EL,copy)(list2->p[i]));
623 :
624 0 : FN(LIST(EL),free)(list1);
625 0 : FN(LIST(EL),free)(list2);
626 0 : return res;
627 : error:
628 0 : FN(LIST(EL),free)(list1);
629 0 : FN(LIST(EL),free)(list2);
630 0 : return NULL;
631 : }
632 :
633 0 : __isl_give isl_printer *CAT(isl_printer_print_,LIST(BASE))(
634 : __isl_take isl_printer *p, __isl_keep LIST(EL) *list)
635 : {
636 : int i;
637 :
638 0 : if (!p || !list)
639 : goto error;
640 0 : p = isl_printer_print_str(p, "(");
641 0 : for (i = 0; i < list->n; ++i) {
642 0 : if (i)
643 0 : p = isl_printer_print_str(p, ",");
644 0 : p = CAT(isl_printer_print_,BASE)(p, list->p[i]);
645 : }
646 0 : p = isl_printer_print_str(p, ")");
647 0 : return p;
648 : error:
649 0 : isl_printer_free(p);
650 0 : return NULL;
651 : }
652 :
653 0 : void FN(LIST(EL),dump)(__isl_keep LIST(EL) *list)
654 : {
655 : isl_printer *printer;
656 :
657 0 : if (!list)
658 0 : return;
659 :
660 0 : printer = isl_printer_to_file(FN(LIST(EL),get_ctx)(list), stderr);
661 0 : printer = CAT(isl_printer_print_,LIST(BASE))(printer, list);
662 0 : printer = isl_printer_end_line(printer);
663 :
664 0 : isl_printer_free(printer);
665 : }
|