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_sub_alloc(struct isl_ctx
*ctx
, isl_int
**row
,
40 unsigned first_row
, unsigned n_row
, unsigned first_col
, unsigned n_col
)
45 mat
= isl_alloc_type(ctx
, struct isl_mat
);
48 mat
->row
= isl_alloc_array(ctx
, isl_int
*, n_row
);
51 for (i
= 0; i
< n_row
; ++i
)
52 mat
->row
[i
] = row
[first_row
+i
] + first_col
;
56 mat
->block
= isl_blk_empty();
57 mat
->flags
= ISL_MAT_BORROWED
;
64 void isl_mat_sub_copy(struct isl_ctx
*ctx
, isl_int
**dst
, isl_int
**src
,
65 unsigned n_row
, unsigned dst_col
, unsigned src_col
, unsigned n_col
)
69 for (i
= 0; i
< n_row
; ++i
)
70 isl_seq_cpy(dst
[i
]+dst_col
, src
[i
]+src_col
, n_col
);
73 void isl_mat_sub_neg(struct isl_ctx
*ctx
, isl_int
**dst
, isl_int
**src
,
74 unsigned n_row
, unsigned dst_col
, unsigned src_col
, unsigned n_col
)
78 for (i
= 0; i
< n_row
; ++i
)
79 isl_seq_neg(dst
[i
]+dst_col
, src
[i
]+src_col
, n_col
);
82 struct isl_mat
*isl_mat_copy(struct isl_ctx
*ctx
, struct isl_mat
*mat
)
91 struct isl_mat
*isl_mat_dup(struct isl_ctx
*ctx
, struct isl_mat
*mat
)
98 mat2
= isl_mat_alloc(ctx
, mat
->n_row
, mat
->n_col
);
101 for (i
= 0; i
< mat
->n_row
; ++i
)
102 isl_seq_cpy(mat2
->row
[i
], mat
->row
[i
], mat
->n_col
);
106 struct isl_mat
*isl_mat_cow(struct isl_ctx
*ctx
, struct isl_mat
*mat
)
108 struct isl_mat
*mat2
;
112 if (mat
->ref
== 1 && !F_ISSET(mat
, ISL_MAT_BORROWED
))
115 mat2
= isl_mat_dup(ctx
, mat
);
116 isl_mat_free(ctx
, mat
);
120 void isl_mat_free(struct isl_ctx
*ctx
, struct isl_mat
*mat
)
128 if (!F_ISSET(mat
, ISL_MAT_BORROWED
))
129 isl_blk_free(ctx
, mat
->block
);
134 struct isl_mat
*isl_mat_identity(struct isl_ctx
*ctx
, unsigned n_row
)
139 mat
= isl_mat_alloc(ctx
, n_row
, n_row
);
142 for (i
= 0; i
< n_row
; ++i
) {
143 isl_seq_clr(mat
->row
[i
], i
);
144 isl_int_set_si(mat
->row
[i
][i
], 1);
145 isl_seq_clr(mat
->row
[i
]+i
+1, n_row
-(i
+1));
151 struct isl_vec
*isl_mat_vec_product(struct isl_ctx
*ctx
,
152 struct isl_mat
*mat
, struct isl_vec
*vec
)
155 struct isl_vec
*prod
;
160 isl_assert(ctx
, mat
->n_col
== vec
->size
, goto error
);
162 prod
= isl_vec_alloc(ctx
, mat
->n_row
);
166 for (i
= 0; i
< prod
->size
; ++i
)
167 isl_seq_inner_product(mat
->row
[i
], vec
->block
.data
, vec
->size
,
168 &prod
->block
.data
[i
]);
169 isl_mat_free(ctx
, mat
);
170 isl_vec_free(ctx
, vec
);
173 isl_mat_free(ctx
, mat
);
174 isl_vec_free(ctx
, vec
);
178 struct isl_mat
*isl_mat_aff_direct_sum(struct isl_ctx
*ctx
,
179 struct isl_mat
*left
, struct isl_mat
*right
)
187 isl_assert(ctx
, left
->n_row
== right
->n_row
, goto error
);
188 isl_assert(ctx
, left
->n_row
>= 1, goto error
);
189 isl_assert(ctx
, left
->n_col
>= 1, goto error
);
190 isl_assert(ctx
, right
->n_col
>= 1, goto error
);
192 isl_seq_first_non_zero(left
->row
[0]+1, left
->n_col
-1) == -1,
195 isl_seq_first_non_zero(right
->row
[0]+1, right
->n_col
-1) == -1,
198 sum
= isl_mat_alloc(ctx
, left
->n_row
, left
->n_col
+ right
->n_col
- 1);
201 isl_int_lcm(sum
->row
[0][0], left
->row
[0][0], right
->row
[0][0]);
202 isl_int_divexact(left
->row
[0][0], sum
->row
[0][0], left
->row
[0][0]);
203 isl_int_divexact(right
->row
[0][0], sum
->row
[0][0], right
->row
[0][0]);
205 isl_seq_clr(sum
->row
[0]+1, sum
->n_col
-1);
206 for (i
= 1; i
< sum
->n_row
; ++i
) {
207 isl_int_mul(sum
->row
[i
][0], left
->row
[0][0], left
->row
[i
][0]);
208 isl_int_addmul(sum
->row
[i
][0],
209 right
->row
[0][0], right
->row
[i
][0]);
210 isl_seq_scale(sum
->row
[i
]+1, left
->row
[i
]+1, left
->row
[0][0],
212 isl_seq_scale(sum
->row
[i
]+left
->n_col
,
213 right
->row
[i
]+1, right
->row
[0][0],
217 isl_int_divexact(left
->row
[0][0], sum
->row
[0][0], left
->row
[0][0]);
218 isl_int_divexact(right
->row
[0][0], sum
->row
[0][0], right
->row
[0][0]);
219 isl_mat_free(ctx
, left
);
220 isl_mat_free(ctx
, right
);
223 isl_mat_free(ctx
, left
);
224 isl_mat_free(ctx
, right
);
228 static void exchange(struct isl_ctx
*ctx
, struct isl_mat
*M
, struct isl_mat
**U
,
229 struct isl_mat
**Q
, unsigned row
, unsigned i
, unsigned j
)
232 for (r
= row
; r
< M
->n_row
; ++r
)
233 isl_int_swap(M
->row
[r
][i
], M
->row
[r
][j
]);
235 for (r
= 0; r
< (*U
)->n_row
; ++r
)
236 isl_int_swap((*U
)->row
[r
][i
], (*U
)->row
[r
][j
]);
239 isl_mat_swap_rows(ctx
, *Q
, i
, j
);
242 static void subtract(struct isl_mat
*M
, struct isl_mat
**U
,
243 struct isl_mat
**Q
, unsigned row
, unsigned i
, unsigned j
, isl_int m
)
246 for (r
= row
; r
< M
->n_row
; ++r
)
247 isl_int_submul(M
->row
[r
][j
], m
, M
->row
[r
][i
]);
249 for (r
= 0; r
< (*U
)->n_row
; ++r
)
250 isl_int_submul((*U
)->row
[r
][j
], m
, (*U
)->row
[r
][i
]);
253 for (r
= 0; r
< (*Q
)->n_col
; ++r
)
254 isl_int_addmul((*Q
)->row
[i
][r
], m
, (*Q
)->row
[j
][r
]);
258 static void oppose(struct isl_ctx
*ctx
, struct isl_mat
*M
, struct isl_mat
**U
,
259 struct isl_mat
**Q
, unsigned row
, unsigned col
)
262 for (r
= row
; r
< M
->n_row
; ++r
)
263 isl_int_neg(M
->row
[r
][col
], M
->row
[r
][col
]);
265 for (r
= 0; r
< (*U
)->n_row
; ++r
)
266 isl_int_neg((*U
)->row
[r
][col
], (*U
)->row
[r
][col
]);
269 isl_seq_neg((*Q
)->row
[col
], (*Q
)->row
[col
], (*Q
)->n_col
);
272 /* Given matrix M, compute
277 * with U and Q unimodular matrices and H a matrix in column echelon form
278 * such that on each echelon row the entries in the non-echelon column
279 * are non-negative (if neg == 0) or non-positive (if neg == 1)
280 * and stricly smaller (in absolute value) than the entries in the echelon
282 * If U or Q are NULL, then these matrices are not computed.
284 struct isl_mat
*isl_mat_left_hermite(struct isl_ctx
*ctx
,
285 struct isl_mat
*M
, int neg
, struct isl_mat
**U
, struct isl_mat
**Q
)
296 M
= isl_mat_cow(ctx
, M
);
300 *U
= isl_mat_identity(ctx
, M
->n_col
);
305 *Q
= isl_mat_identity(ctx
, M
->n_col
);
312 for (row
= 0; row
< M
->n_row
; ++row
) {
314 first
= isl_seq_abs_min_non_zero(M
->row
[row
]+col
, M
->n_col
-col
);
319 exchange(ctx
, M
, U
, Q
, row
, first
, col
);
320 if (isl_int_is_neg(M
->row
[row
][col
]))
321 oppose(ctx
, M
, U
, Q
, row
, col
);
323 while ((off
= isl_seq_first_non_zero(M
->row
[row
]+first
,
324 M
->n_col
-first
)) != -1) {
326 isl_int_fdiv_q(c
, M
->row
[row
][first
], M
->row
[row
][col
]);
327 subtract(M
, U
, Q
, row
, col
, first
, c
);
328 if (!isl_int_is_zero(M
->row
[row
][first
]))
329 exchange(ctx
, M
, U
, Q
, row
, first
, col
);
333 for (i
= 0; i
< col
; ++i
) {
334 if (isl_int_is_zero(M
->row
[row
][i
]))
337 isl_int_cdiv_q(c
, M
->row
[row
][i
], M
->row
[row
][col
]);
339 isl_int_fdiv_q(c
, M
->row
[row
][i
], M
->row
[row
][col
]);
340 if (isl_int_is_zero(c
))
342 subtract(M
, U
, Q
, row
, col
, i
, c
);
351 isl_mat_free(ctx
, *Q
);
355 isl_mat_free(ctx
, *U
);
361 struct isl_mat
*isl_mat_lin_to_aff(struct isl_ctx
*ctx
, struct isl_mat
*mat
)
364 struct isl_mat
*mat2
;
368 mat2
= isl_mat_alloc(ctx
, 1+mat
->n_row
, 1+mat
->n_col
);
371 isl_int_set_si(mat2
->row
[0][0], 1);
372 isl_seq_clr(mat2
->row
[0]+1, mat
->n_col
);
373 for (i
= 0; i
< mat
->n_row
; ++i
) {
374 isl_int_set_si(mat2
->row
[1+i
][0], 0);
375 isl_seq_cpy(mat2
->row
[1+i
]+1, mat
->row
[i
], mat
->n_col
);
377 isl_mat_free(ctx
, mat
);
381 static int row_first_non_zero(isl_int
**row
, unsigned n_row
, unsigned col
)
385 for (i
= 0; i
< n_row
; ++i
)
386 if (!isl_int_is_zero(row
[i
][col
]))
391 static int row_abs_min_non_zero(isl_int
**row
, unsigned n_row
, unsigned col
)
393 int i
, min
= row_first_non_zero(row
, n_row
, col
);
396 for (i
= min
+ 1; i
< n_row
; ++i
) {
397 if (isl_int_is_zero(row
[i
][col
]))
399 if (isl_int_abs_lt(row
[i
][col
], row
[min
][col
]))
405 static void inv_exchange(struct isl_ctx
*ctx
,
406 struct isl_mat
*left
, struct isl_mat
*right
,
407 unsigned i
, unsigned j
)
409 left
= isl_mat_swap_rows(ctx
, left
, i
, j
);
410 right
= isl_mat_swap_rows(ctx
, right
, i
, j
);
413 static void inv_oppose(struct isl_ctx
*ctx
,
414 struct isl_mat
*left
, struct isl_mat
*right
, unsigned row
)
416 isl_seq_neg(left
->row
[row
]+row
, left
->row
[row
]+row
, left
->n_col
-row
);
417 isl_seq_neg(right
->row
[row
], right
->row
[row
], right
->n_col
);
420 static void inv_subtract(struct isl_ctx
*ctx
,
421 struct isl_mat
*left
, struct isl_mat
*right
,
422 unsigned row
, unsigned i
, isl_int m
)
425 isl_seq_combine(left
->row
[i
]+row
,
426 ctx
->one
, left
->row
[i
]+row
,
427 m
, left
->row
[row
]+row
,
429 isl_seq_combine(right
->row
[i
], ctx
->one
, right
->row
[i
],
430 m
, right
->row
[row
], right
->n_col
);
433 /* Compute inv(left)*right
435 struct isl_mat
*isl_mat_inverse_product(struct isl_ctx
*ctx
,
436 struct isl_mat
*left
, struct isl_mat
*right
)
444 isl_assert(ctx
, left
->n_row
== left
->n_col
, goto error
);
445 isl_assert(ctx
, left
->n_row
== right
->n_row
, goto error
);
447 if (left
->n_row
== 0) {
448 isl_mat_free(ctx
, left
);
452 left
= isl_mat_cow(ctx
, left
);
453 right
= isl_mat_cow(ctx
, right
);
459 for (row
= 0; row
< left
->n_row
; ++row
) {
460 int pivot
, first
, i
, off
;
461 pivot
= row_abs_min_non_zero(left
->row
+row
, left
->n_row
-row
, row
);
465 isl_assert(ctx
, pivot
>= 0, goto error
);
469 inv_exchange(ctx
, left
, right
, pivot
, row
);
470 if (isl_int_is_neg(left
->row
[row
][row
]))
471 inv_oppose(ctx
, left
, right
, row
);
473 while ((off
= row_first_non_zero(left
->row
+first
,
474 left
->n_row
-first
, row
)) != -1) {
476 isl_int_fdiv_q(a
, left
->row
[first
][row
],
477 left
->row
[row
][row
]);
478 inv_subtract(ctx
, left
, right
, row
, first
, a
);
479 if (!isl_int_is_zero(left
->row
[first
][row
]))
480 inv_exchange(ctx
, left
, right
, row
, first
);
484 for (i
= 0; i
< row
; ++i
) {
485 if (isl_int_is_zero(left
->row
[i
][row
]))
487 isl_int_gcd(a
, left
->row
[row
][row
], left
->row
[i
][row
]);
488 isl_int_divexact(b
, left
->row
[i
][row
], a
);
489 isl_int_divexact(a
, left
->row
[row
][row
], a
);
491 isl_seq_combine(left
->row
[i
]+row
,
493 b
, left
->row
[row
]+row
,
495 isl_seq_combine(right
->row
[i
], a
, right
->row
[i
],
496 b
, right
->row
[row
], right
->n_col
);
501 isl_int_set(a
, left
->row
[0][0]);
502 for (row
= 1; row
< left
->n_row
; ++row
)
503 isl_int_lcm(a
, a
, left
->row
[row
][row
]);
504 if (isl_int_is_zero(a
)){
506 isl_assert(ctx
, 0, goto error
);
508 for (row
= 0; row
< left
->n_row
; ++row
) {
509 isl_int_divexact(left
->row
[row
][row
], a
, left
->row
[row
][row
]);
510 if (isl_int_is_one(left
->row
[row
][row
]))
512 isl_seq_scale(right
->row
[row
], right
->row
[row
],
513 left
->row
[row
][row
], right
->n_col
);
517 isl_mat_free(ctx
, left
);
520 isl_mat_free(ctx
, left
);
521 isl_mat_free(ctx
, right
);
525 void isl_mat_col_scale(struct isl_mat
*mat
, unsigned col
, isl_int m
)
529 for (i
= 0; i
< mat
->n_row
; ++i
)
530 isl_int_mul(mat
->row
[i
][col
], mat
->row
[i
][col
], m
);
533 void isl_mat_col_combine(struct isl_mat
*mat
, unsigned dst
,
534 isl_int m1
, unsigned src1
, isl_int m2
, unsigned src2
)
540 for (i
= 0; i
< mat
->n_row
; ++i
) {
541 isl_int_mul(tmp
, m1
, mat
->row
[i
][src1
]);
542 isl_int_addmul(tmp
, m2
, mat
->row
[i
][src2
]);
543 isl_int_set(mat
->row
[i
][dst
], tmp
);
548 struct isl_mat
*isl_mat_right_inverse(struct isl_ctx
*ctx
,
555 mat
= isl_mat_cow(ctx
, mat
);
559 inv
= isl_mat_identity(ctx
, mat
->n_col
);
560 inv
= isl_mat_cow(ctx
, inv
);
566 for (row
= 0; row
< mat
->n_row
; ++row
) {
567 int pivot
, first
, i
, off
;
568 pivot
= isl_seq_abs_min_non_zero(mat
->row
[row
]+row
, mat
->n_col
-row
);
576 exchange(ctx
, mat
, &inv
, NULL
, row
, pivot
, row
);
577 if (isl_int_is_neg(mat
->row
[row
][row
]))
578 oppose(ctx
, mat
, &inv
, NULL
, row
, row
);
580 while ((off
= isl_seq_first_non_zero(mat
->row
[row
]+first
,
581 mat
->n_col
-first
)) != -1) {
583 isl_int_fdiv_q(a
, mat
->row
[row
][first
],
585 subtract(mat
, &inv
, NULL
, row
, row
, first
, a
);
586 if (!isl_int_is_zero(mat
->row
[row
][first
]))
587 exchange(ctx
, mat
, &inv
, NULL
, row
, row
, first
);
591 for (i
= 0; i
< row
; ++i
) {
592 if (isl_int_is_zero(mat
->row
[row
][i
]))
594 isl_int_gcd(a
, mat
->row
[row
][row
], mat
->row
[row
][i
]);
595 isl_int_divexact(b
, mat
->row
[row
][i
], a
);
596 isl_int_divexact(a
, mat
->row
[row
][row
], a
);
598 isl_mat_col_combine(mat
, i
, a
, i
, b
, row
);
599 isl_mat_col_combine(inv
, i
, a
, i
, b
, row
);
604 isl_int_set(a
, mat
->row
[0][0]);
605 for (row
= 1; row
< mat
->n_row
; ++row
)
606 isl_int_lcm(a
, a
, mat
->row
[row
][row
]);
607 if (isl_int_is_zero(a
)){
611 for (row
= 0; row
< mat
->n_row
; ++row
) {
612 isl_int_divexact(mat
->row
[row
][row
], a
, mat
->row
[row
][row
]);
613 if (isl_int_is_one(mat
->row
[row
][row
]))
615 isl_mat_col_scale(inv
, row
, mat
->row
[row
][row
]);
619 isl_mat_free(ctx
, mat
);
623 isl_mat_free(ctx
, mat
);
627 struct isl_mat
*isl_mat_swap_rows(struct isl_ctx
*ctx
,
628 struct isl_mat
*mat
, unsigned i
, unsigned j
)
634 mat
= isl_mat_cow(ctx
, mat
);
638 mat
->row
[i
] = mat
->row
[j
];
643 struct isl_mat
*isl_mat_product(struct isl_ctx
*ctx
,
644 struct isl_mat
*left
, struct isl_mat
*right
)
647 struct isl_mat
*prod
;
651 isl_assert(ctx
, left
->n_col
== right
->n_row
, goto error
);
652 prod
= isl_mat_alloc(ctx
, left
->n_row
, right
->n_col
);
655 if (left
->n_col
== 0) {
656 for (i
= 0; i
< prod
->n_row
; ++i
)
657 isl_seq_clr(prod
->row
[i
], prod
->n_col
);
660 for (i
= 0; i
< prod
->n_row
; ++i
) {
661 for (j
= 0; j
< prod
->n_col
; ++j
) {
662 isl_int_mul(prod
->row
[i
][j
],
663 left
->row
[i
][0], right
->row
[0][j
]);
664 for (k
= 1; k
< left
->n_col
; ++k
)
665 isl_int_addmul(prod
->row
[i
][j
],
666 left
->row
[i
][k
], right
->row
[k
][j
]);
669 isl_mat_free(ctx
, left
);
670 isl_mat_free(ctx
, right
);
673 isl_mat_free(ctx
, left
);
674 isl_mat_free(ctx
, right
);
678 /* Replace the variables x in bset by x' given by x = M x', with
681 * If there are fewer variables x' then there are x, then we perform
682 * the transformation in place, which that, in principle,
683 * this frees up some extra variables as the number
684 * of columns remains constant, but we would have to extend
685 * the div array too as the number of rows in this array is assumed
686 * to be equal to extra.
688 struct isl_basic_set
*isl_basic_set_preimage(struct isl_ctx
*ctx
,
689 struct isl_basic_set
*bset
, struct isl_mat
*mat
)
697 bset
= isl_basic_set_cow(bset
);
701 isl_assert(ctx
, bset
->dim
->nparam
== 0, goto error
);
702 isl_assert(ctx
, bset
->n_div
== 0, goto error
);
703 isl_assert(ctx
, 1+bset
->dim
->n_out
== mat
->n_row
, goto error
);
705 if (mat
->n_col
> mat
->n_row
)
706 bset
= isl_basic_set_extend(bset
, 0, mat
->n_col
-1, 0,
708 else if (mat
->n_col
< mat
->n_row
) {
709 bset
->dim
= isl_dim_cow(bset
->dim
);
712 bset
->dim
->n_out
-= mat
->n_row
- mat
->n_col
;
715 t
= isl_mat_sub_alloc(ctx
, bset
->eq
, 0, bset
->n_eq
, 0, mat
->n_row
);
716 t
= isl_mat_product(ctx
, t
, isl_mat_copy(ctx
, mat
));
719 for (i
= 0; i
< bset
->n_eq
; ++i
) {
720 isl_seq_swp_or_cpy(bset
->eq
[i
], t
->row
[i
], t
->n_col
);
721 isl_seq_clr(bset
->eq
[i
]+t
->n_col
, bset
->extra
);
723 isl_mat_free(ctx
, t
);
725 t
= isl_mat_sub_alloc(ctx
, bset
->ineq
, 0, bset
->n_ineq
, 0, mat
->n_row
);
726 t
= isl_mat_product(ctx
, t
, mat
);
729 for (i
= 0; i
< bset
->n_ineq
; ++i
) {
730 isl_seq_swp_or_cpy(bset
->ineq
[i
], t
->row
[i
], t
->n_col
);
731 isl_seq_clr(bset
->ineq
[i
]+t
->n_col
, bset
->extra
);
733 isl_mat_free(ctx
, t
);
735 bset
= isl_basic_set_simplify(bset
);
736 bset
= isl_basic_set_finalize(bset
);
740 isl_mat_free(ctx
, mat
);
742 isl_basic_set_free(bset
);
746 struct isl_set
*isl_set_preimage(struct isl_ctx
*ctx
,
747 struct isl_set
*set
, struct isl_mat
*mat
)
751 set
= isl_set_cow(set
);
756 for (i
= 0; i
< set
->n
; ++i
) {
757 set
->p
[i
] = isl_basic_set_preimage(ctx
, set
->p
[i
],
758 isl_mat_copy(ctx
, mat
));
762 if (mat
->n_col
!= mat
->n_row
) {
763 set
->dim
= isl_dim_cow(set
->dim
);
766 set
->dim
->n_out
+= mat
->n_col
;
767 set
->dim
->n_out
-= mat
->n_row
;
769 isl_mat_free(ctx
, mat
);
773 isl_mat_free(ctx
, mat
);
777 void isl_mat_dump(struct isl_ctx
*ctx
, struct isl_mat
*mat
,
778 FILE *out
, int indent
)
783 fprintf(out
, "null mat\n");
788 fprintf(out
, "%*s[]\n", indent
, "");
790 for (i
= 0; i
< mat
->n_row
; ++i
) {
792 fprintf(out
, "%*s[[", indent
, "");
794 fprintf(out
, "%*s[", indent
+1, "");
795 for (j
= 0; j
< mat
->n_col
; ++j
) {
798 isl_int_print(out
, mat
->row
[i
][j
], 0);
800 if (i
== mat
->n_row
-1)
801 fprintf(out
, "]]\n");
807 struct isl_mat
*isl_mat_drop_cols(struct isl_ctx
*ctx
, struct isl_mat
*mat
,
808 unsigned col
, unsigned n
)
815 if (col
!= mat
->n_col
-n
) {
816 for (r
= 0; r
< mat
->n_row
; ++r
)
817 isl_seq_cpy(mat
->row
[r
]+col
, mat
->row
[r
]+col
+n
,
818 mat
->n_col
- col
- n
);
824 struct isl_mat
*isl_mat_drop_rows(struct isl_ctx
*ctx
, struct isl_mat
*mat
,
825 unsigned row
, unsigned n
)
832 for (r
= row
; r
+n
< mat
->n_row
; ++r
)
833 mat
->row
[r
] = mat
->row
[r
+n
];