2 * Copyright 2008-2009 Katholieke Universiteit Leuven
3 * Copyright 2014 Ecole Normale Superieure
5 * Use of this software is governed by the MIT license
7 * Written by Sven Verdoolaege, K.U.Leuven, Departement
8 * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
9 * and Ecole Normale Superieure, 45 rue d'Ulm, 75230 Paris, France
12 #include <isl_ctx_private.h>
13 #include <isl_map_private.h>
14 #include <isl/space.h>
16 #include <isl_mat_private.h>
17 #include <isl_vec_private.h>
18 #include <isl_space_private.h>
19 #include <isl_val_private.h>
20 #include <isl/deprecated/mat_int.h>
22 isl_ctx
*isl_mat_get_ctx(__isl_keep isl_mat
*mat
)
24 return mat
? mat
->ctx
: NULL
;
27 struct isl_mat
*isl_mat_alloc(struct isl_ctx
*ctx
,
28 unsigned n_row
, unsigned n_col
)
33 mat
= isl_alloc_type(ctx
, struct isl_mat
);
38 mat
->block
= isl_blk_alloc(ctx
, n_row
* n_col
);
39 if (isl_blk_is_error(mat
->block
))
41 mat
->row
= isl_alloc_array(ctx
, isl_int
*, n_row
);
42 if (n_row
&& !mat
->row
)
45 for (i
= 0; i
< n_row
; ++i
)
46 mat
->row
[i
] = mat
->block
.data
+ i
* n_col
;
58 isl_blk_free(ctx
, mat
->block
);
63 struct isl_mat
*isl_mat_extend(struct isl_mat
*mat
,
64 unsigned n_row
, unsigned n_col
)
73 if (mat
->max_col
>= n_col
&& mat
->n_row
>= n_row
) {
74 if (mat
->n_col
< n_col
)
79 if (mat
->max_col
< n_col
) {
80 struct isl_mat
*new_mat
;
82 if (n_row
< mat
->n_row
)
84 new_mat
= isl_mat_alloc(mat
->ctx
, n_row
, n_col
);
87 for (i
= 0; i
< mat
->n_row
; ++i
)
88 isl_seq_cpy(new_mat
->row
[i
], mat
->row
[i
], mat
->n_col
);
93 mat
= isl_mat_cow(mat
);
97 old
= mat
->block
.data
;
98 mat
->block
= isl_blk_extend(mat
->ctx
, mat
->block
, n_row
* mat
->max_col
);
99 if (isl_blk_is_error(mat
->block
))
101 row
= isl_realloc_array(mat
->ctx
, mat
->row
, isl_int
*, n_row
);
106 for (i
= 0; i
< mat
->n_row
; ++i
)
107 mat
->row
[i
] = mat
->block
.data
+ (mat
->row
[i
] - old
);
108 for (i
= mat
->n_row
; i
< n_row
; ++i
)
109 mat
->row
[i
] = mat
->block
.data
+ i
* mat
->max_col
;
111 if (mat
->n_col
< n_col
)
120 __isl_give isl_mat
*isl_mat_sub_alloc6(isl_ctx
*ctx
, isl_int
**row
,
121 unsigned first_row
, unsigned n_row
, unsigned first_col
, unsigned n_col
)
126 mat
= isl_alloc_type(ctx
, struct isl_mat
);
129 mat
->row
= isl_alloc_array(ctx
, isl_int
*, n_row
);
130 if (n_row
&& !mat
->row
)
132 for (i
= 0; i
< n_row
; ++i
)
133 mat
->row
[i
] = row
[first_row
+i
] + first_col
;
139 mat
->block
= isl_blk_empty();
140 mat
->flags
= ISL_MAT_BORROWED
;
147 __isl_give isl_mat
*isl_mat_sub_alloc(__isl_keep isl_mat
*mat
,
148 unsigned first_row
, unsigned n_row
, unsigned first_col
, unsigned n_col
)
152 return isl_mat_sub_alloc6(mat
->ctx
, mat
->row
, first_row
, n_row
,
156 void isl_mat_sub_copy(struct isl_ctx
*ctx
, isl_int
**dst
, isl_int
**src
,
157 unsigned n_row
, unsigned dst_col
, unsigned src_col
, unsigned n_col
)
161 for (i
= 0; i
< n_row
; ++i
)
162 isl_seq_cpy(dst
[i
]+dst_col
, src
[i
]+src_col
, n_col
);
165 void isl_mat_sub_neg(struct isl_ctx
*ctx
, isl_int
**dst
, isl_int
**src
,
166 unsigned n_row
, unsigned dst_col
, unsigned src_col
, unsigned n_col
)
170 for (i
= 0; i
< n_row
; ++i
)
171 isl_seq_neg(dst
[i
]+dst_col
, src
[i
]+src_col
, n_col
);
174 struct isl_mat
*isl_mat_copy(struct isl_mat
*mat
)
183 struct isl_mat
*isl_mat_dup(struct isl_mat
*mat
)
186 struct isl_mat
*mat2
;
190 mat2
= isl_mat_alloc(mat
->ctx
, mat
->n_row
, mat
->n_col
);
193 for (i
= 0; i
< mat
->n_row
; ++i
)
194 isl_seq_cpy(mat2
->row
[i
], mat
->row
[i
], mat
->n_col
);
198 struct isl_mat
*isl_mat_cow(struct isl_mat
*mat
)
200 struct isl_mat
*mat2
;
204 if (mat
->ref
== 1 && !ISL_F_ISSET(mat
, ISL_MAT_BORROWED
))
207 mat2
= isl_mat_dup(mat
);
212 __isl_null isl_mat
*isl_mat_free(__isl_take isl_mat
*mat
)
220 if (!ISL_F_ISSET(mat
, ISL_MAT_BORROWED
))
221 isl_blk_free(mat
->ctx
, mat
->block
);
222 isl_ctx_deref(mat
->ctx
);
229 int isl_mat_rows(__isl_keep isl_mat
*mat
)
231 return mat
? mat
->n_row
: -1;
234 int isl_mat_cols(__isl_keep isl_mat
*mat
)
236 return mat
? mat
->n_col
: -1;
239 int isl_mat_get_element(__isl_keep isl_mat
*mat
, int row
, int col
, isl_int
*v
)
243 if (row
< 0 || row
>= mat
->n_row
)
244 isl_die(mat
->ctx
, isl_error_invalid
, "row out of range",
246 if (col
< 0 || col
>= mat
->n_col
)
247 isl_die(mat
->ctx
, isl_error_invalid
, "column out of range",
249 isl_int_set(*v
, mat
->row
[row
][col
]);
253 /* Extract the element at row "row", oolumn "col" of "mat".
255 __isl_give isl_val
*isl_mat_get_element_val(__isl_keep isl_mat
*mat
,
262 ctx
= isl_mat_get_ctx(mat
);
263 if (row
< 0 || row
>= mat
->n_row
)
264 isl_die(ctx
, isl_error_invalid
, "row out of range",
266 if (col
< 0 || col
>= mat
->n_col
)
267 isl_die(ctx
, isl_error_invalid
, "column out of range",
269 return isl_val_int_from_isl_int(ctx
, mat
->row
[row
][col
]);
272 __isl_give isl_mat
*isl_mat_set_element(__isl_take isl_mat
*mat
,
273 int row
, int col
, isl_int v
)
275 mat
= isl_mat_cow(mat
);
278 if (row
< 0 || row
>= mat
->n_row
)
279 isl_die(mat
->ctx
, isl_error_invalid
, "row out of range",
281 if (col
< 0 || col
>= mat
->n_col
)
282 isl_die(mat
->ctx
, isl_error_invalid
, "column out of range",
284 isl_int_set(mat
->row
[row
][col
], v
);
291 __isl_give isl_mat
*isl_mat_set_element_si(__isl_take isl_mat
*mat
,
292 int row
, int col
, int v
)
294 mat
= isl_mat_cow(mat
);
297 if (row
< 0 || row
>= mat
->n_row
)
298 isl_die(mat
->ctx
, isl_error_invalid
, "row out of range",
300 if (col
< 0 || col
>= mat
->n_col
)
301 isl_die(mat
->ctx
, isl_error_invalid
, "column out of range",
303 isl_int_set_si(mat
->row
[row
][col
], v
);
310 /* Replace the element at row "row", column "col" of "mat" by "v".
312 __isl_give isl_mat
*isl_mat_set_element_val(__isl_take isl_mat
*mat
,
313 int row
, int col
, __isl_take isl_val
*v
)
316 return isl_mat_free(mat
);
317 if (!isl_val_is_int(v
))
318 isl_die(isl_val_get_ctx(v
), isl_error_invalid
,
319 "expecting integer value", goto error
);
320 mat
= isl_mat_set_element(mat
, row
, col
, v
->n
);
325 return isl_mat_free(mat
);
328 __isl_give isl_mat
*isl_mat_diag(isl_ctx
*ctx
, unsigned n_row
, isl_int d
)
333 mat
= isl_mat_alloc(ctx
, n_row
, n_row
);
336 for (i
= 0; i
< n_row
; ++i
) {
337 isl_seq_clr(mat
->row
[i
], i
);
338 isl_int_set(mat
->row
[i
][i
], d
);
339 isl_seq_clr(mat
->row
[i
]+i
+1, n_row
-(i
+1));
345 __isl_give isl_mat
*isl_mat_identity(isl_ctx
*ctx
, unsigned n_row
)
349 return isl_mat_diag(ctx
, n_row
, ctx
->one
);
352 /* Is "mat" a (possibly scaled) identity matrix?
354 int isl_mat_is_scaled_identity(__isl_keep isl_mat
*mat
)
360 if (mat
->n_row
!= mat
->n_col
)
363 for (i
= 0; i
< mat
->n_row
; ++i
) {
364 if (isl_seq_first_non_zero(mat
->row
[i
], i
) != -1)
366 if (isl_int_ne(mat
->row
[0][0], mat
->row
[i
][i
]))
368 if (isl_seq_first_non_zero(mat
->row
[i
] + i
+ 1,
369 mat
->n_col
- (i
+ 1)) != -1)
376 struct isl_vec
*isl_mat_vec_product(struct isl_mat
*mat
, struct isl_vec
*vec
)
379 struct isl_vec
*prod
;
384 isl_assert(mat
->ctx
, mat
->n_col
== vec
->size
, goto error
);
386 prod
= isl_vec_alloc(mat
->ctx
, mat
->n_row
);
390 for (i
= 0; i
< prod
->size
; ++i
)
391 isl_seq_inner_product(mat
->row
[i
], vec
->el
, vec
->size
,
392 &prod
->block
.data
[i
]);
402 __isl_give isl_vec
*isl_mat_vec_inverse_product(__isl_take isl_mat
*mat
,
403 __isl_take isl_vec
*vec
)
405 struct isl_mat
*vec_mat
;
410 vec_mat
= isl_mat_alloc(vec
->ctx
, vec
->size
, 1);
413 for (i
= 0; i
< vec
->size
; ++i
)
414 isl_int_set(vec_mat
->row
[i
][0], vec
->el
[i
]);
415 vec_mat
= isl_mat_inverse_product(mat
, vec_mat
);
419 vec
= isl_vec_alloc(vec_mat
->ctx
, vec_mat
->n_row
);
421 for (i
= 0; i
< vec
->size
; ++i
)
422 isl_int_set(vec
->el
[i
], vec_mat
->row
[i
][0]);
423 isl_mat_free(vec_mat
);
431 struct isl_vec
*isl_vec_mat_product(struct isl_vec
*vec
, struct isl_mat
*mat
)
434 struct isl_vec
*prod
;
439 isl_assert(mat
->ctx
, mat
->n_row
== vec
->size
, goto error
);
441 prod
= isl_vec_alloc(mat
->ctx
, mat
->n_col
);
445 for (i
= 0; i
< prod
->size
; ++i
) {
446 isl_int_set_si(prod
->el
[i
], 0);
447 for (j
= 0; j
< vec
->size
; ++j
)
448 isl_int_addmul(prod
->el
[i
], vec
->el
[j
], mat
->row
[j
][i
]);
459 struct isl_mat
*isl_mat_aff_direct_sum(struct isl_mat
*left
,
460 struct isl_mat
*right
)
468 isl_assert(left
->ctx
, left
->n_row
== right
->n_row
, goto error
);
469 isl_assert(left
->ctx
, left
->n_row
>= 1, goto error
);
470 isl_assert(left
->ctx
, left
->n_col
>= 1, goto error
);
471 isl_assert(left
->ctx
, right
->n_col
>= 1, goto error
);
472 isl_assert(left
->ctx
,
473 isl_seq_first_non_zero(left
->row
[0]+1, left
->n_col
-1) == -1,
475 isl_assert(left
->ctx
,
476 isl_seq_first_non_zero(right
->row
[0]+1, right
->n_col
-1) == -1,
479 sum
= isl_mat_alloc(left
->ctx
, left
->n_row
, left
->n_col
+ right
->n_col
- 1);
482 isl_int_lcm(sum
->row
[0][0], left
->row
[0][0], right
->row
[0][0]);
483 isl_int_divexact(left
->row
[0][0], sum
->row
[0][0], left
->row
[0][0]);
484 isl_int_divexact(right
->row
[0][0], sum
->row
[0][0], right
->row
[0][0]);
486 isl_seq_clr(sum
->row
[0]+1, sum
->n_col
-1);
487 for (i
= 1; i
< sum
->n_row
; ++i
) {
488 isl_int_mul(sum
->row
[i
][0], left
->row
[0][0], left
->row
[i
][0]);
489 isl_int_addmul(sum
->row
[i
][0],
490 right
->row
[0][0], right
->row
[i
][0]);
491 isl_seq_scale(sum
->row
[i
]+1, left
->row
[i
]+1, left
->row
[0][0],
493 isl_seq_scale(sum
->row
[i
]+left
->n_col
,
494 right
->row
[i
]+1, right
->row
[0][0],
498 isl_int_divexact(left
->row
[0][0], sum
->row
[0][0], left
->row
[0][0]);
499 isl_int_divexact(right
->row
[0][0], sum
->row
[0][0], right
->row
[0][0]);
509 static void exchange(struct isl_mat
*M
, struct isl_mat
**U
,
510 struct isl_mat
**Q
, unsigned row
, unsigned i
, unsigned j
)
513 for (r
= row
; r
< M
->n_row
; ++r
)
514 isl_int_swap(M
->row
[r
][i
], M
->row
[r
][j
]);
516 for (r
= 0; r
< (*U
)->n_row
; ++r
)
517 isl_int_swap((*U
)->row
[r
][i
], (*U
)->row
[r
][j
]);
520 isl_mat_swap_rows(*Q
, i
, j
);
523 static void subtract(struct isl_mat
*M
, struct isl_mat
**U
,
524 struct isl_mat
**Q
, unsigned row
, unsigned i
, unsigned j
, isl_int m
)
527 for (r
= row
; r
< M
->n_row
; ++r
)
528 isl_int_submul(M
->row
[r
][j
], m
, M
->row
[r
][i
]);
530 for (r
= 0; r
< (*U
)->n_row
; ++r
)
531 isl_int_submul((*U
)->row
[r
][j
], m
, (*U
)->row
[r
][i
]);
534 for (r
= 0; r
< (*Q
)->n_col
; ++r
)
535 isl_int_addmul((*Q
)->row
[i
][r
], m
, (*Q
)->row
[j
][r
]);
539 static void oppose(struct isl_mat
*M
, struct isl_mat
**U
,
540 struct isl_mat
**Q
, unsigned row
, unsigned col
)
543 for (r
= row
; r
< M
->n_row
; ++r
)
544 isl_int_neg(M
->row
[r
][col
], M
->row
[r
][col
]);
546 for (r
= 0; r
< (*U
)->n_row
; ++r
)
547 isl_int_neg((*U
)->row
[r
][col
], (*U
)->row
[r
][col
]);
550 isl_seq_neg((*Q
)->row
[col
], (*Q
)->row
[col
], (*Q
)->n_col
);
553 /* Given matrix M, compute
558 * with U and Q unimodular matrices and H a matrix in column echelon form
559 * such that on each echelon row the entries in the non-echelon column
560 * are non-negative (if neg == 0) or non-positive (if neg == 1)
561 * and strictly smaller (in absolute value) than the entries in the echelon
563 * If U or Q are NULL, then these matrices are not computed.
565 struct isl_mat
*isl_mat_left_hermite(struct isl_mat
*M
, int neg
,
566 struct isl_mat
**U
, struct isl_mat
**Q
)
581 *U
= isl_mat_identity(M
->ctx
, M
->n_col
);
586 *Q
= isl_mat_identity(M
->ctx
, M
->n_col
);
593 for (row
= 0; row
< M
->n_row
; ++row
) {
595 first
= isl_seq_abs_min_non_zero(M
->row
[row
]+col
, M
->n_col
-col
);
600 exchange(M
, U
, Q
, row
, first
, col
);
601 if (isl_int_is_neg(M
->row
[row
][col
]))
602 oppose(M
, U
, Q
, row
, col
);
604 while ((off
= isl_seq_first_non_zero(M
->row
[row
]+first
,
605 M
->n_col
-first
)) != -1) {
607 isl_int_fdiv_q(c
, M
->row
[row
][first
], M
->row
[row
][col
]);
608 subtract(M
, U
, Q
, row
, col
, first
, c
);
609 if (!isl_int_is_zero(M
->row
[row
][first
]))
610 exchange(M
, U
, Q
, row
, first
, col
);
614 for (i
= 0; i
< col
; ++i
) {
615 if (isl_int_is_zero(M
->row
[row
][i
]))
618 isl_int_cdiv_q(c
, M
->row
[row
][i
], M
->row
[row
][col
]);
620 isl_int_fdiv_q(c
, M
->row
[row
][i
], M
->row
[row
][col
]);
621 if (isl_int_is_zero(c
))
623 subtract(M
, U
, Q
, row
, col
, i
, c
);
643 struct isl_mat
*isl_mat_right_kernel(struct isl_mat
*mat
)
646 struct isl_mat
*U
= NULL
;
649 mat
= isl_mat_left_hermite(mat
, 0, &U
, NULL
);
653 for (i
= 0, rank
= 0; rank
< mat
->n_col
; ++rank
) {
654 while (i
< mat
->n_row
&& isl_int_is_zero(mat
->row
[i
][rank
]))
659 K
= isl_mat_alloc(U
->ctx
, U
->n_row
, U
->n_col
- rank
);
662 isl_mat_sub_copy(K
->ctx
, K
->row
, U
->row
, U
->n_row
, 0, rank
, U
->n_col
-rank
);
672 struct isl_mat
*isl_mat_lin_to_aff(struct isl_mat
*mat
)
675 struct isl_mat
*mat2
;
679 mat2
= isl_mat_alloc(mat
->ctx
, 1+mat
->n_row
, 1+mat
->n_col
);
682 isl_int_set_si(mat2
->row
[0][0], 1);
683 isl_seq_clr(mat2
->row
[0]+1, mat
->n_col
);
684 for (i
= 0; i
< mat
->n_row
; ++i
) {
685 isl_int_set_si(mat2
->row
[1+i
][0], 0);
686 isl_seq_cpy(mat2
->row
[1+i
]+1, mat
->row
[i
], mat
->n_col
);
695 /* Given two matrices M1 and M2, return the block matrix
700 __isl_give isl_mat
*isl_mat_diagonal(__isl_take isl_mat
*mat1
,
701 __isl_take isl_mat
*mat2
)
709 mat
= isl_mat_alloc(mat1
->ctx
, mat1
->n_row
+ mat2
->n_row
,
710 mat1
->n_col
+ mat2
->n_col
);
713 for (i
= 0; i
< mat1
->n_row
; ++i
) {
714 isl_seq_cpy(mat
->row
[i
], mat1
->row
[i
], mat1
->n_col
);
715 isl_seq_clr(mat
->row
[i
] + mat1
->n_col
, mat2
->n_col
);
717 for (i
= 0; i
< mat2
->n_row
; ++i
) {
718 isl_seq_clr(mat
->row
[mat1
->n_row
+ i
], mat1
->n_col
);
719 isl_seq_cpy(mat
->row
[mat1
->n_row
+ i
] + mat1
->n_col
,
720 mat2
->row
[i
], mat2
->n_col
);
731 static int row_first_non_zero(isl_int
**row
, unsigned n_row
, unsigned col
)
735 for (i
= 0; i
< n_row
; ++i
)
736 if (!isl_int_is_zero(row
[i
][col
]))
741 static int row_abs_min_non_zero(isl_int
**row
, unsigned n_row
, unsigned col
)
743 int i
, min
= row_first_non_zero(row
, n_row
, col
);
746 for (i
= min
+ 1; i
< n_row
; ++i
) {
747 if (isl_int_is_zero(row
[i
][col
]))
749 if (isl_int_abs_lt(row
[i
][col
], row
[min
][col
]))
755 static void inv_exchange(struct isl_mat
*left
, struct isl_mat
*right
,
756 unsigned i
, unsigned j
)
758 left
= isl_mat_swap_rows(left
, i
, j
);
759 right
= isl_mat_swap_rows(right
, i
, j
);
762 static void inv_oppose(
763 struct isl_mat
*left
, struct isl_mat
*right
, unsigned row
)
765 isl_seq_neg(left
->row
[row
]+row
, left
->row
[row
]+row
, left
->n_col
-row
);
766 isl_seq_neg(right
->row
[row
], right
->row
[row
], right
->n_col
);
769 static void inv_subtract(struct isl_mat
*left
, struct isl_mat
*right
,
770 unsigned row
, unsigned i
, isl_int m
)
773 isl_seq_combine(left
->row
[i
]+row
,
774 left
->ctx
->one
, left
->row
[i
]+row
,
775 m
, left
->row
[row
]+row
,
777 isl_seq_combine(right
->row
[i
], right
->ctx
->one
, right
->row
[i
],
778 m
, right
->row
[row
], right
->n_col
);
781 /* Compute inv(left)*right
783 struct isl_mat
*isl_mat_inverse_product(struct isl_mat
*left
,
784 struct isl_mat
*right
)
792 isl_assert(left
->ctx
, left
->n_row
== left
->n_col
, goto error
);
793 isl_assert(left
->ctx
, left
->n_row
== right
->n_row
, goto error
);
795 if (left
->n_row
== 0) {
800 left
= isl_mat_cow(left
);
801 right
= isl_mat_cow(right
);
807 for (row
= 0; row
< left
->n_row
; ++row
) {
808 int pivot
, first
, i
, off
;
809 pivot
= row_abs_min_non_zero(left
->row
+row
, left
->n_row
-row
, row
);
813 isl_assert(left
->ctx
, pivot
>= 0, goto error
);
817 inv_exchange(left
, right
, pivot
, row
);
818 if (isl_int_is_neg(left
->row
[row
][row
]))
819 inv_oppose(left
, right
, row
);
821 while ((off
= row_first_non_zero(left
->row
+first
,
822 left
->n_row
-first
, row
)) != -1) {
824 isl_int_fdiv_q(a
, left
->row
[first
][row
],
825 left
->row
[row
][row
]);
826 inv_subtract(left
, right
, row
, first
, a
);
827 if (!isl_int_is_zero(left
->row
[first
][row
]))
828 inv_exchange(left
, right
, row
, first
);
832 for (i
= 0; i
< row
; ++i
) {
833 if (isl_int_is_zero(left
->row
[i
][row
]))
835 isl_int_gcd(a
, left
->row
[row
][row
], left
->row
[i
][row
]);
836 isl_int_divexact(b
, left
->row
[i
][row
], a
);
837 isl_int_divexact(a
, left
->row
[row
][row
], a
);
839 isl_seq_combine(left
->row
[i
] + i
,
841 b
, left
->row
[row
] + i
,
843 isl_seq_combine(right
->row
[i
], a
, right
->row
[i
],
844 b
, right
->row
[row
], right
->n_col
);
849 isl_int_set(a
, left
->row
[0][0]);
850 for (row
= 1; row
< left
->n_row
; ++row
)
851 isl_int_lcm(a
, a
, left
->row
[row
][row
]);
852 if (isl_int_is_zero(a
)){
854 isl_assert(left
->ctx
, 0, goto error
);
856 for (row
= 0; row
< left
->n_row
; ++row
) {
857 isl_int_divexact(left
->row
[row
][row
], a
, left
->row
[row
][row
]);
858 if (isl_int_is_one(left
->row
[row
][row
]))
860 isl_seq_scale(right
->row
[row
], right
->row
[row
],
861 left
->row
[row
][row
], right
->n_col
);
873 void isl_mat_col_scale(struct isl_mat
*mat
, unsigned col
, isl_int m
)
877 for (i
= 0; i
< mat
->n_row
; ++i
)
878 isl_int_mul(mat
->row
[i
][col
], mat
->row
[i
][col
], m
);
881 void isl_mat_col_combine(struct isl_mat
*mat
, unsigned dst
,
882 isl_int m1
, unsigned src1
, isl_int m2
, unsigned src2
)
888 for (i
= 0; i
< mat
->n_row
; ++i
) {
889 isl_int_mul(tmp
, m1
, mat
->row
[i
][src1
]);
890 isl_int_addmul(tmp
, m2
, mat
->row
[i
][src2
]);
891 isl_int_set(mat
->row
[i
][dst
], tmp
);
896 struct isl_mat
*isl_mat_right_inverse(struct isl_mat
*mat
)
902 mat
= isl_mat_cow(mat
);
906 inv
= isl_mat_identity(mat
->ctx
, mat
->n_col
);
907 inv
= isl_mat_cow(inv
);
913 for (row
= 0; row
< mat
->n_row
; ++row
) {
914 int pivot
, first
, i
, off
;
915 pivot
= isl_seq_abs_min_non_zero(mat
->row
[row
]+row
, mat
->n_col
-row
);
919 isl_assert(mat
->ctx
, pivot
>= 0, goto error
);
923 exchange(mat
, &inv
, NULL
, row
, pivot
, row
);
924 if (isl_int_is_neg(mat
->row
[row
][row
]))
925 oppose(mat
, &inv
, NULL
, row
, row
);
927 while ((off
= isl_seq_first_non_zero(mat
->row
[row
]+first
,
928 mat
->n_col
-first
)) != -1) {
930 isl_int_fdiv_q(a
, mat
->row
[row
][first
],
932 subtract(mat
, &inv
, NULL
, row
, row
, first
, a
);
933 if (!isl_int_is_zero(mat
->row
[row
][first
]))
934 exchange(mat
, &inv
, NULL
, row
, row
, first
);
938 for (i
= 0; i
< row
; ++i
) {
939 if (isl_int_is_zero(mat
->row
[row
][i
]))
941 isl_int_gcd(a
, mat
->row
[row
][row
], mat
->row
[row
][i
]);
942 isl_int_divexact(b
, mat
->row
[row
][i
], a
);
943 isl_int_divexact(a
, mat
->row
[row
][row
], a
);
945 isl_mat_col_combine(mat
, i
, a
, i
, b
, row
);
946 isl_mat_col_combine(inv
, i
, a
, i
, b
, row
);
951 isl_int_set(a
, mat
->row
[0][0]);
952 for (row
= 1; row
< mat
->n_row
; ++row
)
953 isl_int_lcm(a
, a
, mat
->row
[row
][row
]);
954 if (isl_int_is_zero(a
)){
958 for (row
= 0; row
< mat
->n_row
; ++row
) {
959 isl_int_divexact(mat
->row
[row
][row
], a
, mat
->row
[row
][row
]);
960 if (isl_int_is_one(mat
->row
[row
][row
]))
962 isl_mat_col_scale(inv
, row
, mat
->row
[row
][row
]);
975 struct isl_mat
*isl_mat_transpose(struct isl_mat
*mat
)
977 struct isl_mat
*transpose
= NULL
;
983 if (mat
->n_col
== mat
->n_row
) {
984 mat
= isl_mat_cow(mat
);
987 for (i
= 0; i
< mat
->n_row
; ++i
)
988 for (j
= i
+ 1; j
< mat
->n_col
; ++j
)
989 isl_int_swap(mat
->row
[i
][j
], mat
->row
[j
][i
]);
992 transpose
= isl_mat_alloc(mat
->ctx
, mat
->n_col
, mat
->n_row
);
995 for (i
= 0; i
< mat
->n_row
; ++i
)
996 for (j
= 0; j
< mat
->n_col
; ++j
)
997 isl_int_set(transpose
->row
[j
][i
], mat
->row
[i
][j
]);
1005 struct isl_mat
*isl_mat_swap_cols(struct isl_mat
*mat
, unsigned i
, unsigned j
)
1009 mat
= isl_mat_cow(mat
);
1012 isl_assert(mat
->ctx
, i
< mat
->n_col
, goto error
);
1013 isl_assert(mat
->ctx
, j
< mat
->n_col
, goto error
);
1015 for (r
= 0; r
< mat
->n_row
; ++r
)
1016 isl_int_swap(mat
->row
[r
][i
], mat
->row
[r
][j
]);
1023 struct isl_mat
*isl_mat_swap_rows(struct isl_mat
*mat
, unsigned i
, unsigned j
)
1029 mat
= isl_mat_cow(mat
);
1033 mat
->row
[i
] = mat
->row
[j
];
1038 /* Calculate the product of two matrices.
1040 * This function is optimized for operand matrices that contain many zeros and
1041 * skips multiplications where we know one of the operands is zero.
1043 __isl_give isl_mat
*isl_mat_product(__isl_take isl_mat
*left
,
1044 __isl_take isl_mat
*right
)
1047 struct isl_mat
*prod
;
1049 if (!left
|| !right
)
1051 isl_assert(left
->ctx
, left
->n_col
== right
->n_row
, goto error
);
1052 prod
= isl_mat_alloc(left
->ctx
, left
->n_row
, right
->n_col
);
1055 if (left
->n_col
== 0) {
1056 for (i
= 0; i
< prod
->n_row
; ++i
)
1057 isl_seq_clr(prod
->row
[i
], prod
->n_col
);
1059 isl_mat_free(right
);
1062 for (i
= 0; i
< prod
->n_row
; ++i
) {
1063 for (j
= 0; j
< prod
->n_col
; ++j
)
1064 isl_int_mul(prod
->row
[i
][j
],
1065 left
->row
[i
][0], right
->row
[0][j
]);
1066 for (k
= 1; k
< left
->n_col
; ++k
) {
1067 if (isl_int_is_zero(left
->row
[i
][k
]))
1069 for (j
= 0; j
< prod
->n_col
; ++j
)
1070 isl_int_addmul(prod
->row
[i
][j
],
1071 left
->row
[i
][k
], right
->row
[k
][j
]);
1075 isl_mat_free(right
);
1079 isl_mat_free(right
);
1083 /* Replace the variables x in the rows q by x' given by x = M x',
1084 * with M the matrix mat.
1086 * If the number of new variables is greater than the original
1087 * number of variables, then the rows q have already been
1088 * preextended. If the new number is smaller, then the coefficients
1089 * of the divs, which are not changed, need to be shifted down.
1090 * The row q may be the equalities, the inequalities or the
1091 * div expressions. In the latter case, has_div is true and
1092 * we need to take into account the extra denominator column.
1094 static int preimage(struct isl_ctx
*ctx
, isl_int
**q
, unsigned n
,
1095 unsigned n_div
, int has_div
, struct isl_mat
*mat
)
1101 if (mat
->n_col
>= mat
->n_row
)
1104 e
= mat
->n_row
- mat
->n_col
;
1106 for (i
= 0; i
< n
; ++i
)
1107 isl_int_mul(q
[i
][0], q
[i
][0], mat
->row
[0][0]);
1108 t
= isl_mat_sub_alloc6(mat
->ctx
, q
, 0, n
, has_div
, mat
->n_row
);
1109 t
= isl_mat_product(t
, mat
);
1112 for (i
= 0; i
< n
; ++i
) {
1113 isl_seq_swp_or_cpy(q
[i
] + has_div
, t
->row
[i
], t
->n_col
);
1114 isl_seq_cpy(q
[i
] + has_div
+ t
->n_col
,
1115 q
[i
] + has_div
+ t
->n_col
+ e
, n_div
);
1116 isl_seq_clr(q
[i
] + has_div
+ t
->n_col
+ n_div
, e
);
1122 /* Replace the variables x in bset by x' given by x = M x', with
1125 * If there are fewer variables x' then there are x, then we perform
1126 * the transformation in place, which that, in principle,
1127 * this frees up some extra variables as the number
1128 * of columns remains constant, but we would have to extend
1129 * the div array too as the number of rows in this array is assumed
1130 * to be equal to extra.
1132 struct isl_basic_set
*isl_basic_set_preimage(struct isl_basic_set
*bset
,
1133 struct isl_mat
*mat
)
1135 struct isl_ctx
*ctx
;
1141 bset
= isl_basic_set_cow(bset
);
1145 isl_assert(ctx
, bset
->dim
->nparam
== 0, goto error
);
1146 isl_assert(ctx
, 1+bset
->dim
->n_out
== mat
->n_row
, goto error
);
1147 isl_assert(ctx
, mat
->n_col
> 0, goto error
);
1149 if (mat
->n_col
> mat
->n_row
) {
1150 bset
= isl_basic_set_extend(bset
, 0, mat
->n_col
-1, 0, 0, 0);
1153 } else if (mat
->n_col
< mat
->n_row
) {
1154 bset
->dim
= isl_space_cow(bset
->dim
);
1157 bset
->dim
->n_out
-= mat
->n_row
- mat
->n_col
;
1160 if (preimage(ctx
, bset
->eq
, bset
->n_eq
, bset
->n_div
, 0,
1161 isl_mat_copy(mat
)) < 0)
1164 if (preimage(ctx
, bset
->ineq
, bset
->n_ineq
, bset
->n_div
, 0,
1165 isl_mat_copy(mat
)) < 0)
1168 if (preimage(ctx
, bset
->div
, bset
->n_div
, bset
->n_div
, 1, mat
) < 0)
1171 ISL_F_CLR(bset
, ISL_BASIC_SET_NO_IMPLICIT
);
1172 ISL_F_CLR(bset
, ISL_BASIC_SET_NO_REDUNDANT
);
1173 ISL_F_CLR(bset
, ISL_BASIC_SET_NORMALIZED
);
1174 ISL_F_CLR(bset
, ISL_BASIC_SET_NORMALIZED_DIVS
);
1175 ISL_F_CLR(bset
, ISL_BASIC_SET_ALL_EQUALITIES
);
1177 bset
= isl_basic_set_simplify(bset
);
1178 bset
= isl_basic_set_finalize(bset
);
1184 isl_basic_set_free(bset
);
1188 struct isl_set
*isl_set_preimage(struct isl_set
*set
, struct isl_mat
*mat
)
1192 set
= isl_set_cow(set
);
1196 for (i
= 0; i
< set
->n
; ++i
) {
1197 set
->p
[i
] = isl_basic_set_preimage(set
->p
[i
],
1202 if (mat
->n_col
!= mat
->n_row
) {
1203 set
->dim
= isl_space_cow(set
->dim
);
1206 set
->dim
->n_out
+= mat
->n_col
;
1207 set
->dim
->n_out
-= mat
->n_row
;
1210 ISL_F_CLR(set
, ISL_SET_NORMALIZED
);
1218 /* Replace the variables x starting at pos in the rows q
1219 * by x' with x = M x' with M the matrix mat.
1220 * That is, replace the corresponding coefficients c by c M.
1222 static int transform(isl_ctx
*ctx
, isl_int
**q
, unsigned n
,
1223 unsigned pos
, __isl_take isl_mat
*mat
)
1228 t
= isl_mat_sub_alloc6(ctx
, q
, 0, n
, pos
, mat
->n_row
);
1229 t
= isl_mat_product(t
, mat
);
1232 for (i
= 0; i
< n
; ++i
)
1233 isl_seq_swp_or_cpy(q
[i
] + pos
, t
->row
[i
], t
->n_col
);
1238 /* Replace the variables x of type "type" starting at "first" in "bset"
1239 * by x' with x = M x' with M the matrix trans.
1240 * That is, replace the corresponding coefficients c by c M.
1242 * The transformation matrix should be a square matrix.
1244 __isl_give isl_basic_set
*isl_basic_set_transform_dims(
1245 __isl_take isl_basic_set
*bset
, enum isl_dim_type type
, unsigned first
,
1246 __isl_take isl_mat
*trans
)
1251 bset
= isl_basic_set_cow(bset
);
1252 if (!bset
|| !trans
)
1255 ctx
= isl_basic_set_get_ctx(bset
);
1256 if (trans
->n_row
!= trans
->n_col
)
1257 isl_die(trans
->ctx
, isl_error_invalid
,
1258 "expecting square transformation matrix", goto error
);
1259 if (first
+ trans
->n_row
> isl_basic_set_dim(bset
, type
))
1260 isl_die(trans
->ctx
, isl_error_invalid
,
1261 "oversized transformation matrix", goto error
);
1263 pos
= isl_basic_set_offset(bset
, type
) + first
;
1265 if (transform(ctx
, bset
->eq
, bset
->n_eq
, pos
, isl_mat_copy(trans
)) < 0)
1267 if (transform(ctx
, bset
->ineq
, bset
->n_ineq
, pos
,
1268 isl_mat_copy(trans
)) < 0)
1270 if (transform(ctx
, bset
->div
, bset
->n_div
, 1 + pos
,
1271 isl_mat_copy(trans
)) < 0)
1274 ISL_F_CLR(bset
, ISL_BASIC_SET_NORMALIZED
);
1275 ISL_F_CLR(bset
, ISL_BASIC_SET_NORMALIZED_DIVS
);
1277 isl_mat_free(trans
);
1280 isl_mat_free(trans
);
1281 isl_basic_set_free(bset
);
1285 void isl_mat_print_internal(__isl_keep isl_mat
*mat
, FILE *out
, int indent
)
1290 fprintf(out
, "%*snull mat\n", indent
, "");
1294 if (mat
->n_row
== 0)
1295 fprintf(out
, "%*s[]\n", indent
, "");
1297 for (i
= 0; i
< mat
->n_row
; ++i
) {
1299 fprintf(out
, "%*s[[", indent
, "");
1301 fprintf(out
, "%*s[", indent
+1, "");
1302 for (j
= 0; j
< mat
->n_col
; ++j
) {
1305 isl_int_print(out
, mat
->row
[i
][j
], 0);
1307 if (i
== mat
->n_row
-1)
1308 fprintf(out
, "]]\n");
1310 fprintf(out
, "]\n");
1314 void isl_mat_dump(__isl_keep isl_mat
*mat
)
1316 isl_mat_print_internal(mat
, stderr
, 0);
1319 struct isl_mat
*isl_mat_drop_cols(struct isl_mat
*mat
, unsigned col
, unsigned n
)
1326 mat
= isl_mat_cow(mat
);
1330 if (col
!= mat
->n_col
-n
) {
1331 for (r
= 0; r
< mat
->n_row
; ++r
)
1332 isl_seq_cpy(mat
->row
[r
]+col
, mat
->row
[r
]+col
+n
,
1333 mat
->n_col
- col
- n
);
1339 struct isl_mat
*isl_mat_drop_rows(struct isl_mat
*mat
, unsigned row
, unsigned n
)
1343 mat
= isl_mat_cow(mat
);
1347 for (r
= row
; r
+n
< mat
->n_row
; ++r
)
1348 mat
->row
[r
] = mat
->row
[r
+n
];
1354 __isl_give isl_mat
*isl_mat_insert_cols(__isl_take isl_mat
*mat
,
1355 unsigned col
, unsigned n
)
1364 ext
= isl_mat_alloc(mat
->ctx
, mat
->n_row
, mat
->n_col
+ n
);
1368 isl_mat_sub_copy(mat
->ctx
, ext
->row
, mat
->row
, mat
->n_row
, 0, 0, col
);
1369 isl_mat_sub_copy(mat
->ctx
, ext
->row
, mat
->row
, mat
->n_row
,
1370 col
+ n
, col
, mat
->n_col
- col
);
1379 __isl_give isl_mat
*isl_mat_insert_zero_cols(__isl_take isl_mat
*mat
,
1380 unsigned first
, unsigned n
)
1386 mat
= isl_mat_insert_cols(mat
, first
, n
);
1390 for (i
= 0; i
< mat
->n_row
; ++i
)
1391 isl_seq_clr(mat
->row
[i
] + first
, n
);
1396 __isl_give isl_mat
*isl_mat_add_zero_cols(__isl_take isl_mat
*mat
, unsigned n
)
1401 return isl_mat_insert_zero_cols(mat
, mat
->n_col
, n
);
1404 __isl_give isl_mat
*isl_mat_insert_rows(__isl_take isl_mat
*mat
,
1405 unsigned row
, unsigned n
)
1414 ext
= isl_mat_alloc(mat
->ctx
, mat
->n_row
+ n
, mat
->n_col
);
1418 isl_mat_sub_copy(mat
->ctx
, ext
->row
, mat
->row
, row
, 0, 0, mat
->n_col
);
1419 isl_mat_sub_copy(mat
->ctx
, ext
->row
+ row
+ n
, mat
->row
+ row
,
1420 mat
->n_row
- row
, 0, 0, mat
->n_col
);
1429 __isl_give isl_mat
*isl_mat_add_rows(__isl_take isl_mat
*mat
, unsigned n
)
1434 return isl_mat_insert_rows(mat
, mat
->n_row
, n
);
1437 __isl_give isl_mat
*isl_mat_insert_zero_rows(__isl_take isl_mat
*mat
,
1438 unsigned row
, unsigned n
)
1442 mat
= isl_mat_insert_rows(mat
, row
, n
);
1446 for (i
= 0; i
< n
; ++i
)
1447 isl_seq_clr(mat
->row
[row
+ i
], mat
->n_col
);
1452 __isl_give isl_mat
*isl_mat_add_zero_rows(__isl_take isl_mat
*mat
, unsigned n
)
1457 return isl_mat_insert_zero_rows(mat
, mat
->n_row
, n
);
1460 void isl_mat_col_submul(struct isl_mat
*mat
,
1461 int dst_col
, isl_int f
, int src_col
)
1465 for (i
= 0; i
< mat
->n_row
; ++i
)
1466 isl_int_submul(mat
->row
[i
][dst_col
], f
, mat
->row
[i
][src_col
]);
1469 void isl_mat_col_add(__isl_keep isl_mat
*mat
, int dst_col
, int src_col
)
1476 for (i
= 0; i
< mat
->n_row
; ++i
)
1477 isl_int_add(mat
->row
[i
][dst_col
],
1478 mat
->row
[i
][dst_col
], mat
->row
[i
][src_col
]);
1481 void isl_mat_col_mul(struct isl_mat
*mat
, int dst_col
, isl_int f
, int src_col
)
1485 for (i
= 0; i
< mat
->n_row
; ++i
)
1486 isl_int_mul(mat
->row
[i
][dst_col
], f
, mat
->row
[i
][src_col
]);
1489 struct isl_mat
*isl_mat_unimodular_complete(struct isl_mat
*M
, int row
)
1492 struct isl_mat
*H
= NULL
, *Q
= NULL
;
1497 isl_assert(M
->ctx
, M
->n_row
== M
->n_col
, goto error
);
1499 H
= isl_mat_left_hermite(isl_mat_copy(M
), 0, NULL
, &Q
);
1500 M
->n_row
= M
->n_col
;
1503 for (r
= 0; r
< row
; ++r
)
1504 isl_assert(M
->ctx
, isl_int_is_one(H
->row
[r
][r
]), goto error
);
1505 for (r
= row
; r
< M
->n_row
; ++r
)
1506 isl_seq_cpy(M
->row
[r
], Q
->row
[r
], M
->n_col
);
1517 __isl_give isl_mat
*isl_mat_concat(__isl_take isl_mat
*top
,
1518 __isl_take isl_mat
*bot
)
1520 struct isl_mat
*mat
;
1525 isl_assert(top
->ctx
, top
->n_col
== bot
->n_col
, goto error
);
1526 if (top
->n_row
== 0) {
1530 if (bot
->n_row
== 0) {
1535 mat
= isl_mat_alloc(top
->ctx
, top
->n_row
+ bot
->n_row
, top
->n_col
);
1538 isl_mat_sub_copy(mat
->ctx
, mat
->row
, top
->row
, top
->n_row
,
1540 isl_mat_sub_copy(mat
->ctx
, mat
->row
+ top
->n_row
, bot
->row
, bot
->n_row
,
1551 int isl_mat_is_equal(__isl_keep isl_mat
*mat1
, __isl_keep isl_mat
*mat2
)
1558 if (mat1
->n_row
!= mat2
->n_row
)
1561 if (mat1
->n_col
!= mat2
->n_col
)
1564 for (i
= 0; i
< mat1
->n_row
; ++i
)
1565 if (!isl_seq_eq(mat1
->row
[i
], mat2
->row
[i
], mat1
->n_col
))
1571 __isl_give isl_mat
*isl_mat_from_row_vec(__isl_take isl_vec
*vec
)
1573 struct isl_mat
*mat
;
1577 mat
= isl_mat_alloc(vec
->ctx
, 1, vec
->size
);
1581 isl_seq_cpy(mat
->row
[0], vec
->el
, vec
->size
);
1590 /* Return a copy of row "row" of "mat" as an isl_vec.
1592 __isl_give isl_vec
*isl_mat_get_row(__isl_keep isl_mat
*mat
, unsigned row
)
1598 if (row
>= mat
->n_row
)
1599 isl_die(mat
->ctx
, isl_error_invalid
, "row out of range",
1602 v
= isl_vec_alloc(isl_mat_get_ctx(mat
), mat
->n_col
);
1605 isl_seq_cpy(v
->el
, mat
->row
[row
], mat
->n_col
);
1610 __isl_give isl_mat
*isl_mat_vec_concat(__isl_take isl_mat
*top
,
1611 __isl_take isl_vec
*bot
)
1613 return isl_mat_concat(top
, isl_mat_from_row_vec(bot
));
1616 __isl_give isl_mat
*isl_mat_move_cols(__isl_take isl_mat
*mat
,
1617 unsigned dst_col
, unsigned src_col
, unsigned n
)
1623 if (n
== 0 || dst_col
== src_col
)
1626 res
= isl_mat_alloc(mat
->ctx
, mat
->n_row
, mat
->n_col
);
1630 if (dst_col
< src_col
) {
1631 isl_mat_sub_copy(res
->ctx
, res
->row
, mat
->row
, mat
->n_row
,
1633 isl_mat_sub_copy(res
->ctx
, res
->row
, mat
->row
, mat
->n_row
,
1634 dst_col
, src_col
, n
);
1635 isl_mat_sub_copy(res
->ctx
, res
->row
, mat
->row
, mat
->n_row
,
1636 dst_col
+ n
, dst_col
, src_col
- dst_col
);
1637 isl_mat_sub_copy(res
->ctx
, res
->row
, mat
->row
, mat
->n_row
,
1638 src_col
+ n
, src_col
+ n
,
1639 res
->n_col
- src_col
- n
);
1641 isl_mat_sub_copy(res
->ctx
, res
->row
, mat
->row
, mat
->n_row
,
1643 isl_mat_sub_copy(res
->ctx
, res
->row
, mat
->row
, mat
->n_row
,
1644 src_col
, src_col
+ n
, dst_col
- src_col
);
1645 isl_mat_sub_copy(res
->ctx
, res
->row
, mat
->row
, mat
->n_row
,
1646 dst_col
, src_col
, n
);
1647 isl_mat_sub_copy(res
->ctx
, res
->row
, mat
->row
, mat
->n_row
,
1648 dst_col
+ n
, dst_col
+ n
,
1649 res
->n_col
- dst_col
- n
);
1659 void isl_mat_gcd(__isl_keep isl_mat
*mat
, isl_int
*gcd
)
1664 isl_int_set_si(*gcd
, 0);
1669 for (i
= 0; i
< mat
->n_row
; ++i
) {
1670 isl_seq_gcd(mat
->row
[i
], mat
->n_col
, &g
);
1671 isl_int_gcd(*gcd
, *gcd
, g
);
1676 __isl_give isl_mat
*isl_mat_scale_down(__isl_take isl_mat
*mat
, isl_int m
)
1680 if (isl_int_is_one(m
))
1683 mat
= isl_mat_cow(mat
);
1687 for (i
= 0; i
< mat
->n_row
; ++i
)
1688 isl_seq_scale_down(mat
->row
[i
], mat
->row
[i
], m
, mat
->n_col
);
1693 __isl_give isl_mat
*isl_mat_scale_down_row(__isl_take isl_mat
*mat
, int row
,
1696 if (isl_int_is_one(m
))
1699 mat
= isl_mat_cow(mat
);
1703 isl_seq_scale_down(mat
->row
[row
], mat
->row
[row
], m
, mat
->n_col
);
1708 __isl_give isl_mat
*isl_mat_normalize(__isl_take isl_mat
*mat
)
1716 isl_mat_gcd(mat
, &gcd
);
1717 mat
= isl_mat_scale_down(mat
, gcd
);
1723 __isl_give isl_mat
*isl_mat_normalize_row(__isl_take isl_mat
*mat
, int row
)
1725 mat
= isl_mat_cow(mat
);
1729 isl_seq_normalize(mat
->ctx
, mat
->row
[row
], mat
->n_col
);
1734 /* Number of initial non-zero columns.
1736 int isl_mat_initial_non_zero_cols(__isl_keep isl_mat
*mat
)
1743 for (i
= 0; i
< mat
->n_col
; ++i
)
1744 if (row_first_non_zero(mat
->row
, mat
->n_row
, i
) < 0)