X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=isl_mat.c;h=9a8a55823890efc50382ce81185a6996f60b691f;hb=79f39689bc1521ec66cec1add03b45aa71d2a9ea;hp=6f4f889afa575f041ecba668932348d0dea0405b;hpb=0d1dd2cf289c05b28244399a9c4bd981f393332c;p=platform%2Fupstream%2Fisl.git diff --git a/isl_mat.c b/isl_mat.c index 6f4f889..9a8a558 100644 --- a/isl_mat.c +++ b/isl_mat.c @@ -7,10 +7,12 @@ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium */ -#include "isl_dim.h" -#include "isl_seq.h" -#include "isl_mat.h" +#include +#include +#include +#include #include "isl_map_private.h" +#include struct isl_mat *isl_mat_alloc(struct isl_ctx *ctx, unsigned n_row, unsigned n_col) @@ -53,6 +55,7 @@ struct isl_mat *isl_mat_extend(struct isl_mat *mat, { int i; isl_int *old; + isl_int **row; if (!mat) return NULL; @@ -81,14 +84,14 @@ struct isl_mat *isl_mat_extend(struct isl_mat *mat, if (!mat) goto error; - assert(mat->ref == 1); old = mat->block.data; mat->block = isl_blk_extend(mat->ctx, mat->block, n_row * mat->max_col); if (isl_blk_is_error(mat->block)) goto error; - mat->row = isl_realloc_array(mat->ctx, mat->row, isl_int *, n_row); - if (!mat->row) + row = isl_realloc_array(mat->ctx, mat->row, isl_int *, n_row); + if (!row) goto error; + mat->row = row; for (i = 0; i < mat->n_row; ++i) mat->row[i] = mat->block.data + (mat->row[i] - old); @@ -202,6 +205,68 @@ void isl_mat_free(struct isl_mat *mat) free(mat); } +int isl_mat_rows(__isl_keep isl_mat *mat) +{ + return mat ? mat->n_row : -1; +} + +int isl_mat_cols(__isl_keep isl_mat *mat) +{ + return mat ? mat->n_col : -1; +} + +int isl_mat_get_element(__isl_keep isl_mat *mat, int row, int col, isl_int *v) +{ + if (!mat) + return -1; + if (row < 0 || row >= mat->n_row) + isl_die(mat->ctx, isl_error_invalid, "row out of range", + return -1); + if (col < 0 || col >= mat->n_col) + isl_die(mat->ctx, isl_error_invalid, "column out of range", + return -1); + isl_int_set(*v, mat->row[row][col]); + return 0; +} + +__isl_give isl_mat *isl_mat_set_element(__isl_take isl_mat *mat, + int row, int col, isl_int v) +{ + mat = isl_mat_cow(mat); + if (!mat) + return NULL; + if (row < 0 || row >= mat->n_row) + isl_die(mat->ctx, isl_error_invalid, "row out of range", + goto error); + if (col < 0 || col >= mat->n_col) + isl_die(mat->ctx, isl_error_invalid, "column out of range", + goto error); + isl_int_set(mat->row[row][col], v); + return mat; +error: + isl_mat_free(mat); + return NULL; +} + +__isl_give isl_mat *isl_mat_set_element_si(__isl_take isl_mat *mat, + int row, int col, int v) +{ + mat = isl_mat_cow(mat); + if (!mat) + return NULL; + if (row < 0 || row >= mat->n_row) + isl_die(mat->ctx, isl_error_invalid, "row out of range", + goto error); + if (col < 0 || col >= mat->n_col) + isl_die(mat->ctx, isl_error_invalid, "column out of range", + goto error); + isl_int_set_si(mat->row[row][col], v); + return mat; +error: + isl_mat_free(mat); + return NULL; +} + struct isl_mat *isl_mat_identity(struct isl_ctx *ctx, unsigned n_row) { int i; @@ -482,6 +547,7 @@ error: isl_mat_free(*U); *U = NULL; } + isl_mat_free(M); return NULL; } @@ -523,7 +589,7 @@ struct isl_mat *isl_mat_lin_to_aff(struct isl_mat *mat) return NULL; mat2 = isl_mat_alloc(mat->ctx, 1+mat->n_row, 1+mat->n_col); if (!mat2) - return NULL; + goto error; isl_int_set_si(mat2->row[0][0], 1); isl_seq_clr(mat2->row[0]+1, mat->n_col); for (i = 0; i < mat->n_row; ++i) { @@ -532,6 +598,45 @@ struct isl_mat *isl_mat_lin_to_aff(struct isl_mat *mat) } isl_mat_free(mat); return mat2; +error: + isl_mat_free(mat); + return NULL; +} + +/* Given two matrices M1 and M2, return the block matrix + * + * [ M1 0 ] + * [ 0 M2 ] + */ +__isl_give isl_mat *isl_mat_diagonal(__isl_take isl_mat *mat1, + __isl_take isl_mat *mat2) +{ + int i; + isl_mat *mat; + + if (!mat1 || !mat2) + goto error; + + mat = isl_mat_alloc(mat1->ctx, mat1->n_row + mat2->n_row, + mat1->n_col + mat2->n_col); + if (!mat) + goto error; + for (i = 0; i < mat1->n_row; ++i) { + isl_seq_cpy(mat->row[i], mat1->row[i], mat1->n_col); + isl_seq_clr(mat->row[i] + mat1->n_col, mat2->n_col); + } + for (i = 0; i < mat2->n_row; ++i) { + isl_seq_clr(mat->row[mat1->n_row + i], mat1->n_col); + isl_seq_cpy(mat->row[mat1->n_row + i] + mat1->n_col, + mat2->row[i], mat2->n_col); + } + isl_mat_free(mat1); + isl_mat_free(mat2); + return mat; +error: + isl_mat_free(mat1); + isl_mat_free(mat2); + return NULL; } static int row_first_non_zero(isl_int **row, unsigned n_row, unsigned col) @@ -774,6 +879,7 @@ struct isl_mat *isl_mat_right_inverse(struct isl_mat *mat) return inv; error: isl_mat_free(mat); + isl_mat_free(inv); return NULL; } @@ -851,6 +957,8 @@ struct isl_mat *isl_mat_product(struct isl_mat *left, struct isl_mat *right) if (left->n_col == 0) { for (i = 0; i < prod->n_row; ++i) isl_seq_clr(prod->row[i], prod->n_col); + isl_mat_free(left); + isl_mat_free(right); return prod; } for (i = 0; i < prod->n_row; ++i) { @@ -937,10 +1045,11 @@ struct isl_basic_set *isl_basic_set_preimage(struct isl_basic_set *bset, isl_assert(ctx, 1+bset->dim->n_out == mat->n_row, goto error); isl_assert(ctx, mat->n_col > 0, goto error); - if (mat->n_col > mat->n_row) - bset = isl_basic_set_extend(bset, 0, mat->n_col-1, 0, - 0, 0); - else if (mat->n_col < mat->n_row) { + if (mat->n_col > mat->n_row) { + bset = isl_basic_set_extend(bset, 0, mat->n_col-1, 0, 0, 0); + if (!bset) + goto error; + } else if (mat->n_col < mat->n_row) { bset->dim = isl_dim_cow(bset->dim); if (!bset->dim) goto error; @@ -1093,6 +1202,64 @@ error: return NULL; } +__isl_give isl_mat *isl_mat_insert_zero_cols(__isl_take isl_mat *mat, + unsigned first, unsigned n) +{ + int i; + + if (!mat) + return NULL; + mat = isl_mat_insert_cols(mat, first, n); + if (!mat) + return NULL; + + for (i = 0; i < mat->n_row; ++i) + isl_seq_clr(mat->row[i] + first, n); + + return mat; +} + +__isl_give isl_mat *isl_mat_add_zero_cols(__isl_take isl_mat *mat, unsigned n) +{ + if (!mat) + return NULL; + + return isl_mat_insert_zero_cols(mat, mat->n_col, n); +} + +__isl_give isl_mat *isl_mat_insert_rows(__isl_take isl_mat *mat, + unsigned row, unsigned n) +{ + isl_mat *ext; + + if (!mat) + return NULL; + if (n == 0) + return mat; + + ext = isl_mat_alloc(mat->ctx, mat->n_row + n, mat->n_col); + if (!ext) + goto error; + + isl_mat_sub_copy(mat->ctx, ext->row, mat->row, row, 0, 0, mat->n_col); + isl_mat_sub_copy(mat->ctx, ext->row + row + n, mat->row + row, + mat->n_row - row, 0, 0, mat->n_col); + + isl_mat_free(mat); + return ext; +error: + isl_mat_free(mat); + return NULL; +} + +__isl_give isl_mat *isl_mat_add_rows(__isl_take isl_mat *mat, unsigned n) +{ + if (!mat) + return NULL; + + return isl_mat_insert_rows(mat, mat->n_row, n); +} + void isl_mat_col_submul(struct isl_mat *mat, int dst_col, isl_int f, int src_col) { @@ -1102,6 +1269,18 @@ void isl_mat_col_submul(struct isl_mat *mat, isl_int_submul(mat->row[i][dst_col], f, mat->row[i][src_col]); } +void isl_mat_col_add(__isl_keep isl_mat *mat, int dst_col, int src_col) +{ + int i; + + if (!mat) + return; + + for (i = 0; i < mat->n_row; ++i) + isl_int_add(mat->row[i][dst_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) { int i; @@ -1259,3 +1438,64 @@ error: isl_mat_free(mat); return NULL; } + +void isl_mat_gcd(__isl_keep isl_mat *mat, isl_int *gcd) +{ + int i; + isl_int g; + + isl_int_set_si(*gcd, 0); + if (!mat) + return; + + isl_int_init(g); + for (i = 0; i < mat->n_row; ++i) { + isl_seq_gcd(mat->row[i], mat->n_col, &g); + isl_int_gcd(*gcd, *gcd, g); + } + isl_int_clear(g); +} + +__isl_give isl_mat *isl_mat_scale_down(__isl_take isl_mat *mat, isl_int m) +{ + int i; + + if (!mat) + return NULL; + + for (i = 0; i < mat->n_row; ++i) + isl_seq_scale_down(mat->row[i], mat->row[i], m, mat->n_col); + + return mat; +} + +__isl_give isl_mat *isl_mat_normalize(__isl_take isl_mat *mat) +{ + isl_int gcd; + + if (!mat) + return NULL; + + isl_int_init(gcd); + isl_mat_gcd(mat, &gcd); + mat = isl_mat_scale_down(mat, gcd); + isl_int_clear(gcd); + + return mat; +} + +/* Number of initial non-zero columns. + */ +int isl_mat_initial_non_zero_cols(__isl_keep isl_mat *mat) +{ + int i; + + if (!mat) + return -1; + + for (i = 0; i < mat->n_col; ++i) + if (row_first_non_zero(mat->row, mat->n_row, i) < 0) + break; + + return i; +}