isl_basic_map_from_local_space: don't finalize result
[isl.git] / isl_aff.c
blob26937b529961f62ad22361ada42c70e74db1cb1a
1 /*
2 * Copyright 2011 INRIA Saclay
4 * Use of this software is governed by the GNU LGPLv2.1 license
6 * Written by Sven Verdoolaege, INRIA Saclay - Ile-de-France,
7 * Parc Club Orsay Universite, ZAC des vignes, 4 rue Jacques Monod,
8 * 91893 Orsay, France
9 */
11 #include <isl_aff_private.h>
12 #include <isl_local_space_private.h>
13 #include <isl/seq.h>
15 __isl_give isl_aff *isl_aff_alloc_vec(__isl_take isl_local_space *ls,
16 __isl_take isl_vec *v)
18 isl_aff *aff;
20 if (!ls || !v)
21 goto error;
23 aff = isl_calloc_type(v->ctx, struct isl_aff);
24 if (!aff)
25 goto error;
27 aff->ref = 1;
28 aff->ls = ls;
29 aff->v = v;
31 return aff;
32 error:
33 isl_local_space_free(ls);
34 isl_vec_free(v);
35 return NULL;
38 __isl_give isl_aff *isl_aff_alloc(__isl_take isl_local_space *ls)
40 isl_ctx *ctx;
41 isl_vec *v;
42 unsigned total;
44 if (!ls)
45 return NULL;
47 ctx = isl_local_space_get_ctx(ls);
48 total = isl_local_space_dim(ls, isl_dim_all);
49 v = isl_vec_alloc(ctx, 1 + 1 + total);
50 return isl_aff_alloc_vec(ls, v);
53 __isl_give isl_aff *isl_aff_zero(__isl_take isl_local_space *ls)
55 isl_aff *aff;
57 aff = isl_aff_alloc(ls);
58 if (!aff)
59 return NULL;
61 isl_int_set_si(aff->v->el[0], 1);
62 isl_seq_clr(aff->v->el + 1, aff->v->size - 1);
64 return aff;
67 __isl_give isl_aff *isl_aff_copy(__isl_keep isl_aff *aff)
69 if (!aff)
70 return NULL;
72 aff->ref++;
73 return aff;
76 __isl_give isl_aff *isl_aff_dup(__isl_keep isl_aff *aff)
78 if (!aff)
79 return NULL;
81 return isl_aff_alloc_vec(isl_local_space_copy(aff->ls),
82 isl_vec_copy(aff->v));
85 __isl_give isl_aff *isl_aff_cow(__isl_take isl_aff *aff)
87 if (!aff)
88 return NULL;
90 if (aff->ref == 1)
91 return aff;
92 aff->ref--;
93 return isl_aff_dup(aff);
96 void *isl_aff_free(__isl_take isl_aff *aff)
98 if (!aff)
99 return NULL;
101 if (--aff->ref > 0)
102 return NULL;
104 isl_local_space_free(aff->ls);
105 isl_vec_free(aff->v);
107 free(aff);
109 return NULL;
112 isl_ctx *isl_aff_get_ctx(__isl_keep isl_aff *aff)
114 return aff ? isl_local_space_get_ctx(aff->ls) : NULL;
117 int isl_aff_dim(__isl_keep isl_aff *aff, enum isl_dim_type type)
119 return aff ? isl_local_space_dim(aff->ls, type) : 0;
122 __isl_give isl_local_space *isl_aff_get_local_space(__isl_keep isl_aff *aff)
124 return aff ? isl_local_space_copy(aff->ls) : NULL;
127 const char *isl_aff_get_dim_name(__isl_keep isl_aff *aff,
128 enum isl_dim_type type, unsigned pos)
130 return aff ? isl_local_space_get_dim_name(aff->ls, type, pos) : 0;
133 int isl_aff_get_denominator(__isl_keep isl_aff *aff, isl_int *v)
135 if (!aff)
136 return -1;
137 isl_int_set(*v, aff->v->el[0]);
138 return 0;
141 int isl_aff_get_constant(__isl_keep isl_aff *aff, isl_int *v)
143 if (!aff)
144 return -1;
145 isl_int_set(*v, aff->v->el[1]);
146 return 0;
149 int isl_aff_get_coefficient(__isl_keep isl_aff *aff,
150 enum isl_dim_type type, int pos, isl_int *v)
152 if (!aff)
153 return -1;
155 if (pos >= isl_local_space_dim(aff->ls, type))
156 isl_die(aff->v->ctx, isl_error_invalid,
157 "position out of bounds", return -1);
159 pos += isl_local_space_offset(aff->ls, type);
160 isl_int_set(*v, aff->v->el[1 + pos]);
162 return 0;
165 __isl_give isl_aff *isl_aff_set_denominator(__isl_take isl_aff *aff, isl_int v)
167 aff = isl_aff_cow(aff);
168 if (!aff)
169 return NULL;
171 aff->v = isl_vec_cow(aff->v);
172 if (!aff->v)
173 return isl_aff_free(aff);
175 isl_int_set(aff->v->el[0], v);
177 return aff;
180 __isl_give isl_aff *isl_aff_set_constant(__isl_take isl_aff *aff, isl_int v)
182 aff = isl_aff_cow(aff);
183 if (!aff)
184 return NULL;
186 aff->v = isl_vec_cow(aff->v);
187 if (!aff->v)
188 return isl_aff_free(aff);
190 isl_int_set(aff->v->el[1], v);
192 return aff;
195 __isl_give isl_aff *isl_aff_add_constant(__isl_take isl_aff *aff, isl_int v)
197 if (isl_int_is_zero(v))
198 return aff;
200 aff = isl_aff_cow(aff);
201 if (!aff)
202 return NULL;
204 aff->v = isl_vec_cow(aff->v);
205 if (!aff->v)
206 return isl_aff_free(aff);
208 isl_int_addmul(aff->v->el[1], aff->v->el[0], v);
210 return aff;
213 __isl_give isl_aff *isl_aff_set_constant_si(__isl_take isl_aff *aff, int v)
215 aff = isl_aff_cow(aff);
216 if (!aff)
217 return NULL;
219 aff->v = isl_vec_cow(aff->v);
220 if (!aff->v)
221 return isl_aff_free(aff);
223 isl_int_set_si(aff->v->el[1], v);
225 return aff;
228 __isl_give isl_aff *isl_aff_set_coefficient(__isl_take isl_aff *aff,
229 enum isl_dim_type type, int pos, isl_int v)
231 if (!aff)
232 return NULL;
234 if (pos >= isl_local_space_dim(aff->ls, type))
235 isl_die(aff->v->ctx, isl_error_invalid,
236 "position out of bounds", return isl_aff_free(aff));
238 aff = isl_aff_cow(aff);
239 if (!aff)
240 return NULL;
242 aff->v = isl_vec_cow(aff->v);
243 if (!aff->v)
244 return isl_aff_free(aff);
246 pos += isl_local_space_offset(aff->ls, type);
247 isl_int_set(aff->v->el[1 + pos], v);
249 return aff;
252 __isl_give isl_aff *isl_aff_set_coefficient_si(__isl_take isl_aff *aff,
253 enum isl_dim_type type, int pos, int v)
255 if (!aff)
256 return NULL;
258 if (pos >= isl_local_space_dim(aff->ls, type))
259 isl_die(aff->v->ctx, isl_error_invalid,
260 "position out of bounds", return isl_aff_free(aff));
262 aff = isl_aff_cow(aff);
263 if (!aff)
264 return NULL;
266 aff->v = isl_vec_cow(aff->v);
267 if (!aff->v)
268 return isl_aff_free(aff);
270 pos += isl_local_space_offset(aff->ls, type);
271 isl_int_set_si(aff->v->el[1 + pos], v);
273 return aff;
276 __isl_give isl_aff *isl_aff_add_coefficient(__isl_take isl_aff *aff,
277 enum isl_dim_type type, int pos, isl_int v)
279 if (!aff)
280 return NULL;
282 if (pos >= isl_local_space_dim(aff->ls, type))
283 isl_die(aff->v->ctx, isl_error_invalid,
284 "position out of bounds", return isl_aff_free(aff));
286 aff = isl_aff_cow(aff);
287 if (!aff)
288 return NULL;
290 aff->v = isl_vec_cow(aff->v);
291 if (!aff->v)
292 return isl_aff_free(aff);
294 pos += isl_local_space_offset(aff->ls, type);
295 isl_int_addmul(aff->v->el[1 + pos], aff->v->el[0], v);
297 return aff;
300 __isl_give isl_aff *isl_aff_add_coefficient_si(__isl_take isl_aff *aff,
301 enum isl_dim_type type, int pos, int v)
303 isl_int t;
305 isl_int_init(t);
306 isl_int_set_si(t, v);
307 aff = isl_aff_add_coefficient(aff, type, pos, t);
308 isl_int_clear(t);
310 return aff;
313 __isl_give isl_div *isl_aff_get_div(__isl_keep isl_aff *aff, int pos)
315 if (!aff)
316 return NULL;
318 return isl_local_space_get_div(aff->ls, pos);
321 __isl_give isl_aff *isl_aff_neg(__isl_take isl_aff *aff)
323 aff = isl_aff_cow(aff);
324 if (!aff)
325 return NULL;
326 aff->v = isl_vec_cow(aff->v);
327 if (!aff->v)
328 return isl_aff_free(aff);
330 isl_seq_neg(aff->v->el + 1, aff->v->el + 1, aff->v->size - 1);
332 return aff;
335 /* Given f, return ceil(f).
336 * If f is an integer expression, then just return f.
337 * Otherwise, create a new div d = [-f] and return the expression -d.
339 __isl_give isl_aff *isl_aff_ceil(__isl_take isl_aff *aff)
341 int size;
342 isl_ctx *ctx;
344 if (!aff)
345 return NULL;
347 if (isl_int_is_one(aff->v->el[0]))
348 return aff;
350 aff = isl_aff_cow(aff);
351 if (!aff)
352 return NULL;
354 isl_seq_neg(aff->v->el + 1, aff->v->el + 1, aff->v->size - 1);
355 aff->ls = isl_local_space_add_div(aff->ls, isl_vec_copy(aff->v));
356 if (!aff->ls)
357 goto error;
359 ctx = isl_aff_get_ctx(aff);
360 size = aff->v->size;
361 isl_vec_free(aff->v);
362 aff->v = isl_vec_alloc(ctx, size + 1);
363 aff->v = isl_vec_clr(aff->v);
364 if (!aff->v)
365 goto error;
366 isl_int_set_si(aff->v->el[0], 1);
367 isl_int_set_si(aff->v->el[size], -1);
369 return aff;
370 error:
371 isl_aff_free(aff);
372 return NULL;
375 /* Apply the expansion computed by isl_merge_divs.
376 * The expansion itself is given by "exp" while the resulting
377 * list of divs is given by "div".
379 __isl_give isl_aff *isl_aff_expand_divs( __isl_take isl_aff *aff,
380 __isl_take isl_mat *div, int *exp)
382 int i, j;
383 int old_n_div;
384 int new_n_div;
385 int offset;
387 aff = isl_aff_cow(aff);
388 if (!aff || !div)
389 goto error;
391 old_n_div = isl_local_space_dim(aff->ls, isl_dim_div);
392 new_n_div = isl_mat_rows(div);
393 if (new_n_div < old_n_div)
394 isl_die(isl_mat_get_ctx(div), isl_error_invalid,
395 "not an expansion", goto error);
397 aff->v = isl_vec_extend(aff->v, aff->v->size + new_n_div - old_n_div);
398 if (!aff->v)
399 goto error;
401 offset = 1 + isl_local_space_offset(aff->ls, isl_dim_div);
402 j = old_n_div - 1;
403 for (i = new_n_div - 1; i >= 0; --i) {
404 if (j >= 0 && exp[j] == i) {
405 if (i != j)
406 isl_int_swap(aff->v->el[offset + i],
407 aff->v->el[offset + j]);
408 j--;
409 } else
410 isl_int_set_si(aff->v->el[offset + j], 0);
413 aff->ls = isl_local_space_replace_divs(aff->ls, isl_mat_copy(div));
414 if (!aff->ls)
415 goto error;
416 isl_mat_free(div);
417 return aff;
418 error:
419 isl_aff_free(aff);
420 isl_mat_free(div);
421 return NULL;