add isl_schedule_node_schedule
[isl.git] / isl_mat.c
index f08a20e..54c52d3 100644 (file)
--- a/isl_mat.c
+++ b/isl_mat.c
@@ -2,7 +2,7 @@
  * Copyright 2008-2009 Katholieke Universiteit Leuven
  * Copyright 2010      INRIA Saclay
  * Copyright 2014      Ecole Normale Superieure
- * Copyright 2017      Sven Verdoolaege
+ * Copyright 2016-2017 Sven Verdoolaege
  *
  * Use of this software is governed by the MIT license
  *
@@ -64,12 +64,14 @@ __isl_give isl_mat *isl_mat_alloc(isl_ctx *ctx,
        mat->block = isl_blk_alloc(ctx, n_row * n_col);
        if (isl_blk_is_error(mat->block))
                goto error;
-       mat->row = isl_alloc_array(ctx, isl_int *, n_row);
+       mat->row = isl_calloc_array(ctx, isl_int *, n_row);
        if (n_row && !mat->row)
                goto error;
 
-       for (i = 0; i < n_row; ++i)
-               mat->row[i] = mat->block.data + i * n_col;
+       if (n_col != 0) {
+               for (i = 0; i < n_row; ++i)
+                       mat->row[i] = mat->block.data + i * n_col;
+       }
 
        mat->ctx = ctx;
        isl_ctx_ref(ctx);
@@ -580,8 +582,8 @@ error:
        return NULL;
 }
 
