1 | /* |
2 | * Copyright 2008-2009 Katholieke Universiteit Leuven |
3 | * Copyright 2011 Sven Verdoolaege |
4 | * Copyright 2013 Ecole Normale Superieure |
5 | * |
6 | * Use of this software is governed by the MIT license |
7 | * |
8 | * Written by Sven Verdoolaege, K.U.Leuven, Departement |
9 | * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium |
10 | * and Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France |
11 | */ |
12 | |
13 | #include <isl_ctx_private.h> |
14 | #include <isl_seq.h> |
15 | #include <isl_val_private.h> |
16 | #include <isl_vec_private.h> |
17 | |
18 | isl_ctx *isl_vec_get_ctx(__isl_keep isl_vec *vec) |
19 | { |
20 | return vec ? vec->ctx : NULL; |
21 | } |
22 | |
23 | /* Return a hash value that digests "vec". |
24 | */ |
25 | uint32_t isl_vec_get_hash(__isl_keep isl_vec *vec) |
26 | { |
27 | if (!vec) |
28 | return 0; |
29 | |
30 | return isl_seq_get_hash(p: vec->el, len: vec->size); |
31 | } |
32 | |
33 | __isl_give isl_vec *isl_vec_alloc(struct isl_ctx *ctx, unsigned size) |
34 | { |
35 | struct isl_vec *vec; |
36 | |
37 | vec = isl_alloc_type(ctx, struct isl_vec); |
38 | if (!vec) |
39 | return NULL; |
40 | |
41 | vec->block = isl_blk_alloc(ctx, n: size); |
42 | if (isl_blk_is_error(block: vec->block)) |
43 | goto error; |
44 | |
45 | vec->ctx = ctx; |
46 | isl_ctx_ref(ctx); |
47 | vec->ref = 1; |
48 | vec->size = size; |
49 | vec->el = vec->block.data; |
50 | |
51 | return vec; |
52 | error: |
53 | isl_blk_free(ctx, block: vec->block); |
54 | free(ptr: vec); |
55 | return NULL; |
56 | } |
57 | |
58 | __isl_give isl_vec *isl_vec_extend(__isl_take isl_vec *vec, unsigned size) |
59 | { |
60 | if (!vec) |
61 | return NULL; |
62 | if (size <= vec->size) |
63 | return vec; |
64 | |
65 | vec = isl_vec_cow(vec); |
66 | if (!vec) |
67 | return NULL; |
68 | |
69 | vec->block = isl_blk_extend(ctx: vec->ctx, block: vec->block, new_n: size); |
70 | if (!vec->block.data) |
71 | goto error; |
72 | |
73 | vec->size = size; |
74 | vec->el = vec->block.data; |
75 | |
76 | return vec; |
77 | error: |
78 | isl_vec_free(vec); |
79 | return NULL; |
80 | } |
81 | |
82 | /* Apply the expansion specified by "exp" to the "n" elements starting at "pos". |
83 | * "expanded" it the number of elements that need to replace those "n" |
84 | * elements. The entries in "exp" have increasing values between |
85 | * 0 and "expanded". |
86 | */ |
87 | __isl_give isl_vec *isl_vec_expand(__isl_take isl_vec *vec, int pos, int n, |
88 | int *exp, int expanded) |
89 | { |
90 | int i, j; |
91 | int old_size, ; |
92 | |
93 | if (!vec) |
94 | return NULL; |
95 | if (expanded < n) |
96 | isl_die(isl_vec_get_ctx(vec), isl_error_invalid, |
97 | "not an expansion" , return isl_vec_free(vec)); |
98 | if (expanded == n) |
99 | return vec; |
100 | if (pos < 0 || n < 0 || pos + n > vec->size) |
101 | isl_die(isl_vec_get_ctx(vec), isl_error_invalid, |
102 | "position out of bounds" , return isl_vec_free(vec)); |
103 | |
104 | old_size = vec->size; |
105 | extra = expanded - n; |
106 | vec = isl_vec_extend(vec, size: old_size + extra); |
107 | vec = isl_vec_cow(vec); |
108 | if (!vec) |
109 | return NULL; |
110 | |
111 | for (i = old_size - 1; i >= pos + n; --i) |
112 | isl_int_set(vec->el[i + extra], vec->el[i]); |
113 | |
114 | j = n - 1; |
115 | for (i = expanded - 1; i >= 0; --i) { |
116 | if (j >= 0 && exp[j] == i) { |
117 | if (i != j) |
118 | isl_int_swap(vec->el[pos + i], |
119 | vec->el[pos + j]); |
120 | j--; |
121 | } else { |
122 | isl_int_set_si(vec->el[pos + i], 0); |
123 | } |
124 | } |
125 | |
126 | return vec; |
127 | } |
128 | |
129 | /* Create a vector of size "size" with zero-valued elements. |
130 | */ |
131 | __isl_give isl_vec *isl_vec_zero(isl_ctx *ctx, unsigned size) |
132 | { |
133 | isl_vec *vec; |
134 | |
135 | vec = isl_vec_alloc(ctx, size); |
136 | if (!vec) |
137 | return NULL; |
138 | isl_seq_clr(p: vec->el, len: size); |
139 | return vec; |
140 | } |
141 | |
142 | __isl_give isl_vec *isl_vec_zero_extend(__isl_take isl_vec *vec, unsigned size) |
143 | { |
144 | int ; |
145 | |
146 | if (!vec) |
147 | return NULL; |
148 | if (size <= vec->size) |
149 | return vec; |
150 | |
151 | vec = isl_vec_cow(vec); |
152 | if (!vec) |
153 | return NULL; |
154 | |
155 | extra = size - vec->size; |
156 | vec = isl_vec_extend(vec, size); |
157 | if (!vec) |
158 | return NULL; |
159 | |
160 | isl_seq_clr(p: vec->el + size - extra, len: extra); |
161 | |
162 | return vec; |
163 | } |
164 | |
165 | /* Return a vector containing the elements of "vec1" followed by |
166 | * those of "vec2". |
167 | */ |
168 | __isl_give isl_vec *isl_vec_concat(__isl_take isl_vec *vec1, |
169 | __isl_take isl_vec *vec2) |
170 | { |
171 | if (!vec1 || !vec2) |
172 | goto error; |
173 | |
174 | if (vec2->size == 0) { |
175 | isl_vec_free(vec: vec2); |
176 | return vec1; |
177 | } |
178 | |
179 | if (vec1->size == 0) { |
180 | isl_vec_free(vec: vec1); |
181 | return vec2; |
182 | } |
183 | |
184 | vec1 = isl_vec_extend(vec: vec1, size: vec1->size + vec2->size); |
185 | if (!vec1) |
186 | goto error; |
187 | |
188 | isl_seq_cpy(dst: vec1->el + vec1->size - vec2->size, src: vec2->el, len: vec2->size); |
189 | |
190 | isl_vec_free(vec: vec2); |
191 | return vec1; |
192 | error: |
193 | isl_vec_free(vec: vec1); |
194 | isl_vec_free(vec: vec2); |
195 | return NULL; |
196 | } |
197 | |
198 | __isl_give isl_vec *isl_vec_copy(__isl_keep isl_vec *vec) |
199 | { |
200 | if (!vec) |
201 | return NULL; |
202 | |
203 | vec->ref++; |
204 | return vec; |
205 | } |
206 | |
207 | __isl_give isl_vec *isl_vec_dup(__isl_keep isl_vec *vec) |
208 | { |
209 | struct isl_vec *vec2; |
210 | |
211 | if (!vec) |
212 | return NULL; |
213 | vec2 = isl_vec_alloc(ctx: vec->ctx, size: vec->size); |
214 | if (!vec2) |
215 | return NULL; |
216 | isl_seq_cpy(dst: vec2->el, src: vec->el, len: vec->size); |
217 | return vec2; |
218 | } |
219 | |
220 | __isl_give isl_vec *isl_vec_cow(__isl_take isl_vec *vec) |
221 | { |
222 | struct isl_vec *vec2; |
223 | if (!vec) |
224 | return NULL; |
225 | |
226 | if (vec->ref == 1) |
227 | return vec; |
228 | |
229 | vec2 = isl_vec_dup(vec); |
230 | isl_vec_free(vec); |
231 | return vec2; |
232 | } |
233 | |
234 | __isl_null isl_vec *isl_vec_free(__isl_take isl_vec *vec) |
235 | { |
236 | if (!vec) |
237 | return NULL; |
238 | |
239 | if (--vec->ref > 0) |
240 | return NULL; |
241 | |
242 | isl_ctx_deref(ctx: vec->ctx); |
243 | isl_blk_free(ctx: vec->ctx, block: vec->block); |
244 | free(ptr: vec); |
245 | |
246 | return NULL; |
247 | } |
248 | |
249 | isl_size isl_vec_size(__isl_keep isl_vec *vec) |
250 | { |
251 | return vec ? vec->size : isl_size_error; |
252 | } |
253 | |
254 | /* Extract the element at position "pos" of "vec". |
255 | */ |
256 | __isl_give isl_val *isl_vec_get_element_val(__isl_keep isl_vec *vec, int pos) |
257 | { |
258 | isl_ctx *ctx; |
259 | |
260 | if (!vec) |
261 | return NULL; |
262 | ctx = isl_vec_get_ctx(vec); |
263 | if (pos < 0 || pos >= vec->size) |
264 | isl_die(ctx, isl_error_invalid, "position out of range" , |
265 | return NULL); |
266 | return isl_val_int_from_isl_int(ctx, n: vec->el[pos]); |
267 | } |
268 | |
269 | __isl_give isl_vec *isl_vec_set_element(__isl_take isl_vec *vec, |
270 | int pos, isl_int v) |
271 | { |
272 | vec = isl_vec_cow(vec); |
273 | if (!vec) |
274 | return NULL; |
275 | if (pos < 0 || pos >= vec->size) |
276 | isl_die(vec->ctx, isl_error_invalid, "position out of range" , |
277 | goto error); |
278 | isl_int_set(vec->el[pos], v); |
279 | return vec; |
280 | error: |
281 | isl_vec_free(vec); |
282 | return NULL; |
283 | } |
284 | |
285 | __isl_give isl_vec *isl_vec_set_element_si(__isl_take isl_vec *vec, |
286 | int pos, int v) |
287 | { |
288 | vec = isl_vec_cow(vec); |
289 | if (!vec) |
290 | return NULL; |
291 | if (pos < 0 || pos >= vec->size) |
292 | isl_die(vec->ctx, isl_error_invalid, "position out of range" , |
293 | goto error); |
294 | isl_int_set_si(vec->el[pos], v); |
295 | return vec; |
296 | error: |
297 | isl_vec_free(vec); |
298 | return NULL; |
299 | } |
300 | |
301 | /* Replace the element at position "pos" of "vec" by "v". |
302 | */ |
303 | __isl_give isl_vec *isl_vec_set_element_val(__isl_take isl_vec *vec, |
304 | int pos, __isl_take isl_val *v) |
305 | { |
306 | if (!v) |
307 | return isl_vec_free(vec); |
308 | if (!isl_val_is_int(v)) |
309 | isl_die(isl_val_get_ctx(v), isl_error_invalid, |
310 | "expecting integer value" , goto error); |
311 | vec = isl_vec_set_element(vec, pos, v: v->n); |
312 | isl_val_free(v); |
313 | return vec; |
314 | error: |
315 | isl_val_free(v); |
316 | return isl_vec_free(vec); |
317 | } |
318 | |
319 | /* Compare the elements of "vec1" and "vec2" at position "pos". |
320 | */ |
321 | int isl_vec_cmp_element(__isl_keep isl_vec *vec1, __isl_keep isl_vec *vec2, |
322 | int pos) |
323 | { |
324 | if (!vec1 || !vec2) |
325 | return 0; |
326 | if (pos < 0 || pos >= vec1->size || pos >= vec2->size) |
327 | isl_die(isl_vec_get_ctx(vec1), isl_error_invalid, |
328 | "position out of range" , return 0); |
329 | return isl_int_cmp(vec1->el[pos], vec2->el[pos]); |
330 | } |
331 | |
332 | /* Does "vec" contain only zero elements? |
333 | */ |
334 | isl_bool isl_vec_is_zero(__isl_keep isl_vec *vec) |
335 | { |
336 | if (!vec) |
337 | return isl_bool_error; |
338 | return isl_bool_ok(b: isl_seq_first_non_zero(p: vec->el, len: vec->size) < 0); |
339 | } |
340 | |
341 | isl_bool isl_vec_is_equal(__isl_keep isl_vec *vec1, __isl_keep isl_vec *vec2) |
342 | { |
343 | if (!vec1 || !vec2) |
344 | return isl_bool_error; |
345 | |
346 | if (vec1->size != vec2->size) |
347 | return isl_bool_false; |
348 | |
349 | return isl_bool_ok(b: isl_seq_eq(p1: vec1->el, p2: vec2->el, len: vec1->size)); |
350 | } |
351 | |
352 | __isl_give isl_printer *isl_printer_print_vec(__isl_take isl_printer *printer, |
353 | __isl_keep isl_vec *vec) |
354 | { |
355 | int i; |
356 | |
357 | if (!printer || !vec) |
358 | goto error; |
359 | |
360 | printer = isl_printer_print_str(p: printer, s: "[" ); |
361 | for (i = 0; i < vec->size; ++i) { |
362 | if (i) |
363 | printer = isl_printer_print_str(p: printer, s: "," ); |
364 | printer = isl_printer_print_isl_int(p: printer, i: vec->el[i]); |
365 | } |
366 | printer = isl_printer_print_str(p: printer, s: "]" ); |
367 | |
368 | return printer; |
369 | error: |
370 | isl_printer_free(printer); |
371 | return NULL; |
372 | } |
373 | |
374 | void isl_vec_dump(__isl_keep isl_vec *vec) |
375 | { |
376 | isl_printer *printer; |
377 | |
378 | if (!vec) |
379 | return; |
380 | |
381 | printer = isl_printer_to_file(ctx: vec->ctx, stderr); |
382 | printer = isl_printer_print_vec(printer, vec); |
383 | printer = isl_printer_end_line(p: printer); |
384 | |
385 | isl_printer_free(printer); |
386 | } |
387 | |
388 | __isl_give isl_vec *isl_vec_set(__isl_take isl_vec *vec, isl_int v) |
389 | { |
390 | vec = isl_vec_cow(vec); |
391 | if (!vec) |
392 | return NULL; |
393 | isl_seq_set(p: vec->el, v, len: vec->size); |
394 | return vec; |
395 | } |
396 | |
397 | __isl_give isl_vec *isl_vec_set_si(__isl_take isl_vec *vec, int v) |
398 | { |
399 | vec = isl_vec_cow(vec); |
400 | if (!vec) |
401 | return NULL; |
402 | isl_seq_set_si(p: vec->el, v, len: vec->size); |
403 | return vec; |
404 | } |
405 | |
406 | /* Replace all elements of "vec" by "v". |
407 | */ |
408 | __isl_give isl_vec *isl_vec_set_val(__isl_take isl_vec *vec, |
409 | __isl_take isl_val *v) |
410 | { |
411 | vec = isl_vec_cow(vec); |
412 | if (!vec || !v) |
413 | goto error; |
414 | if (!isl_val_is_int(v)) |
415 | isl_die(isl_val_get_ctx(v), isl_error_invalid, |
416 | "expecting integer value" , goto error); |
417 | isl_seq_set(p: vec->el, v: v->n, len: vec->size); |
418 | isl_val_free(v); |
419 | return vec; |
420 | error: |
421 | isl_vec_free(vec); |
422 | isl_val_free(v); |
423 | return NULL; |
424 | } |
425 | |
426 | __isl_give isl_vec *isl_vec_clr(__isl_take isl_vec *vec) |
427 | { |
428 | vec = isl_vec_cow(vec); |
429 | if (!vec) |
430 | return NULL; |
431 | isl_seq_clr(p: vec->el, len: vec->size); |
432 | return vec; |
433 | } |
434 | |
435 | void isl_vec_lcm(__isl_keep isl_vec *vec, isl_int *lcm) |
436 | { |
437 | isl_seq_lcm(p: vec->block.data, len: vec->size, lcm); |
438 | } |
439 | |
440 | /* Given a rational vector, with the denominator in the first element |
441 | * of the vector, round up all coordinates. |
442 | */ |
443 | __isl_give isl_vec *isl_vec_ceil(__isl_take isl_vec *vec) |
444 | { |
445 | vec = isl_vec_cow(vec); |
446 | if (!vec) |
447 | return NULL; |
448 | |
449 | isl_seq_cdiv_q(dst: vec->el + 1, src: vec->el + 1, m: vec->el[0], len: vec->size - 1); |
450 | |
451 | isl_int_set_si(vec->el[0], 1); |
452 | |
453 | return vec; |
454 | } |
455 | |
456 | __isl_give isl_vec *isl_vec_normalize(__isl_take isl_vec *vec) |
457 | { |
458 | if (!vec) |
459 | return NULL; |
460 | isl_seq_normalize(ctx: vec->ctx, p: vec->el, len: vec->size); |
461 | return vec; |
462 | } |
463 | |
464 | __isl_give isl_vec *isl_vec_neg(__isl_take isl_vec *vec) |
465 | { |
466 | vec = isl_vec_cow(vec); |
467 | if (!vec) |
468 | return NULL; |
469 | isl_seq_neg(dst: vec->el, src: vec->el, len: vec->size); |
470 | return vec; |
471 | } |
472 | |
473 | __isl_give isl_vec *isl_vec_scale(__isl_take isl_vec *vec, isl_int m) |
474 | { |
475 | if (isl_int_is_one(m)) |
476 | return vec; |
477 | vec = isl_vec_cow(vec); |
478 | if (!vec) |
479 | return NULL; |
480 | isl_seq_scale(dst: vec->el, src: vec->el, f: m, len: vec->size); |
481 | return vec; |
482 | } |
483 | |
484 | /* Reduce the elements of "vec" modulo "m". |
485 | */ |
486 | __isl_give isl_vec *isl_vec_fdiv_r(__isl_take isl_vec *vec, isl_int m) |
487 | { |
488 | vec = isl_vec_cow(vec); |
489 | if (!vec) |
490 | return NULL; |
491 | |
492 | isl_seq_fdiv_r(dst: vec->el, src: vec->el, m, len: vec->size); |
493 | |
494 | return vec; |
495 | } |
496 | |
497 | __isl_give isl_vec *isl_vec_add(__isl_take isl_vec *vec1, |
498 | __isl_take isl_vec *vec2) |
499 | { |
500 | vec1 = isl_vec_cow(vec: vec1); |
501 | if (!vec1 || !vec2) |
502 | goto error; |
503 | |
504 | isl_assert(vec1->ctx, vec1->size == vec2->size, goto error); |
505 | |
506 | isl_seq_combine(dst: vec1->el, m1: vec1->ctx->one, src1: vec1->el, |
507 | m2: vec1->ctx->one, src2: vec2->el, len: vec1->size); |
508 | |
509 | isl_vec_free(vec: vec2); |
510 | return vec1; |
511 | error: |
512 | isl_vec_free(vec: vec1); |
513 | isl_vec_free(vec: vec2); |
514 | return NULL; |
515 | } |
516 | |
517 | static int qsort_int_cmp(const void *p1, const void *p2) |
518 | { |
519 | const isl_int *i1 = (const isl_int *) p1; |
520 | const isl_int *i2 = (const isl_int *) p2; |
521 | |
522 | return isl_int_cmp(*i1, *i2); |
523 | } |
524 | |
525 | __isl_give isl_vec *isl_vec_sort(__isl_take isl_vec *vec) |
526 | { |
527 | if (!vec) |
528 | return NULL; |
529 | |
530 | qsort(base: vec->el, nmemb: vec->size, size: sizeof(*vec->el), compar: &qsort_int_cmp); |
531 | |
532 | return vec; |
533 | } |
534 | |
535 | __isl_give isl_vec *isl_vec_drop_els(__isl_take isl_vec *vec, |
536 | unsigned pos, unsigned n) |
537 | { |
538 | if (n == 0) |
539 | return vec; |
540 | vec = isl_vec_cow(vec); |
541 | if (!vec) |
542 | return NULL; |
543 | |
544 | if (pos + n > vec->size) |
545 | isl_die(vec->ctx, isl_error_invalid, |
546 | "range out of bounds" , goto error); |
547 | |
548 | if (pos + n != vec->size) |
549 | isl_seq_cpy(dst: vec->el + pos, src: vec->el + pos + n, |
550 | len: vec->size - pos - n); |
551 | |
552 | vec->size -= n; |
553 | |
554 | return vec; |
555 | error: |
556 | isl_vec_free(vec); |
557 | return NULL; |
558 | } |
559 | |
560 | __isl_give isl_vec *isl_vec_insert_els(__isl_take isl_vec *vec, |
561 | unsigned pos, unsigned n) |
562 | { |
563 | isl_vec *ext = NULL; |
564 | |
565 | if (n == 0) |
566 | return vec; |
567 | if (!vec) |
568 | return NULL; |
569 | |
570 | if (pos > vec->size) |
571 | isl_die(vec->ctx, isl_error_invalid, |
572 | "position out of bounds" , goto error); |
573 | |
574 | ext = isl_vec_alloc(ctx: vec->ctx, size: vec->size + n); |
575 | if (!ext) |
576 | goto error; |
577 | |
578 | isl_seq_cpy(dst: ext->el, src: vec->el, len: pos); |
579 | isl_seq_cpy(dst: ext->el + pos + n, src: vec->el + pos, len: vec->size - pos); |
580 | |
581 | isl_vec_free(vec); |
582 | return ext; |
583 | error: |
584 | isl_vec_free(vec); |
585 | isl_vec_free(vec: ext); |
586 | return NULL; |
587 | } |
588 | |
589 | /* Add "n" elements at the end of "vec". |
590 | */ |
591 | __isl_give isl_vec *isl_vec_add_els(__isl_take isl_vec *vec, unsigned n) |
592 | { |
593 | if (!vec) |
594 | return NULL; |
595 | return isl_vec_insert_els(vec, pos: vec->size, n); |
596 | } |
597 | |
598 | __isl_give isl_vec *isl_vec_insert_zero_els(__isl_take isl_vec *vec, |
599 | unsigned pos, unsigned n) |
600 | { |
601 | vec = isl_vec_insert_els(vec, pos, n); |
602 | if (!vec) |
603 | return NULL; |
604 | |
605 | isl_seq_clr(p: vec->el + pos, len: n); |
606 | |
607 | return vec; |
608 | } |
609 | |
610 | /* Move the "n" elements starting as "src_pos" of "vec" |
611 | * to "dst_pos". The elements originally at "dst_pos" are moved |
612 | * up or down depending on whether "dst_pos" is smaller or greater |
613 | * than "src_pos". |
614 | */ |
615 | __isl_give isl_vec *isl_vec_move_els(__isl_take isl_vec *vec, |
616 | unsigned dst_pos, unsigned src_pos, unsigned n) |
617 | { |
618 | isl_vec *res; |
619 | |
620 | if (!vec) |
621 | return NULL; |
622 | |
623 | if (src_pos + n > vec->size) |
624 | isl_die(vec->ctx, isl_error_invalid, |
625 | "source range out of bounds" , return isl_vec_free(vec)); |
626 | if (dst_pos + n > vec->size) |
627 | isl_die(vec->ctx, isl_error_invalid, |
628 | "destination range out of bounds" , |
629 | return isl_vec_free(vec)); |
630 | |
631 | if (n == 0 || dst_pos == src_pos) |
632 | return vec; |
633 | |
634 | res = isl_vec_alloc(ctx: vec->ctx, size: vec->size); |
635 | if (!res) |
636 | return isl_vec_free(vec); |
637 | |
638 | if (dst_pos < src_pos) { |
639 | isl_seq_cpy(dst: res->el, src: vec->el, len: dst_pos); |
640 | isl_seq_cpy(dst: res->el + dst_pos, src: vec->el + src_pos, len: n); |
641 | isl_seq_cpy(dst: res->el + dst_pos + n, |
642 | src: vec->el + dst_pos, len: src_pos - dst_pos); |
643 | isl_seq_cpy(dst: res->el + src_pos + n, |
644 | src: vec->el + src_pos + n, len: res->size - src_pos - n); |
645 | } else { |
646 | isl_seq_cpy(dst: res->el, src: vec->el, len: src_pos); |
647 | isl_seq_cpy(dst: res->el + src_pos, |
648 | src: vec->el + src_pos + n, len: dst_pos - src_pos); |
649 | isl_seq_cpy(dst: res->el + dst_pos, src: vec->el + src_pos, len: n); |
650 | isl_seq_cpy(dst: res->el + dst_pos + n, |
651 | src: vec->el + dst_pos + n, len: res->size - dst_pos - n); |
652 | } |
653 | |
654 | isl_vec_free(vec); |
655 | return res; |
656 | } |
657 | |
658 | /* Reorder the elements of "vec" starting at "offset" based |
659 | * on the given reordering. |
660 | */ |
661 | __isl_give isl_vec *isl_vec_reorder(__isl_take isl_vec *vec, |
662 | unsigned offset, __isl_take isl_reordering *r) |
663 | { |
664 | isl_vec *res; |
665 | int i; |
666 | |
667 | if (!vec || !r) |
668 | goto error; |
669 | |
670 | res = isl_vec_alloc(ctx: vec->ctx, size: offset + r->dst_len); |
671 | if (!res) |
672 | goto error; |
673 | isl_seq_cpy(dst: res->el, src: vec->el, len: offset); |
674 | isl_seq_clr(p: res->el + offset, len: res->size - offset); |
675 | for (i = 0; i < r->src_len; ++i) |
676 | isl_int_set(res->el[offset + r->pos[i]], vec->el[offset + i]); |
677 | |
678 | isl_reordering_free(exp: r); |
679 | isl_vec_free(vec); |
680 | return res; |
681 | error: |
682 | isl_vec_free(vec); |
683 | isl_reordering_free(exp: r); |
684 | return NULL; |
685 | } |
686 | |