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 if (!isl_local_space_divs_known(ls
))
49 isl_die(ctx
, isl_error_invalid
, "local space has unknown divs",
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
);
56 isl_local_space_free(ls
);
60 __isl_give isl_aff
*isl_aff_zero(__isl_take isl_local_space
*ls
)
64 aff
= isl_aff_alloc(ls
);
68 isl_int_set_si(aff
->v
->el
[0], 1);
69 isl_seq_clr(aff
->v
->el
+ 1, aff
->v
->size
- 1);
74 __isl_give isl_aff
*isl_aff_copy(__isl_keep isl_aff
*aff
)
83 __isl_give isl_aff
*isl_aff_dup(__isl_keep isl_aff
*aff
)
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
)
100 return isl_aff_dup(aff
);
103 void *isl_aff_free(__isl_take isl_aff
*aff
)
111 isl_local_space_free(aff
->ls
);
112 isl_vec_free(aff
->v
);
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
)
149 isl_int_set(*v
, aff
->v
->el
[0]);
153 int isl_aff_get_constant(__isl_keep isl_aff
*aff
, isl_int
*v
)
157 isl_int_set(*v
, aff
->v
->el
[1]);
161 int isl_aff_get_coefficient(__isl_keep isl_aff
*aff
,
162 enum isl_dim_type type
, int pos
, isl_int
*v
)
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
]);
177 __isl_give isl_aff
*isl_aff_set_denominator(__isl_take isl_aff
*aff
, isl_int v
)
179 aff
= isl_aff_cow(aff
);
183 aff
->v
= isl_vec_cow(aff
->v
);
185 return isl_aff_free(aff
);
187 isl_int_set(aff
->v
->el
[0], v
);
192 __isl_give isl_aff
*isl_aff_set_constant(__isl_take isl_aff
*aff
, isl_int v
)
194 aff
= isl_aff_cow(aff
);
198 aff
->v
= isl_vec_cow(aff
->v
);
200 return isl_aff_free(aff
);
202 isl_int_set(aff
->v
->el
[1], v
);
207 __isl_give isl_aff
*isl_aff_add_constant(__isl_take isl_aff
*aff
, isl_int v
)
209 if (isl_int_is_zero(v
))
212 aff
= isl_aff_cow(aff
);
216 aff
->v
= isl_vec_cow(aff
->v
);
218 return isl_aff_free(aff
);
220 isl_int_addmul(aff
->v
->el
[1], aff
->v
->el
[0], v
);
225 __isl_give isl_aff
*isl_aff_set_constant_si(__isl_take isl_aff
*aff
, int v
)
227 aff
= isl_aff_cow(aff
);
231 aff
->v
= isl_vec_cow(aff
->v
);
233 return isl_aff_free(aff
);
235 isl_int_set_si(aff
->v
->el
[1], v
);
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
)
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
);
254 aff
->v
= isl_vec_cow(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
);
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
)
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
);
278 aff
->v
= isl_vec_cow(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
);
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
)
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
);
302 aff
->v
= isl_vec_cow(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
);
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
)
318 isl_int_set_si(t
, v
);
319 aff
= isl_aff_add_coefficient(aff
, type
, pos
, t
);
325 __isl_give isl_div
*isl_aff_get_div(__isl_keep isl_aff
*aff
, int pos
)
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
);
338 aff
->v
= isl_vec_cow(aff
->v
);
340 return isl_aff_free(aff
);
342 isl_seq_neg(aff
->v
->el
+ 1, aff
->v
->el
+ 1, aff
->v
->size
- 1);
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
)
359 if (isl_int_is_one(aff
->v
->el
[0]))
362 aff
= isl_aff_cow(aff
);
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
));
371 ctx
= isl_aff_get_ctx(aff
);
373 isl_vec_free(aff
->v
);
374 aff
->v
= isl_vec_alloc(ctx
, size
+ 1);
375 aff
->v
= isl_vec_clr(aff
->v
);
378 isl_int_set_si(aff
->v
->el
[0], 1);
379 isl_int_set_si(aff
->v
->el
[size
], -1);
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
)
399 aff
= isl_aff_cow(aff
);
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
);
413 offset
= 1 + isl_local_space_offset(aff
->ls
, isl_dim_div
);
415 for (i
= new_n_div
- 1; i
>= 0; --i
) {
416 if (j
>= 0 && exp
[j
] == i
) {
418 isl_int_swap(aff
->v
->el
[offset
+ i
],
419 aff
->v
->el
[offset
+ j
]);
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
));