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,
11 #include <isl_aff_private.h>
12 #include <isl_local_space_private.h>
15 __isl_give isl_aff *isl_aff_alloc_vec(__isl_take isl_local_space *ls,
16 __isl_take isl_vec *v)
23 aff = isl_calloc_type(v->ctx, struct isl_aff);
33 isl_local_space_free(ls);
38 __isl_give isl_aff *isl_aff_alloc(__isl_take isl_local_space *ls)
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)
57 aff = isl_aff_alloc(ls);
61 isl_int_set_si(aff->v->el[0], 1);
62 isl_seq_clr(aff->v->el + 1, aff->v->size - 1);
67 __isl_give isl_aff *isl_aff_copy(__isl_keep isl_aff *aff)
76 __isl_give isl_aff *isl_aff_dup(__isl_keep isl_aff *aff)
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)
93 return isl_aff_dup(aff);
96 void *isl_aff_free(__isl_take isl_aff *aff)
104 isl_local_space_free(aff->ls);
105 isl_vec_free(aff->v);
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_dim *isl_aff_get_dim(__isl_keep isl_aff *aff)
124 return aff ? isl_local_space_get_dim(aff->ls) : NULL;
127 __isl_give isl_local_space *isl_aff_get_local_space(__isl_keep isl_aff *aff)
129 return aff ? isl_local_space_copy(aff->ls) : NULL;
132 const char *isl_aff_get_dim_name(__isl_keep isl_aff *aff,
133 enum isl_dim_type type, unsigned pos)
135 return aff ? isl_local_space_get_dim_name(aff->ls, type, pos) : 0;
138 int isl_aff_get_denominator(__isl_keep isl_aff *aff, isl_int *v)
142 isl_int_set(*v, aff->v->el[0]);
146 int isl_aff_get_constant(__isl_keep isl_aff *aff, isl_int *v)
150 isl_int_set(*v, aff->v->el[1]);
154 int isl_aff_get_coefficient(__isl_keep isl_aff *aff,
155 enum isl_dim_type type, int pos, isl_int *v)
160 if (pos >= isl_local_space_dim(aff->ls, type))
161 isl_die(aff->v->ctx, isl_error_invalid,
162 "position out of bounds", return -1);
164 pos += isl_local_space_offset(aff->ls, type);
165 isl_int_set(*v, aff->v->el[1 + pos]);
170 __isl_give isl_aff *isl_aff_set_denominator(__isl_take isl_aff *aff, isl_int v)
172 aff = isl_aff_cow(aff);
176 aff->v = isl_vec_cow(aff->v);
178 return isl_aff_free(aff);
180 isl_int_set(aff->v->el[0], v);
185 __isl_give isl_aff *isl_aff_set_constant(__isl_take isl_aff *aff, isl_int v)
187 aff = isl_aff_cow(aff);
191 aff->v = isl_vec_cow(aff->v);
193 return isl_aff_free(aff);
195 isl_int_set(aff->v->el[1], v);
200 __isl_give isl_aff *isl_aff_add_constant(__isl_take isl_aff *aff, isl_int v)
202 if (isl_int_is_zero(v))
205 aff = isl_aff_cow(aff);
209 aff->v = isl_vec_cow(aff->v);
211 return isl_aff_free(aff);
213 isl_int_addmul(aff->v->el[1], aff->v->el[0], v);
218 __isl_give isl_aff *isl_aff_set_constant_si(__isl_take isl_aff *aff, int v)
220 aff = isl_aff_cow(aff);
224 aff->v = isl_vec_cow(aff->v);
226 return isl_aff_free(aff);
228 isl_int_set_si(aff->v->el[1], v);
233 __isl_give isl_aff *isl_aff_set_coefficient(__isl_take isl_aff *aff,
234 enum isl_dim_type type, int pos, isl_int v)
239 if (pos >= isl_local_space_dim(aff->ls, type))
240 isl_die(aff->v->ctx, isl_error_invalid,
241 "position out of bounds", return isl_aff_free(aff));
243 aff = isl_aff_cow(aff);
247 aff->v = isl_vec_cow(aff->v);
249 return isl_aff_free(aff);
251 pos += isl_local_space_offset(aff->ls, type);
252 isl_int_set(aff->v->el[1 + pos], v);
257 __isl_give isl_aff *isl_aff_set_coefficient_si(__isl_take isl_aff *aff,
258 enum isl_dim_type type, int pos, int v)
263 if (pos >= isl_local_space_dim(aff->ls, type))
264 isl_die(aff->v->ctx, isl_error_invalid,
265 "position out of bounds", return isl_aff_free(aff));
267 aff = isl_aff_cow(aff);
271 aff->v = isl_vec_cow(aff->v);
273 return isl_aff_free(aff);
275 pos += isl_local_space_offset(aff->ls, type);
276 isl_int_set_si(aff->v->el[1 + pos], v);
281 __isl_give isl_aff *isl_aff_add_coefficient(__isl_take isl_aff *aff,
282 enum isl_dim_type type, int pos, isl_int v)
287 if (pos >= isl_local_space_dim(aff->ls, type))
288 isl_die(aff->v->ctx, isl_error_invalid,
289 "position out of bounds", return isl_aff_free(aff));
291 aff = isl_aff_cow(aff);
295 aff->v = isl_vec_cow(aff->v);
297 return isl_aff_free(aff);
299 pos += isl_local_space_offset(aff->ls, type);
300 isl_int_addmul(aff->v->el[1 + pos], aff->v->el[0], v);
305 __isl_give isl_aff *isl_aff_add_coefficient_si(__isl_take isl_aff *aff,
306 enum isl_dim_type type, int pos, int v)
311 isl_int_set_si(t, v);
312 aff = isl_aff_add_coefficient(aff, type, pos, t);
318 __isl_give isl_div *isl_aff_get_div(__isl_keep isl_aff *aff, int pos)
323 return isl_local_space_get_div(aff->ls, pos);
326 __isl_give isl_aff *isl_aff_neg(__isl_take isl_aff *aff)
328 aff = isl_aff_cow(aff);
331 aff->v = isl_vec_cow(aff->v);
333 return isl_aff_free(aff);
335 isl_seq_neg(aff->v->el + 1, aff->v->el + 1, aff->v->size - 1);
340 /* Given f, return ceil(f).
341 * If f is an integer expression, then just return f.
342 * Otherwise, create a new div d = [-f] and return the expression -d.
344 __isl_give isl_aff *isl_aff_ceil(__isl_take isl_aff *aff)
352 if (isl_int_is_one(aff->v->el[0]))
355 aff = isl_aff_cow(aff);
359 isl_seq_neg(aff->v->el + 1, aff->v->el + 1, aff->v->size - 1);
360 aff->ls = isl_local_space_add_div(aff->ls, isl_vec_copy(aff->v));
364 ctx = isl_aff_get_ctx(aff);
366 isl_vec_free(aff->v);
367 aff->v = isl_vec_alloc(ctx, size + 1);
368 aff->v = isl_vec_clr(aff->v);
371 isl_int_set_si(aff->v->el[0], 1);
372 isl_int_set_si(aff->v->el[size], -1);
380 /* Apply the expansion computed by isl_merge_divs.
381 * The expansion itself is given by "exp" while the resulting
382 * list of divs is given by "div".
384 __isl_give isl_aff *isl_aff_expand_divs( __isl_take isl_aff *aff,
385 __isl_take isl_mat *div, int *exp)
392 aff = isl_aff_cow(aff);
396 old_n_div = isl_local_space_dim(aff->ls, isl_dim_div);
397 new_n_div = isl_mat_rows(div);
398 if (new_n_div < old_n_div)
399 isl_die(isl_mat_get_ctx(div), isl_error_invalid,
400 "not an expansion", goto error);
402 aff->v = isl_vec_extend(aff->v, aff->v->size + new_n_div - old_n_div);
406 offset = 1 + isl_local_space_offset(aff->ls, isl_dim_div);
408 for (i = new_n_div - 1; i >= 0; --i) {
409 if (j >= 0 && exp[j] == i) {
411 isl_int_swap(aff->v->el[offset + i],
412 aff->v->el[offset + j]);
415 isl_int_set_si(aff->v->el[offset + j], 0);
418 aff->ls = isl_local_space_replace_divs(aff->ls, isl_mat_copy(div));