4 #include "isl_map_private.h"
6 struct isl_mat *isl_mat_alloc(struct isl_ctx *ctx,
7 unsigned n_row, unsigned n_col)
12 mat = isl_alloc_type(ctx, struct isl_mat);
17 mat->block = isl_blk_alloc(ctx, n_row * n_col);
18 if (isl_blk_is_error(mat->block))
20 mat->row = isl_alloc_array(ctx, isl_int *, n_row);
24 for (i = 0; i < n_row; ++i)
25 mat->row[i] = mat->block.data + i * n_col;
34 isl_blk_free(ctx, mat->block);
39 struct isl_mat *isl_mat_extend(struct isl_ctx *ctx, struct isl_mat *mat,
40 unsigned n_row, unsigned n_col)
48 if (mat->n_col >= n_col && mat->n_row >= n_row)
51 if (mat->n_col < n_col) {
52 struct isl_mat *new_mat;
54 new_mat = isl_mat_alloc(ctx, n_row, n_col);
57 for (i = 0; i < mat->n_row; ++i)
58 isl_seq_cpy(new_mat->row[i], mat->row[i], mat->n_col);
59 isl_mat_free(ctx, mat);
63 mat = isl_mat_cow(ctx, mat);
67 assert(mat->ref == 1);
68 old = mat->block.data;
69 mat->block = isl_blk_extend(ctx, mat->block, n_row * mat->n_col);
70 if (isl_blk_is_error(mat->block))
72 mat->row = isl_realloc_array(ctx, mat->row, isl_int *, n_row);
76 for (i = 0; i < mat->n_row; ++i)
77 mat->row[i] = mat->block.data + (mat->row[i] - old);
78 for (i = mat->n_row; i < n_row; ++i)
79 mat->row[i] = mat->block.data + i * mat->n_col;
84 isl_mat_free(ctx, mat);
88 struct isl_mat *isl_mat_sub_alloc(struct isl_ctx *ctx, isl_int **row,
89 unsigned first_row, unsigned n_row, unsigned first_col, unsigned n_col)
94 mat = isl_alloc_type(ctx, struct isl_mat);
97 mat->row = isl_alloc_array(ctx, isl_int *, n_row);
100 for (i = 0; i < n_row; ++i)
101 mat->row[i] = row[first_row+i] + first_col;
105 mat->block = isl_blk_empty();
106 mat->flags = ISL_MAT_BORROWED;
113 void isl_mat_sub_copy(struct isl_ctx *ctx, isl_int **dst, isl_int **src,
114 unsigned n_row, unsigned dst_col, unsigned src_col, unsigned n_col)
118 for (i = 0; i < n_row; ++i)
119 isl_seq_cpy(dst[i]+dst_col, src[i]+src_col, n_col);
122 void isl_mat_sub_neg(struct isl_ctx *ctx, isl_int **dst, isl_int **src,
123 unsigned n_row, unsigned dst_col, unsigned src_col, unsigned n_col)
127 for (i = 0; i < n_row; ++i)
128 isl_seq_neg(dst[i]+dst_col, src[i]+src_col, n_col);
131 struct isl_mat *isl_mat_copy(struct isl_ctx *ctx, struct isl_mat *mat)
140 struct isl_mat *isl_mat_dup(struct isl_ctx *ctx, struct isl_mat *mat)
143 struct isl_mat *mat2;
147 mat2 = isl_mat_alloc(ctx, mat->n_row, mat->n_col);
150 for (i = 0; i < mat->n_row; ++i)
151 isl_seq_cpy(mat2->row[i], mat->row[i], mat->n_col);
155 struct isl_mat *isl_mat_cow(struct isl_ctx *ctx, struct isl_mat *mat)
157 struct isl_mat *mat2;
161 if (mat->ref == 1 && !ISL_F_ISSET(mat, ISL_MAT_BORROWED))
164 mat2 = isl_mat_dup(ctx, mat);
165 isl_mat_free(ctx, mat);
169 void isl_mat_free(struct isl_ctx *ctx, struct isl_mat *mat)
177 if (!ISL_F_ISSET(mat, ISL_MAT_BORROWED))
178 isl_blk_free(ctx, mat->block);
183 struct isl_mat *isl_mat_identity(struct isl_ctx *ctx, unsigned n_row)
188 mat = isl_mat_alloc(ctx, n_row, n_row);
191 for (i = 0; i < n_row; ++i) {
192 isl_seq_clr(mat->row[i], i);
193 isl_int_set_si(mat->row[i][i], 1);
194 isl_seq_clr(mat->row[i]+i+1, n_row-(i+1));
200 struct isl_vec *isl_mat_vec_product(struct isl_ctx *ctx,
201 struct isl_mat *mat, struct isl_vec *vec)
204 struct isl_vec *prod;
209 isl_assert(ctx, mat->n_col == vec->size, goto error);
211 prod = isl_vec_alloc(ctx, mat->n_row);
215 for (i = 0; i < prod->size; ++i)
216 isl_seq_inner_product(mat->row[i], vec->el, vec->size,
217 &prod->block.data[i]);
218 isl_mat_free(ctx, mat);
222 isl_mat_free(ctx, mat);
227 struct isl_mat *isl_mat_aff_direct_sum(struct isl_ctx *ctx,
228 struct isl_mat *left, struct isl_mat *right)
236 isl_assert(ctx, left->n_row == right->n_row, goto error);
237 isl_assert(ctx, left->n_row >= 1, goto error);
238 isl_assert(ctx, left->n_col >= 1, goto error);
239 isl_assert(ctx, right->n_col >= 1, goto error);
241 isl_seq_first_non_zero(left->row[0]+1, left->n_col-1) == -1,
244 isl_seq_first_non_zero(right->row[0]+1, right->n_col-1) == -1,
247 sum = isl_mat_alloc(ctx, left->n_row, left->n_col + right->n_col - 1);
250 isl_int_lcm(sum->row[0][0], left->row[0][0], right->row[0][0]);
251 isl_int_divexact(left->row[0][0], sum->row[0][0], left->row[0][0]);
252 isl_int_divexact(right->row[0][0], sum->row[0][0], right->row[0][0]);
254 isl_seq_clr(sum->row[0]+1, sum->n_col-1);
255 for (i = 1; i < sum->n_row; ++i) {
256 isl_int_mul(sum->row[i][0], left->row[0][0], left->row[i][0]);
257 isl_int_addmul(sum->row[i][0],
258 right->row[0][0], right->row[i][0]);
259 isl_seq_scale(sum->row[i]+1, left->row[i]+1, left->row[0][0],
261 isl_seq_scale(sum->row[i]+left->n_col,
262 right->row[i]+1, right->row[0][0],
266 isl_int_divexact(left->row[0][0], sum->row[0][0], left->row[0][0]);
267 isl_int_divexact(right->row[0][0], sum->row[0][0], right->row[0][0]);
268 isl_mat_free(ctx, left);
269 isl_mat_free(ctx, right);
272 isl_mat_free(ctx, left);
273 isl_mat_free(ctx, right);
277 static void exchange(struct isl_ctx *ctx, struct isl_mat *M, struct isl_mat **U,
278 struct isl_mat **Q, unsigned row, unsigned i, unsigned j)
281 for (r = row; r < M->n_row; ++r)
282 isl_int_swap(M->row[r][i], M->row[r][j]);
284 for (r = 0; r < (*U)->n_row; ++r)
285 isl_int_swap((*U)->row[r][i], (*U)->row[r][j]);
288 isl_mat_swap_rows(ctx, *Q, i, j);
291 static void subtract(struct isl_mat *M, struct isl_mat **U,
292 struct isl_mat **Q, unsigned row, unsigned i, unsigned j, isl_int m)
295 for (r = row; r < M->n_row; ++r)
296 isl_int_submul(M->row[r][j], m, M->row[r][i]);
298 for (r = 0; r < (*U)->n_row; ++r)
299 isl_int_submul((*U)->row[r][j], m, (*U)->row[r][i]);
302 for (r = 0; r < (*Q)->n_col; ++r)
303 isl_int_addmul((*Q)->row[i][r], m, (*Q)->row[j][r]);
307 static void oppose(struct isl_ctx *ctx, struct isl_mat *M, struct isl_mat **U,
308 struct isl_mat **Q, unsigned row, unsigned col)
311 for (r = row; r < M->n_row; ++r)
312 isl_int_neg(M->row[r][col], M->row[r][col]);
314 for (r = 0; r < (*U)->n_row; ++r)
315 isl_int_neg((*U)->row[r][col], (*U)->row[r][col]);
318 isl_seq_neg((*Q)->row[col], (*Q)->row[col], (*Q)->n_col);
321 /* Given matrix M, compute
326 * with U and Q unimodular matrices and H a matrix in column echelon form
327 * such that on each echelon row the entries in the non-echelon column
328 * are non-negative (if neg == 0) or non-positive (if neg == 1)
329 * and stricly smaller (in absolute value) than the entries in the echelon
331 * If U or Q are NULL, then these matrices are not computed.
333 struct isl_mat *isl_mat_left_hermite(struct isl_ctx *ctx,
334 struct isl_mat *M, int neg, struct isl_mat **U, struct isl_mat **Q)
345 M = isl_mat_cow(ctx, M);
349 *U = isl_mat_identity(ctx, M->n_col);
354 *Q = isl_mat_identity(ctx, M->n_col);
361 for (row = 0; row < M->n_row; ++row) {
363 first = isl_seq_abs_min_non_zero(M->row[row]+col, M->n_col-col);
368 exchange(ctx, M, U, Q, row, first, col);
369 if (isl_int_is_neg(M->row[row][col]))
370 oppose(ctx, M, U, Q, row, col);
372 while ((off = isl_seq_first_non_zero(M->row[row]+first,
373 M->n_col-first)) != -1) {
375 isl_int_fdiv_q(c, M->row[row][first], M->row[row][col]);
376 subtract(M, U, Q, row, col, first, c);
377 if (!isl_int_is_zero(M->row[row][first]))
378 exchange(ctx, M, U, Q, row, first, col);
382 for (i = 0; i < col; ++i) {
383 if (isl_int_is_zero(M->row[row][i]))
386 isl_int_cdiv_q(c, M->row[row][i], M->row[row][col]);
388 isl_int_fdiv_q(c, M->row[row][i], M->row[row][col]);
389 if (isl_int_is_zero(c))
391 subtract(M, U, Q, row, col, i, c);
400 isl_mat_free(ctx, *Q);
404 isl_mat_free(ctx, *U);
410 struct isl_mat *isl_mat_right_kernel(struct isl_ctx *ctx, struct isl_mat *mat)
413 struct isl_mat *U = NULL;
416 mat = isl_mat_left_hermite(ctx, mat, 0, &U, NULL);
420 for (i = 0, rank = 0; rank < mat->n_col; ++rank) {
421 while (i < mat->n_row && isl_int_is_zero(mat->row[i][rank]))
426 K = isl_mat_alloc(ctx, U->n_row, U->n_col - rank);
429 isl_mat_sub_copy(ctx, K->row, U->row, U->n_row, 0, rank, U->n_col-rank);
430 isl_mat_free(ctx, mat);
431 isl_mat_free(ctx, U);
434 isl_mat_free(ctx, mat);
435 isl_mat_free(ctx, U);
439 struct isl_mat *isl_mat_lin_to_aff(struct isl_ctx *ctx, struct isl_mat *mat)
442 struct isl_mat *mat2;
446 mat2 = isl_mat_alloc(ctx, 1+mat->n_row, 1+mat->n_col);
449 isl_int_set_si(mat2->row[0][0], 1);
450 isl_seq_clr(mat2->row[0]+1, mat->n_col);
451 for (i = 0; i < mat->n_row; ++i) {
452 isl_int_set_si(mat2->row[1+i][0], 0);
453 isl_seq_cpy(mat2->row[1+i]+1, mat->row[i], mat->n_col);
455 isl_mat_free(ctx, mat);
459 static int row_first_non_zero(isl_int **row, unsigned n_row, unsigned col)
463 for (i = 0; i < n_row; ++i)
464 if (!isl_int_is_zero(row[i][col]))
469 static int row_abs_min_non_zero(isl_int **row, unsigned n_row, unsigned col)
471 int i, min = row_first_non_zero(row, n_row, col);
474 for (i = min + 1; i < n_row; ++i) {
475 if (isl_int_is_zero(row[i][col]))
477 if (isl_int_abs_lt(row[i][col], row[min][col]))
483 static void inv_exchange(struct isl_ctx *ctx,
484 struct isl_mat *left, struct isl_mat *right,
485 unsigned i, unsigned j)
487 left = isl_mat_swap_rows(ctx, left, i, j);
488 right = isl_mat_swap_rows(ctx, right, i, j);
491 static void inv_oppose(struct isl_ctx *ctx,
492 struct isl_mat *left, struct isl_mat *right, unsigned row)
494 isl_seq_neg(left->row[row]+row, left->row[row]+row, left->n_col-row);
495 isl_seq_neg(right->row[row], right->row[row], right->n_col);
498 static void inv_subtract(struct isl_ctx *ctx,
499 struct isl_mat *left, struct isl_mat *right,
500 unsigned row, unsigned i, isl_int m)
503 isl_seq_combine(left->row[i]+row,
504 ctx->one, left->row[i]+row,
505 m, left->row[row]+row,
507 isl_seq_combine(right->row[i], ctx->one, right->row[i],
508 m, right->row[row], right->n_col);
511 /* Compute inv(left)*right
513 struct isl_mat *isl_mat_inverse_product(struct isl_ctx *ctx,
514 struct isl_mat *left, struct isl_mat *right)
522 isl_assert(ctx, left->n_row == left->n_col, goto error);
523 isl_assert(ctx, left->n_row == right->n_row, goto error);
525 if (left->n_row == 0) {
526 isl_mat_free(ctx, left);
530 left = isl_mat_cow(ctx, left);
531 right = isl_mat_cow(ctx, right);
537 for (row = 0; row < left->n_row; ++row) {
538 int pivot, first, i, off;
539 pivot = row_abs_min_non_zero(left->row+row, left->n_row-row, row);
543 isl_assert(ctx, pivot >= 0, goto error);
547 inv_exchange(ctx, left, right, pivot, row);
548 if (isl_int_is_neg(left->row[row][row]))
549 inv_oppose(ctx, left, right, row);
551 while ((off = row_first_non_zero(left->row+first,
552 left->n_row-first, row)) != -1) {
554 isl_int_fdiv_q(a, left->row[first][row],
555 left->row[row][row]);
556 inv_subtract(ctx, left, right, row, first, a);
557 if (!isl_int_is_zero(left->row[first][row]))
558 inv_exchange(ctx, left, right, row, first);
562 for (i = 0; i < row; ++i) {
563 if (isl_int_is_zero(left->row[i][row]))
565 isl_int_gcd(a, left->row[row][row], left->row[i][row]);
566 isl_int_divexact(b, left->row[i][row], a);
567 isl_int_divexact(a, left->row[row][row], a);
569 isl_seq_combine(left->row[i]+row,
571 b, left->row[row]+row,
573 isl_seq_combine(right->row[i], a, right->row[i],
574 b, right->row[row], right->n_col);
579 isl_int_set(a, left->row[0][0]);
580 for (row = 1; row < left->n_row; ++row)
581 isl_int_lcm(a, a, left->row[row][row]);
582 if (isl_int_is_zero(a)){
584 isl_assert(ctx, 0, goto error);
586 for (row = 0; row < left->n_row; ++row) {
587 isl_int_divexact(left->row[row][row], a, left->row[row][row]);
588 if (isl_int_is_one(left->row[row][row]))
590 isl_seq_scale(right->row[row], right->row[row],
591 left->row[row][row], right->n_col);
595 isl_mat_free(ctx, left);
598 isl_mat_free(ctx, left);
599 isl_mat_free(ctx, right);
603 void isl_mat_col_scale(struct isl_mat *mat, unsigned col, isl_int m)
607 for (i = 0; i < mat->n_row; ++i)
608 isl_int_mul(mat->row[i][col], mat->row[i][col], m);
611 void isl_mat_col_combine(struct isl_mat *mat, unsigned dst,
612 isl_int m1, unsigned src1, isl_int m2, unsigned src2)
618 for (i = 0; i < mat->n_row; ++i) {
619 isl_int_mul(tmp, m1, mat->row[i][src1]);
620 isl_int_addmul(tmp, m2, mat->row[i][src2]);
621 isl_int_set(mat->row[i][dst], tmp);
626 struct isl_mat *isl_mat_right_inverse(struct isl_ctx *ctx,
633 mat = isl_mat_cow(ctx, mat);
637 inv = isl_mat_identity(ctx, mat->n_col);
638 inv = isl_mat_cow(ctx, inv);
644 for (row = 0; row < mat->n_row; ++row) {
645 int pivot, first, i, off;
646 pivot = isl_seq_abs_min_non_zero(mat->row[row]+row, mat->n_col-row);
654 exchange(ctx, mat, &inv, NULL, row, pivot, row);
655 if (isl_int_is_neg(mat->row[row][row]))
656 oppose(ctx, mat, &inv, NULL, row, row);
658 while ((off = isl_seq_first_non_zero(mat->row[row]+first,
659 mat->n_col-first)) != -1) {
661 isl_int_fdiv_q(a, mat->row[row][first],
663 subtract(mat, &inv, NULL, row, row, first, a);
664 if (!isl_int_is_zero(mat->row[row][first]))
665 exchange(ctx, mat, &inv, NULL, row, row, first);
669 for (i = 0; i < row; ++i) {
670 if (isl_int_is_zero(mat->row[row][i]))
672 isl_int_gcd(a, mat->row[row][row], mat->row[row][i]);
673 isl_int_divexact(b, mat->row[row][i], a);
674 isl_int_divexact(a, mat->row[row][row], a);
676 isl_mat_col_combine(mat, i, a, i, b, row);
677 isl_mat_col_combine(inv, i, a, i, b, row);
682 isl_int_set(a, mat->row[0][0]);
683 for (row = 1; row < mat->n_row; ++row)
684 isl_int_lcm(a, a, mat->row[row][row]);
685 if (isl_int_is_zero(a)){
689 for (row = 0; row < mat->n_row; ++row) {
690 isl_int_divexact(mat->row[row][row], a, mat->row[row][row]);
691 if (isl_int_is_one(mat->row[row][row]))
693 isl_mat_col_scale(inv, row, mat->row[row][row]);
697 isl_mat_free(ctx, mat);
701 isl_mat_free(ctx, mat);
705 struct isl_mat *isl_mat_transpose(struct isl_ctx *ctx, struct isl_mat *mat)
707 struct isl_mat *transpose = NULL;
710 if (mat->n_col == mat->n_row) {
711 mat = isl_mat_cow(ctx, mat);
714 for (i = 0; i < mat->n_row; ++i)
715 for (j = i + 1; j < mat->n_col; ++j)
716 isl_int_swap(mat->row[i][j], mat->row[j][i]);
719 transpose = isl_mat_alloc(ctx, mat->n_col, mat->n_row);
722 for (i = 0; i < mat->n_row; ++i)
723 for (j = 0; j < mat->n_col; ++j)
724 isl_int_set(transpose->row[j][i], mat->row[i][j]);
725 isl_mat_free(ctx, mat);
728 isl_mat_free(ctx, mat);
732 struct isl_mat *isl_mat_swap_cols(struct isl_ctx *ctx,
733 struct isl_mat *mat, unsigned i, unsigned j)
737 mat = isl_mat_cow(ctx, mat);
740 isl_assert(ctx, i < mat->n_col, goto error);
741 isl_assert(ctx, j < mat->n_col, goto error);
743 for (r = 0; r < mat->n_row; ++r)
744 isl_int_swap(mat->row[r][i], mat->row[r][j]);
747 isl_mat_free(ctx, mat);
751 struct isl_mat *isl_mat_swap_rows(struct isl_ctx *ctx,
752 struct isl_mat *mat, unsigned i, unsigned j)
758 mat = isl_mat_cow(ctx, mat);
762 mat->row[i] = mat->row[j];
767 struct isl_mat *isl_mat_product(struct isl_ctx *ctx,
768 struct isl_mat *left, struct isl_mat *right)
771 struct isl_mat *prod;
775 isl_assert(ctx, left->n_col == right->n_row, goto error);
776 prod = isl_mat_alloc(ctx, left->n_row, right->n_col);
779 if (left->n_col == 0) {
780 for (i = 0; i < prod->n_row; ++i)
781 isl_seq_clr(prod->row[i], prod->n_col);
784 for (i = 0; i < prod->n_row; ++i) {
785 for (j = 0; j < prod->n_col; ++j) {
786 isl_int_mul(prod->row[i][j],
787 left->row[i][0], right->row[0][j]);
788 for (k = 1; k < left->n_col; ++k)
789 isl_int_addmul(prod->row[i][j],
790 left->row[i][k], right->row[k][j]);
793 isl_mat_free(ctx, left);
794 isl_mat_free(ctx, right);
797 isl_mat_free(ctx, left);
798 isl_mat_free(ctx, right);
802 /* Replace the variables x in the rows q by x' given by x = M x',
803 * with M the matrix mat.
805 * If the number of new variables is greater than the original
806 * number of variables, then the rows q have already been
807 * preextended. If the new number is smaller, then the coefficients
808 * of the divs, which are not changed, need to be shifted down.
809 * The row q may be the equalities, the inequalities or the
810 * div expressions. In the latter case, has_div is true and
811 * we need to take into account the extra denominator column.
813 static int preimage(struct isl_ctx *ctx, isl_int **q, unsigned n,
814 unsigned n_div, int has_div, struct isl_mat *mat)
820 if (mat->n_col >= mat->n_row)
823 e = mat->n_row - mat->n_col;
825 for (i = 0; i < n; ++i)
826 isl_int_mul(q[i][0], q[i][0], mat->row[0][0]);
827 t = isl_mat_sub_alloc(ctx, q, 0, n, has_div, mat->n_row);
828 t = isl_mat_product(ctx, t, mat);
831 for (i = 0; i < n; ++i) {
832 isl_seq_swp_or_cpy(q[i] + has_div, t->row[i], t->n_col);
833 isl_seq_cpy(q[i] + has_div + t->n_col,
834 q[i] + has_div + t->n_col + e, n_div);
835 isl_seq_clr(q[i] + has_div + t->n_col + n_div, e);
837 isl_mat_free(ctx, t);
841 /* Replace the variables x in bset by x' given by x = M x', with
844 * If there are fewer variables x' then there are x, then we perform
845 * the transformation in place, which that, in principle,
846 * this frees up some extra variables as the number
847 * of columns remains constant, but we would have to extend
848 * the div array too as the number of rows in this array is assumed
849 * to be equal to extra.
851 struct isl_basic_set *isl_basic_set_preimage(struct isl_basic_set *bset,
860 bset = isl_basic_set_cow(bset);
864 isl_assert(ctx, bset->dim->nparam == 0, goto error);
865 isl_assert(ctx, 1+bset->dim->n_out == mat->n_row, goto error);
867 if (mat->n_col > mat->n_row)
868 bset = isl_basic_set_extend(bset, 0, mat->n_col-1, 0,
870 else if (mat->n_col < mat->n_row) {
871 bset->dim = isl_dim_cow(bset->dim);
874 bset->dim->n_out -= mat->n_row - mat->n_col;
877 if (preimage(ctx, bset->eq, bset->n_eq, bset->n_div, 0,
878 isl_mat_copy(ctx, mat)) < 0)
881 if (preimage(ctx, bset->ineq, bset->n_ineq, bset->n_div, 0,
882 isl_mat_copy(ctx, mat)) < 0)
885 if (preimage(ctx, bset->div, bset->n_div, bset->n_div, 1, mat) < 0)
888 ISL_F_CLR(bset, ISL_BASIC_SET_NO_IMPLICIT);
889 ISL_F_CLR(bset, ISL_BASIC_SET_NO_REDUNDANT);
890 ISL_F_CLR(bset, ISL_BASIC_SET_NORMALIZED);
891 ISL_F_CLR(bset, ISL_BASIC_SET_NORMALIZED_DIVS);
892 ISL_F_CLR(bset, ISL_BASIC_SET_ALL_EQUALITIES);
894 bset = isl_basic_set_simplify(bset);
895 bset = isl_basic_set_finalize(bset);
899 isl_mat_free(ctx, mat);
901 isl_basic_set_free(bset);
905 struct isl_set *isl_set_preimage(struct isl_set *set, struct isl_mat *mat)
910 set = isl_set_cow(set);
915 for (i = 0; i < set->n; ++i) {
916 set->p[i] = isl_basic_set_preimage(set->p[i],
917 isl_mat_copy(ctx, mat));
921 if (mat->n_col != mat->n_row) {
922 set->dim = isl_dim_cow(set->dim);
925 set->dim->n_out += mat->n_col;
926 set->dim->n_out -= mat->n_row;
928 isl_mat_free(ctx, mat);
929 ISL_F_CLR(set, ISL_SET_NORMALIZED);
933 isl_mat_free(ctx, mat);
937 void isl_mat_dump(struct isl_ctx *ctx, struct isl_mat *mat,
938 FILE *out, int indent)
943 fprintf(out, "%*snull mat\n", indent, "");
948 fprintf(out, "%*s[]\n", indent, "");
950 for (i = 0; i < mat->n_row; ++i) {
952 fprintf(out, "%*s[[", indent, "");
954 fprintf(out, "%*s[", indent+1, "");
955 for (j = 0; j < mat->n_col; ++j) {
958 isl_int_print(out, mat->row[i][j], 0);
960 if (i == mat->n_row-1)
961 fprintf(out, "]]\n");
967 struct isl_mat *isl_mat_drop_cols(struct isl_ctx *ctx, struct isl_mat *mat,
968 unsigned col, unsigned n)
972 mat = isl_mat_cow(ctx, mat);
976 if (col != mat->n_col-n) {
977 for (r = 0; r < mat->n_row; ++r)
978 isl_seq_cpy(mat->row[r]+col, mat->row[r]+col+n,
979 mat->n_col - col - n);
985 struct isl_mat *isl_mat_drop_rows(struct isl_ctx *ctx, struct isl_mat *mat,
986 unsigned row, unsigned n)
990 mat = isl_mat_cow(ctx, mat);
994 for (r = row; r+n < mat->n_row; ++r)
995 mat->row[r] = mat->row[r+n];
1001 void isl_mat_col_submul(struct isl_mat *mat,
1002 int dst_col, isl_int f, int src_col)
1006 for (i = 0; i < mat->n_row; ++i)
1007 isl_int_submul(mat->row[i][dst_col], f, mat->row[i][src_col]);
1010 void isl_mat_col_mul(struct isl_mat *mat, int dst_col, isl_int f, int src_col)
1014 for (i = 0; i < mat->n_row; ++i)
1015 isl_int_mul(mat->row[i][dst_col], f, mat->row[i][src_col]);
1018 struct isl_mat *isl_mat_unimodular_complete(struct isl_ctx *ctx,
1019 struct isl_mat *M, int row)
1022 struct isl_mat *H = NULL, *Q = NULL;
1024 isl_assert(ctx, M->n_row == M->n_col, goto error);
1026 H = isl_mat_left_hermite(ctx, isl_mat_copy(ctx, M), 0, NULL, &Q);
1027 M->n_row = M->n_col;
1030 for (r = 0; r < row; ++r)
1031 isl_assert(ctx, isl_int_is_one(H->row[r][r]), goto error);
1032 for (r = row; r < M->n_row; ++r)
1033 isl_seq_cpy(M->row[r], Q->row[r], M->n_col);
1034 isl_mat_free(ctx, H);
1035 isl_mat_free(ctx, Q);
1038 isl_mat_free(ctx, H);
1039 isl_mat_free(ctx, Q);
1040 isl_mat_free(ctx, M);