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)
47 if (mat->n_col >= n_col && mat->n_row >= n_row)
50 if (mat->n_col < n_col) {
51 struct isl_mat *new_mat;
53 new_mat = isl_mat_alloc(ctx, n_row, n_col);
56 for (i = 0; i < mat->n_row; ++i)
57 isl_seq_cpy(new_mat->row[i], mat->row[i], mat->n_col);
58 isl_mat_free(ctx, mat);
62 mat = isl_mat_cow(ctx, mat);
66 assert(mat->ref == 1);
67 mat->block = isl_blk_extend(ctx, mat->block, n_row * mat->n_col);
68 if (isl_blk_is_error(mat->block))
70 mat->row = isl_realloc_array(ctx, mat->row, isl_int *, n_row);
74 for (i = 0; i < n_row; ++i)
75 mat->row[i] = mat->block.data + i * mat->n_col;
80 isl_mat_free(ctx, mat);
84 struct isl_mat *isl_mat_sub_alloc(struct isl_ctx *ctx, isl_int **row,
85 unsigned first_row, unsigned n_row, unsigned first_col, unsigned n_col)
90 mat = isl_alloc_type(ctx, struct isl_mat);
93 mat->row = isl_alloc_array(ctx, isl_int *, n_row);
96 for (i = 0; i < n_row; ++i)
97 mat->row[i] = row[first_row+i] + first_col;
101 mat->block = isl_blk_empty();
102 mat->flags = ISL_MAT_BORROWED;
109 void isl_mat_sub_copy(struct isl_ctx *ctx, isl_int **dst, isl_int **src,
110 unsigned n_row, unsigned dst_col, unsigned src_col, unsigned n_col)
114 for (i = 0; i < n_row; ++i)
115 isl_seq_cpy(dst[i]+dst_col, src[i]+src_col, n_col);
118 void isl_mat_sub_neg(struct isl_ctx *ctx, isl_int **dst, isl_int **src,
119 unsigned n_row, unsigned dst_col, unsigned src_col, unsigned n_col)
123 for (i = 0; i < n_row; ++i)
124 isl_seq_neg(dst[i]+dst_col, src[i]+src_col, n_col);
127 struct isl_mat *isl_mat_copy(struct isl_ctx *ctx, struct isl_mat *mat)
136 struct isl_mat *isl_mat_dup(struct isl_ctx *ctx, struct isl_mat *mat)
139 struct isl_mat *mat2;
143 mat2 = isl_mat_alloc(ctx, mat->n_row, mat->n_col);
146 for (i = 0; i < mat->n_row; ++i)
147 isl_seq_cpy(mat2->row[i], mat->row[i], mat->n_col);
151 struct isl_mat *isl_mat_cow(struct isl_ctx *ctx, struct isl_mat *mat)
153 struct isl_mat *mat2;
157 if (mat->ref == 1 && !ISL_F_ISSET(mat, ISL_MAT_BORROWED))
160 mat2 = isl_mat_dup(ctx, mat);
161 isl_mat_free(ctx, mat);
165 void isl_mat_free(struct isl_ctx *ctx, struct isl_mat *mat)
173 if (!ISL_F_ISSET(mat, ISL_MAT_BORROWED))
174 isl_blk_free(ctx, mat->block);
179 struct isl_mat *isl_mat_identity(struct isl_ctx *ctx, unsigned n_row)
184 mat = isl_mat_alloc(ctx, n_row, n_row);
187 for (i = 0; i < n_row; ++i) {
188 isl_seq_clr(mat->row[i], i);
189 isl_int_set_si(mat->row[i][i], 1);
190 isl_seq_clr(mat->row[i]+i+1, n_row-(i+1));
196 struct isl_vec *isl_mat_vec_product(struct isl_ctx *ctx,
197 struct isl_mat *mat, struct isl_vec *vec)
200 struct isl_vec *prod;
205 isl_assert(ctx, mat->n_col == vec->size, goto error);
207 prod = isl_vec_alloc(ctx, mat->n_row);
211 for (i = 0; i < prod->size; ++i)
212 isl_seq_inner_product(mat->row[i], vec->block.data, vec->size,
213 &prod->block.data[i]);
214 isl_mat_free(ctx, mat);
215 isl_vec_free(ctx, vec);
218 isl_mat_free(ctx, mat);
219 isl_vec_free(ctx, vec);
223 struct isl_mat *isl_mat_aff_direct_sum(struct isl_ctx *ctx,
224 struct isl_mat *left, struct isl_mat *right)
232 isl_assert(ctx, left->n_row == right->n_row, goto error);
233 isl_assert(ctx, left->n_row >= 1, goto error);
234 isl_assert(ctx, left->n_col >= 1, goto error);
235 isl_assert(ctx, right->n_col >= 1, goto error);
237 isl_seq_first_non_zero(left->row[0]+1, left->n_col-1) == -1,
240 isl_seq_first_non_zero(right->row[0]+1, right->n_col-1) == -1,
243 sum = isl_mat_alloc(ctx, left->n_row, left->n_col + right->n_col - 1);
246 isl_int_lcm(sum->row[0][0], left->row[0][0], right->row[0][0]);
247 isl_int_divexact(left->row[0][0], sum->row[0][0], left->row[0][0]);
248 isl_int_divexact(right->row[0][0], sum->row[0][0], right->row[0][0]);
250 isl_seq_clr(sum->row[0]+1, sum->n_col-1);
251 for (i = 1; i < sum->n_row; ++i) {
252 isl_int_mul(sum->row[i][0], left->row[0][0], left->row[i][0]);
253 isl_int_addmul(sum->row[i][0],
254 right->row[0][0], right->row[i][0]);
255 isl_seq_scale(sum->row[i]+1, left->row[i]+1, left->row[0][0],
257 isl_seq_scale(sum->row[i]+left->n_col,
258 right->row[i]+1, right->row[0][0],
262 isl_int_divexact(left->row[0][0], sum->row[0][0], left->row[0][0]);
263 isl_int_divexact(right->row[0][0], sum->row[0][0], right->row[0][0]);
264 isl_mat_free(ctx, left);
265 isl_mat_free(ctx, right);
268 isl_mat_free(ctx, left);
269 isl_mat_free(ctx, right);
273 static void exchange(struct isl_ctx *ctx, struct isl_mat *M, struct isl_mat **U,
274 struct isl_mat **Q, unsigned row, unsigned i, unsigned j)
277 for (r = row; r < M->n_row; ++r)
278 isl_int_swap(M->row[r][i], M->row[r][j]);
280 for (r = 0; r < (*U)->n_row; ++r)
281 isl_int_swap((*U)->row[r][i], (*U)->row[r][j]);
284 isl_mat_swap_rows(ctx, *Q, i, j);
287 static void subtract(struct isl_mat *M, struct isl_mat **U,
288 struct isl_mat **Q, unsigned row, unsigned i, unsigned j, isl_int m)
291 for (r = row; r < M->n_row; ++r)
292 isl_int_submul(M->row[r][j], m, M->row[r][i]);
294 for (r = 0; r < (*U)->n_row; ++r)
295 isl_int_submul((*U)->row[r][j], m, (*U)->row[r][i]);
298 for (r = 0; r < (*Q)->n_col; ++r)
299 isl_int_addmul((*Q)->row[i][r], m, (*Q)->row[j][r]);
303 static void oppose(struct isl_ctx *ctx, struct isl_mat *M, struct isl_mat **U,
304 struct isl_mat **Q, unsigned row, unsigned col)
307 for (r = row; r < M->n_row; ++r)
308 isl_int_neg(M->row[r][col], M->row[r][col]);
310 for (r = 0; r < (*U)->n_row; ++r)
311 isl_int_neg((*U)->row[r][col], (*U)->row[r][col]);
314 isl_seq_neg((*Q)->row[col], (*Q)->row[col], (*Q)->n_col);
317 /* Given matrix M, compute
322 * with U and Q unimodular matrices and H a matrix in column echelon form
323 * such that on each echelon row the entries in the non-echelon column
324 * are non-negative (if neg == 0) or non-positive (if neg == 1)
325 * and stricly smaller (in absolute value) than the entries in the echelon
327 * If U or Q are NULL, then these matrices are not computed.
329 struct isl_mat *isl_mat_left_hermite(struct isl_ctx *ctx,
330 struct isl_mat *M, int neg, struct isl_mat **U, struct isl_mat **Q)
341 M = isl_mat_cow(ctx, M);
345 *U = isl_mat_identity(ctx, M->n_col);
350 *Q = isl_mat_identity(ctx, M->n_col);
357 for (row = 0; row < M->n_row; ++row) {
359 first = isl_seq_abs_min_non_zero(M->row[row]+col, M->n_col-col);
364 exchange(ctx, M, U, Q, row, first, col);
365 if (isl_int_is_neg(M->row[row][col]))
366 oppose(ctx, M, U, Q, row, col);
368 while ((off = isl_seq_first_non_zero(M->row[row]+first,
369 M->n_col-first)) != -1) {
371 isl_int_fdiv_q(c, M->row[row][first], M->row[row][col]);
372 subtract(M, U, Q, row, col, first, c);
373 if (!isl_int_is_zero(M->row[row][first]))
374 exchange(ctx, M, U, Q, row, first, col);
378 for (i = 0; i < col; ++i) {
379 if (isl_int_is_zero(M->row[row][i]))
382 isl_int_cdiv_q(c, M->row[row][i], M->row[row][col]);
384 isl_int_fdiv_q(c, M->row[row][i], M->row[row][col]);
385 if (isl_int_is_zero(c))
387 subtract(M, U, Q, row, col, i, c);
396 isl_mat_free(ctx, *Q);
400 isl_mat_free(ctx, *U);
406 struct isl_mat *isl_mat_right_kernel(struct isl_ctx *ctx, struct isl_mat *mat)
409 struct isl_mat *U = NULL;
412 mat = isl_mat_left_hermite(ctx, mat, 0, &U, NULL);
416 for (i = 0, rank = 0; rank < mat->n_col; ++rank) {
417 while (i < mat->n_row && isl_int_is_zero(mat->row[i][rank]))
422 K = isl_mat_alloc(ctx, U->n_row, U->n_col - rank);
425 isl_mat_sub_copy(ctx, K->row, U->row, U->n_row, 0, rank, U->n_col-rank);
426 isl_mat_free(ctx, mat);
427 isl_mat_free(ctx, U);
430 isl_mat_free(ctx, mat);
431 isl_mat_free(ctx, U);
435 struct isl_mat *isl_mat_lin_to_aff(struct isl_ctx *ctx, struct isl_mat *mat)
438 struct isl_mat *mat2;
442 mat2 = isl_mat_alloc(ctx, 1+mat->n_row, 1+mat->n_col);
445 isl_int_set_si(mat2->row[0][0], 1);
446 isl_seq_clr(mat2->row[0]+1, mat->n_col);
447 for (i = 0; i < mat->n_row; ++i) {
448 isl_int_set_si(mat2->row[1+i][0], 0);
449 isl_seq_cpy(mat2->row[1+i]+1, mat->row[i], mat->n_col);
451 isl_mat_free(ctx, mat);
455 static int row_first_non_zero(isl_int **row, unsigned n_row, unsigned col)
459 for (i = 0; i < n_row; ++i)
460 if (!isl_int_is_zero(row[i][col]))
465 static int row_abs_min_non_zero(isl_int **row, unsigned n_row, unsigned col)
467 int i, min = row_first_non_zero(row, n_row, col);
470 for (i = min + 1; i < n_row; ++i) {
471 if (isl_int_is_zero(row[i][col]))
473 if (isl_int_abs_lt(row[i][col], row[min][col]))
479 static void inv_exchange(struct isl_ctx *ctx,
480 struct isl_mat *left, struct isl_mat *right,
481 unsigned i, unsigned j)
483 left = isl_mat_swap_rows(ctx, left, i, j);
484 right = isl_mat_swap_rows(ctx, right, i, j);
487 static void inv_oppose(struct isl_ctx *ctx,
488 struct isl_mat *left, struct isl_mat *right, unsigned row)
490 isl_seq_neg(left->row[row]+row, left->row[row]+row, left->n_col-row);
491 isl_seq_neg(right->row[row], right->row[row], right->n_col);
494 static void inv_subtract(struct isl_ctx *ctx,
495 struct isl_mat *left, struct isl_mat *right,
496 unsigned row, unsigned i, isl_int m)
499 isl_seq_combine(left->row[i]+row,
500 ctx->one, left->row[i]+row,
501 m, left->row[row]+row,
503 isl_seq_combine(right->row[i], ctx->one, right->row[i],
504 m, right->row[row], right->n_col);
507 /* Compute inv(left)*right
509 struct isl_mat *isl_mat_inverse_product(struct isl_ctx *ctx,
510 struct isl_mat *left, struct isl_mat *right)
518 isl_assert(ctx, left->n_row == left->n_col, goto error);
519 isl_assert(ctx, left->n_row == right->n_row, goto error);
521 if (left->n_row == 0) {
522 isl_mat_free(ctx, left);
526 left = isl_mat_cow(ctx, left);
527 right = isl_mat_cow(ctx, right);
533 for (row = 0; row < left->n_row; ++row) {
534 int pivot, first, i, off;
535 pivot = row_abs_min_non_zero(left->row+row, left->n_row-row, row);
539 isl_assert(ctx, pivot >= 0, goto error);
543 inv_exchange(ctx, left, right, pivot, row);
544 if (isl_int_is_neg(left->row[row][row]))
545 inv_oppose(ctx, left, right, row);
547 while ((off = row_first_non_zero(left->row+first,
548 left->n_row-first, row)) != -1) {
550 isl_int_fdiv_q(a, left->row[first][row],
551 left->row[row][row]);
552 inv_subtract(ctx, left, right, row, first, a);
553 if (!isl_int_is_zero(left->row[first][row]))
554 inv_exchange(ctx, left, right, row, first);
558 for (i = 0; i < row; ++i) {
559 if (isl_int_is_zero(left->row[i][row]))
561 isl_int_gcd(a, left->row[row][row], left->row[i][row]);
562 isl_int_divexact(b, left->row[i][row], a);
563 isl_int_divexact(a, left->row[row][row], a);
565 isl_seq_combine(left->row[i]+row,
567 b, left->row[row]+row,
569 isl_seq_combine(right->row[i], a, right->row[i],
570 b, right->row[row], right->n_col);
575 isl_int_set(a, left->row[0][0]);
576 for (row = 1; row < left->n_row; ++row)
577 isl_int_lcm(a, a, left->row[row][row]);
578 if (isl_int_is_zero(a)){
580 isl_assert(ctx, 0, goto error);
582 for (row = 0; row < left->n_row; ++row) {
583 isl_int_divexact(left->row[row][row], a, left->row[row][row]);
584 if (isl_int_is_one(left->row[row][row]))
586 isl_seq_scale(right->row[row], right->row[row],
587 left->row[row][row], right->n_col);
591 isl_mat_free(ctx, left);
594 isl_mat_free(ctx, left);
595 isl_mat_free(ctx, right);
599 void isl_mat_col_scale(struct isl_mat *mat, unsigned col, isl_int m)
603 for (i = 0; i < mat->n_row; ++i)
604 isl_int_mul(mat->row[i][col], mat->row[i][col], m);
607 void isl_mat_col_combine(struct isl_mat *mat, unsigned dst,
608 isl_int m1, unsigned src1, isl_int m2, unsigned src2)
614 for (i = 0; i < mat->n_row; ++i) {
615 isl_int_mul(tmp, m1, mat->row[i][src1]);
616 isl_int_addmul(tmp, m2, mat->row[i][src2]);
617 isl_int_set(mat->row[i][dst], tmp);
622 struct isl_mat *isl_mat_right_inverse(struct isl_ctx *ctx,
629 mat = isl_mat_cow(ctx, mat);
633 inv = isl_mat_identity(ctx, mat->n_col);
634 inv = isl_mat_cow(ctx, inv);
640 for (row = 0; row < mat->n_row; ++row) {
641 int pivot, first, i, off;
642 pivot = isl_seq_abs_min_non_zero(mat->row[row]+row, mat->n_col-row);
650 exchange(ctx, mat, &inv, NULL, row, pivot, row);
651 if (isl_int_is_neg(mat->row[row][row]))
652 oppose(ctx, mat, &inv, NULL, row, row);
654 while ((off = isl_seq_first_non_zero(mat->row[row]+first,
655 mat->n_col-first)) != -1) {
657 isl_int_fdiv_q(a, mat->row[row][first],
659 subtract(mat, &inv, NULL, row, row, first, a);
660 if (!isl_int_is_zero(mat->row[row][first]))
661 exchange(ctx, mat, &inv, NULL, row, row, first);
665 for (i = 0; i < row; ++i) {
666 if (isl_int_is_zero(mat->row[row][i]))
668 isl_int_gcd(a, mat->row[row][row], mat->row[row][i]);
669 isl_int_divexact(b, mat->row[row][i], a);
670 isl_int_divexact(a, mat->row[row][row], a);
672 isl_mat_col_combine(mat, i, a, i, b, row);
673 isl_mat_col_combine(inv, i, a, i, b, row);
678 isl_int_set(a, mat->row[0][0]);
679 for (row = 1; row < mat->n_row; ++row)
680 isl_int_lcm(a, a, mat->row[row][row]);
681 if (isl_int_is_zero(a)){
685 for (row = 0; row < mat->n_row; ++row) {
686 isl_int_divexact(mat->row[row][row], a, mat->row[row][row]);
687 if (isl_int_is_one(mat->row[row][row]))
689 isl_mat_col_scale(inv, row, mat->row[row][row]);
693 isl_mat_free(ctx, mat);
697 isl_mat_free(ctx, mat);
701 struct isl_mat *isl_mat_transpose(struct isl_ctx *ctx, struct isl_mat *mat)
705 mat = isl_mat_cow(ctx, mat);
708 isl_assert(ctx, mat->n_col == mat->n_row, goto error);
709 for (i = 0; i < mat->n_row; ++i)
710 for (j = i + 1; j < mat->n_col; ++j)
711 isl_int_swap(mat->row[i][j], mat->row[j][i]);
714 isl_mat_free(ctx, mat);
718 struct isl_mat *isl_mat_swap_cols(struct isl_ctx *ctx,
719 struct isl_mat *mat, unsigned i, unsigned j)
723 mat = isl_mat_cow(ctx, mat);
726 isl_assert(ctx, i < mat->n_col, goto error);
727 isl_assert(ctx, j < mat->n_col, goto error);
729 for (r = 0; r < mat->n_row; ++r)
730 isl_int_swap(mat->row[r][i], mat->row[r][j]);
733 isl_mat_free(ctx, mat);
737 struct isl_mat *isl_mat_swap_rows(struct isl_ctx *ctx,
738 struct isl_mat *mat, unsigned i, unsigned j)
744 mat = isl_mat_cow(ctx, mat);
748 mat->row[i] = mat->row[j];
753 struct isl_mat *isl_mat_product(struct isl_ctx *ctx,
754 struct isl_mat *left, struct isl_mat *right)
757 struct isl_mat *prod;
761 isl_assert(ctx, left->n_col == right->n_row, goto error);
762 prod = isl_mat_alloc(ctx, left->n_row, right->n_col);
765 if (left->n_col == 0) {
766 for (i = 0; i < prod->n_row; ++i)
767 isl_seq_clr(prod->row[i], prod->n_col);
770 for (i = 0; i < prod->n_row; ++i) {
771 for (j = 0; j < prod->n_col; ++j) {
772 isl_int_mul(prod->row[i][j],
773 left->row[i][0], right->row[0][j]);
774 for (k = 1; k < left->n_col; ++k)
775 isl_int_addmul(prod->row[i][j],
776 left->row[i][k], right->row[k][j]);
779 isl_mat_free(ctx, left);
780 isl_mat_free(ctx, right);
783 isl_mat_free(ctx, left);
784 isl_mat_free(ctx, right);
788 /* Replace the variables x in bset by x' given by x = M x', with
791 * If there are fewer variables x' then there are x, then we perform
792 * the transformation in place, which that, in principle,
793 * this frees up some extra variables as the number
794 * of columns remains constant, but we would have to extend
795 * the div array too as the number of rows in this array is assumed
796 * to be equal to extra.
798 struct isl_basic_set *isl_basic_set_preimage(struct isl_basic_set *bset,
809 bset = isl_basic_set_cow(bset);
813 isl_assert(ctx, bset->dim->nparam == 0, goto error);
814 isl_assert(ctx, bset->n_div == 0, goto error);
815 isl_assert(ctx, 1+bset->dim->n_out == mat->n_row, goto error);
817 if (mat->n_col > mat->n_row)
818 bset = isl_basic_set_extend(bset, 0, mat->n_col-1, 0,
820 else if (mat->n_col < mat->n_row) {
821 bset->dim = isl_dim_cow(bset->dim);
824 bset->dim->n_out -= mat->n_row - mat->n_col;
827 t = isl_mat_sub_alloc(ctx, bset->eq, 0, bset->n_eq, 0, mat->n_row);
828 t = isl_mat_product(ctx, t, isl_mat_copy(ctx, mat));
831 for (i = 0; i < bset->n_eq; ++i) {
832 isl_seq_swp_or_cpy(bset->eq[i], t->row[i], t->n_col);
833 isl_seq_clr(bset->eq[i]+t->n_col, bset->extra);
835 isl_mat_free(ctx, t);
837 t = isl_mat_sub_alloc(ctx, bset->ineq, 0, bset->n_ineq, 0, mat->n_row);
838 t = isl_mat_product(ctx, t, mat);
841 for (i = 0; i < bset->n_ineq; ++i) {
842 isl_seq_swp_or_cpy(bset->ineq[i], t->row[i], t->n_col);
843 isl_seq_clr(bset->ineq[i]+t->n_col, bset->extra);
845 isl_mat_free(ctx, t);
847 bset = isl_basic_set_simplify(bset);
848 bset = isl_basic_set_finalize(bset);
852 isl_mat_free(ctx, mat);
854 isl_basic_set_free(bset);
858 struct isl_set *isl_set_preimage(struct isl_set *set, struct isl_mat *mat)
863 set = isl_set_cow(set);
868 for (i = 0; i < set->n; ++i) {
869 set->p[i] = isl_basic_set_preimage(set->p[i],
870 isl_mat_copy(ctx, mat));
874 if (mat->n_col != mat->n_row) {
875 set->dim = isl_dim_cow(set->dim);
878 set->dim->n_out += mat->n_col;
879 set->dim->n_out -= mat->n_row;
881 isl_mat_free(ctx, mat);
882 ISL_F_CLR(set, ISL_SET_NORMALIZED);
886 isl_mat_free(ctx, mat);
890 void isl_mat_dump(struct isl_ctx *ctx, struct isl_mat *mat,
891 FILE *out, int indent)
896 fprintf(out, "%*snull mat\n", indent, "");
901 fprintf(out, "%*s[]\n", indent, "");
903 for (i = 0; i < mat->n_row; ++i) {
905 fprintf(out, "%*s[[", indent, "");
907 fprintf(out, "%*s[", indent+1, "");
908 for (j = 0; j < mat->n_col; ++j) {
911 isl_int_print(out, mat->row[i][j], 0);
913 if (i == mat->n_row-1)
914 fprintf(out, "]]\n");
920 struct isl_mat *isl_mat_drop_cols(struct isl_ctx *ctx, struct isl_mat *mat,
921 unsigned col, unsigned n)
925 mat = isl_mat_cow(ctx, mat);
929 if (col != mat->n_col-n) {
930 for (r = 0; r < mat->n_row; ++r)
931 isl_seq_cpy(mat->row[r]+col, mat->row[r]+col+n,
932 mat->n_col - col - n);
938 struct isl_mat *isl_mat_drop_rows(struct isl_ctx *ctx, struct isl_mat *mat,
939 unsigned row, unsigned n)
943 mat = isl_mat_cow(ctx, mat);
947 for (r = row; r+n < mat->n_row; ++r)
948 mat->row[r] = mat->row[r+n];
954 void isl_mat_col_submul(struct isl_mat *mat,
955 int dst_col, isl_int f, int src_col)
959 for (i = 0; i < mat->n_row; ++i)
960 isl_int_submul(mat->row[i][dst_col], f, mat->row[i][src_col]);
963 void isl_mat_col_mul(struct isl_mat *mat, int dst_col, isl_int f, int src_col)
967 for (i = 0; i < mat->n_row; ++i)
968 isl_int_mul(mat->row[i][dst_col], f, mat->row[i][src_col]);