isl_tab_pip.c: remove unused context_lex_extend
[isl.git] / isl_aff.c
blobd0a4e751343c88176c0f9cb64663f9d9b0d171a3
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 if (!isl_local_space_divs_known(ls))
49 isl_die(ctx, isl_error_invalid, "local space has unknown divs",
50 goto error);
52 total = isl_local_space_dim(ls, isl_dim_all);
53 v = isl_vec_alloc(ctx, 1 + 1 + total);
54 return isl_aff_alloc_vec(ls, v);
55 error:
56 isl_local_space_free(ls);
57 return NULL;
60 __isl_give isl_aff *isl_aff_zero(__isl_take isl_local_space *ls)
62 isl_aff *aff;
64 aff = isl_aff_alloc(ls);
65 if (!aff)
66 return NULL;
68 isl_int_set_si(aff->v->el[0], 1);
69 isl_seq_clr(aff->v->el + 1, aff->v->size - 1);
71 return aff;
74 __isl_give isl_aff *isl_aff_copy(__isl_keep isl_aff *aff)
76 if (!aff)
77 return NULL;
79 aff->ref++;
80 return aff;
83 __isl_give isl_aff *isl_aff_dup(__isl_keep isl_aff *aff)
85 if (!aff)
86 return NULL;
88 return isl_aff_alloc_vec(isl_local_space_copy(aff->ls),
89 isl_vec_copy(aff->v));
92 __isl_give isl_aff *isl_aff_cow(__isl_take isl_aff *aff)
94 if (!aff)
95 return NULL;
97 if (aff->ref == 1)
98 return aff;
99 aff->ref--;
100 return isl_aff_dup(aff);
103 void *isl_aff_free(__isl_take isl_aff *aff)
105 if (!aff)
106 return NULL;
108 if (--aff->ref > 0)
109 return NULL;
111 isl_local_space_free(aff->ls);
112 isl_vec_free(aff->v);
114 free(aff);
116 return NULL;
119 isl_ctx *isl_aff_get_ctx(__isl_keep isl_aff *aff)
121 return aff ? isl_local_space_get_ctx(aff->ls) : NULL;
124 int isl_aff_dim(__isl_keep isl_aff *aff, enum isl_dim_type type)
126 return aff ? isl_local_space_dim(aff->ls, type) : 0;
129 __isl_give isl_dim *isl_aff_get_dim(__isl_keep isl_aff *aff)
131 return aff ? isl_local_space_get_dim(aff->ls) : NULL;
134 __isl_give isl_local_space *isl_aff_get_local_space(__isl_keep isl_aff *aff)
136 return aff ? isl_local_space_copy(aff->ls) : NULL;
139 const char *isl_aff_get_dim_name(__isl_keep isl_aff *aff,
140 enum isl_dim_type type, unsigned pos)
142 return aff ? isl_local_space_get_dim_name(aff->ls, type, pos) : 0;
145 int isl_aff_get_denominator(__isl_keep isl_aff *aff, isl_int *v)
147 if (!aff)
148 return -1;
149 isl_int_set(*v, aff->v->el[0]);
150 return 0;
153 int isl_aff_get_constant(__isl_keep isl_aff *aff, isl_int *v)
155 if (!aff)
156 return -1;
157 isl_int_set(*v, aff->v->el[1]);
158 return 0;
161 int isl_aff_get_coefficient(__isl_keep isl_aff *aff,
162 enum isl_dim_type type, int pos, isl_int *v)
164 if (!aff)
165 return -1;
167 if (pos >= isl_local_space_dim(aff->ls, type))
168 isl_die(aff->v->ctx, isl_error_invalid,
169 "position out of bounds", return -1);
171 pos += isl_local_space_offset(aff->ls, type);
172 isl_int_set(*v, aff->v->el[1 + pos]);
174 return 0;
177 __isl_give isl_aff *isl_aff_set_denominator(__isl_take isl_aff *aff, isl_int v)
179 aff = isl_aff_cow(aff);
180 if (!aff)
181 return NULL;
183 aff->v = isl_vec_cow(aff->v);
184 if (!aff->v)
185 return isl_aff_free(aff);
187 isl_int_set(aff->v->el[0], v);
189 return aff;
192 __isl_give isl_aff *isl_aff_set_constant(__isl_take isl_aff *aff, isl_int v)
194 aff = isl_aff_cow(aff);
195 if (!aff)
196 return NULL;
198 aff->v = isl_vec_cow(aff->v);
199 if (!aff->v)
200 return isl_aff_free(aff);
202 isl_int_set(aff->v->el[1], v);
204 return aff;
207 __isl_give isl_aff *isl_aff_add_constant(__isl_take isl_aff *aff, isl_int v)
209 if (isl_int_is_zero(v))
210 return aff;
212 aff = isl_aff_cow(aff);
213 if (!aff)
214 return NULL;
216 aff->v = isl_vec_cow(aff->v);
217 if (!aff->v)
218 return isl_aff_free(aff);
220 isl_int_addmul(aff->v->el[1], aff->v->el[0], v);
222 return aff;
225 __isl_give isl_aff *isl_aff_set_constant_si(__isl_take isl_aff *aff, int v)
227 aff = isl_aff_cow(aff);
228 if (!aff)
229 return NULL;
231 aff->v = isl_vec_cow(aff->v);
232 if (!aff->v)
233 return isl_aff_free(aff);
235 isl_int_set_si(aff->v->el[1], v);
237 return aff;
240 __isl_give isl_aff *isl_aff_set_coefficient(__isl_take isl_aff *aff,
241 enum isl_dim_type type, int pos, isl_int v)
243 if (!aff)
244 return NULL;
246 if (pos >= isl_local_space_dim(aff->ls, type))
247 isl_die(aff->v->ctx, isl_error_invalid,
248 "position out of bounds", return isl_aff_free(aff));
250 aff = isl_aff_cow(aff);
251 if (!aff)
252 return NULL;
254 aff->v = isl_vec_cow(aff->v);
255 if (!aff->v)
256 return isl_aff_free(aff);
258 pos += isl_local_space_offset(aff->ls, type);
259 isl_int_set(aff->v->el[1 + pos], v);
261 return aff;
264 __isl_give isl_aff *isl_aff_set_coefficient_si(__isl_take isl_aff *aff,
265 enum isl_dim_type type, int pos, int v)
267 if (!aff)
268 return NULL;
270 if (pos >= isl_local_space_dim(aff->ls, type))
271 isl_die(aff->v->ctx, isl_error_invalid,
272 "position out of bounds", return isl_aff_free(aff));
274 aff = isl_aff_cow(aff);
275 if (!aff)
276 return NULL;
278 aff->v = isl_vec_cow(aff->v);
279 if (!aff->v)
280 return isl_aff_free(aff);
282 pos += isl_local_space_offset(aff->ls, type);
283 isl_int_set_si(aff->v->el[1 + pos], v);
285 return aff;
288 __isl_give isl_aff *isl_aff_add_coefficient(__isl_take isl_aff *aff,
289 enum isl_dim_type type, int pos, isl_int v)
291 if (!aff)
292 return NULL;
294 if (pos >= isl_local_space_dim(aff->ls, type))
295 isl_die(aff->v->ctx, isl_error_invalid,
296 "position out of bounds", return isl_aff_free(aff));
298 aff = isl_aff_cow(aff);
299 if (!aff)
300 return NULL;
302 aff->v = isl_vec_cow(aff->v);
303 if (!aff->v)
304 return isl_aff_free(aff);
306 pos += isl_local_space_offset(aff->ls, type);
307 isl_int_addmul(aff->v->el[1 + pos], aff->v->el[0], v);
309 return aff;
312 __isl_give isl_aff *isl_aff_add_coefficient_si(__isl_take isl_aff *aff,
313 enum isl_dim_type type, int pos, int v)
315 isl_int t;
317 isl_int_init(t);
318 isl_int_set_si(t, v);
319 aff = isl_aff_add_coefficient(aff, type, pos, t);
320 isl_int_clear(t);
322 return aff;
325 __isl_give isl_div *isl_aff_get_div(__isl_keep isl_aff *aff, int pos)
327 if (!aff)
328 return NULL;
330 return isl_local_space_get_div(aff->ls, pos);
333 __isl_give isl_aff *isl_aff_neg(__isl_take isl_aff *aff)
335 aff = isl_aff_cow(aff);
336 if (!aff)
337 return NULL;
338 aff->v = isl_vec_cow(aff->v);
339 if (!aff->v)
340 return isl_aff_free(aff);
342 isl_seq_neg(aff->v->el + 1, aff->v->el + 1, aff->v->size - 1);
344 return aff;
347 /* Given f, return ceil(f).
348 * If f is an integer expression, then just return f.
349 * Otherwise, create a new div d = [-f] and return the expression -d.
351 __isl_give isl_aff *isl_aff_ceil(__isl_take isl_aff *aff)
353 int size;
354 isl_ctx *ctx;
356 if (!aff)
357 return NULL;
359 if (isl_int_is_one(aff->v->el[0]))
360 return aff;
362 aff = isl_aff_cow(aff);
363 if (!aff)
364 return NULL;
366 isl_seq_neg(aff->v->el + 1, aff->v->el + 1, aff->v->size - 1);
367 aff->ls = isl_local_space_add_div(aff->ls, isl_vec_copy(aff->v));
368 if (!aff->ls)
369 goto error;
371 ctx = isl_aff_get_ctx(aff);
372 size = aff->v->size;
373 isl_vec_free(aff->v);
374 aff->v = isl_vec_alloc(ctx, size + 1);
375 aff->v = isl_vec_clr(aff->v);
376 if (!aff->v)
377 goto error;
378 isl_int_set_si(aff->v->el[0], 1);
379 isl_int_set_si(aff->v->el[size], -1);
381 return aff;
382 error:
383 isl_aff_free(aff);
384 return NULL;
387 /* Apply the expansion computed by isl_merge_divs.
388 * The expansion itself is given by "exp" while the resulting
389 * list of divs is given by "div".
391 __isl_give isl_aff *isl_aff_expand_divs( __isl_take isl_aff *aff,
392 __isl_take isl_mat *div, int *exp)
394 int i, j;
395 int old_n_div;
396 int new_n_div;
397 int offset;
399 aff = isl_aff_cow(aff);
400 if (!aff || !div)
401 goto error;
403 old_n_div = isl_local_space_dim(aff->ls, isl_dim_div);
404 new_n_div = isl_mat_rows(div);
405 if (new_n_div < old_n_div)
406 isl_die(isl_mat_get_ctx(div), isl_error_invalid,
407 "not an expansion", goto error);
409 aff->v = isl_vec_extend(aff->v, aff->v->size + new_n_div - old_n_div);
410 if (!aff->v)
411 goto error;
413 offset = 1 + isl_local_space_offset(aff->ls, isl_dim_div);
414 j = old_n_div - 1;
415 for (i = new_n_div - 1; i >= 0; --i) {
416 if (j >= 0 && exp[j] == i) {
417 if (i != j)
418 isl_int_swap(aff->v->el[offset + i],
419 aff->v->el[offset + j]);
420 j--;
421 } else
422 isl_int_set_si(aff->v->el[offset + i], 0);
425 aff->ls = isl_local_space_replace_divs(aff->ls, isl_mat_copy(div));
426 if (!aff->ls)
427 goto error;
428 isl_mat_free(div);
429 return aff;
430 error:
431 isl_aff_free(aff);
432 isl_mat_free(div);
433 return NULL;