add isl_vec_concat
[platform/upstream/isl.git] / isl_vec.c
1 /*
2  * Copyright 2008-2009 Katholieke Universiteit Leuven
3  *
4  * Use of this software is governed by the MIT license
5  *
6  * Written by Sven Verdoolaege, K.U.Leuven, Departement
7  * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
8  */
9
10 #include <isl_ctx_private.h>
11 #include <isl/seq.h>
12 #include <isl/vec.h>
13
14 isl_ctx *isl_vec_get_ctx(__isl_keep isl_vec *vec)
15 {
16         return vec ? vec->ctx : NULL;
17 }
18
19 struct isl_vec *isl_vec_alloc(struct isl_ctx *ctx, unsigned size)
20 {
21         struct isl_vec *vec;
22
23         vec = isl_alloc_type(ctx, struct isl_vec);
24         if (!vec)
25                 return NULL;
26
27         vec->block = isl_blk_alloc(ctx, size);
28         if (isl_blk_is_error(vec->block))
29                 goto error;
30
31         vec->ctx = ctx;
32         isl_ctx_ref(ctx);
33         vec->ref = 1;
34         vec->size = size;
35         vec->el = vec->block.data;
36
37         return vec;
38 error:
39         isl_blk_free(ctx, vec->block);
40         return NULL;
41 }
42
43 __isl_give isl_vec *isl_vec_extend(__isl_take isl_vec *vec, unsigned size)
44 {
45         if (!vec)
46                 return NULL;
47         if (size <= vec->size)
48                 return vec;
49
50         vec = isl_vec_cow(vec);
51         if (!vec)
52                 return NULL;
53
54         vec->block = isl_blk_extend(vec->ctx, vec->block, size);
55         if (!vec->block.data)
56                 goto error;
57
58         vec->size = size;
59         vec->el = vec->block.data;
60
61         return vec;
62 error:
63         isl_vec_free(vec);
64         return NULL;
65 }
66
67 __isl_give isl_vec *isl_vec_zero_extend(__isl_take isl_vec *vec, unsigned size)
68 {
69         int extra;
70
71         if (!vec)
72                 return NULL;
73         if (size <= vec->size)
74                 return vec;
75
76         vec = isl_vec_cow(vec);
77         if (!vec)
78                 return NULL;
79
80         extra = size - vec->size;
81         vec = isl_vec_extend(vec, size);
82         if (!vec)
83                 return NULL;
84
85         isl_seq_clr(vec->el + size - extra, extra);
86
87         return vec;
88 }
89
90 /* Return a vector containing the elements of "vec1" followed by
91  * those of "vec2".
92  */
93 __isl_give isl_vec *isl_vec_concat(__isl_take isl_vec *vec1,
94         __isl_take isl_vec *vec2)
95 {
96         if (!vec1 || !vec2)
97                 goto error;
98
99         if (vec2->size == 0) {
100                 isl_vec_free(vec2);
101                 return vec1;
102         }
103
104         if (vec1->size == 0) {
105                 isl_vec_free(vec1);
106                 return vec2;
107         }
108
109         vec1 = isl_vec_extend(vec1, vec1->size + vec2->size);
110         if (!vec1)
111                 goto error;
112
113         isl_seq_cpy(vec1->el + vec1->size - vec2->size, vec2->el, vec2->size);
114
115         isl_vec_free(vec2);
116         return vec1;
117 error:
118         isl_vec_free(vec1);
119         isl_vec_free(vec2);
120         return NULL;
121 }
122
123 struct isl_vec *isl_vec_copy(struct isl_vec *vec)
124 {
125         if (!vec)
126                 return NULL;
127
128         vec->ref++;
129         return vec;
130 }
131
132 struct isl_vec *isl_vec_dup(struct isl_vec *vec)
133 {
134         struct isl_vec *vec2;
135
136         if (!vec)
137                 return NULL;
138         vec2 = isl_vec_alloc(vec->ctx, vec->size);
139         isl_seq_cpy(vec2->el, vec->el, vec->size);
140         return vec2;
141 }
142
143 struct isl_vec *isl_vec_cow(struct isl_vec *vec)
144 {
145         struct isl_vec *vec2;
146         if (!vec)
147                 return NULL;
148
149         if (vec->ref == 1)
150                 return vec;
151
152         vec2 = isl_vec_dup(vec);
153         isl_vec_free(vec);
154         return vec2;
155 }
156
157 void *isl_vec_free(__isl_take isl_vec *vec)
158 {
159         if (!vec)
160                 return NULL;
161
162         if (--vec->ref > 0)
163                 return NULL;
164
165         isl_ctx_deref(vec->ctx);
166         isl_blk_free(vec->ctx, vec->block);
167         free(vec);
168
169         return NULL;
170 }
171
172 int isl_vec_size(__isl_keep isl_vec *vec)
173 {
174         return vec ? vec->size : -1;
175 }
176
177 int isl_vec_get_element(__isl_keep isl_vec *vec, int pos, isl_int *v)
178 {
179         if (!vec)
180                 return -1;
181
182         if (pos < 0 || pos >= vec->size)
183                 isl_die(vec->ctx, isl_error_invalid, "position out of range",
184                         return -1);
185         isl_int_set(*v, vec->el[pos]);
186         return 0;
187 }
188
189 __isl_give isl_vec *isl_vec_set_element(__isl_take isl_vec *vec,
190         int pos, isl_int v)
191 {
192         vec = isl_vec_cow(vec);
193         if (!vec)
194                 return NULL;
195         if (pos < 0 || pos >= vec->size)
196                 isl_die(vec->ctx, isl_error_invalid, "position out of range",
197                         goto error);
198         isl_int_set(vec->el[pos], v);
199         return vec;
200 error:
201         isl_vec_free(vec);
202         return NULL;
203 }
204
205 __isl_give isl_vec *isl_vec_set_element_si(__isl_take isl_vec *vec,
206         int pos, int v)
207 {
208         vec = isl_vec_cow(vec);
209         if (!vec)
210                 return NULL;
211         if (pos < 0 || pos >= vec->size)
212                 isl_die(vec->ctx, isl_error_invalid, "position out of range",
213                         goto error);
214         isl_int_set_si(vec->el[pos], v);
215         return vec;
216 error:
217         isl_vec_free(vec);
218         return NULL;
219 }
220
221 int isl_vec_is_equal(__isl_keep isl_vec *vec1, __isl_keep isl_vec *vec2)
222 {
223         if (!vec1 || !vec2)
224                 return -1;
225
226         if (vec1->size != vec2->size)
227                 return 0;
228
229         return isl_seq_eq(vec1->el, vec2->el, vec1->size);
230 }
231
232 __isl_give isl_printer *isl_printer_print_vec(__isl_take isl_printer *printer,
233         __isl_keep isl_vec *vec)
234 {
235         int i;
236
237         if (!printer || !vec)
238                 goto error;
239
240         printer = isl_printer_print_str(printer, "[");
241         for (i = 0; i < vec->size; ++i) {
242                 if (i)
243                         printer = isl_printer_print_str(printer, ",");
244                 printer = isl_printer_print_isl_int(printer, vec->el[i]);
245         }
246         printer = isl_printer_print_str(printer, "]");
247
248         return printer;
249 error:
250         isl_printer_free(printer);
251         return NULL;
252 }
253
254 void isl_vec_dump(struct isl_vec *vec)
255 {
256         isl_printer *printer;
257
258         if (!vec)
259                 return;
260
261         printer = isl_printer_to_file(vec->ctx, stderr);
262         printer = isl_printer_print_vec(printer, vec);
263         printer = isl_printer_end_line(printer);
264
265         isl_printer_free(printer);
266 }
267
268 __isl_give isl_vec *isl_vec_set(__isl_take isl_vec *vec, isl_int v)
269 {
270         vec = isl_vec_cow(vec);
271         if (!vec)
272                 return NULL;
273         isl_seq_set(vec->el, v, vec->size);
274         return vec;
275 }
276
277 __isl_give isl_vec *isl_vec_set_si(__isl_take isl_vec *vec, int v)
278 {
279         vec = isl_vec_cow(vec);
280         if (!vec)
281                 return NULL;
282         isl_seq_set_si(vec->el, v, vec->size);
283         return vec;
284 }
285
286 __isl_give isl_vec *isl_vec_clr(__isl_take isl_vec *vec)
287 {
288         vec = isl_vec_cow(vec);
289         if (!vec)
290                 return NULL;
291         isl_seq_clr(vec->el, vec->size);
292         return vec;
293 }
294
295 void isl_vec_lcm(struct isl_vec *vec, isl_int *lcm)
296 {
297         isl_seq_lcm(vec->block.data, vec->size, lcm);
298 }
299
300 /* Given a rational vector, with the denominator in the first element
301  * of the vector, round up all coordinates.
302  */
303 struct isl_vec *isl_vec_ceil(struct isl_vec *vec)
304 {
305         vec = isl_vec_cow(vec);
306         if (!vec)
307                 return NULL;
308
309         isl_seq_cdiv_q(vec->el + 1, vec->el + 1, vec->el[0], vec->size - 1);
310
311         isl_int_set_si(vec->el[0], 1);
312
313         return vec;
314 }
315
316 struct isl_vec *isl_vec_normalize(struct isl_vec *vec)
317 {
318         if (!vec)
319                 return NULL;
320         isl_seq_normalize(vec->ctx, vec->el, vec->size);
321         return vec;
322 }
323
324 __isl_give isl_vec *isl_vec_neg(__isl_take isl_vec *vec)
325 {
326         vec = isl_vec_cow(vec);
327         if (!vec)
328                 return NULL;
329         isl_seq_neg(vec->el, vec->el, vec->size);
330         return vec;
331 }
332
333 __isl_give isl_vec *isl_vec_scale(__isl_take isl_vec *vec, isl_int m)
334 {
335         if (isl_int_is_one(m))
336                 return vec;
337         vec = isl_vec_cow(vec);
338         if (!vec)
339                 return NULL;
340         isl_seq_scale(vec->el, vec->el, m, vec->size);
341         return vec;
342 }
343
344 __isl_give isl_vec *isl_vec_add(__isl_take isl_vec *vec1,
345         __isl_take isl_vec *vec2)
346 {
347         vec1 = isl_vec_cow(vec1);
348         if (!vec1 || !vec2)
349                 goto error;
350
351         isl_assert(vec1->ctx, vec1->size == vec2->size, goto error);
352
353         isl_seq_combine(vec1->el, vec1->ctx->one, vec1->el,
354                         vec1->ctx->one, vec2->el, vec1->size);
355         
356         isl_vec_free(vec2);
357         return vec1;
358 error:
359         isl_vec_free(vec1);
360         isl_vec_free(vec2);
361         return NULL;
362 }
363
364 static int qsort_int_cmp(const void *p1, const void *p2)
365 {
366         const isl_int *i1 = (const isl_int *) p1;
367         const isl_int *i2 = (const isl_int *) p2;
368
369         return isl_int_cmp(*i1, *i2);
370 }
371
372 __isl_give isl_vec *isl_vec_sort(__isl_take isl_vec *vec)
373 {
374         if (!vec)
375                 return NULL;
376         
377         qsort(vec->el, vec->size, sizeof(*vec->el), &qsort_int_cmp);
378
379         return vec;
380 }
381
382 __isl_give isl_vec *isl_vec_drop_els(__isl_take isl_vec *vec,
383         unsigned pos, unsigned n)
384 {
385         if (n == 0)
386                 return vec;
387         vec = isl_vec_cow(vec);
388         if (!vec)
389                 return NULL;
390
391         if (pos + n > vec->size)
392                 isl_die(vec->ctx, isl_error_invalid,
393                         "range out of bounds", goto error);
394
395         if (pos + n != vec->size)
396                 isl_seq_cpy(vec->el + pos, vec->el + pos + n,
397                             vec->size - pos - n);
398
399         vec->size -= n;
400         
401         return vec;
402 error:
403         isl_vec_free(vec);
404         return NULL;
405 }
406
407 __isl_give isl_vec *isl_vec_insert_els(__isl_take isl_vec *vec,
408         unsigned pos, unsigned n)
409 {
410         isl_vec *ext = NULL;
411
412         if (n == 0)
413                 return vec;
414         if (!vec)
415                 return NULL;
416
417         if (pos > vec->size)
418                 isl_die(vec->ctx, isl_error_invalid,
419                         "position out of bounds", goto error);
420
421         ext =  isl_vec_alloc(vec->ctx, vec->size + n);
422         if (!ext)
423                 goto error;
424
425         isl_seq_cpy(ext->el, vec->el, pos);
426         isl_seq_cpy(ext->el + pos + n, vec->el + pos, vec->size - pos);
427
428         isl_vec_free(vec);
429         return ext;
430 error:
431         isl_vec_free(vec);
432         isl_vec_free(ext);
433         return NULL;
434 }
435
436 __isl_give isl_vec *isl_vec_insert_zero_els(__isl_take isl_vec *vec,
437         unsigned pos, unsigned n)
438 {
439         vec = isl_vec_insert_els(vec, pos, n);
440         if (!vec)
441                 return NULL;
442
443         isl_seq_clr(vec->el + pos, n);
444
445         return vec;
446 }