doc: use biblatex for printing references
[isl.git] / isl_vec.c
blob29b9d43573ee1f846682c97d4f2af1e8dd6ecd50
1 /*
2 * Copyright 2008-2009 Katholieke Universiteit Leuven
3 * Copyright 2013 Ecole Normale Superieure
5 * Use of this software is governed by the MIT license
7 * Written by Sven Verdoolaege, K.U.Leuven, Departement
8 * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
9 * and Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France
12 #include <isl_ctx_private.h>
13 #include <isl_seq.h>
14 #include <isl_val_private.h>
15 #include <isl_vec_private.h>
16 #include <isl/deprecated/vec_int.h>
18 isl_ctx *isl_vec_get_ctx(__isl_keep isl_vec *vec)
20 return vec ? vec->ctx : NULL;
23 /* Return a hash value that digests "vec".
25 uint32_t isl_vec_get_hash(__isl_keep isl_vec *vec)
27 if (!vec)
28 return 0;
30 return isl_seq_get_hash(vec->el, vec->size);
33 struct isl_vec *isl_vec_alloc(struct isl_ctx *ctx, unsigned size)
35 struct isl_vec *vec;
37 vec = isl_alloc_type(ctx, struct isl_vec);
38 if (!vec)
39 return NULL;
41 vec->block = isl_blk_alloc(ctx, size);
42 if (isl_blk_is_error(vec->block))
43 goto error;
45 vec->ctx = ctx;
46 isl_ctx_ref(ctx);
47 vec->ref = 1;
48 vec->size = size;
49 vec->el = vec->block.data;
51 return vec;
52 error:
53 isl_blk_free(ctx, vec->block);
54 return NULL;
57 __isl_give isl_vec *isl_vec_extend(__isl_take isl_vec *vec, unsigned size)
59 if (!vec)
60 return NULL;
61 if (size <= vec->size)
62 return vec;
64 vec = isl_vec_cow(vec);
65 if (!vec)
66 return NULL;
68 vec->block = isl_blk_extend(vec->ctx, vec->block, size);
69 if (!vec->block.data)
70 goto error;
72 vec->size = size;
73 vec->el = vec->block.data;
75 return vec;
76 error:
77 isl_vec_free(vec);
78 return NULL;
81 /* Apply the expansion specified by "exp" to the "n" elements starting at "pos".
82 * "expanded" it the number of elements that need to replace those "n"
83 * elements. The entries in "exp" have increasing values between
84 * 0 and "expanded".
86 __isl_give isl_vec *isl_vec_expand(__isl_take isl_vec *vec, int pos, int n,
87 int *exp, int expanded)
89 int i, j;
90 int old_size, extra;
92 if (!vec)
93 return NULL;
94 if (expanded < n)
95 isl_die(isl_vec_get_ctx(vec), isl_error_invalid,
96 "not an expansion", isl_vec_free(vec));
97 if (expanded == n)
98 return vec;
99 if (pos < 0 || n < 0 || pos + n > vec->size)
100 isl_die(isl_vec_get_ctx(vec), isl_error_invalid,
101 "position out of bounds", return isl_vec_free(vec));
103 old_size = vec->size;
104 extra = expanded - n;
105 vec = isl_vec_extend(vec, old_size + extra);
106 vec = isl_vec_cow(vec);
107 if (!vec)
108 return NULL;
110 for (i = old_size - 1; i >= pos + n; --i)
111 isl_int_set(vec->el[i + extra], vec->el[i]);
113 j = n - 1;
114 for (i = expanded - 1; i >= 0; --i) {
115 if (j >= 0 && exp[j] == i) {
116 if (i != j)
117 isl_int_swap(vec->el[pos + i],
118 vec->el[pos + j]);
119 j--;
120 } else {
121 isl_int_set_si(vec->el[pos + i], 0);
125 return vec;
128 __isl_give isl_vec *isl_vec_zero_extend(__isl_take isl_vec *vec, unsigned size)
130 int extra;
132 if (!vec)
133 return NULL;
134 if (size <= vec->size)
135 return vec;
137 vec = isl_vec_cow(vec);
138 if (!vec)
139 return NULL;
141 extra = size - vec->size;
142 vec = isl_vec_extend(vec, size);
143 if (!vec)
144 return NULL;
146 isl_seq_clr(vec->el + size - extra, extra);
148 return vec;
151 /* Return a vector containing the elements of "vec1" followed by
152 * those of "vec2".
154 __isl_give isl_vec *isl_vec_concat(__isl_take isl_vec *vec1,
155 __isl_take isl_vec *vec2)
157 if (!vec1 || !vec2)
158 goto error;
160 if (vec2->size == 0) {
161 isl_vec_free(vec2);
162 return vec1;
165 if (vec1->size == 0) {
166 isl_vec_free(vec1);
167 return vec2;
170 vec1 = isl_vec_extend(vec1, vec1->size + vec2->size);
171 if (!vec1)
172 goto error;
174 isl_seq_cpy(vec1->el + vec1->size - vec2->size, vec2->el, vec2->size);
176 isl_vec_free(vec2);
177 return vec1;
178 error:
179 isl_vec_free(vec1);
180 isl_vec_free(vec2);
181 return NULL;
184 struct isl_vec *isl_vec_copy(struct isl_vec *vec)
186 if (!vec)
187 return NULL;
189 vec->ref++;
190 return vec;
193 struct isl_vec *isl_vec_dup(struct isl_vec *vec)
195 struct isl_vec *vec2;
197 if (!vec)
198 return NULL;
199 vec2 = isl_vec_alloc(vec->ctx, vec->size);
200 if (!vec2)
201 return NULL;
202 isl_seq_cpy(vec2->el, vec->el, vec->size);
203 return vec2;
206 struct isl_vec *isl_vec_cow(struct isl_vec *vec)
208 struct isl_vec *vec2;
209 if (!vec)
210 return NULL;
212 if (vec->ref == 1)
213 return vec;
215 vec2 = isl_vec_dup(vec);
216 isl_vec_free(vec);
217 return vec2;
220 __isl_null isl_vec *isl_vec_free(__isl_take isl_vec *vec)
222 if (!vec)
223 return NULL;
225 if (--vec->ref > 0)
226 return NULL;
228 isl_ctx_deref(vec->ctx);
229 isl_blk_free(vec->ctx, vec->block);
230 free(vec);
232 return NULL;
235 int isl_vec_size(__isl_keep isl_vec *vec)
237 return vec ? vec->size : -1;
240 int isl_vec_get_element(__isl_keep isl_vec *vec, int pos, isl_int *v)
242 if (!vec)
243 return -1;
245 if (pos < 0 || pos >= vec->size)
246 isl_die(vec->ctx, isl_error_invalid, "position out of range",
247 return -1);
248 isl_int_set(*v, vec->el[pos]);
249 return 0;
252 /* Extract the element at position "pos" of "vec".
254 __isl_give isl_val *isl_vec_get_element_val(__isl_keep isl_vec *vec, int pos)
256 isl_ctx *ctx;
258 if (!vec)
259 return NULL;
260 ctx = isl_vec_get_ctx(vec);
261 if (pos < 0 || pos >= vec->size)
262 isl_die(ctx, isl_error_invalid, "position out of range",
263 return NULL);
264 return isl_val_int_from_isl_int(ctx, vec->el[pos]);
267 __isl_give isl_vec *isl_vec_set_element(__isl_take isl_vec *vec,
268 int pos, isl_int v)
270 vec = isl_vec_cow(vec);
271 if (!vec)
272 return NULL;
273 if (pos < 0 || pos >= vec->size)
274 isl_die(vec->ctx, isl_error_invalid, "position out of range",
275 goto error);
276 isl_int_set(vec->el[pos], v);
277 return vec;
278 error:
279 isl_vec_free(vec);
280 return NULL;
283 __isl_give isl_vec *isl_vec_set_element_si(__isl_take isl_vec *vec,
284 int pos, int v)
286 vec = isl_vec_cow(vec);
287 if (!vec)
288 return NULL;
289 if (pos < 0 || pos >= vec->size)
290 isl_die(vec->ctx, isl_error_invalid, "position out of range",
291 goto error);
292 isl_int_set_si(vec->el[pos], v);
293 return vec;
294 error:
295 isl_vec_free(vec);
296 return NULL;
299 /* Replace the element at position "pos" of "vec" by "v".
301 __isl_give isl_vec *isl_vec_set_element_val(__isl_take isl_vec *vec,
302 int pos, __isl_take isl_val *v)
304 if (!v)
305 return isl_vec_free(vec);
306 if (!isl_val_is_int(v))
307 isl_die(isl_val_get_ctx(v), isl_error_invalid,
308 "expecting integer value", goto error);
309 vec = isl_vec_set_element(vec, pos, v->n);
310 isl_val_free(v);
311 return vec;
312 error:
313 isl_val_free(v);
314 return isl_vec_free(vec);
317 /* Compare the elements of "vec1" and "vec2" at position "pos".
319 int isl_vec_cmp_element(__isl_keep isl_vec *vec1, __isl_keep isl_vec *vec2,
320 int pos)
322 if (!vec1 || !vec2)
323 return 0;
324 if (pos < 0 || pos >= vec1->size || pos >= vec2->size)
325 isl_die(isl_vec_get_ctx(vec1), isl_error_invalid,
326 "position out of range", return 0);
327 return isl_int_cmp(vec1->el[pos], vec2->el[pos]);
330 isl_bool isl_vec_is_equal(__isl_keep isl_vec *vec1, __isl_keep isl_vec *vec2)
332 if (!vec1 || !vec2)
333 return isl_bool_error;
335 if (vec1->size != vec2->size)
336 return isl_bool_false;
338 return isl_seq_eq(vec1->el, vec2->el, vec1->size);
341 __isl_give isl_printer *isl_printer_print_vec(__isl_take isl_printer *printer,
342 __isl_keep isl_vec *vec)
344 int i;
346 if (!printer || !vec)
347 goto error;
349 printer = isl_printer_print_str(printer, "[");
350 for (i = 0; i < vec->size; ++i) {
351 if (i)
352 printer = isl_printer_print_str(printer, ",");
353 printer = isl_printer_print_isl_int(printer, vec->el[i]);
355 printer = isl_printer_print_str(printer, "]");
357 return printer;
358 error:
359 isl_printer_free(printer);
360 return NULL;
363 void isl_vec_dump(struct isl_vec *vec)
365 isl_printer *printer;
367 if (!vec)
368 return;
370 printer = isl_printer_to_file(vec->ctx, stderr);
371 printer = isl_printer_print_vec(printer, vec);
372 printer = isl_printer_end_line(printer);
374 isl_printer_free(printer);
377 __isl_give isl_vec *isl_vec_set(__isl_take isl_vec *vec, isl_int v)
379 vec = isl_vec_cow(vec);
380 if (!vec)
381 return NULL;
382 isl_seq_set(vec->el, v, vec->size);
383 return vec;
386 __isl_give isl_vec *isl_vec_set_si(__isl_take isl_vec *vec, int v)
388 vec = isl_vec_cow(vec);
389 if (!vec)
390 return NULL;
391 isl_seq_set_si(vec->el, v, vec->size);
392 return vec;
395 /* Replace all elements of "vec" by "v".
397 __isl_give isl_vec *isl_vec_set_val(__isl_take isl_vec *vec,
398 __isl_take isl_val *v)
400 vec = isl_vec_cow(vec);
401 if (!vec || !v)
402 goto error;
403 if (!isl_val_is_int(v))
404 isl_die(isl_val_get_ctx(v), isl_error_invalid,
405 "expecting integer value", goto error);
406 isl_seq_set(vec->el, v->n, vec->size);
407 isl_val_free(v);
408 return vec;
409 error:
410 isl_vec_free(vec);
411 isl_val_free(v);
412 return NULL;
415 __isl_give isl_vec *isl_vec_clr(__isl_take isl_vec *vec)
417 vec = isl_vec_cow(vec);
418 if (!vec)
419 return NULL;
420 isl_seq_clr(vec->el, vec->size);
421 return vec;
424 void isl_vec_lcm(struct isl_vec *vec, isl_int *lcm)
426 isl_seq_lcm(vec->block.data, vec->size, lcm);
429 /* Given a rational vector, with the denominator in the first element
430 * of the vector, round up all coordinates.
432 struct isl_vec *isl_vec_ceil(struct isl_vec *vec)
434 vec = isl_vec_cow(vec);
435 if (!vec)
436 return NULL;
438 isl_seq_cdiv_q(vec->el + 1, vec->el + 1, vec->el[0], vec->size - 1);
440 isl_int_set_si(vec->el[0], 1);
442 return vec;
445 struct isl_vec *isl_vec_normalize(struct isl_vec *vec)
447 if (!vec)
448 return NULL;
449 isl_seq_normalize(vec->ctx, vec->el, vec->size);
450 return vec;
453 __isl_give isl_vec *isl_vec_neg(__isl_take isl_vec *vec)
455 vec = isl_vec_cow(vec);
456 if (!vec)
457 return NULL;
458 isl_seq_neg(vec->el, vec->el, vec->size);
459 return vec;
462 __isl_give isl_vec *isl_vec_scale(__isl_take isl_vec *vec, isl_int m)
464 if (isl_int_is_one(m))
465 return vec;
466 vec = isl_vec_cow(vec);
467 if (!vec)
468 return NULL;
469 isl_seq_scale(vec->el, vec->el, m, vec->size);
470 return vec;
473 /* Reduce the elements of "vec" modulo "m".
475 __isl_give isl_vec *isl_vec_fdiv_r(__isl_take isl_vec *vec, isl_int m)
477 vec = isl_vec_cow(vec);
478 if (!vec)
479 return NULL;
481 isl_seq_fdiv_r(vec->el, vec->el, m, vec->size);
483 return vec;
486 __isl_give isl_vec *isl_vec_add(__isl_take isl_vec *vec1,
487 __isl_take isl_vec *vec2)
489 vec1 = isl_vec_cow(vec1);
490 if (!vec1 || !vec2)
491 goto error;
493 isl_assert(vec1->ctx, vec1->size == vec2->size, goto error);
495 isl_seq_combine(vec1->el, vec1->ctx->one, vec1->el,
496 vec1->ctx->one, vec2->el, vec1->size);
498 isl_vec_free(vec2);
499 return vec1;
500 error:
501 isl_vec_free(vec1);
502 isl_vec_free(vec2);
503 return NULL;
506 static int qsort_int_cmp(const void *p1, const void *p2)
508 const isl_int *i1 = (const isl_int *) p1;
509 const isl_int *i2 = (const isl_int *) p2;
511 return isl_int_cmp(*i1, *i2);
514 __isl_give isl_vec *isl_vec_sort(__isl_take isl_vec *vec)
516 if (!vec)
517 return NULL;
519 qsort(vec->el, vec->size, sizeof(*vec->el), &qsort_int_cmp);
521 return vec;
524 __isl_give isl_vec *isl_vec_drop_els(__isl_take isl_vec *vec,
525 unsigned pos, unsigned n)
527 if (n == 0)
528 return vec;
529 vec = isl_vec_cow(vec);
530 if (!vec)
531 return NULL;
533 if (pos + n > vec->size)
534 isl_die(vec->ctx, isl_error_invalid,
535 "range out of bounds", goto error);
537 if (pos + n != vec->size)
538 isl_seq_cpy(vec->el + pos, vec->el + pos + n,
539 vec->size - pos - n);
541 vec->size -= n;
543 return vec;
544 error:
545 isl_vec_free(vec);
546 return NULL;
549 __isl_give isl_vec *isl_vec_insert_els(__isl_take isl_vec *vec,
550 unsigned pos, unsigned n)
552 isl_vec *ext = NULL;
554 if (n == 0)
555 return vec;
556 if (!vec)
557 return NULL;
559 if (pos > vec->size)
560 isl_die(vec->ctx, isl_error_invalid,
561 "position out of bounds", goto error);
563 ext = isl_vec_alloc(vec->ctx, vec->size + n);
564 if (!ext)
565 goto error;
567 isl_seq_cpy(ext->el, vec->el, pos);
568 isl_seq_cpy(ext->el + pos + n, vec->el + pos, vec->size - pos);
570 isl_vec_free(vec);
571 return ext;
572 error:
573 isl_vec_free(vec);
574 isl_vec_free(ext);
575 return NULL;
578 __isl_give isl_vec *isl_vec_insert_zero_els(__isl_take isl_vec *vec,
579 unsigned pos, unsigned n)
581 vec = isl_vec_insert_els(vec, pos, n);
582 if (!vec)
583 return NULL;
585 isl_seq_clr(vec->el + pos, n);
587 return vec;
590 /* Move the "n" elements starting as "src_pos" of "vec"
591 * to "dst_pos". The elements originally at "dst_pos" are moved
592 * up or down depending on whether "dst_pos" is smaller or greater
593 * than "src_pos".
595 __isl_give isl_vec *isl_vec_move_els(__isl_take isl_vec *vec,
596 unsigned dst_pos, unsigned src_pos, unsigned n)
598 isl_vec *res;
600 if (!vec)
601 return NULL;
603 if (src_pos + n > vec->size)
604 isl_die(vec->ctx, isl_error_invalid,
605 "source range out of bounds", return isl_vec_free(vec));
606 if (dst_pos + n > vec->size)
607 isl_die(vec->ctx, isl_error_invalid,
608 "destination range out of bounds",
609 return isl_vec_free(vec));
611 if (n == 0 || dst_pos == src_pos)
612 return vec;
614 res = isl_vec_alloc(vec->ctx, vec->size);
615 if (!res)
616 return isl_vec_free(vec);
618 if (dst_pos < src_pos) {
619 isl_seq_cpy(res->el, vec->el, dst_pos);
620 isl_seq_cpy(res->el + dst_pos, vec->el + src_pos, n);
621 isl_seq_cpy(res->el + dst_pos + n,
622 vec->el + dst_pos, src_pos - dst_pos);
623 isl_seq_cpy(res->el + src_pos + n,
624 vec->el + src_pos + n, res->size - src_pos - n);
625 } else {
626 isl_seq_cpy(res->el, vec->el, src_pos);
627 isl_seq_cpy(res->el + src_pos,
628 vec->el + src_pos + n, dst_pos - src_pos);
629 isl_seq_cpy(res->el + dst_pos, vec->el + src_pos, n);
630 isl_seq_cpy(res->el + dst_pos + n,
631 vec->el + dst_pos + n, res->size - dst_pos - n);
634 isl_vec_free(vec);
635 return res;