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