-static void exchange(struct isl_mat *M, struct isl_mat **U,
-       struct isl_mat **Q, unsigned row, unsigned i, unsigned j)
+static void exchange(__isl_keep isl_mat *M, __isl_keep isl_mat **U,
+       __isl_keep isl_mat **Q, unsigned row, unsigned i, unsigned j)
 {
        int r;
        for (r = row; r < M->n_row; ++r)
@@ -594,8 +596,8 @@ static void exchange(struct isl_mat *M, struct isl_mat **U,
                isl_mat_swap_rows(*Q, i, j);
 }
 
-static void subtract(struct isl_mat *M, struct isl_mat **U,
-       struct isl_mat **Q, unsigned row, unsigned i, unsigned j, isl_int m)
+static void subtract(__isl_keep isl_mat *M, __isl_keep isl_mat **U,
+       __isl_keep isl_mat **Q, unsigned row, unsigned i, unsigned j, isl_int m)
 {
        int r;
        for (r = row; r < M->n_row; ++r)
@@ -610,8 +612,8 @@ static void subtract(struct isl_mat *M, struct isl_mat **U,
        }
 }
 
-static void oppose(struct isl_mat *M, struct isl_mat **U,
-       struct isl_mat **Q, unsigned row, unsigned col)
+static void oppose(__isl_keep isl_mat *M, __isl_keep isl_mat **U,
+       __isl_keep isl_mat **Q, unsigned row, unsigned col)
 {
        int r;
        for (r = row; r < M->n_row; ++r)
@@ -648,9 +650,6 @@ __isl_give isl_mat *isl_mat_left_hermite(__isl_take isl_mat *M, int neg,
                *Q = NULL;
        if (!M)
                goto error;
-       M = isl_mat_cow(M);
-       if (!M)
-               goto error;
        if (U) {
                *U = isl_mat_identity(M->ctx, M->n_col);
                if (!*U)
@@ -662,6 +661,13 @@ __isl_give isl_mat *isl_mat_left_hermite(__isl_take isl_mat *M, int neg,
                        goto error;
        }
 
+       if (M->n_col == 0)
+               return M;
+
+       M = isl_mat_cow(M);
+       if (!M)
+               goto error;
+
        col = 0;
        isl_int_init(c);
        for (row = 0; row < M->n_row; ++row) {
@@ -884,6 +890,18 @@ error:
        return NULL;
 }
 
+/* Return a basis for the orthogonal complement of the space spanned
+ * by the rows of "M".
+ * That is, each of the rows of the result is orthogonal to each
+ * of the rows of "M".
+ *
+ * The complement is derived as the transpose of the right kernel.
+ */
+__isl_give isl_mat *isl_mat_row_complement(__isl_take isl_mat *mat)
+{
+       return isl_mat_transpose(isl_mat_right_kernel(mat));
+}
+
 __isl_give isl_mat *isl_mat_lin_to_aff(__isl_take isl_mat *mat)
 {
        int i;
@@ -979,13 +997,13 @@ static isl_stat inv_exchange(__isl_keep isl_mat **left,
 }
 
 static void inv_oppose(
-       struct isl_mat *left, struct isl_mat *right, unsigned row)
+       __isl_keep isl_mat *left, __isl_keep isl_mat *right, unsigned row)
 {
        isl_seq_neg(left->row[row]+row, left->row[row]+row, left->n_col-row);
        isl_seq_neg(right->row[row], right->row[row], right->n_col);
 }
 
-static void inv_subtract(struct isl_mat *left, struct isl_mat *right,
+static void inv_subtract(__isl_keep isl_mat *left, __isl_keep isl_mat *right,
        unsigned row, unsigned i, isl_int m)
 {
        isl_int_neg(m, m);
@@ -1092,7 +1110,7 @@ error:
        return NULL;
 }
 
-void isl_mat_col_scale(struct isl_mat *mat, unsigned col, isl_int m)
+void isl_mat_col_scale(__isl_keep isl_mat *mat, unsigned col, isl_int m)
 {
        int i;
 
@@ -1100,7 +1118,7 @@ void isl_mat_col_scale(struct isl_mat *mat, unsigned col, isl_int m)
                isl_int_mul(mat->row[i][col], mat->row[i][col], m);
 }
 
-void isl_mat_col_combine(struct isl_mat *mat, unsigned dst,
+void isl_mat_col_combine(__isl_keep isl_mat *mat, unsigned dst,
        isl_int m1, unsigned src1, isl_int m2, unsigned src2)
 {
        int i;
@@ -1639,7 +1657,7 @@ __isl_give isl_mat *isl_mat_add_zero_rows(__isl_take isl_mat *mat, unsigned n)
        return isl_mat_insert_zero_rows(mat, mat->n_row, n);
 }
 
-void isl_mat_col_submul(struct isl_mat *mat,
+void isl_mat_col_submul(__isl_keep isl_mat *mat,
                        int dst_col, isl_int f, int src_col)
 {
        int i;
@@ -1660,7 +1678,8 @@ void isl_mat_col_add(__isl_keep isl_mat *mat, int dst_col, int src_col)
                            mat->row[i][dst_col], mat->row[i][src_col]);
 }
 
-void isl_mat_col_mul(struct isl_mat *mat, int dst_col, isl_int f, int src_col)
+void isl_mat_col_mul(__isl_keep isl_mat *mat, int dst_col, isl_int f,
+       int src_col)
 {
        int i;
 
@@ -1848,6 +1867,25 @@ __isl_give isl_vec *isl_mat_get_row(__isl_keep isl_mat *mat, unsigned row)
        return v;
 }
 
+/* Return a copy of column "col" of "mat" as an isl_vec.
+ */
+__isl_give isl_vec *isl_mat_get_col(__isl_keep isl_mat *mat, unsigned col)
+{
+       int i;
+       isl_vec *v;
+
+       if (check_col_range(mat, col, 1) < 0)
+               return NULL;
+
+       v = isl_vec_alloc(isl_mat_get_ctx(mat), mat->n_row);
+       if (!v)
+               return NULL;
+       for (i = 0; i < mat->n_row; ++i)
+               isl_int_set(v->el[i], mat->row[i][col]);
+
+       return v;
+}
+
 __isl_give isl_mat *isl_mat_vec_concat(__isl_take isl_mat *top,
        __isl_take isl_vec *bot)
 {