add isl_aff_add and isl_aff_sub
authorSven Verdoolaege <skimo@kotnet.org>
Thu, 2 Jun 2011 12:11:35 +0000 (14:11 +0200)
committerSven Verdoolaege <skimo@kotnet.org>
Thu, 2 Jun 2011 13:53:01 +0000 (15:53 +0200)
Signed-off-by: Sven Verdoolaege <skimo@kotnet.org>
doc/user.pod
include/isl/aff.h
isl_aff.c

index 1ff5198..9a345c7 100644 (file)
@@ -2120,6 +2120,10 @@ the possibly rational constant or coefficient.
 Operations include
 
        #include <isl/aff.h>
+       __isl_give isl_aff *isl_aff_add(__isl_take isl_aff *aff1,
+               __isl_take isl_aff *aff2);
+       __isl_give isl_aff *isl_aff_sub(__isl_take isl_aff *aff1,
+               __isl_take isl_aff *aff2);
        __isl_give isl_aff *isl_aff_neg(__isl_take isl_aff *aff);
        __isl_give isl_aff *isl_aff_ceil(__isl_take isl_aff *aff);
 
index 1769857..80836eb 100644 (file)
@@ -46,6 +46,11 @@ __isl_give isl_div *isl_aff_get_div(__isl_keep isl_aff *aff, int pos);
 __isl_give isl_aff *isl_aff_neg(__isl_take isl_aff *aff);
 __isl_give isl_aff *isl_aff_ceil(__isl_take isl_aff *aff);
 
+__isl_give isl_aff *isl_aff_add(__isl_take isl_aff *aff1,
+       __isl_take isl_aff *aff2);
+__isl_give isl_aff *isl_aff_sub(__isl_take isl_aff *aff1,
+       __isl_take isl_aff *aff2);
+
 __isl_give isl_printer *isl_printer_print_aff(__isl_take isl_printer *p,
        __isl_keep isl_aff *aff);
 void isl_aff_dump(__isl_keep isl_aff *aff);
index d0a4e75..fe07d4a 100644 (file)
--- a/isl_aff.c
+++ b/isl_aff.c
@@ -10,6 +10,7 @@
 
 #include <isl_aff_private.h>
 #include <isl_local_space_private.h>
+#include <isl_mat_private.h>
 #include <isl/seq.h>
 
 __isl_give isl_aff *isl_aff_alloc_vec(__isl_take isl_local_space *ls,
@@ -432,3 +433,83 @@ error:
        isl_mat_free(div);
        return NULL;
 }
+
+/* Add two affine expressions that live in the same local space.
+ */
+static __isl_give isl_aff *add_expanded(__isl_take isl_aff *aff1,
+       __isl_take isl_aff *aff2)
+{
+       isl_int gcd, f;
+
+       aff1 = isl_aff_cow(aff1);
+       if (!aff1 || !aff2)
+               goto error;
+
+       aff1->v = isl_vec_cow(aff1->v);
+       if (!aff1->v)
+               goto error;
+
+       isl_int_init(gcd);
+       isl_int_init(f);
+       isl_int_gcd(gcd, aff1->v->el[0], aff2->v->el[0]);
+       isl_int_divexact(f, aff2->v->el[0], gcd);
+       isl_seq_scale(aff1->v->el + 1, aff1->v->el + 1, f, aff1->v->size - 1);
+       isl_int_divexact(f, aff1->v->el[0], gcd);
+       isl_seq_addmul(aff1->v->el + 1, f, aff2->v->el + 1, aff1->v->size - 1);
+       isl_int_divexact(f, aff2->v->el[0], gcd);
+       isl_int_mul(aff1->v->el[0], aff1->v->el[0], f);
+       isl_int_clear(f);
+       isl_int_clear(gcd);
+
+       isl_aff_free(aff2);
+       return aff1;
+error:
+       isl_aff_free(aff1);
+       isl_aff_free(aff2);
+       return NULL;
+}
+
+__isl_give isl_aff *isl_aff_add(__isl_take isl_aff *aff1,
+       __isl_take isl_aff *aff2)
+{
+       isl_ctx *ctx;
+       int *exp1 = NULL;
+       int *exp2 = NULL;
+       isl_mat *div;
+
+       if (!aff1 || !aff2)
+               goto error;
+
+       ctx = isl_aff_get_ctx(aff1);
+       if (!isl_dim_equal(aff1->ls->dim, aff2->ls->dim))
+               isl_die(ctx, isl_error_invalid,
+                       "spaces don't match", goto error);
+
+       if (aff1->ls->div->n_row == 0 && aff2->ls->div->n_row == 0)
+               return add_expanded(aff1, aff2);
+
+       exp1 = isl_alloc_array(ctx, int, aff1->ls->div->n_row);
+       exp2 = isl_alloc_array(ctx, int, aff2->ls->div->n_row);
+       if (!exp1 || !exp2)
+               goto error;
+
+       div = isl_merge_divs(aff1->ls->div, aff2->ls->div, exp1, exp2);
+       aff1 = isl_aff_expand_divs(aff1, isl_mat_copy(div), exp1);
+       aff2 = isl_aff_expand_divs(aff2, div, exp2);
+       free(exp1);
+       free(exp2);
+
+       return add_expanded(aff1, aff2);
+error:
+       free(exp1);
+       free(exp2);
+       isl_aff_free(aff1);
+       isl_aff_free(aff2);
+       return NULL;
+}
+
+__isl_give isl_aff *isl_aff_sub(__isl_take isl_aff *aff1,
+       __isl_take isl_aff *aff2)
+{
+       return isl_aff_add(aff1, isl_aff_neg(aff2));
+}