2 * Copyright 2008-2009 Katholieke Universiteit Leuven
3 * Copyright 2010 INRIA Saclay
4 * Copyright 2014 Ecole Normale Superieure
5 * Copyright 2017 Sven Verdoolaege
7 * Use of this software is governed by the MIT license
9 * Written by Sven Verdoolaege, K.U.Leuven, Departement
10 * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
11 * and INRIA Saclay - Ile-de-France, Parc Club Orsay Universite,
12 * ZAC des vignes, 4 rue Jacques Monod, 91893 Orsay, France
13 * and Ecole Normale Superieure, 45 rue d'Ulm, 75230 Paris, France
16 #include <isl_ctx_private.h>
17 #include <isl_map_private.h>
18 #include <isl/space.h>
20 #include <isl_mat_private.h>
21 #include <isl_vec_private.h>
22 #include <isl_space_private.h>
23 #include <isl_val_private.h>
25 isl_ctx
*isl_mat_get_ctx(__isl_keep isl_mat
*mat
)
27 return mat
? mat
->ctx
: NULL
;
30 /* Return a hash value that digests "mat".
32 uint32_t isl_mat_get_hash(__isl_keep isl_mat
*mat
)
40 hash
= isl_hash_init();
41 isl_hash_byte(hash
, mat
->n_row
& 0xFF);
42 isl_hash_byte(hash
, mat
->n_col
& 0xFF);
43 for (i
= 0; i
< mat
->n_row
; ++i
) {
46 row_hash
= isl_seq_get_hash(mat
->row
[i
], mat
->n_col
);
47 isl_hash_hash(hash
, row_hash
);
53 __isl_give isl_mat
*isl_mat_alloc(isl_ctx
*ctx
,
54 unsigned n_row
, unsigned n_col
)
59 mat
= isl_alloc_type(ctx
, struct isl_mat
);
64 mat
->block
= isl_blk_alloc(ctx
, n_row
* n_col
);
65 if (isl_blk_is_error(mat
->block
))
67 mat
->row
= isl_calloc_array(ctx
, isl_int
*, n_row
);
68 if (n_row
&& !mat
->row
)
72 for (i
= 0; i
< n_row
; ++i
)
73 mat
->row
[i
] = mat
->block
.data
+ i
* n_col
;
86 isl_blk_free(ctx
, mat
->block
);
91 __isl_give isl_mat
*isl_mat_extend(__isl_take isl_mat
*mat
,
92 unsigned n_row
, unsigned n_col
)
101 if (mat
->max_col
>= n_col
&& mat
->n_row
>= n_row
) {
102 if (mat
->n_col
< n_col
)
107 if (mat
->max_col
< n_col
) {
108 struct isl_mat
*new_mat
;
110 if (n_row
< mat
->n_row
)
112 new_mat
= isl_mat_alloc(mat
->ctx
, n_row
, n_col
);
115 for (i
= 0; i
< mat
->n_row
; ++i
)
116 isl_seq_cpy(new_mat
->row
[i
], mat
->row
[i
], mat
->n_col
);
121 mat
= isl_mat_cow(mat
);
125 old
= mat
->block
.data
;
126 mat
->block
= isl_blk_extend(mat
->ctx
, mat
->block
, n_row
* mat
->max_col
);
127 if (isl_blk_is_error(mat
->block
))
129 row
= isl_realloc_array(mat
->ctx
, mat
->row
, isl_int
*, n_row
);
134 for (i
= 0; i
< mat
->n_row
; ++i
)
135 mat
->row
[i
] = mat
->block
.data
+ (mat
->row
[i
] - old
);
136 for (i
= mat
->n_row
; i
< n_row
; ++i
)
137 mat
->row
[i
] = mat
->block
.data
+ i
* mat
->max_col
;
139 if (mat
->n_col
< n_col
)
148 __isl_give isl_mat
*isl_mat_sub_alloc6(isl_ctx
*ctx
, isl_int
**row
,
149 unsigned first_row
, unsigned n_row
, unsigned first_col
, unsigned n_col
)
154 mat
= isl_alloc_type(ctx
, struct isl_mat
);
157 mat
->row
= isl_alloc_array(ctx
, isl_int
*, n_row
);
158 if (n_row
&& !mat
->row
)
160 for (i
= 0; i
< n_row
; ++i
)
161 mat
->row
[i
] = row
[first_row
+i
] + first_col
;
167 mat
->block
= isl_blk_empty();
168 mat
->flags
= ISL_MAT_BORROWED
;
175 __isl_give isl_mat
*isl_mat_sub_alloc(__isl_keep isl_mat
*mat
,
176 unsigned first_row
, unsigned n_row
, unsigned first_col
, unsigned n_col
)
180 return isl_mat_sub_alloc6(mat
->ctx
, mat
->row
, first_row
, n_row
,
184 void isl_mat_sub_copy(struct isl_ctx
*ctx
, isl_int
**dst
, isl_int
**src
,
185 unsigned n_row
, unsigned dst_col
, unsigned src_col
, unsigned n_col
)
189 for (i
= 0; i
< n_row
; ++i
)
190 isl_seq_cpy(dst
[i
]+dst_col
, src
[i
]+src_col
, n_col
);
193 void isl_mat_sub_neg(struct isl_ctx
*ctx
, isl_int
**dst
, isl_int
**src
,
194 unsigned n_row
, unsigned dst_col
, unsigned src_col
, unsigned n_col
)
198 for (i
= 0; i
< n_row
; ++i
)
199 isl_seq_neg(dst
[i
]+dst_col
, src
[i
]+src_col
, n_col
);
202 __isl_give isl_mat
*isl_mat_copy(__isl_keep isl_mat
*mat
)
211 __isl_give isl_mat
*isl_mat_dup(__isl_keep isl_mat
*mat
)
214 struct isl_mat
*mat2
;
218 mat2
= isl_mat_alloc(mat
->ctx
, mat
->n_row
, mat
->n_col
);
221 for (i
= 0; i
< mat
->n_row
; ++i
)
222 isl_seq_cpy(mat2
->row
[i
], mat
->row
[i
], mat
->n_col
);
226 __isl_give isl_mat
*isl_mat_cow(__isl_take isl_mat
*mat
)
228 struct isl_mat
*mat2
;
232 if (mat
->ref
== 1 && !ISL_F_ISSET(mat
, ISL_MAT_BORROWED
))
235 mat2
= isl_mat_dup(mat
);
240 __isl_null isl_mat
*isl_mat_free(__isl_take isl_mat
*mat
)
248 if (!ISL_F_ISSET(mat
, ISL_MAT_BORROWED
))
249 isl_blk_free(mat
->ctx
, mat
->block
);
250 isl_ctx_deref(mat
->ctx
);
257 isl_size
isl_mat_rows(__isl_keep isl_mat
*mat
)
259 return mat
? mat
->n_row
: isl_size_error
;
262 isl_size
isl_mat_cols(__isl_keep isl_mat
*mat
)
264 return mat
? mat
->n_col
: isl_size_error
;
267 /* Check that "col" is a valid column position for "mat".
269 static isl_stat
check_col(__isl_keep isl_mat
*mat
, int col
)
272 return isl_stat_error
;
273 if (col
< 0 || col
>= mat
->n_col
)
274 isl_die(isl_mat_get_ctx(mat
), isl_error_invalid
,
275 "column out of range", return isl_stat_error
);
279 /* Check that "row" is a valid row position for "mat".
281 static isl_stat
check_row(__isl_keep isl_mat
*mat
, int row
)
284 return isl_stat_error
;
285 if (row
< 0 || row
>= mat
->n_row
)
286 isl_die(isl_mat_get_ctx(mat
), isl_error_invalid
,
287 "row out of range", return isl_stat_error
);
291 /* Check that there are "n" columns starting at position "first" in "mat".
293 static isl_stat
check_col_range(__isl_keep isl_mat
*mat
, unsigned first
,
297 return isl_stat_error
;
298 if (first
+ n
> mat
->n_col
|| first
+ n
< first
)
299 isl_die(isl_mat_get_ctx(mat
), isl_error_invalid
,
300 "column position or range out of bounds",
301 return isl_stat_error
);
305 /* Check that there are "n" rows starting at position "first" in "mat".
307 static isl_stat
check_row_range(__isl_keep isl_mat
*mat
, unsigned first
,
311 return isl_stat_error
;
312 if (first
+ n
> mat
->n_row
|| first
+ n
< first
)
313 isl_die(isl_mat_get_ctx(mat
), isl_error_invalid
,
314 "row position or range out of bounds",
315 return isl_stat_error
);
319 int isl_mat_get_element(__isl_keep isl_mat
*mat
, int row
, int col
, isl_int
*v
)
321 if (check_row(mat
, row
) < 0)
323 if (check_col(mat
, col
) < 0)
325 isl_int_set(*v
, mat
->row
[row
][col
]);
329 /* Extract the element at row "row", oolumn "col" of "mat".
331 __isl_give isl_val
*isl_mat_get_element_val(__isl_keep isl_mat
*mat
,
336 if (check_row(mat
, row
) < 0)
338 if (check_col(mat
, col
) < 0)
340 ctx
= isl_mat_get_ctx(mat
);
341 return isl_val_int_from_isl_int(ctx
, mat
->row
[row
][col
]);
344 __isl_give isl_mat
*isl_mat_set_element(__isl_take isl_mat
*mat
,
345 int row
, int col
, isl_int v
)
347 mat
= isl_mat_cow(mat
);
348 if (check_row(mat
, row
) < 0)
349 return isl_mat_free(mat
);
350 if (check_col(mat
, col
) < 0)
351 return isl_mat_free(mat
);
352 isl_int_set(mat
->row
[row
][col
], v
);
356 __isl_give isl_mat
*isl_mat_set_element_si(__isl_take isl_mat
*mat
,
357 int row
, int col
, int v
)
359 mat
= isl_mat_cow(mat
);
360 if (check_row(mat
, row
) < 0)
361 return isl_mat_free(mat
);
362 if (check_col(mat
, col
) < 0)
363 return isl_mat_free(mat
);
364 isl_int_set_si(mat
->row
[row
][col
], v
);
368 /* Replace the element at row "row", column "col" of "mat" by "v".
370 __isl_give isl_mat
*isl_mat_set_element_val(__isl_take isl_mat
*mat
,
371 int row
, int col
, __isl_take isl_val
*v
)
374 return isl_mat_free(mat
);
375 if (!isl_val_is_int(v
))
376 isl_die(isl_val_get_ctx(v
), isl_error_invalid
,
377 "expecting integer value", goto error
);
378 mat
= isl_mat_set_element(mat
, row
, col
, v
->n
);
383 return isl_mat_free(mat
);
386 __isl_give isl_mat
*isl_mat_diag(isl_ctx
*ctx
, unsigned n_row
, isl_int d
)
391 mat
= isl_mat_alloc(ctx
, n_row
, n_row
);
394 for (i
= 0; i
< n_row
; ++i
) {
395 isl_seq_clr(mat
->row
[i
], i
);
396 isl_int_set(mat
->row
[i
][i
], d
);
397 isl_seq_clr(mat
->row
[i
]+i
+1, n_row
-(i
+1));
403 /* Create an "n_row" by "n_col" matrix with zero elements.
405 __isl_give isl_mat
*isl_mat_zero(isl_ctx
*ctx
, unsigned n_row
, unsigned n_col
)
410 mat
= isl_mat_alloc(ctx
, n_row
, n_col
);
413 for (i
= 0; i
< n_row
; ++i
)
414 isl_seq_clr(mat
->row
[i
], n_col
);
419 __isl_give isl_mat
*isl_mat_identity(isl_ctx
*ctx
, unsigned n_row
)
423 return isl_mat_diag(ctx
, n_row
, ctx
->one
);
426 /* Is "mat" a (possibly scaled) identity matrix?
428 isl_bool
isl_mat_is_scaled_identity(__isl_keep isl_mat
*mat
)
433 return isl_bool_error
;
434 if (mat
->n_row
!= mat
->n_col
)
435 return isl_bool_false
;
437 for (i
= 0; i
< mat
->n_row
; ++i
) {
438 if (isl_seq_first_non_zero(mat
->row
[i
], i
) != -1)
439 return isl_bool_false
;
440 if (isl_int_ne(mat
->row
[0][0], mat
->row
[i
][i
]))
441 return isl_bool_false
;
442 if (isl_seq_first_non_zero(mat
->row
[i
] + i
+ 1,
443 mat
->n_col
- (i
+ 1)) != -1)
444 return isl_bool_false
;
447 return isl_bool_true
;
450 __isl_give isl_vec
*isl_mat_vec_product(__isl_take isl_mat
*mat
,
451 __isl_take isl_vec
*vec
)
454 struct isl_vec
*prod
;
459 isl_assert(mat
->ctx
, mat
->n_col
== vec
->size
, goto error
);
461 prod
= isl_vec_alloc(mat
->ctx
, mat
->n_row
);
465 for (i
= 0; i
< prod
->size
; ++i
)
466 isl_seq_inner_product(mat
->row
[i
], vec
->el
, vec
->size
,
467 &prod
->block
.data
[i
]);
477 __isl_give isl_vec
*isl_mat_vec_inverse_product(__isl_take isl_mat
*mat
,
478 __isl_take isl_vec
*vec
)
480 struct isl_mat
*vec_mat
;
485 vec_mat
= isl_mat_alloc(vec
->ctx
, vec
->size
, 1);
488 for (i
= 0; i
< vec
->size
; ++i
)
489 isl_int_set(vec_mat
->row
[i
][0], vec
->el
[i
]);
490 vec_mat
= isl_mat_inverse_product(mat
, vec_mat
);
494 vec
= isl_vec_alloc(vec_mat
->ctx
, vec_mat
->n_row
);
496 for (i
= 0; i
< vec
->size
; ++i
)
497 isl_int_set(vec
->el
[i
], vec_mat
->row
[i
][0]);
498 isl_mat_free(vec_mat
);
506 __isl_give isl_vec
*isl_vec_mat_product(__isl_take isl_vec
*vec
,
507 __isl_take isl_mat
*mat
)
510 struct isl_vec
*prod
;
515 isl_assert(mat
->ctx
, mat
->n_row
== vec
->size
, goto error
);
517 prod
= isl_vec_alloc(mat
->ctx
, mat
->n_col
);
521 for (i
= 0; i
< prod
->size
; ++i
) {
522 isl_int_set_si(prod
->el
[i
], 0);
523 for (j
= 0; j
< vec
->size
; ++j
)
524 isl_int_addmul(prod
->el
[i
], vec
->el
[j
], mat
->row
[j
][i
]);
535 __isl_give isl_mat
*isl_mat_aff_direct_sum(__isl_take isl_mat
*left
,
536 __isl_take isl_mat
*right
)
544 isl_assert(left
->ctx
, left
->n_row
== right
->n_row
, goto error
);
545 isl_assert(left
->ctx
, left
->n_row
>= 1, goto error
);
546 isl_assert(left
->ctx
, left
->n_col
>= 1, goto error
);
547 isl_assert(left
->ctx
, right
->n_col
>= 1, goto error
);
548 isl_assert(left
->ctx
,
549 isl_seq_first_non_zero(left
->row
[0]+1, left
->n_col
-1) == -1,
551 isl_assert(left
->ctx
,
552 isl_seq_first_non_zero(right
->row
[0]+1, right
->n_col
-1) == -1,
555 sum
= isl_mat_alloc(left
->ctx
, left
->n_row
, left
->n_col
+ right
->n_col
- 1);
558 isl_int_lcm(sum
->row
[0][0], left
->row
[0][0], right
->row
[0][0]);
559 isl_int_divexact(left
->row
[0][0], sum
->row
[0][0], left
->row
[0][0]);
560 isl_int_divexact(right
->row
[0][0], sum
->row
[0][0], right
->row
[0][0]);
562 isl_seq_clr(sum
->row
[0]+1, sum
->n_col
-1);
563 for (i
= 1; i
< sum
->n_row
; ++i
) {
564 isl_int_mul(sum
->row
[i
][0], left
->row
[0][0], left
->row
[i
][0]);
565 isl_int_addmul(sum
->row
[i
][0],
566 right
->row
[0][0], right
->row
[i
][0]);
567 isl_seq_scale(sum
->row
[i
]+1, left
->row
[i
]+1, left
->row
[0][0],
569 isl_seq_scale(sum
->row
[i
]+left
->n_col
,
570 right
->row
[i
]+1, right
->row
[0][0],
574 isl_int_divexact(left
->row
[0][0], sum
->row
[0][0], left
->row
[0][0]);
575 isl_int_divexact(right
->row
[0][0], sum
->row
[0][0], right
->row
[0][0]);
585 static void exchange(__isl_keep isl_mat
*M
, __isl_keep isl_mat
**U
,
586 __isl_keep isl_mat
**Q
, unsigned row
, unsigned i
, unsigned j
)
589 for (r
= row
; r
< M
->n_row
; ++r
)
590 isl_int_swap(M
->row
[r
][i
], M
->row
[r
][j
]);
592 for (r
= 0; r
< (*U
)->n_row
; ++r
)
593 isl_int_swap((*U
)->row
[r
][i
], (*U
)->row
[r
][j
]);
596 isl_mat_swap_rows(*Q
, i
, j
);
599 static void subtract(__isl_keep isl_mat
*M
, __isl_keep isl_mat
**U
,
600 __isl_keep isl_mat
**Q
, unsigned row
, unsigned i
, unsigned j
, isl_int m
)
603 for (r
= row
; r
< M
->n_row
; ++r
)
604 isl_int_submul(M
->row
[r
][j
], m
, M
->row
[r
][i
]);
606 for (r
= 0; r
< (*U
)->n_row
; ++r
)
607 isl_int_submul((*U
)->row
[r
][j
], m
, (*U
)->row
[r
][i
]);
610 for (r
= 0; r
< (*Q
)->n_col
; ++r
)
611 isl_int_addmul((*Q
)->row
[i
][r
], m
, (*Q
)->row
[j
][r
]);
615 static void oppose(__isl_keep isl_mat
*M
, __isl_keep isl_mat
**U
,
616 __isl_keep isl_mat
**Q
, unsigned row
, unsigned col
)
619 for (r
= row
; r
< M
->n_row
; ++r
)
620 isl_int_neg(M
->row
[r
][col
], M
->row
[r
][col
]);
622 for (r
= 0; r
< (*U
)->n_row
; ++r
)
623 isl_int_neg((*U
)->row
[r
][col
], (*U
)->row
[r
][col
]);
626 isl_seq_neg((*Q
)->row
[col
], (*Q
)->row
[col
], (*Q
)->n_col
);
629 /* Given matrix M, compute
634 * with U and Q unimodular matrices and H a matrix in column echelon form
635 * such that on each echelon row the entries in the non-echelon column
636 * are non-negative (if neg == 0) or non-positive (if neg == 1)
637 * and strictly smaller (in absolute value) than the entries in the echelon
639 * If U or Q are NULL, then these matrices are not computed.
641 __isl_give isl_mat
*isl_mat_left_hermite(__isl_take isl_mat
*M
, int neg
,
642 __isl_give isl_mat
**U
, __isl_give isl_mat
**Q
)
654 *U
= isl_mat_identity(M
->ctx
, M
->n_col
);
659 *Q
= isl_mat_identity(M
->ctx
, M
->n_col
);
673 for (row
= 0; row
< M
->n_row
; ++row
) {
675 first
= isl_seq_abs_min_non_zero(M
->row
[row
]+col
, M
->n_col
-col
);
680 exchange(M
, U
, Q
, row
, first
, col
);
681 if (isl_int_is_neg(M
->row
[row
][col
]))
682 oppose(M
, U
, Q
, row
, col
);
684 while ((off
= isl_seq_first_non_zero(M
->row
[row
]+first
,
685 M
->n_col
-first
)) != -1) {
687 isl_int_fdiv_q(c
, M
->row
[row
][first
], M
->row
[row
][col
]);
688 subtract(M
, U
, Q
, row
, col
, first
, c
);
689 if (!isl_int_is_zero(M
->row
[row
][first
]))
690 exchange(M
, U
, Q
, row
, first
, col
);
694 for (i
= 0; i
< col
; ++i
) {
695 if (isl_int_is_zero(M
->row
[row
][i
]))
698 isl_int_cdiv_q(c
, M
->row
[row
][i
], M
->row
[row
][col
]);
700 isl_int_fdiv_q(c
, M
->row
[row
][i
], M
->row
[row
][col
]);
701 if (isl_int_is_zero(c
))
703 subtract(M
, U
, Q
, row
, col
, i
, c
);
723 /* Use row "row" of "mat" to eliminate column "col" from all other rows.
725 static __isl_give isl_mat
*eliminate(__isl_take isl_mat
*mat
, int row
, int col
)
731 nr
= isl_mat_rows(mat
);
732 nc
= isl_mat_cols(mat
);
733 if (nr
< 0 || nc
< 0)
734 return isl_mat_free(mat
);
736 ctx
= isl_mat_get_ctx(mat
);
738 for (k
= 0; k
< nr
; ++k
) {
741 if (isl_int_is_zero(mat
->row
[k
][col
]))
743 mat
= isl_mat_cow(mat
);
746 isl_seq_elim(mat
->row
[k
], mat
->row
[row
], col
, nc
, NULL
);
747 isl_seq_normalize(ctx
, mat
->row
[k
], nc
);
753 /* Perform Gaussian elimination on the rows of "mat", but start
754 * from the final row and the final column.
755 * Any zero rows that result from the elimination are removed.
757 * In particular, for each column from last to first,
758 * look for the last row with a non-zero coefficient in that column,
759 * move it last (but before other rows moved last in previous steps) and
760 * use it to eliminate the column from the other rows.
762 __isl_give isl_mat
*isl_mat_reverse_gauss(__isl_take isl_mat
*mat
)
767 nr
= isl_mat_rows(mat
);
768 nc
= isl_mat_cols(mat
);
769 if (nr
< 0 || nc
< 0)
770 return isl_mat_free(mat
);
773 for (row
= nr
- 1; row
>= 0; --row
) {
774 for (; last
>= 0; --last
) {
775 for (k
= row
; k
>= 0; --k
)
776 if (!isl_int_is_zero(mat
->row
[k
][last
]))
784 mat
= isl_mat_swap_rows(mat
, k
, row
);
787 if (isl_int_is_neg(mat
->row
[row
][last
]))
788 mat
= isl_mat_row_neg(mat
, row
);
789 mat
= eliminate(mat
, row
, last
);
793 mat
= isl_mat_drop_rows(mat
, 0, row
+ 1);
798 /* Negate the lexicographically negative rows of "mat" such that
799 * all rows in the result are lexicographically non-negative.
801 __isl_give isl_mat
*isl_mat_lexnonneg_rows(__isl_take isl_mat
*mat
)
806 nr
= isl_mat_rows(mat
);
807 nc
= isl_mat_cols(mat
);
808 if (nr
< 0 || nc
< 0)
809 return isl_mat_free(mat
);
811 for (i
= 0; i
< nr
; ++i
) {
814 pos
= isl_seq_first_non_zero(mat
->row
[i
], nc
);
817 if (isl_int_is_nonneg(mat
->row
[i
][pos
]))
819 mat
= isl_mat_row_neg(mat
, i
);
827 /* Given a matrix "H" is column echelon form, what is the first
828 * zero column? That is how many initial columns are non-zero?
829 * Start looking at column "first_col" and only consider
830 * the columns to be of size "n_row".
831 * "H" is assumed to be non-NULL.
833 * Since "H" is in column echelon form, the first non-zero entry
834 * in a column is always in a later position compared to the previous column.
836 static int hermite_first_zero_col(__isl_keep isl_mat
*H
, int first_col
,
841 for (col
= first_col
, row
= 0; col
< H
->n_col
; ++col
) {
842 for (; row
< n_row
; ++row
)
843 if (!isl_int_is_zero(H
->row
[row
][col
]))
852 /* Return the rank of "mat", or isl_size_error in case of error.
854 isl_size
isl_mat_rank(__isl_keep isl_mat
*mat
)
859 H
= isl_mat_left_hermite(isl_mat_copy(mat
), 0, NULL
, NULL
);
861 return isl_size_error
;
863 rank
= hermite_first_zero_col(H
, 0, H
->n_row
);
869 __isl_give isl_mat
*isl_mat_right_kernel(__isl_take isl_mat
*mat
)
872 struct isl_mat
*U
= NULL
;
875 mat
= isl_mat_left_hermite(mat
, 0, &U
, NULL
);
879 rank
= hermite_first_zero_col(mat
, 0, mat
->n_row
);
880 K
= isl_mat_alloc(U
->ctx
, U
->n_row
, U
->n_col
- rank
);
883 isl_mat_sub_copy(K
->ctx
, K
->row
, U
->row
, U
->n_row
, 0, rank
, U
->n_col
-rank
);
893 __isl_give isl_mat
*isl_mat_lin_to_aff(__isl_take isl_mat
*mat
)
896 struct isl_mat
*mat2
;
900 mat2
= isl_mat_alloc(mat
->ctx
, 1+mat
->n_row
, 1+mat
->n_col
);
903 isl_int_set_si(mat2
->row
[0][0], 1);
904 isl_seq_clr(mat2
->row
[0]+1, mat
->n_col
);
905 for (i
= 0; i
< mat
->n_row
; ++i
) {
906 isl_int_set_si(mat2
->row
[1+i
][0], 0);
907 isl_seq_cpy(mat2
->row
[1+i
]+1, mat
->row
[i
], mat
->n_col
);
916 /* Given two matrices M1 and M2, return the block matrix
921 __isl_give isl_mat
*isl_mat_diagonal(__isl_take isl_mat
*mat1
,
922 __isl_take isl_mat
*mat2
)
930 mat
= isl_mat_alloc(mat1
->ctx
, mat1
->n_row
+ mat2
->n_row
,
931 mat1
->n_col
+ mat2
->n_col
);
934 for (i
= 0; i
< mat1
->n_row
; ++i
) {
935 isl_seq_cpy(mat
->row
[i
], mat1
->row
[i
], mat1
->n_col
);
936 isl_seq_clr(mat
->row
[i
] + mat1
->n_col
, mat2
->n_col
);
938 for (i
= 0; i
< mat2
->n_row
; ++i
) {
939 isl_seq_clr(mat
->row
[mat1
->n_row
+ i
], mat1
->n_col
);
940 isl_seq_cpy(mat
->row
[mat1
->n_row
+ i
] + mat1
->n_col
,
941 mat2
->row
[i
], mat2
->n_col
);
952 static int row_first_non_zero(isl_int
**row
, unsigned n_row
, unsigned col
)
956 for (i
= 0; i
< n_row
; ++i
)
957 if (!isl_int_is_zero(row
[i
][col
]))
962 static int row_abs_min_non_zero(isl_int
**row
, unsigned n_row
, unsigned col
)
964 int i
, min
= row_first_non_zero(row
, n_row
, col
);
967 for (i
= min
+ 1; i
< n_row
; ++i
) {
968 if (isl_int_is_zero(row
[i
][col
]))
970 if (isl_int_abs_lt(row
[i
][col
], row
[min
][col
]))
976 static isl_stat
inv_exchange(__isl_keep isl_mat
**left
,
977 __isl_keep isl_mat
**right
, unsigned i
, unsigned j
)
979 *left
= isl_mat_swap_rows(*left
, i
, j
);
980 *right
= isl_mat_swap_rows(*right
, i
, j
);
982 if (!*left
|| !*right
)
983 return isl_stat_error
;
987 static void inv_oppose(
988 __isl_keep isl_mat
*left
, __isl_keep isl_mat
*right
, unsigned row
)
990 isl_seq_neg(left
->row
[row
]+row
, left
->row
[row
]+row
, left
->n_col
-row
);
991 isl_seq_neg(right
->row
[row
], right
->row
[row
], right
->n_col
);
994 static void inv_subtract(__isl_keep isl_mat
*left
, __isl_keep isl_mat
*right
,
995 unsigned row
, unsigned i
, isl_int m
)
998 isl_seq_combine(left
->row
[i
]+row
,
999 left
->ctx
->one
, left
->row
[i
]+row
,
1000 m
, left
->row
[row
]+row
,
1002 isl_seq_combine(right
->row
[i
], right
->ctx
->one
, right
->row
[i
],
1003 m
, right
->row
[row
], right
->n_col
);
1006 /* Compute inv(left)*right
1008 __isl_give isl_mat
*isl_mat_inverse_product(__isl_take isl_mat
*left
,
1009 __isl_take isl_mat
*right
)
1014 if (!left
|| !right
)
1017 isl_assert(left
->ctx
, left
->n_row
== left
->n_col
, goto error
);
1018 isl_assert(left
->ctx
, left
->n_row
== right
->n_row
, goto error
);
1020 if (left
->n_row
== 0) {
1025 left
= isl_mat_cow(left
);
1026 right
= isl_mat_cow(right
);
1027 if (!left
|| !right
)
1032 for (row
= 0; row
< left
->n_row
; ++row
) {
1033 int pivot
, first
, i
, off
;
1034 pivot
= row_abs_min_non_zero(left
->row
+row
, left
->n_row
-row
, row
);
1038 isl_assert(left
->ctx
, pivot
>= 0, goto error
);
1042 if (inv_exchange(&left
, &right
, pivot
, row
) < 0)
1044 if (isl_int_is_neg(left
->row
[row
][row
]))
1045 inv_oppose(left
, right
, row
);
1047 while ((off
= row_first_non_zero(left
->row
+first
,
1048 left
->n_row
-first
, row
)) != -1) {
1050 isl_int_fdiv_q(a
, left
->row
[first
][row
],
1051 left
->row
[row
][row
]);
1052 inv_subtract(left
, right
, row
, first
, a
);
1053 if (!isl_int_is_zero(left
->row
[first
][row
])) {
1054 if (inv_exchange(&left
, &right
, row
, first
) < 0)
1060 for (i
= 0; i
< row
; ++i
) {
1061 if (isl_int_is_zero(left
->row
[i
][row
]))
1063 isl_int_gcd(a
, left
->row
[row
][row
], left
->row
[i
][row
]);
1064 isl_int_divexact(b
, left
->row
[i
][row
], a
);
1065 isl_int_divexact(a
, left
->row
[row
][row
], a
);
1067 isl_seq_combine(left
->row
[i
] + i
,
1068 a
, left
->row
[i
] + i
,
1069 b
, left
->row
[row
] + i
,
1071 isl_seq_combine(right
->row
[i
], a
, right
->row
[i
],
1072 b
, right
->row
[row
], right
->n_col
);
1077 isl_int_set(a
, left
->row
[0][0]);
1078 for (row
= 1; row
< left
->n_row
; ++row
)
1079 isl_int_lcm(a
, a
, left
->row
[row
][row
]);
1080 if (isl_int_is_zero(a
)){
1082 isl_assert(left
->ctx
, 0, goto error
);
1084 for (row
= 0; row
< left
->n_row
; ++row
) {
1085 isl_int_divexact(left
->row
[row
][row
], a
, left
->row
[row
][row
]);
1086 if (isl_int_is_one(left
->row
[row
][row
]))
1088 isl_seq_scale(right
->row
[row
], right
->row
[row
],
1089 left
->row
[row
][row
], right
->n_col
);
1097 isl_mat_free(right
);
1101 void isl_mat_col_scale(__isl_keep isl_mat
*mat
, unsigned col
, isl_int m
)
1105 for (i
= 0; i
< mat
->n_row
; ++i
)
1106 isl_int_mul(mat
->row
[i
][col
], mat
->row
[i
][col
], m
);
1109 void isl_mat_col_combine(__isl_keep isl_mat
*mat
, unsigned dst
,
1110 isl_int m1
, unsigned src1
, isl_int m2
, unsigned src2
)
1116 for (i
= 0; i
< mat
->n_row
; ++i
) {
1117 isl_int_mul(tmp
, m1
, mat
->row
[i
][src1
]);
1118 isl_int_addmul(tmp
, m2
, mat
->row
[i
][src2
]);
1119 isl_int_set(mat
->row
[i
][dst
], tmp
);
1124 __isl_give isl_mat
*isl_mat_right_inverse(__isl_take isl_mat
*mat
)
1126 struct isl_mat
*inv
;
1130 mat
= isl_mat_cow(mat
);
1134 inv
= isl_mat_identity(mat
->ctx
, mat
->n_col
);
1135 inv
= isl_mat_cow(inv
);
1141 for (row
= 0; row
< mat
->n_row
; ++row
) {
1142 int pivot
, first
, i
, off
;
1143 pivot
= isl_seq_abs_min_non_zero(mat
->row
[row
]+row
, mat
->n_col
-row
);
1147 isl_assert(mat
->ctx
, pivot
>= 0, goto error
);
1151 exchange(mat
, &inv
, NULL
, row
, pivot
, row
);
1152 if (isl_int_is_neg(mat
->row
[row
][row
]))
1153 oppose(mat
, &inv
, NULL
, row
, row
);
1155 while ((off
= isl_seq_first_non_zero(mat
->row
[row
]+first
,
1156 mat
->n_col
-first
)) != -1) {
1158 isl_int_fdiv_q(a
, mat
->row
[row
][first
],
1159 mat
->row
[row
][row
]);
1160 subtract(mat
, &inv
, NULL
, row
, row
, first
, a
);
1161 if (!isl_int_is_zero(mat
->row
[row
][first
]))
1162 exchange(mat
, &inv
, NULL
, row
, row
, first
);
1166 for (i
= 0; i
< row
; ++i
) {
1167 if (isl_int_is_zero(mat
->row
[row
][i
]))
1169 isl_int_gcd(a
, mat
->row
[row
][row
], mat
->row
[row
][i
]);
1170 isl_int_divexact(b
, mat
->row
[row
][i
], a
);
1171 isl_int_divexact(a
, mat
->row
[row
][row
], a
);
1173 isl_mat_col_combine(mat
, i
, a
, i
, b
, row
);
1174 isl_mat_col_combine(inv
, i
, a
, i
, b
, row
);
1179 isl_int_set(a
, mat
->row
[0][0]);
1180 for (row
= 1; row
< mat
->n_row
; ++row
)
1181 isl_int_lcm(a
, a
, mat
->row
[row
][row
]);
1182 if (isl_int_is_zero(a
)){
1186 for (row
= 0; row
< mat
->n_row
; ++row
) {
1187 isl_int_divexact(mat
->row
[row
][row
], a
, mat
->row
[row
][row
]);
1188 if (isl_int_is_one(mat
->row
[row
][row
]))
1190 isl_mat_col_scale(inv
, row
, mat
->row
[row
][row
]);
1203 __isl_give isl_mat
*isl_mat_transpose(__isl_take isl_mat
*mat
)
1205 struct isl_mat
*transpose
= NULL
;
1211 if (mat
->n_col
== mat
->n_row
) {
1212 mat
= isl_mat_cow(mat
);
1215 for (i
= 0; i
< mat
->n_row
; ++i
)
1216 for (j
= i
+ 1; j
< mat
->n_col
; ++j
)
1217 isl_int_swap(mat
->row
[i
][j
], mat
->row
[j
][i
]);
1220 transpose
= isl_mat_alloc(mat
->ctx
, mat
->n_col
, mat
->n_row
);
1223 for (i
= 0; i
< mat
->n_row
; ++i
)
1224 for (j
= 0; j
< mat
->n_col
; ++j
)
1225 isl_int_set(transpose
->row
[j
][i
], mat
->row
[i
][j
]);
1233 __isl_give isl_mat
*isl_mat_swap_cols(__isl_take isl_mat
*mat
,
1234 unsigned i
, unsigned j
)
1238 mat
= isl_mat_cow(mat
);
1239 if (check_col_range(mat
, i
, 1) < 0 ||
1240 check_col_range(mat
, j
, 1) < 0)
1241 return isl_mat_free(mat
);
1243 for (r
= 0; r
< mat
->n_row
; ++r
)
1244 isl_int_swap(mat
->row
[r
][i
], mat
->row
[r
][j
]);
1248 __isl_give isl_mat
*isl_mat_swap_rows(__isl_take isl_mat
*mat
,
1249 unsigned i
, unsigned j
)
1255 mat
= isl_mat_cow(mat
);
1256 if (check_row_range(mat
, i
, 1) < 0 ||
1257 check_row_range(mat
, j
, 1) < 0)
1258 return isl_mat_free(mat
);
1261 mat
->row
[i
] = mat
->row
[j
];
1266 /* Calculate the product of two matrices.
1268 * This function is optimized for operand matrices that contain many zeros and
1269 * skips multiplications where we know one of the operands is zero.
1271 __isl_give isl_mat
*isl_mat_product(__isl_take isl_mat
*left
,
1272 __isl_take isl_mat
*right
)
1275 struct isl_mat
*prod
;
1277 if (!left
|| !right
)
1279 isl_assert(left
->ctx
, left
->n_col
== right
->n_row
, goto error
);
1280 prod
= isl_mat_alloc(left
->ctx
, left
->n_row
, right
->n_col
);
1283 if (left
->n_col
== 0) {
1284 for (i
= 0; i
< prod
->n_row
; ++i
)
1285 isl_seq_clr(prod
->row
[i
], prod
->n_col
);
1287 isl_mat_free(right
);
1290 for (i
= 0; i
< prod
->n_row
; ++i
) {
1291 for (j
= 0; j
< prod
->n_col
; ++j
)
1292 isl_int_mul(prod
->row
[i
][j
],
1293 left
->row
[i
][0], right
->row
[0][j
]);
1294 for (k
= 1; k
< left
->n_col
; ++k
) {
1295 if (isl_int_is_zero(left
->row
[i
][k
]))
1297 for (j
= 0; j
< prod
->n_col
; ++j
)
1298 isl_int_addmul(prod
->row
[i
][j
],
1299 left
->row
[i
][k
], right
->row
[k
][j
]);
1303 isl_mat_free(right
);
1307 isl_mat_free(right
);
1311 /* Replace the variables x in the rows q by x' given by x = M x',
1312 * with M the matrix mat.
1314 * If the number of new variables is greater than the original
1315 * number of variables, then the rows q have already been
1316 * preextended. If the new number is smaller, then the coefficients
1317 * of the divs, which are not changed, need to be shifted down.
1318 * The row q may be the equalities, the inequalities or the
1319 * div expressions. In the latter case, has_div is true and
1320 * we need to take into account the extra denominator column.
1322 static int preimage(struct isl_ctx
*ctx
, isl_int
**q
, unsigned n
,
1323 unsigned n_div
, int has_div
, struct isl_mat
*mat
)
1329 if (mat
->n_col
>= mat
->n_row
)
1332 e
= mat
->n_row
- mat
->n_col
;
1334 for (i
= 0; i
< n
; ++i
)
1335 isl_int_mul(q
[i
][0], q
[i
][0], mat
->row
[0][0]);
1336 t
= isl_mat_sub_alloc6(mat
->ctx
, q
, 0, n
, has_div
, mat
->n_row
);
1337 t
= isl_mat_product(t
, mat
);
1340 for (i
= 0; i
< n
; ++i
) {
1341 isl_seq_swp_or_cpy(q
[i
] + has_div
, t
->row
[i
], t
->n_col
);
1342 isl_seq_cpy(q
[i
] + has_div
+ t
->n_col
,
1343 q
[i
] + has_div
+ t
->n_col
+ e
, n_div
);
1344 isl_seq_clr(q
[i
] + has_div
+ t
->n_col
+ n_div
, e
);
1350 /* Replace the variables x in bset by x' given by x = M x', with
1353 * If there are fewer variables x' then there are x, then we perform
1354 * the transformation in place, which means that, in principle,
1355 * this frees up some extra variables as the number
1356 * of columns remains constant, but we would have to extend
1357 * the div array too as the number of rows in this array is assumed
1358 * to be equal to extra.
1360 __isl_give isl_basic_set
*isl_basic_set_preimage(
1361 __isl_take isl_basic_set
*bset
, __isl_take isl_mat
*mat
)
1363 struct isl_ctx
*ctx
;
1369 bset
= isl_basic_set_cow(bset
);
1370 if (isl_basic_set_check_no_params(bset
) < 0)
1373 isl_assert(ctx
, 1+bset
->dim
->n_out
== mat
->n_row
, goto error
);
1374 isl_assert(ctx
, mat
->n_col
> 0, goto error
);
1376 if (mat
->n_col
> mat
->n_row
) {
1377 bset
= isl_basic_set_add_dims(bset
, isl_dim_set
,
1378 mat
->n_col
- mat
->n_row
);
1381 } else if (mat
->n_col
< mat
->n_row
) {
1382 bset
->dim
= isl_space_cow(bset
->dim
);
1385 bset
->dim
->n_out
-= mat
->n_row
- mat
->n_col
;
1388 if (preimage(ctx
, bset
->eq
, bset
->n_eq
, bset
->n_div
, 0,
1389 isl_mat_copy(mat
)) < 0)
1392 if (preimage(ctx
, bset
->ineq
, bset
->n_ineq
, bset
->n_div
, 0,
1393 isl_mat_copy(mat
)) < 0)
1396 if (preimage(ctx
, bset
->div
, bset
->n_div
, bset
->n_div
, 1, mat
) < 0)
1399 ISL_F_CLR(bset
, ISL_BASIC_SET_NO_IMPLICIT
);
1400 ISL_F_CLR(bset
, ISL_BASIC_SET_NO_REDUNDANT
);
1401 ISL_F_CLR(bset
, ISL_BASIC_SET_SORTED
);
1402 ISL_F_CLR(bset
, ISL_BASIC_SET_NORMALIZED_DIVS
);
1403 ISL_F_CLR(bset
, ISL_BASIC_SET_ALL_EQUALITIES
);
1404 ISL_F_CLR(bset
, ISL_BASIC_SET_REDUCED_COEFFICIENTS
);
1406 bset
= isl_basic_set_simplify(bset
);
1407 bset
= isl_basic_set_finalize(bset
);
1413 isl_basic_set_free(bset
);
1417 __isl_give isl_set
*isl_set_preimage(
1418 __isl_take isl_set
*set
, __isl_take isl_mat
*mat
)
1422 set
= isl_set_cow(set
);
1426 for (i
= 0; i
< set
->n
; ++i
) {
1427 set
->p
[i
] = isl_basic_set_preimage(set
->p
[i
],
1432 if (mat
->n_col
!= mat
->n_row
) {
1433 set
->dim
= isl_space_cow(set
->dim
);
1436 set
->dim
->n_out
+= mat
->n_col
;
1437 set
->dim
->n_out
-= mat
->n_row
;
1440 ISL_F_CLR(set
, ISL_SET_NORMALIZED
);
1448 /* Replace the variables x starting at "first_col" in the rows "rows"
1449 * of some coefficient matrix by x' with x = M x' with M the matrix mat.
1450 * That is, replace the corresponding coefficients c by c M.
1452 isl_stat
isl_mat_sub_transform(isl_int
**row
, unsigned n_row
,
1453 unsigned first_col
, __isl_take isl_mat
*mat
)
1460 return isl_stat_error
;
1461 ctx
= isl_mat_get_ctx(mat
);
1462 t
= isl_mat_sub_alloc6(ctx
, row
, 0, n_row
, first_col
, mat
->n_row
);
1463 t
= isl_mat_product(t
, mat
);
1465 return isl_stat_error
;
1466 for (i
= 0; i
< n_row
; ++i
)
1467 isl_seq_swp_or_cpy(row
[i
] + first_col
, t
->row
[i
], t
->n_col
);
1472 void isl_mat_print_internal(__isl_keep isl_mat
*mat
, FILE *out
, int indent
)
1477 fprintf(out
, "%*snull mat\n", indent
, "");
1481 if (mat
->n_row
== 0)
1482 fprintf(out
, "%*s[]\n", indent
, "");
1484 for (i
= 0; i
< mat
->n_row
; ++i
) {
1486 fprintf(out
, "%*s[[", indent
, "");
1488 fprintf(out
, "%*s[", indent
+1, "");
1489 for (j
= 0; j
< mat
->n_col
; ++j
) {
1492 isl_int_print(out
, mat
->row
[i
][j
], 0);
1494 if (i
== mat
->n_row
-1)
1495 fprintf(out
, "]]\n");
1497 fprintf(out
, "]\n");
1501 void isl_mat_dump(__isl_keep isl_mat
*mat
)
1503 isl_mat_print_internal(mat
, stderr
, 0);
1506 __isl_give isl_mat
*isl_mat_drop_cols(__isl_take isl_mat
*mat
,
1507 unsigned col
, unsigned n
)
1514 mat
= isl_mat_cow(mat
);
1515 if (check_col_range(mat
, col
, n
) < 0)
1516 return isl_mat_free(mat
);
1518 if (col
!= mat
->n_col
-n
) {
1519 for (r
= 0; r
< mat
->n_row
; ++r
)
1520 isl_seq_cpy(mat
->row
[r
]+col
, mat
->row
[r
]+col
+n
,
1521 mat
->n_col
- col
- n
);
1527 __isl_give isl_mat
*isl_mat_drop_rows(__isl_take isl_mat
*mat
,
1528 unsigned row
, unsigned n
)
1532 mat
= isl_mat_cow(mat
);
1533 if (check_row_range(mat
, row
, n
) < 0)
1534 return isl_mat_free(mat
);
1536 for (r
= row
; r
+n
< mat
->n_row
; ++r
)
1537 mat
->row
[r
] = mat
->row
[r
+n
];
1543 __isl_give isl_mat
*isl_mat_insert_cols(__isl_take isl_mat
*mat
,
1544 unsigned col
, unsigned n
)
1548 if (check_col_range(mat
, col
, 0) < 0)
1549 return isl_mat_free(mat
);
1553 ext
= isl_mat_alloc(mat
->ctx
, mat
->n_row
, mat
->n_col
+ n
);
1557 isl_mat_sub_copy(mat
->ctx
, ext
->row
, mat
->row
, mat
->n_row
, 0, 0, col
);
1558 isl_mat_sub_copy(mat
->ctx
, ext
->row
, mat
->row
, mat
->n_row
,
1559 col
+ n
, col
, mat
->n_col
- col
);
1568 __isl_give isl_mat
*isl_mat_insert_zero_cols(__isl_take isl_mat
*mat
,
1569 unsigned first
, unsigned n
)
1575 mat
= isl_mat_insert_cols(mat
, first
, n
);
1579 for (i
= 0; i
< mat
->n_row
; ++i
)
1580 isl_seq_clr(mat
->row
[i
] + first
, n
);
1585 __isl_give isl_mat
*isl_mat_add_zero_cols(__isl_take isl_mat
*mat
, unsigned n
)
1590 return isl_mat_insert_zero_cols(mat
, mat
->n_col
, n
);
1593 __isl_give isl_mat
*isl_mat_insert_rows(__isl_take isl_mat
*mat
,
1594 unsigned row
, unsigned n
)
1598 if (check_row_range(mat
, row
, 0) < 0)
1599 return isl_mat_free(mat
);
1603 ext
= isl_mat_alloc(mat
->ctx
, mat
->n_row
+ n
, mat
->n_col
);
1607 isl_mat_sub_copy(mat
->ctx
, ext
->row
, mat
->row
, row
, 0, 0, mat
->n_col
);
1608 isl_mat_sub_copy(mat
->ctx
, ext
->row
+ row
+ n
, mat
->row
+ row
,
1609 mat
->n_row
- row
, 0, 0, mat
->n_col
);
1618 __isl_give isl_mat
*isl_mat_add_rows(__isl_take isl_mat
*mat
, unsigned n
)
1623 return isl_mat_insert_rows(mat
, mat
->n_row
, n
);
1626 __isl_give isl_mat
*isl_mat_insert_zero_rows(__isl_take isl_mat
*mat
,
1627 unsigned row
, unsigned n
)
1631 mat
= isl_mat_insert_rows(mat
, row
, n
);
1635 for (i
= 0; i
< n
; ++i
)
1636 isl_seq_clr(mat
->row
[row
+ i
], mat
->n_col
);
1641 __isl_give isl_mat
*isl_mat_add_zero_rows(__isl_take isl_mat
*mat
, unsigned n
)
1646 return isl_mat_insert_zero_rows(mat
, mat
->n_row
, n
);
1649 void isl_mat_col_submul(__isl_keep isl_mat
*mat
,
1650 int dst_col
, isl_int f
, int src_col
)
1654 for (i
= 0; i
< mat
->n_row
; ++i
)
1655 isl_int_submul(mat
->row
[i
][dst_col
], f
, mat
->row
[i
][src_col
]);
1658 void isl_mat_col_add(__isl_keep isl_mat
*mat
, int dst_col
, int src_col
)
1665 for (i
= 0; i
< mat
->n_row
; ++i
)
1666 isl_int_add(mat
->row
[i
][dst_col
],
1667 mat
->row
[i
][dst_col
], mat
->row
[i
][src_col
]);
1670 void isl_mat_col_mul(__isl_keep isl_mat
*mat
, int dst_col
, isl_int f
,
1675 for (i
= 0; i
< mat
->n_row
; ++i
)
1676 isl_int_mul(mat
->row
[i
][dst_col
], f
, mat
->row
[i
][src_col
]);
1679 /* Add "f" times column "src_col" to column "dst_col" of "mat" and
1680 * return the result.
1682 __isl_give isl_mat
*isl_mat_col_addmul(__isl_take isl_mat
*mat
, int dst_col
,
1683 isl_int f
, int src_col
)
1687 if (check_col(mat
, dst_col
) < 0 || check_col(mat
, src_col
) < 0)
1688 return isl_mat_free(mat
);
1690 for (i
= 0; i
< mat
->n_row
; ++i
) {
1691 if (isl_int_is_zero(mat
->row
[i
][src_col
]))
1693 mat
= isl_mat_cow(mat
);
1696 isl_int_addmul(mat
->row
[i
][dst_col
], f
, mat
->row
[i
][src_col
]);
1702 /* Negate column "col" of "mat" and return the result.
1704 __isl_give isl_mat
*isl_mat_col_neg(__isl_take isl_mat
*mat
, int col
)
1708 if (check_col(mat
, col
) < 0)
1709 return isl_mat_free(mat
);
1711 for (i
= 0; i
< mat
->n_row
; ++i
) {
1712 if (isl_int_is_zero(mat
->row
[i
][col
]))
1714 mat
= isl_mat_cow(mat
);
1717 isl_int_neg(mat
->row
[i
][col
], mat
->row
[i
][col
]);
1723 /* Negate row "row" of "mat" and return the result.
1725 __isl_give isl_mat
*isl_mat_row_neg(__isl_take isl_mat
*mat
, int row
)
1727 if (check_row(mat
, row
) < 0)
1728 return isl_mat_free(mat
);
1729 if (isl_seq_first_non_zero(mat
->row
[row
], mat
->n_col
) == -1)
1731 mat
= isl_mat_cow(mat
);
1734 isl_seq_neg(mat
->row
[row
], mat
->row
[row
], mat
->n_col
);
1738 __isl_give isl_mat
*isl_mat_unimodular_complete(__isl_take isl_mat
*M
, int row
)
1741 struct isl_mat
*H
= NULL
, *Q
= NULL
;
1746 isl_assert(M
->ctx
, M
->n_row
== M
->n_col
, goto error
);
1748 H
= isl_mat_left_hermite(isl_mat_copy(M
), 0, NULL
, &Q
);
1749 M
->n_row
= M
->n_col
;
1752 for (r
= 0; r
< row
; ++r
)
1753 isl_assert(M
->ctx
, isl_int_is_one(H
->row
[r
][r
]), goto error
);
1754 for (r
= row
; r
< M
->n_row
; ++r
)
1755 isl_seq_cpy(M
->row
[r
], Q
->row
[r
], M
->n_col
);
1766 __isl_give isl_mat
*isl_mat_concat(__isl_take isl_mat
*top
,
1767 __isl_take isl_mat
*bot
)
1769 struct isl_mat
*mat
;
1774 isl_assert(top
->ctx
, top
->n_col
== bot
->n_col
, goto error
);
1775 if (top
->n_row
== 0) {
1779 if (bot
->n_row
== 0) {
1784 mat
= isl_mat_alloc(top
->ctx
, top
->n_row
+ bot
->n_row
, top
->n_col
);
1787 isl_mat_sub_copy(mat
->ctx
, mat
->row
, top
->row
, top
->n_row
,
1789 isl_mat_sub_copy(mat
->ctx
, mat
->row
+ top
->n_row
, bot
->row
, bot
->n_row
,
1800 isl_bool
isl_mat_is_equal(__isl_keep isl_mat
*mat1
, __isl_keep isl_mat
*mat2
)
1805 return isl_bool_error
;
1807 if (mat1
->n_row
!= mat2
->n_row
)
1808 return isl_bool_false
;
1810 if (mat1
->n_col
!= mat2
->n_col
)
1811 return isl_bool_false
;
1813 for (i
= 0; i
< mat1
->n_row
; ++i
)
1814 if (!isl_seq_eq(mat1
->row
[i
], mat2
->row
[i
], mat1
->n_col
))
1815 return isl_bool_false
;
1817 return isl_bool_true
;
1820 __isl_give isl_mat
*isl_mat_from_row_vec(__isl_take isl_vec
*vec
)
1822 struct isl_mat
*mat
;
1826 mat
= isl_mat_alloc(vec
->ctx
, 1, vec
->size
);
1830 isl_seq_cpy(mat
->row
[0], vec
->el
, vec
->size
);
1839 /* Return a copy of row "row" of "mat" as an isl_vec.
1841 __isl_give isl_vec
*isl_mat_get_row(__isl_keep isl_mat
*mat
, unsigned row
)
1847 if (row
>= mat
->n_row
)
1848 isl_die(mat
->ctx
, isl_error_invalid
, "row out of range",
1851 v
= isl_vec_alloc(isl_mat_get_ctx(mat
), mat
->n_col
);
1854 isl_seq_cpy(v
->el
, mat
->row
[row
], mat
->n_col
);
1859 __isl_give isl_mat
*isl_mat_vec_concat(__isl_take isl_mat
*top
,
1860 __isl_take isl_vec
*bot
)
1862 return isl_mat_concat(top
, isl_mat_from_row_vec(bot
));
1865 __isl_give isl_mat
*isl_mat_move_cols(__isl_take isl_mat
*mat
,
1866 unsigned dst_col
, unsigned src_col
, unsigned n
)
1872 if (n
== 0 || dst_col
== src_col
)
1875 res
= isl_mat_alloc(mat
->ctx
, mat
->n_row
, mat
->n_col
);
1879 if (dst_col
< src_col
) {
1880 isl_mat_sub_copy(res
->ctx
, res
->row
, mat
->row
, mat
->n_row
,
1882 isl_mat_sub_copy(res
->ctx
, res
->row
, mat
->row
, mat
->n_row
,
1883 dst_col
, src_col
, n
);
1884 isl_mat_sub_copy(res
->ctx
, res
->row
, mat
->row
, mat
->n_row
,
1885 dst_col
+ n
, dst_col
, src_col
- dst_col
);
1886 isl_mat_sub_copy(res
->ctx
, res
->row
, mat
->row
, mat
->n_row
,
1887 src_col
+ n
, src_col
+ n
,
1888 res
->n_col
- src_col
- n
);
1890 isl_mat_sub_copy(res
->ctx
, res
->row
, mat
->row
, mat
->n_row
,
1892 isl_mat_sub_copy(res
->ctx
, res
->row
, mat
->row
, mat
->n_row
,
1893 src_col
, src_col
+ n
, dst_col
- src_col
);
1894 isl_mat_sub_copy(res
->ctx
, res
->row
, mat
->row
, mat
->n_row
,
1895 dst_col
, src_col
, n
);
1896 isl_mat_sub_copy(res
->ctx
, res
->row
, mat
->row
, mat
->n_row
,
1897 dst_col
+ n
, dst_col
+ n
,
1898 res
->n_col
- dst_col
- n
);
1908 /* Return the gcd of the elements in row "row" of "mat" in *gcd.
1909 * Return isl_stat_ok on success and isl_stat_error on failure.
1911 isl_stat
isl_mat_row_gcd(__isl_keep isl_mat
*mat
, int row
, isl_int
*gcd
)
1913 if (check_row(mat
, row
) < 0)
1914 return isl_stat_error
;
1916 isl_seq_gcd(mat
->row
[row
], mat
->n_col
, gcd
);
1921 void isl_mat_gcd(__isl_keep isl_mat
*mat
, isl_int
*gcd
)
1926 isl_int_set_si(*gcd
, 0);
1931 for (i
= 0; i
< mat
->n_row
; ++i
) {
1932 isl_seq_gcd(mat
->row
[i
], mat
->n_col
, &g
);
1933 isl_int_gcd(*gcd
, *gcd
, g
);
1938 /* Return the result of scaling "mat" by a factor of "m".
1940 __isl_give isl_mat
*isl_mat_scale(__isl_take isl_mat
*mat
, isl_int m
)
1944 if (isl_int_is_one(m
))
1947 mat
= isl_mat_cow(mat
);
1951 for (i
= 0; i
< mat
->n_row
; ++i
)
1952 isl_seq_scale(mat
->row
[i
], mat
->row
[i
], m
, mat
->n_col
);
1957 __isl_give isl_mat
*isl_mat_scale_down(__isl_take isl_mat
*mat
, isl_int m
)
1961 if (isl_int_is_one(m
))
1964 mat
= isl_mat_cow(mat
);
1968 for (i
= 0; i
< mat
->n_row
; ++i
)
1969 isl_seq_scale_down(mat
->row
[i
], mat
->row
[i
], m
, mat
->n_col
);
1974 __isl_give isl_mat
*isl_mat_scale_down_row(__isl_take isl_mat
*mat
, int row
,
1977 if (isl_int_is_one(m
))
1980 mat
= isl_mat_cow(mat
);
1984 isl_seq_scale_down(mat
->row
[row
], mat
->row
[row
], m
, mat
->n_col
);
1989 __isl_give isl_mat
*isl_mat_normalize(__isl_take isl_mat
*mat
)
1997 isl_mat_gcd(mat
, &gcd
);
1998 mat
= isl_mat_scale_down(mat
, gcd
);
2004 __isl_give isl_mat
*isl_mat_normalize_row(__isl_take isl_mat
*mat
, int row
)
2006 mat
= isl_mat_cow(mat
);
2010 isl_seq_normalize(mat
->ctx
, mat
->row
[row
], mat
->n_col
);
2015 /* Number of initial non-zero columns.
2017 int isl_mat_initial_non_zero_cols(__isl_keep isl_mat
*mat
)
2024 for (i
= 0; i
< mat
->n_col
; ++i
)
2025 if (row_first_non_zero(mat
->row
, mat
->n_row
, i
) < 0)
2031 /* Return a basis for the space spanned by the rows of "mat".
2032 * Any basis will do, so simply perform Gaussian elimination and
2033 * remove the empty rows.
2035 __isl_give isl_mat
*isl_mat_row_basis(__isl_take isl_mat
*mat
)
2037 return isl_mat_reverse_gauss(mat
);
2040 /* Return rows that extend a basis of "mat1" to one
2041 * that covers both "mat1" and "mat2".
2042 * The Hermite normal form of the concatenation of the two matrices is
2045 * [ M1 ] = [ H1 0 0 ] [ Q2 ]
2046 * [ M2 ] = [ H2 H3 0 ] [ Q3 ]
2048 * The number of columns in H1 and H3 determine the number of rows
2049 * in Q1 and Q2. Q1 is a basis for M1, while Q2 extends this basis
2052 __isl_give isl_mat
*isl_mat_row_basis_extension(
2053 __isl_take isl_mat
*mat1
, __isl_take isl_mat
*mat2
)
2060 n1
= isl_mat_rows(mat1
);
2061 H
= isl_mat_concat(mat1
, mat2
);
2062 H
= isl_mat_left_hermite(H
, 0, NULL
, &Q
);
2063 if (n1
< 0 || !H
|| !Q
)
2066 r1
= hermite_first_zero_col(H
, 0, n1
);
2067 r
= hermite_first_zero_col(H
, r1
, H
->n_row
);
2068 n_row
= isl_mat_rows(Q
);
2071 Q
= isl_mat_drop_rows(Q
, r
, n_row
- r
);
2072 Q
= isl_mat_drop_rows(Q
, 0, r1
);
2082 /* Are the rows of "mat1" linearly independent of those of "mat2"?
2083 * That is, is there no linear dependence among the combined rows
2084 * that is not already present in either "mat1" or "mat2"?
2085 * In other words, is the rank of "mat1" and "mat2" combined equal
2086 * to the sum of the ranks of "mat1" and "mat2"?
2088 isl_bool
isl_mat_has_linearly_independent_rows(__isl_keep isl_mat
*mat1
,
2089 __isl_keep isl_mat
*mat2
)
2094 r1
= isl_mat_rank(mat1
);
2096 return isl_bool_error
;
2098 return isl_bool_true
;
2099 r2
= isl_mat_rank(mat2
);
2101 return isl_bool_error
;
2103 return isl_bool_true
;
2105 mat
= isl_mat_concat(isl_mat_copy(mat1
), isl_mat_copy(mat2
));
2106 r
= isl_mat_rank(mat
);
2109 return isl_bool_error
;
2110 return isl_bool_ok(r
== r1
+ r2
);