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>
13 #include <isl_mat_private.h>
16 __isl_give isl_aff
*isl_aff_alloc_vec(__isl_take isl_local_space
*ls
,
17 __isl_take isl_vec
*v
)
24 aff
= isl_calloc_type(v
->ctx
, struct isl_aff
);
34 isl_local_space_free(ls
);
39 __isl_give isl_aff
*isl_aff_alloc(__isl_take isl_local_space
*ls
)
48 ctx
= isl_local_space_get_ctx(ls
);
49 if (!isl_local_space_divs_known(ls
))
50 isl_die(ctx
, isl_error_invalid
, "local space has unknown divs",
53 total
= isl_local_space_dim(ls
, isl_dim_all
);
54 v
= isl_vec_alloc(ctx
, 1 + 1 + total
);
55 return isl_aff_alloc_vec(ls
, v
);
57 isl_local_space_free(ls
);
61 __isl_give isl_aff
*isl_aff_zero(__isl_take isl_local_space
*ls
)
65 aff
= isl_aff_alloc(ls
);
69 isl_int_set_si(aff
->v
->el
[0], 1);
70 isl_seq_clr(aff
->v
->el
+ 1, aff
->v
->size
- 1);
75 __isl_give isl_aff
*isl_aff_copy(__isl_keep isl_aff
*aff
)
84 __isl_give isl_aff
*isl_aff_dup(__isl_keep isl_aff
*aff
)
89 return isl_aff_alloc_vec(isl_local_space_copy(aff
->ls
),
90 isl_vec_copy(aff
->v
));
93 __isl_give isl_aff
*isl_aff_cow(__isl_take isl_aff
*aff
)
101 return isl_aff_dup(aff
);
104 void *isl_aff_free(__isl_take isl_aff
*aff
)
112 isl_local_space_free(aff
->ls
);
113 isl_vec_free(aff
->v
);
120 isl_ctx
*isl_aff_get_ctx(__isl_keep isl_aff
*aff
)
122 return aff
? isl_local_space_get_ctx(aff
->ls
) : NULL
;
125 int isl_aff_dim(__isl_keep isl_aff
*aff
, enum isl_dim_type type
)
127 return aff
? isl_local_space_dim(aff
->ls
, type
) : 0;
130 __isl_give isl_dim
*isl_aff_get_dim(__isl_keep isl_aff
*aff
)
132 return aff
? isl_local_space_get_dim(aff
->ls
) : NULL
;
135 __isl_give isl_local_space
*isl_aff_get_local_space(__isl_keep isl_aff
*aff
)
137 return aff
? isl_local_space_copy(aff
->ls
) : NULL
;
140 const char *isl_aff_get_dim_name(__isl_keep isl_aff
*aff
,
141 enum isl_dim_type type
, unsigned pos
)
143 return aff
? isl_local_space_get_dim_name(aff
->ls
, type
, pos
) : 0;
146 int isl_aff_plain_is_zero(__isl_keep isl_aff
*aff
)
151 return isl_seq_first_non_zero(aff
->v
->el
+ 1, aff
->v
->size
- 1) < 0;
154 int isl_aff_plain_is_equal(__isl_keep isl_aff
*aff1
, __isl_keep isl_aff
*aff2
)
161 equal
= isl_local_space_is_equal(aff1
->ls
, aff2
->ls
);
162 if (equal
< 0 || !equal
)
165 return isl_vec_is_equal(aff1
->v
, aff2
->v
);
168 int isl_aff_get_denominator(__isl_keep isl_aff
*aff
, isl_int
*v
)
172 isl_int_set(*v
, aff
->v
->el
[0]);
176 int isl_aff_get_constant(__isl_keep isl_aff
*aff
, isl_int
*v
)
180 isl_int_set(*v
, aff
->v
->el
[1]);
184 int isl_aff_get_coefficient(__isl_keep isl_aff
*aff
,
185 enum isl_dim_type type
, int pos
, isl_int
*v
)
190 if (pos
>= isl_local_space_dim(aff
->ls
, type
))
191 isl_die(aff
->v
->ctx
, isl_error_invalid
,
192 "position out of bounds", return -1);
194 pos
+= isl_local_space_offset(aff
->ls
, type
);
195 isl_int_set(*v
, aff
->v
->el
[1 + pos
]);
200 __isl_give isl_aff
*isl_aff_set_denominator(__isl_take isl_aff
*aff
, isl_int v
)
202 aff
= isl_aff_cow(aff
);
206 aff
->v
= isl_vec_cow(aff
->v
);
208 return isl_aff_free(aff
);
210 isl_int_set(aff
->v
->el
[0], v
);
215 __isl_give isl_aff
*isl_aff_set_constant(__isl_take isl_aff
*aff
, isl_int v
)
217 aff
= isl_aff_cow(aff
);
221 aff
->v
= isl_vec_cow(aff
->v
);
223 return isl_aff_free(aff
);
225 isl_int_set(aff
->v
->el
[1], v
);
230 __isl_give isl_aff
*isl_aff_add_constant(__isl_take isl_aff
*aff
, isl_int v
)
232 if (isl_int_is_zero(v
))
235 aff
= isl_aff_cow(aff
);
239 aff
->v
= isl_vec_cow(aff
->v
);
241 return isl_aff_free(aff
);
243 isl_int_addmul(aff
->v
->el
[1], aff
->v
->el
[0], v
);
248 __isl_give isl_aff
*isl_aff_add_constant_si(__isl_take isl_aff
*aff
, int v
)
253 isl_int_set_si(t
, v
);
254 aff
= isl_aff_add_constant(aff
, t
);
260 __isl_give isl_aff
*isl_aff_set_constant_si(__isl_take isl_aff
*aff
, int v
)
262 aff
= isl_aff_cow(aff
);
266 aff
->v
= isl_vec_cow(aff
->v
);
268 return isl_aff_free(aff
);
270 isl_int_set_si(aff
->v
->el
[1], v
);
275 __isl_give isl_aff
*isl_aff_set_coefficient(__isl_take isl_aff
*aff
,
276 enum isl_dim_type type
, int pos
, isl_int v
)
281 if (pos
>= isl_local_space_dim(aff
->ls
, type
))
282 isl_die(aff
->v
->ctx
, isl_error_invalid
,
283 "position out of bounds", return isl_aff_free(aff
));
285 aff
= isl_aff_cow(aff
);
289 aff
->v
= isl_vec_cow(aff
->v
);
291 return isl_aff_free(aff
);
293 pos
+= isl_local_space_offset(aff
->ls
, type
);
294 isl_int_set(aff
->v
->el
[1 + pos
], v
);
299 __isl_give isl_aff
*isl_aff_set_coefficient_si(__isl_take isl_aff
*aff
,
300 enum isl_dim_type type
, int pos
, int v
)
305 if (pos
>= isl_local_space_dim(aff
->ls
, type
))
306 isl_die(aff
->v
->ctx
, isl_error_invalid
,
307 "position out of bounds", return isl_aff_free(aff
));
309 aff
= isl_aff_cow(aff
);
313 aff
->v
= isl_vec_cow(aff
->v
);
315 return isl_aff_free(aff
);
317 pos
+= isl_local_space_offset(aff
->ls
, type
);
318 isl_int_set_si(aff
->v
->el
[1 + pos
], v
);
323 __isl_give isl_aff
*isl_aff_add_coefficient(__isl_take isl_aff
*aff
,
324 enum isl_dim_type type
, int pos
, isl_int v
)
329 if (pos
>= isl_local_space_dim(aff
->ls
, type
))
330 isl_die(aff
->v
->ctx
, isl_error_invalid
,
331 "position out of bounds", return isl_aff_free(aff
));
333 aff
= isl_aff_cow(aff
);
337 aff
->v
= isl_vec_cow(aff
->v
);
339 return isl_aff_free(aff
);
341 pos
+= isl_local_space_offset(aff
->ls
, type
);
342 isl_int_addmul(aff
->v
->el
[1 + pos
], aff
->v
->el
[0], v
);
347 __isl_give isl_aff
*isl_aff_add_coefficient_si(__isl_take isl_aff
*aff
,
348 enum isl_dim_type type
, int pos
, int v
)
353 isl_int_set_si(t
, v
);
354 aff
= isl_aff_add_coefficient(aff
, type
, pos
, t
);
360 __isl_give isl_div
*isl_aff_get_div(__isl_keep isl_aff
*aff
, int pos
)
365 return isl_local_space_get_div(aff
->ls
, pos
);
368 __isl_give isl_aff
*isl_aff_neg(__isl_take isl_aff
*aff
)
370 aff
= isl_aff_cow(aff
);
373 aff
->v
= isl_vec_cow(aff
->v
);
375 return isl_aff_free(aff
);
377 isl_seq_neg(aff
->v
->el
+ 1, aff
->v
->el
+ 1, aff
->v
->size
- 1);
382 /* Given f, return floor(f).
383 * If f is an integer expression, then just return f.
384 * Otherwise, create a new div d = [f] and return the expression d.
386 __isl_give isl_aff
*isl_aff_floor(__isl_take isl_aff
*aff
)
394 if (isl_int_is_one(aff
->v
->el
[0]))
397 aff
= isl_aff_cow(aff
);
401 aff
->ls
= isl_local_space_add_div(aff
->ls
, isl_vec_copy(aff
->v
));
403 return isl_aff_free(aff
);
405 ctx
= isl_aff_get_ctx(aff
);
407 isl_vec_free(aff
->v
);
408 aff
->v
= isl_vec_alloc(ctx
, size
+ 1);
409 aff
->v
= isl_vec_clr(aff
->v
);
411 return isl_aff_free(aff
);
412 isl_int_set_si(aff
->v
->el
[0], 1);
413 isl_int_set_si(aff
->v
->el
[size
], 1);
418 /* Given f, return ceil(f).
419 * If f is an integer expression, then just return f.
420 * Otherwise, create a new div d = [-f] and return the expression -d.
422 __isl_give isl_aff
*isl_aff_ceil(__isl_take isl_aff
*aff
)
427 if (isl_int_is_one(aff
->v
->el
[0]))
430 aff
= isl_aff_neg(aff
);
431 aff
= isl_aff_floor(aff
);
432 aff
= isl_aff_neg(aff
);
437 /* Apply the expansion computed by isl_merge_divs.
438 * The expansion itself is given by "exp" while the resulting
439 * list of divs is given by "div".
441 __isl_give isl_aff
*isl_aff_expand_divs( __isl_take isl_aff
*aff
,
442 __isl_take isl_mat
*div
, int *exp
)
449 aff
= isl_aff_cow(aff
);
453 old_n_div
= isl_local_space_dim(aff
->ls
, isl_dim_div
);
454 new_n_div
= isl_mat_rows(div
);
455 if (new_n_div
< old_n_div
)
456 isl_die(isl_mat_get_ctx(div
), isl_error_invalid
,
457 "not an expansion", goto error
);
459 aff
->v
= isl_vec_extend(aff
->v
, aff
->v
->size
+ new_n_div
- old_n_div
);
463 offset
= 1 + isl_local_space_offset(aff
->ls
, isl_dim_div
);
465 for (i
= new_n_div
- 1; i
>= 0; --i
) {
466 if (j
>= 0 && exp
[j
] == i
) {
468 isl_int_swap(aff
->v
->el
[offset
+ i
],
469 aff
->v
->el
[offset
+ j
]);
472 isl_int_set_si(aff
->v
->el
[offset
+ i
], 0);
475 aff
->ls
= isl_local_space_replace_divs(aff
->ls
, isl_mat_copy(div
));
486 /* Add two affine expressions that live in the same local space.
488 static __isl_give isl_aff
*add_expanded(__isl_take isl_aff
*aff1
,
489 __isl_take isl_aff
*aff2
)
493 aff1
= isl_aff_cow(aff1
);
497 aff1
->v
= isl_vec_cow(aff1
->v
);
503 isl_int_gcd(gcd
, aff1
->v
->el
[0], aff2
->v
->el
[0]);
504 isl_int_divexact(f
, aff2
->v
->el
[0], gcd
);
505 isl_seq_scale(aff1
->v
->el
+ 1, aff1
->v
->el
+ 1, f
, aff1
->v
->size
- 1);
506 isl_int_divexact(f
, aff1
->v
->el
[0], gcd
);
507 isl_seq_addmul(aff1
->v
->el
+ 1, f
, aff2
->v
->el
+ 1, aff1
->v
->size
- 1);
508 isl_int_divexact(f
, aff2
->v
->el
[0], gcd
);
509 isl_int_mul(aff1
->v
->el
[0], aff1
->v
->el
[0], f
);
521 __isl_give isl_aff
*isl_aff_add(__isl_take isl_aff
*aff1
,
522 __isl_take isl_aff
*aff2
)
532 ctx
= isl_aff_get_ctx(aff1
);
533 if (!isl_dim_equal(aff1
->ls
->dim
, aff2
->ls
->dim
))
534 isl_die(ctx
, isl_error_invalid
,
535 "spaces don't match", goto error
);
537 if (aff1
->ls
->div
->n_row
== 0 && aff2
->ls
->div
->n_row
== 0)
538 return add_expanded(aff1
, aff2
);
540 exp1
= isl_alloc_array(ctx
, int, aff1
->ls
->div
->n_row
);
541 exp2
= isl_alloc_array(ctx
, int, aff2
->ls
->div
->n_row
);
545 div
= isl_merge_divs(aff1
->ls
->div
, aff2
->ls
->div
, exp1
, exp2
);
546 aff1
= isl_aff_expand_divs(aff1
, isl_mat_copy(div
), exp1
);
547 aff2
= isl_aff_expand_divs(aff2
, div
, exp2
);
551 return add_expanded(aff1
, aff2
);
560 __isl_give isl_aff
*isl_aff_sub(__isl_take isl_aff
*aff1
,
561 __isl_take isl_aff
*aff2
)
563 return isl_aff_add(aff1
, isl_aff_neg(aff2
));
566 __isl_give isl_aff
*isl_aff_scale(__isl_take isl_aff
*aff
, isl_int f
)
570 if (isl_int_is_one(f
))
573 aff
= isl_aff_cow(aff
);
576 aff
->v
= isl_vec_cow(aff
->v
);
578 return isl_aff_free(aff
);
581 isl_int_gcd(gcd
, aff
->v
->el
[0], f
);
582 isl_int_divexact(aff
->v
->el
[0], aff
->v
->el
[0], gcd
);
583 isl_int_divexact(gcd
, f
, gcd
);
584 isl_seq_scale(aff
->v
->el
+ 1, aff
->v
->el
+ 1, gcd
, aff
->v
->size
- 1);
590 __isl_give isl_aff
*isl_aff_scale_down(__isl_take isl_aff
*aff
, isl_int f
)
594 if (isl_int_is_one(f
))
597 aff
= isl_aff_cow(aff
);
600 aff
->v
= isl_vec_cow(aff
->v
);
602 return isl_aff_free(aff
);
605 isl_seq_gcd(aff
->v
->el
+ 1, aff
->v
->size
- 1, &gcd
);
606 isl_int_gcd(gcd
, gcd
, f
);
607 isl_seq_scale_down(aff
->v
->el
+ 1, aff
->v
->el
+ 1, gcd
, aff
->v
->size
- 1);
608 isl_int_divexact(gcd
, f
, gcd
);
609 isl_int_mul(aff
->v
->el
[0], aff
->v
->el
[0], gcd
);
615 __isl_give isl_aff
*isl_aff_scale_down_ui(__isl_take isl_aff
*aff
, unsigned f
)
623 isl_int_set_ui(v
, f
);
624 aff
= isl_aff_scale_down(aff
, v
);
630 __isl_give isl_aff
*isl_aff_set_dim_name(__isl_take isl_aff
*aff
,
631 enum isl_dim_type type
, unsigned pos
, const char *s
)
633 aff
= isl_aff_cow(aff
);
636 aff
->ls
= isl_local_space_set_dim_name(aff
->ls
, type
, pos
, s
);
638 return isl_aff_free(aff
);