2 * Copyright 2008-2009 Katholieke Universiteit Leuven
4 * Use of this software is governed by the MIT license
6 * Written by Sven Verdoolaege, K.U.Leuven, Departement
7 * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
10 #include <isl_ctx_private.h>
11 #include <isl_map_private.h>
12 #include <isl/space.h>
14 #include <isl_mat_private.h>
15 #include <isl_space_private.h>
17 isl_ctx
*isl_mat_get_ctx(__isl_keep isl_mat
*mat
)
19 return mat
? mat
->ctx
: NULL
;
22 struct isl_mat
*isl_mat_alloc(struct isl_ctx
*ctx
,
23 unsigned n_row
, unsigned n_col
)
28 mat
= isl_alloc_type(ctx
, struct isl_mat
);
33 mat
->block
= isl_blk_alloc(ctx
, n_row
* n_col
);
34 if (isl_blk_is_error(mat
->block
))
36 mat
->row
= isl_alloc_array(ctx
, isl_int
*, n_row
);
40 for (i
= 0; i
< n_row
; ++i
)
41 mat
->row
[i
] = mat
->block
.data
+ i
* n_col
;
53 isl_blk_free(ctx
, mat
->block
);
58 struct isl_mat
*isl_mat_extend(struct isl_mat
*mat
,
59 unsigned n_row
, unsigned n_col
)
68 if (mat
->max_col
>= n_col
&& mat
->n_row
>= n_row
) {
69 if (mat
->n_col
< n_col
)
74 if (mat
->max_col
< n_col
) {
75 struct isl_mat
*new_mat
;
77 if (n_row
< mat
->n_row
)
79 new_mat
= isl_mat_alloc(mat
->ctx
, n_row
, n_col
);
82 for (i
= 0; i
< mat
->n_row
; ++i
)
83 isl_seq_cpy(new_mat
->row
[i
], mat
->row
[i
], mat
->n_col
);
88 mat
= isl_mat_cow(mat
);
92 old
= mat
->block
.data
;
93 mat
->block
= isl_blk_extend(mat
->ctx
, mat
->block
, n_row
* mat
->max_col
);
94 if (isl_blk_is_error(mat
->block
))
96 row
= isl_realloc_array(mat
->ctx
, mat
->row
, isl_int
*, n_row
);
101 for (i
= 0; i
< mat
->n_row
; ++i
)
102 mat
->row
[i
] = mat
->block
.data
+ (mat
->row
[i
] - old
);
103 for (i
= mat
->n_row
; i
< n_row
; ++i
)
104 mat
->row
[i
] = mat
->block
.data
+ i
* mat
->max_col
;
106 if (mat
->n_col
< n_col
)
115 __isl_give isl_mat
*isl_mat_sub_alloc6(isl_ctx
*ctx
, isl_int
**row
,
116 unsigned first_row
, unsigned n_row
, unsigned first_col
, unsigned n_col
)
121 mat
= isl_alloc_type(ctx
, struct isl_mat
);
124 mat
->row
= isl_alloc_array(ctx
, isl_int
*, n_row
);
127 for (i
= 0; i
< n_row
; ++i
)
128 mat
->row
[i
] = row
[first_row
+i
] + first_col
;
134 mat
->block
= isl_blk_empty();
135 mat
->flags
= ISL_MAT_BORROWED
;
142 __isl_give isl_mat
*isl_mat_sub_alloc(__isl_keep isl_mat
*mat
,
143 unsigned first_row
, unsigned n_row
, unsigned first_col
, unsigned n_col
)
147 return isl_mat_sub_alloc6(mat
->ctx
, mat
->row
, first_row
, n_row
,
151 void isl_mat_sub_copy(struct isl_ctx
*ctx
, isl_int
**dst
, isl_int
**src
,
152 unsigned n_row
, unsigned dst_col
, unsigned src_col
, unsigned n_col
)
156 for (i
= 0; i
< n_row
; ++i
)
157 isl_seq_cpy(dst
[i
]+dst_col
, src
[i
]+src_col
, n_col
);
160 void isl_mat_sub_neg(struct isl_ctx
*ctx
, isl_int
**dst
, isl_int
**src
,
161 unsigned n_row
, unsigned dst_col
, unsigned src_col
, unsigned n_col
)
165 for (i
= 0; i
< n_row
; ++i
)
166 isl_seq_neg(dst
[i
]+dst_col
, src
[i
]+src_col
, n_col
);
169 struct isl_mat
*isl_mat_copy(struct isl_mat
*mat
)
178 struct isl_mat
*isl_mat_dup(struct isl_mat
*mat
)
181 struct isl_mat
*mat2
;
185 mat2
= isl_mat_alloc(mat
->ctx
, mat
->n_row
, mat
->n_col
);
188 for (i
= 0; i
< mat
->n_row
; ++i
)
189 isl_seq_cpy(mat2
->row
[i
], mat
->row
[i
], mat
->n_col
);
193 struct isl_mat
*isl_mat_cow(struct isl_mat
*mat
)
195 struct isl_mat
*mat2
;
199 if (mat
->ref
== 1 && !ISL_F_ISSET(mat
, ISL_MAT_BORROWED
))
202 mat2
= isl_mat_dup(mat
);
207 void *isl_mat_free(struct isl_mat
*mat
)
215 if (!ISL_F_ISSET(mat
, ISL_MAT_BORROWED
))
216 isl_blk_free(mat
->ctx
, mat
->block
);
217 isl_ctx_deref(mat
->ctx
);
224 int isl_mat_rows(__isl_keep isl_mat
*mat
)
226 return mat
? mat
->n_row
: -1;
229 int isl_mat_cols(__isl_keep isl_mat
*mat
)
231 return mat
? mat
->n_col
: -1;
234 int isl_mat_get_element(__isl_keep isl_mat
*mat
, int row
, int col
, isl_int
*v
)
238 if (row
< 0 || row
>= mat
->n_row
)
239 isl_die(mat
->ctx
, isl_error_invalid
, "row out of range",
241 if (col
< 0 || col
>= mat
->n_col
)
242 isl_die(mat
->ctx
, isl_error_invalid
, "column out of range",
244 isl_int_set(*v
, mat
->row
[row
][col
]);
248 __isl_give isl_mat
*isl_mat_set_element(__isl_take isl_mat
*mat
,
249 int row
, int col
, isl_int v
)
251 mat
= isl_mat_cow(mat
);
254 if (row
< 0 || row
>= mat
->n_row
)
255 isl_die(mat
->ctx
, isl_error_invalid
, "row out of range",
257 if (col
< 0 || col
>= mat
->n_col
)
258 isl_die(mat
->ctx
, isl_error_invalid
, "column out of range",
260 isl_int_set(mat
->row
[row
][col
], v
);
267 __isl_give isl_mat
*isl_mat_set_element_si(__isl_take isl_mat
*mat
,
268 int row
, int col
, int v
)
270 mat
= isl_mat_cow(mat
);
273 if (row
< 0 || row
>= mat
->n_row
)
274 isl_die(mat
->ctx
, isl_error_invalid
, "row out of range",
276 if (col
< 0 || col
>= mat
->n_col
)
277 isl_die(mat
->ctx
, isl_error_invalid
, "column out of range",
279 isl_int_set_si(mat
->row
[row
][col
], v
);
286 __isl_give isl_mat
*isl_mat_diag(isl_ctx
*ctx
, unsigned n_row
, isl_int d
)
291 mat
= isl_mat_alloc(ctx
, n_row
, n_row
);
294 for (i
= 0; i
< n_row
; ++i
) {
295 isl_seq_clr(mat
->row
[i
], i
);
296 isl_int_set(mat
->row
[i
][i
], d
);
297 isl_seq_clr(mat
->row
[i
]+i
+1, n_row
-(i
+1));
303 __isl_give isl_mat
*isl_mat_identity(isl_ctx
*ctx
, unsigned n_row
)
307 return isl_mat_diag(ctx
, n_row
, ctx
->one
);
310 struct isl_vec
*isl_mat_vec_product(struct isl_mat
*mat
, struct isl_vec
*vec
)
313 struct isl_vec
*prod
;
318 isl_assert(mat
->ctx
, mat
->n_col
== vec
->size
, goto error
);
320 prod
= isl_vec_alloc(mat
->ctx
, mat
->n_row
);
324 for (i
= 0; i
< prod
->size
; ++i
)
325 isl_seq_inner_product(mat
->row
[i
], vec
->el
, vec
->size
,
326 &prod
->block
.data
[i
]);
336 __isl_give isl_vec
*isl_mat_vec_inverse_product(__isl_take isl_mat
*mat
,
337 __isl_take isl_vec
*vec
)
339 struct isl_mat
*vec_mat
;
344 vec_mat
= isl_mat_alloc(vec
->ctx
, vec
->size
, 1);
347 for (i
= 0; i
< vec
->size
; ++i
)
348 isl_int_set(vec_mat
->row
[i
][0], vec
->el
[i
]);
349 vec_mat
= isl_mat_inverse_product(mat
, vec_mat
);
353 vec
= isl_vec_alloc(vec_mat
->ctx
, vec_mat
->n_row
);
355 for (i
= 0; i
< vec
->size
; ++i
)
356 isl_int_set(vec
->el
[i
], vec_mat
->row
[i
][0]);
357 isl_mat_free(vec_mat
);
365 struct isl_vec
*isl_vec_mat_product(struct isl_vec
*vec
, struct isl_mat
*mat
)
368 struct isl_vec
*prod
;
373 isl_assert(mat
->ctx
, mat
->n_row
== vec
->size
, goto error
);
375 prod
= isl_vec_alloc(mat
->ctx
, mat
->n_col
);
379 for (i
= 0; i
< prod
->size
; ++i
) {
380 isl_int_set_si(prod
->el
[i
], 0);
381 for (j
= 0; j
< vec
->size
; ++j
)
382 isl_int_addmul(prod
->el
[i
], vec
->el
[j
], mat
->row
[j
][i
]);
393 struct isl_mat
*isl_mat_aff_direct_sum(struct isl_mat
*left
,
394 struct isl_mat
*right
)
402 isl_assert(left
->ctx
, left
->n_row
== right
->n_row
, goto error
);
403 isl_assert(left
->ctx
, left
->n_row
>= 1, goto error
);
404 isl_assert(left
->ctx
, left
->n_col
>= 1, goto error
);
405 isl_assert(left
->ctx
, right
->n_col
>= 1, goto error
);
406 isl_assert(left
->ctx
,
407 isl_seq_first_non_zero(left
->row
[0]+1, left
->n_col
-1) == -1,
409 isl_assert(left
->ctx
,
410 isl_seq_first_non_zero(right
->row
[0]+1, right
->n_col
-1) == -1,
413 sum
= isl_mat_alloc(left
->ctx
, left
->n_row
, left
->n_col
+ right
->n_col
- 1);
416 isl_int_lcm(sum
->row
[0][0], left
->row
[0][0], right
->row
[0][0]);
417 isl_int_divexact(left
->row
[0][0], sum
->row
[0][0], left
->row
[0][0]);
418 isl_int_divexact(right
->row
[0][0], sum
->row
[0][0], right
->row
[0][0]);
420 isl_seq_clr(sum
->row
[0]+1, sum
->n_col
-1);
421 for (i
= 1; i
< sum
->n_row
; ++i
) {
422 isl_int_mul(sum
->row
[i
][0], left
->row
[0][0], left
->row
[i
][0]);
423 isl_int_addmul(sum
->row
[i
][0],
424 right
->row
[0][0], right
->row
[i
][0]);
425 isl_seq_scale(sum
->row
[i
]+1, left
->row
[i
]+1, left
->row
[0][0],
427 isl_seq_scale(sum
->row
[i
]+left
->n_col
,
428 right
->row
[i
]+1, right
->row
[0][0],
432 isl_int_divexact(left
->row
[0][0], sum
->row
[0][0], left
->row
[0][0]);
433 isl_int_divexact(right
->row
[0][0], sum
->row
[0][0], right
->row
[0][0]);
443 static void exchange(struct isl_mat
*M
, struct isl_mat
**U
,
444 struct isl_mat
**Q
, unsigned row
, unsigned i
, unsigned j
)
447 for (r
= row
; r
< M
->n_row
; ++r
)
448 isl_int_swap(M
->row
[r
][i
], M
->row
[r
][j
]);
450 for (r
= 0; r
< (*U
)->n_row
; ++r
)
451 isl_int_swap((*U
)->row
[r
][i
], (*U
)->row
[r
][j
]);
454 isl_mat_swap_rows(*Q
, i
, j
);
457 static void subtract(struct isl_mat
*M
, struct isl_mat
**U
,
458 struct isl_mat
**Q
, unsigned row
, unsigned i
, unsigned j
, isl_int m
)
461 for (r
= row
; r
< M
->n_row
; ++r
)
462 isl_int_submul(M
->row
[r
][j
], m
, M
->row
[r
][i
]);
464 for (r
= 0; r
< (*U
)->n_row
; ++r
)
465 isl_int_submul((*U
)->row
[r
][j
], m
, (*U
)->row
[r
][i
]);
468 for (r
= 0; r
< (*Q
)->n_col
; ++r
)
469 isl_int_addmul((*Q
)->row
[i
][r
], m
, (*Q
)->row
[j
][r
]);
473 static void oppose(struct isl_mat
*M
, struct isl_mat
**U
,
474 struct isl_mat
**Q
, unsigned row
, unsigned col
)
477 for (r
= row
; r
< M
->n_row
; ++r
)
478 isl_int_neg(M
->row
[r
][col
], M
->row
[r
][col
]);
480 for (r
= 0; r
< (*U
)->n_row
; ++r
)
481 isl_int_neg((*U
)->row
[r
][col
], (*U
)->row
[r
][col
]);
484 isl_seq_neg((*Q
)->row
[col
], (*Q
)->row
[col
], (*Q
)->n_col
);
487 /* Given matrix M, compute
492 * with U and Q unimodular matrices and H a matrix in column echelon form
493 * such that on each echelon row the entries in the non-echelon column
494 * are non-negative (if neg == 0) or non-positive (if neg == 1)
495 * and stricly smaller (in absolute value) than the entries in the echelon
497 * If U or Q are NULL, then these matrices are not computed.
499 struct isl_mat
*isl_mat_left_hermite(struct isl_mat
*M
, int neg
,
500 struct isl_mat
**U
, struct isl_mat
**Q
)
515 *U
= isl_mat_identity(M
->ctx
, M
->n_col
);
520 *Q
= isl_mat_identity(M
->ctx
, M
->n_col
);
527 for (row
= 0; row
< M
->n_row
; ++row
) {
529 first
= isl_seq_abs_min_non_zero(M
->row
[row
]+col
, M
->n_col
-col
);
534 exchange(M
, U
, Q
, row
, first
, col
);
535 if (isl_int_is_neg(M
->row
[row
][col
]))
536 oppose(M
, U
, Q
, row
, col
);
538 while ((off
= isl_seq_first_non_zero(M
->row
[row
]+first
,
539 M
->n_col
-first
)) != -1) {
541 isl_int_fdiv_q(c
, M
->row
[row
][first
], M
->row
[row
][col
]);
542 subtract(M
, U
, Q
, row
, col
, first
, c
);
543 if (!isl_int_is_zero(M
->row
[row
][first
]))
544 exchange(M
, U
, Q
, row
, first
, col
);
548 for (i
= 0; i
< col
; ++i
) {
549 if (isl_int_is_zero(M
->row
[row
][i
]))
552 isl_int_cdiv_q(c
, M
->row
[row
][i
], M
->row
[row
][col
]);
554 isl_int_fdiv_q(c
, M
->row
[row
][i
], M
->row
[row
][col
]);
555 if (isl_int_is_zero(c
))
557 subtract(M
, U
, Q
, row
, col
, i
, c
);
577 struct isl_mat
*isl_mat_right_kernel(struct isl_mat
*mat
)
580 struct isl_mat
*U
= NULL
;
583 mat
= isl_mat_left_hermite(mat
, 0, &U
, NULL
);
587 for (i
= 0, rank
= 0; rank
< mat
->n_col
; ++rank
) {
588 while (i
< mat
->n_row
&& isl_int_is_zero(mat
->row
[i
][rank
]))
593 K
= isl_mat_alloc(U
->ctx
, U
->n_row
, U
->n_col
- rank
);
596 isl_mat_sub_copy(K
->ctx
, K
->row
, U
->row
, U
->n_row
, 0, rank
, U
->n_col
-rank
);
606 struct isl_mat
*isl_mat_lin_to_aff(struct isl_mat
*mat
)
609 struct isl_mat
*mat2
;
613 mat2
= isl_mat_alloc(mat
->ctx
, 1+mat
->n_row
, 1+mat
->n_col
);
616 isl_int_set_si(mat2
->row
[0][0], 1);
617 isl_seq_clr(mat2
->row
[0]+1, mat
->n_col
);
618 for (i
= 0; i
< mat
->n_row
; ++i
) {
619 isl_int_set_si(mat2
->row
[1+i
][0], 0);
620 isl_seq_cpy(mat2
->row
[1+i
]+1, mat
->row
[i
], mat
->n_col
);
629 /* Given two matrices M1 and M2, return the block matrix
634 __isl_give isl_mat
*isl_mat_diagonal(__isl_take isl_mat
*mat1
,
635 __isl_take isl_mat
*mat2
)
643 mat
= isl_mat_alloc(mat1
->ctx
, mat1
->n_row
+ mat2
->n_row
,
644 mat1
->n_col
+ mat2
->n_col
);
647 for (i
= 0; i
< mat1
->n_row
; ++i
) {
648 isl_seq_cpy(mat
->row
[i
], mat1
->row
[i
], mat1
->n_col
);
649 isl_seq_clr(mat
->row
[i
] + mat1
->n_col
, mat2
->n_col
);
651 for (i
= 0; i
< mat2
->n_row
; ++i
) {
652 isl_seq_clr(mat
->row
[mat1
->n_row
+ i
], mat1
->n_col
);
653 isl_seq_cpy(mat
->row
[mat1
->n_row
+ i
] + mat1
->n_col
,
654 mat2
->row
[i
], mat2
->n_col
);
665 static int row_first_non_zero(isl_int
**row
, unsigned n_row
, unsigned col
)
669 for (i
= 0; i
< n_row
; ++i
)
670 if (!isl_int_is_zero(row
[i
][col
]))
675 static int row_abs_min_non_zero(isl_int
**row
, unsigned n_row
, unsigned col
)
677 int i
, min
= row_first_non_zero(row
, n_row
, col
);
680 for (i
= min
+ 1; i
< n_row
; ++i
) {
681 if (isl_int_is_zero(row
[i
][col
]))
683 if (isl_int_abs_lt(row
[i
][col
], row
[min
][col
]))
689 static void inv_exchange(struct isl_mat
*left
, struct isl_mat
*right
,
690 unsigned i
, unsigned j
)
692 left
= isl_mat_swap_rows(left
, i
, j
);
693 right
= isl_mat_swap_rows(right
, i
, j
);
696 static void inv_oppose(
697 struct isl_mat
*left
, struct isl_mat
*right
, unsigned row
)
699 isl_seq_neg(left
->row
[row
]+row
, left
->row
[row
]+row
, left
->n_col
-row
);
700 isl_seq_neg(right
->row
[row
], right
->row
[row
], right
->n_col
);
703 static void inv_subtract(struct isl_mat
*left
, struct isl_mat
*right
,
704 unsigned row
, unsigned i
, isl_int m
)
707 isl_seq_combine(left
->row
[i
]+row
,
708 left
->ctx
->one
, left
->row
[i
]+row
,
709 m
, left
->row
[row
]+row
,
711 isl_seq_combine(right
->row
[i
], right
->ctx
->one
, right
->row
[i
],
712 m
, right
->row
[row
], right
->n_col
);
715 /* Compute inv(left)*right
717 struct isl_mat
*isl_mat_inverse_product(struct isl_mat
*left
,
718 struct isl_mat
*right
)
726 isl_assert(left
->ctx
, left
->n_row
== left
->n_col
, goto error
);
727 isl_assert(left
->ctx
, left
->n_row
== right
->n_row
, goto error
);
729 if (left
->n_row
== 0) {
734 left
= isl_mat_cow(left
);
735 right
= isl_mat_cow(right
);
741 for (row
= 0; row
< left
->n_row
; ++row
) {
742 int pivot
, first
, i
, off
;
743 pivot
= row_abs_min_non_zero(left
->row
+row
, left
->n_row
-row
, row
);
747 isl_assert(left
->ctx
, pivot
>= 0, goto error
);
751 inv_exchange(left
, right
, pivot
, row
);
752 if (isl_int_is_neg(left
->row
[row
][row
]))
753 inv_oppose(left
, right
, row
);
755 while ((off
= row_first_non_zero(left
->row
+first
,
756 left
->n_row
-first
, row
)) != -1) {
758 isl_int_fdiv_q(a
, left
->row
[first
][row
],
759 left
->row
[row
][row
]);
760 inv_subtract(left
, right
, row
, first
, a
);
761 if (!isl_int_is_zero(left
->row
[first
][row
]))
762 inv_exchange(left
, right
, row
, first
);
766 for (i
= 0; i
< row
; ++i
) {
767 if (isl_int_is_zero(left
->row
[i
][row
]))
769 isl_int_gcd(a
, left
->row
[row
][row
], left
->row
[i
][row
]);
770 isl_int_divexact(b
, left
->row
[i
][row
], a
);
771 isl_int_divexact(a
, left
->row
[row
][row
], a
);
773 isl_seq_combine(left
->row
[i
] + i
,
775 b
, left
->row
[row
] + i
,
777 isl_seq_combine(right
->row
[i
], a
, right
->row
[i
],
778 b
, right
->row
[row
], right
->n_col
);
783 isl_int_set(a
, left
->row
[0][0]);
784 for (row
= 1; row
< left
->n_row
; ++row
)
785 isl_int_lcm(a
, a
, left
->row
[row
][row
]);
786 if (isl_int_is_zero(a
)){
788 isl_assert(left
->ctx
, 0, goto error
);
790 for (row
= 0; row
< left
->n_row
; ++row
) {
791 isl_int_divexact(left
->row
[row
][row
], a
, left
->row
[row
][row
]);
792 if (isl_int_is_one(left
->row
[row
][row
]))
794 isl_seq_scale(right
->row
[row
], right
->row
[row
],
795 left
->row
[row
][row
], right
->n_col
);
807 void isl_mat_col_scale(struct isl_mat
*mat
, unsigned col
, isl_int m
)
811 for (i
= 0; i
< mat
->n_row
; ++i
)
812 isl_int_mul(mat
->row
[i
][col
], mat
->row
[i
][col
], m
);
815 void isl_mat_col_combine(struct isl_mat
*mat
, unsigned dst
,
816 isl_int m1
, unsigned src1
, isl_int m2
, unsigned src2
)
822 for (i
= 0; i
< mat
->n_row
; ++i
) {
823 isl_int_mul(tmp
, m1
, mat
->row
[i
][src1
]);
824 isl_int_addmul(tmp
, m2
, mat
->row
[i
][src2
]);
825 isl_int_set(mat
->row
[i
][dst
], tmp
);
830 struct isl_mat
*isl_mat_right_inverse(struct isl_mat
*mat
)
836 mat
= isl_mat_cow(mat
);
840 inv
= isl_mat_identity(mat
->ctx
, mat
->n_col
);
841 inv
= isl_mat_cow(inv
);
847 for (row
= 0; row
< mat
->n_row
; ++row
) {
848 int pivot
, first
, i
, off
;
849 pivot
= isl_seq_abs_min_non_zero(mat
->row
[row
]+row
, mat
->n_col
-row
);
853 isl_assert(mat
->ctx
, pivot
>= 0, goto error
);
857 exchange(mat
, &inv
, NULL
, row
, pivot
, row
);
858 if (isl_int_is_neg(mat
->row
[row
][row
]))
859 oppose(mat
, &inv
, NULL
, row
, row
);
861 while ((off
= isl_seq_first_non_zero(mat
->row
[row
]+first
,
862 mat
->n_col
-first
)) != -1) {
864 isl_int_fdiv_q(a
, mat
->row
[row
][first
],
866 subtract(mat
, &inv
, NULL
, row
, row
, first
, a
);
867 if (!isl_int_is_zero(mat
->row
[row
][first
]))
868 exchange(mat
, &inv
, NULL
, row
, row
, first
);
872 for (i
= 0; i
< row
; ++i
) {
873 if (isl_int_is_zero(mat
->row
[row
][i
]))
875 isl_int_gcd(a
, mat
->row
[row
][row
], mat
->row
[row
][i
]);
876 isl_int_divexact(b
, mat
->row
[row
][i
], a
);
877 isl_int_divexact(a
, mat
->row
[row
][row
], a
);
879 isl_mat_col_combine(mat
, i
, a
, i
, b
, row
);
880 isl_mat_col_combine(inv
, i
, a
, i
, b
, row
);
885 isl_int_set(a
, mat
->row
[0][0]);
886 for (row
= 1; row
< mat
->n_row
; ++row
)
887 isl_int_lcm(a
, a
, mat
->row
[row
][row
]);
888 if (isl_int_is_zero(a
)){
892 for (row
= 0; row
< mat
->n_row
; ++row
) {
893 isl_int_divexact(mat
->row
[row
][row
], a
, mat
->row
[row
][row
]);
894 if (isl_int_is_one(mat
->row
[row
][row
]))
896 isl_mat_col_scale(inv
, row
, mat
->row
[row
][row
]);
909 struct isl_mat
*isl_mat_transpose(struct isl_mat
*mat
)
911 struct isl_mat
*transpose
= NULL
;
917 if (mat
->n_col
== mat
->n_row
) {
918 mat
= isl_mat_cow(mat
);
921 for (i
= 0; i
< mat
->n_row
; ++i
)
922 for (j
= i
+ 1; j
< mat
->n_col
; ++j
)
923 isl_int_swap(mat
->row
[i
][j
], mat
->row
[j
][i
]);
926 transpose
= isl_mat_alloc(mat
->ctx
, mat
->n_col
, mat
->n_row
);
929 for (i
= 0; i
< mat
->n_row
; ++i
)
930 for (j
= 0; j
< mat
->n_col
; ++j
)
931 isl_int_set(transpose
->row
[j
][i
], mat
->row
[i
][j
]);
939 struct isl_mat
*isl_mat_swap_cols(struct isl_mat
*mat
, unsigned i
, unsigned j
)
943 mat
= isl_mat_cow(mat
);
946 isl_assert(mat
->ctx
, i
< mat
->n_col
, goto error
);
947 isl_assert(mat
->ctx
, j
< mat
->n_col
, goto error
);
949 for (r
= 0; r
< mat
->n_row
; ++r
)
950 isl_int_swap(mat
->row
[r
][i
], mat
->row
[r
][j
]);
957 struct isl_mat
*isl_mat_swap_rows(struct isl_mat
*mat
, unsigned i
, unsigned j
)
963 mat
= isl_mat_cow(mat
);
967 mat
->row
[i
] = mat
->row
[j
];
972 __isl_give isl_mat
*isl_mat_product(__isl_take isl_mat
*left
,
973 __isl_take isl_mat
*right
)
976 struct isl_mat
*prod
;
980 isl_assert(left
->ctx
, left
->n_col
== right
->n_row
, goto error
);
981 prod
= isl_mat_alloc(left
->ctx
, left
->n_row
, right
->n_col
);
984 if (left
->n_col
== 0) {
985 for (i
= 0; i
< prod
->n_row
; ++i
)
986 isl_seq_clr(prod
->row
[i
], prod
->n_col
);
991 for (i
= 0; i
< prod
->n_row
; ++i
) {
992 for (j
= 0; j
< prod
->n_col
; ++j
) {
993 isl_int_mul(prod
->row
[i
][j
],
994 left
->row
[i
][0], right
->row
[0][j
]);
995 for (k
= 1; k
< left
->n_col
; ++k
)
996 isl_int_addmul(prod
->row
[i
][j
],
997 left
->row
[i
][k
], right
->row
[k
][j
]);
1001 isl_mat_free(right
);
1005 isl_mat_free(right
);
1009 /* Replace the variables x in the rows q by x' given by x = M x',
1010 * with M the matrix mat.
1012 * If the number of new variables is greater than the original
1013 * number of variables, then the rows q have already been
1014 * preextended. If the new number is smaller, then the coefficients
1015 * of the divs, which are not changed, need to be shifted down.
1016 * The row q may be the equalities, the inequalities or the
1017 * div expressions. In the latter case, has_div is true and
1018 * we need to take into account the extra denominator column.
1020 static int preimage(struct isl_ctx
*ctx
, isl_int
**q
, unsigned n
,
1021 unsigned n_div
, int has_div
, struct isl_mat
*mat
)
1027 if (mat
->n_col
>= mat
->n_row
)
1030 e
= mat
->n_row
- mat
->n_col
;
1032 for (i
= 0; i
< n
; ++i
)
1033 isl_int_mul(q
[i
][0], q
[i
][0], mat
->row
[0][0]);
1034 t
= isl_mat_sub_alloc6(mat
->ctx
, q
, 0, n
, has_div
, mat
->n_row
);
1035 t
= isl_mat_product(t
, mat
);
1038 for (i
= 0; i
< n
; ++i
) {
1039 isl_seq_swp_or_cpy(q
[i
] + has_div
, t
->row
[i
], t
->n_col
);
1040 isl_seq_cpy(q
[i
] + has_div
+ t
->n_col
,
1041 q
[i
] + has_div
+ t
->n_col
+ e
, n_div
);
1042 isl_seq_clr(q
[i
] + has_div
+ t
->n_col
+ n_div
, e
);
1048 /* Replace the variables x in bset by x' given by x = M x', with
1051 * If there are fewer variables x' then there are x, then we perform
1052 * the transformation in place, which that, in principle,
1053 * this frees up some extra variables as the number
1054 * of columns remains constant, but we would have to extend
1055 * the div array too as the number of rows in this array is assumed
1056 * to be equal to extra.
1058 struct isl_basic_set
*isl_basic_set_preimage(struct isl_basic_set
*bset
,
1059 struct isl_mat
*mat
)
1061 struct isl_ctx
*ctx
;
1067 bset
= isl_basic_set_cow(bset
);
1071 isl_assert(ctx
, bset
->dim
->nparam
== 0, goto error
);
1072 isl_assert(ctx
, 1+bset
->dim
->n_out
== mat
->n_row
, goto error
);
1073 isl_assert(ctx
, mat
->n_col
> 0, goto error
);
1075 if (mat
->n_col
> mat
->n_row
) {
1076 bset
= isl_basic_set_extend(bset
, 0, mat
->n_col
-1, 0, 0, 0);
1079 } else if (mat
->n_col
< mat
->n_row
) {
1080 bset
->dim
= isl_space_cow(bset
->dim
);
1083 bset
->dim
->n_out
-= mat
->n_row
- mat
->n_col
;
1086 if (preimage(ctx
, bset
->eq
, bset
->n_eq
, bset
->n_div
, 0,
1087 isl_mat_copy(mat
)) < 0)
1090 if (preimage(ctx
, bset
->ineq
, bset
->n_ineq
, bset
->n_div
, 0,
1091 isl_mat_copy(mat
)) < 0)
1094 if (preimage(ctx
, bset
->div
, bset
->n_div
, bset
->n_div
, 1, mat
) < 0)
1097 ISL_F_CLR(bset
, ISL_BASIC_SET_NO_IMPLICIT
);
1098 ISL_F_CLR(bset
, ISL_BASIC_SET_NO_REDUNDANT
);
1099 ISL_F_CLR(bset
, ISL_BASIC_SET_NORMALIZED
);
1100 ISL_F_CLR(bset
, ISL_BASIC_SET_NORMALIZED_DIVS
);
1101 ISL_F_CLR(bset
, ISL_BASIC_SET_ALL_EQUALITIES
);
1103 bset
= isl_basic_set_simplify(bset
);
1104 bset
= isl_basic_set_finalize(bset
);
1110 isl_basic_set_free(bset
);
1114 struct isl_set
*isl_set_preimage(struct isl_set
*set
, struct isl_mat
*mat
)
1116 struct isl_ctx
*ctx
;
1119 set
= isl_set_cow(set
);
1124 for (i
= 0; i
< set
->n
; ++i
) {
1125 set
->p
[i
] = isl_basic_set_preimage(set
->p
[i
],
1130 if (mat
->n_col
!= mat
->n_row
) {
1131 set
->dim
= isl_space_cow(set
->dim
);
1134 set
->dim
->n_out
+= mat
->n_col
;
1135 set
->dim
->n_out
-= mat
->n_row
;
1138 ISL_F_CLR(set
, ISL_SET_NORMALIZED
);
1146 /* Replace the variables x starting at pos in the rows q
1147 * by x' with x = M x' with M the matrix mat.
1148 * That is, replace the corresponding coefficients c by c M.
1150 static int transform(isl_ctx
*ctx
, isl_int
**q
, unsigned n
,
1151 unsigned pos
, __isl_take isl_mat
*mat
)
1156 t
= isl_mat_sub_alloc6(ctx
, q
, 0, n
, pos
, mat
->n_row
);
1157 t
= isl_mat_product(t
, mat
);
1160 for (i
= 0; i
< n
; ++i
)
1161 isl_seq_swp_or_cpy(q
[i
] + pos
, t
->row
[i
], t
->n_col
);
1166 /* Replace the variables x of type "type" starting at "first" in "bset"
1167 * by x' with x = M x' with M the matrix trans.
1168 * That is, replace the corresponding coefficients c by c M.
1170 * The transformation matrix should be a square matrix.
1172 __isl_give isl_basic_set
*isl_basic_set_transform_dims(
1173 __isl_take isl_basic_set
*bset
, enum isl_dim_type type
, unsigned first
,
1174 __isl_take isl_mat
*trans
)
1179 bset
= isl_basic_set_cow(bset
);
1180 if (!bset
|| !trans
)
1183 ctx
= isl_basic_set_get_ctx(bset
);
1184 if (trans
->n_row
!= trans
->n_col
)
1185 isl_die(trans
->ctx
, isl_error_invalid
,
1186 "expecting square transformation matrix", goto error
);
1187 if (first
+ trans
->n_row
> isl_basic_set_dim(bset
, type
))
1188 isl_die(trans
->ctx
, isl_error_invalid
,
1189 "oversized transformation matrix", goto error
);
1191 pos
= isl_basic_set_offset(bset
, type
) + first
;
1193 if (transform(ctx
, bset
->eq
, bset
->n_eq
, pos
, isl_mat_copy(trans
)) < 0)
1195 if (transform(ctx
, bset
->ineq
, bset
->n_ineq
, pos
,
1196 isl_mat_copy(trans
)) < 0)
1198 if (transform(ctx
, bset
->div
, bset
->n_div
, 1 + pos
,
1199 isl_mat_copy(trans
)) < 0)
1202 ISL_F_CLR(bset
, ISL_BASIC_SET_NORMALIZED
);
1203 ISL_F_CLR(bset
, ISL_BASIC_SET_NORMALIZED_DIVS
);
1205 isl_mat_free(trans
);
1208 isl_mat_free(trans
);
1209 isl_basic_set_free(bset
);
1213 void isl_mat_print_internal(__isl_keep isl_mat
*mat
, FILE *out
, int indent
)
1218 fprintf(out
, "%*snull mat\n", indent
, "");
1222 if (mat
->n_row
== 0)
1223 fprintf(out
, "%*s[]\n", indent
, "");
1225 for (i
= 0; i
< mat
->n_row
; ++i
) {
1227 fprintf(out
, "%*s[[", indent
, "");
1229 fprintf(out
, "%*s[", indent
+1, "");
1230 for (j
= 0; j
< mat
->n_col
; ++j
) {
1233 isl_int_print(out
, mat
->row
[i
][j
], 0);
1235 if (i
== mat
->n_row
-1)
1236 fprintf(out
, "]]\n");
1238 fprintf(out
, "]\n");
1242 void isl_mat_dump(__isl_keep isl_mat
*mat
)
1244 isl_mat_print_internal(mat
, stderr
, 0);
1247 struct isl_mat
*isl_mat_drop_cols(struct isl_mat
*mat
, unsigned col
, unsigned n
)
1254 mat
= isl_mat_cow(mat
);
1258 if (col
!= mat
->n_col
-n
) {
1259 for (r
= 0; r
< mat
->n_row
; ++r
)
1260 isl_seq_cpy(mat
->row
[r
]+col
, mat
->row
[r
]+col
+n
,
1261 mat
->n_col
- col
- n
);
1267 struct isl_mat
*isl_mat_drop_rows(struct isl_mat
*mat
, unsigned row
, unsigned n
)
1271 mat
= isl_mat_cow(mat
);
1275 for (r
= row
; r
+n
< mat
->n_row
; ++r
)
1276 mat
->row
[r
] = mat
->row
[r
+n
];
1282 __isl_give isl_mat
*isl_mat_insert_cols(__isl_take isl_mat
*mat
,
1283 unsigned col
, unsigned n
)
1292 ext
= isl_mat_alloc(mat
->ctx
, mat
->n_row
, mat
->n_col
+ n
);
1296 isl_mat_sub_copy(mat
->ctx
, ext
->row
, mat
->row
, mat
->n_row
, 0, 0, col
);
1297 isl_mat_sub_copy(mat
->ctx
, ext
->row
, mat
->row
, mat
->n_row
,
1298 col
+ n
, col
, mat
->n_col
- col
);
1307 __isl_give isl_mat
*isl_mat_insert_zero_cols(__isl_take isl_mat
*mat
,
1308 unsigned first
, unsigned n
)
1314 mat
= isl_mat_insert_cols(mat
, first
, n
);
1318 for (i
= 0; i
< mat
->n_row
; ++i
)
1319 isl_seq_clr(mat
->row
[i
] + first
, n
);
1324 __isl_give isl_mat
*isl_mat_add_zero_cols(__isl_take isl_mat
*mat
, unsigned n
)
1329 return isl_mat_insert_zero_cols(mat
, mat
->n_col
, n
);
1332 __isl_give isl_mat
*isl_mat_insert_rows(__isl_take isl_mat
*mat
,
1333 unsigned row
, unsigned n
)
1342 ext
= isl_mat_alloc(mat
->ctx
, mat
->n_row
+ n
, mat
->n_col
);
1346 isl_mat_sub_copy(mat
->ctx
, ext
->row
, mat
->row
, row
, 0, 0, mat
->n_col
);
1347 isl_mat_sub_copy(mat
->ctx
, ext
->row
+ row
+ n
, mat
->row
+ row
,
1348 mat
->n_row
- row
, 0, 0, mat
->n_col
);
1357 __isl_give isl_mat
*isl_mat_add_rows(__isl_take isl_mat
*mat
, unsigned n
)
1362 return isl_mat_insert_rows(mat
, mat
->n_row
, n
);
1365 __isl_give isl_mat
*isl_mat_insert_zero_rows(__isl_take isl_mat
*mat
,
1366 unsigned row
, unsigned n
)
1370 mat
= isl_mat_insert_rows(mat
, row
, n
);
1374 for (i
= 0; i
< n
; ++i
)
1375 isl_seq_clr(mat
->row
[row
+ i
], mat
->n_col
);
1380 __isl_give isl_mat
*isl_mat_add_zero_rows(__isl_take isl_mat
*mat
, unsigned n
)
1385 return isl_mat_insert_zero_rows(mat
, mat
->n_row
, n
);
1388 void isl_mat_col_submul(struct isl_mat
*mat
,
1389 int dst_col
, isl_int f
, int src_col
)
1393 for (i
= 0; i
< mat
->n_row
; ++i
)
1394 isl_int_submul(mat
->row
[i
][dst_col
], f
, mat
->row
[i
][src_col
]);
1397 void isl_mat_col_add(__isl_keep isl_mat
*mat
, int dst_col
, int src_col
)
1404 for (i
= 0; i
< mat
->n_row
; ++i
)
1405 isl_int_add(mat
->row
[i
][dst_col
],
1406 mat
->row
[i
][dst_col
], mat
->row
[i
][src_col
]);
1409 void isl_mat_col_mul(struct isl_mat
*mat
, int dst_col
, isl_int f
, int src_col
)
1413 for (i
= 0; i
< mat
->n_row
; ++i
)
1414 isl_int_mul(mat
->row
[i
][dst_col
], f
, mat
->row
[i
][src_col
]);
1417 struct isl_mat
*isl_mat_unimodular_complete(struct isl_mat
*M
, int row
)
1420 struct isl_mat
*H
= NULL
, *Q
= NULL
;
1425 isl_assert(M
->ctx
, M
->n_row
== M
->n_col
, goto error
);
1427 H
= isl_mat_left_hermite(isl_mat_copy(M
), 0, NULL
, &Q
);
1428 M
->n_row
= M
->n_col
;
1431 for (r
= 0; r
< row
; ++r
)
1432 isl_assert(M
->ctx
, isl_int_is_one(H
->row
[r
][r
]), goto error
);
1433 for (r
= row
; r
< M
->n_row
; ++r
)
1434 isl_seq_cpy(M
->row
[r
], Q
->row
[r
], M
->n_col
);
1445 __isl_give isl_mat
*isl_mat_concat(__isl_take isl_mat
*top
,
1446 __isl_take isl_mat
*bot
)
1448 struct isl_mat
*mat
;
1453 isl_assert(top
->ctx
, top
->n_col
== bot
->n_col
, goto error
);
1454 if (top
->n_row
== 0) {
1458 if (bot
->n_row
== 0) {
1463 mat
= isl_mat_alloc(top
->ctx
, top
->n_row
+ bot
->n_row
, top
->n_col
);
1466 isl_mat_sub_copy(mat
->ctx
, mat
->row
, top
->row
, top
->n_row
,
1468 isl_mat_sub_copy(mat
->ctx
, mat
->row
+ top
->n_row
, bot
->row
, bot
->n_row
,
1479 int isl_mat_is_equal(__isl_keep isl_mat
*mat1
, __isl_keep isl_mat
*mat2
)
1486 if (mat1
->n_row
!= mat2
->n_row
)
1489 if (mat1
->n_col
!= mat2
->n_col
)
1492 for (i
= 0; i
< mat1
->n_row
; ++i
)
1493 if (!isl_seq_eq(mat1
->row
[i
], mat2
->row
[i
], mat1
->n_col
))
1499 __isl_give isl_mat
*isl_mat_from_row_vec(__isl_take isl_vec
*vec
)
1501 struct isl_mat
*mat
;
1505 mat
= isl_mat_alloc(vec
->ctx
, 1, vec
->size
);
1509 isl_seq_cpy(mat
->row
[0], vec
->el
, vec
->size
);
1518 __isl_give isl_mat
*isl_mat_vec_concat(__isl_take isl_mat
*top
,
1519 __isl_take isl_vec
*bot
)
1521 return isl_mat_concat(top
, isl_mat_from_row_vec(bot
));
1524 __isl_give isl_mat
*isl_mat_move_cols(__isl_take isl_mat
*mat
,
1525 unsigned dst_col
, unsigned src_col
, unsigned n
)
1531 if (n
== 0 || dst_col
== src_col
)
1534 res
= isl_mat_alloc(mat
->ctx
, mat
->n_row
, mat
->n_col
);
1538 if (dst_col
< src_col
) {
1539 isl_mat_sub_copy(res
->ctx
, res
->row
, mat
->row
, mat
->n_row
,
1541 isl_mat_sub_copy(res
->ctx
, res
->row
, mat
->row
, mat
->n_row
,
1542 dst_col
, src_col
, n
);
1543 isl_mat_sub_copy(res
->ctx
, res
->row
, mat
->row
, mat
->n_row
,
1544 dst_col
+ n
, dst_col
, src_col
- dst_col
);
1545 isl_mat_sub_copy(res
->ctx
, res
->row
, mat
->row
, mat
->n_row
,
1546 src_col
+ n
, src_col
+ n
,
1547 res
->n_col
- src_col
- n
);
1549 isl_mat_sub_copy(res
->ctx
, res
->row
, mat
->row
, mat
->n_row
,
1551 isl_mat_sub_copy(res
->ctx
, res
->row
, mat
->row
, mat
->n_row
,
1552 src_col
, src_col
+ n
, dst_col
- src_col
);
1553 isl_mat_sub_copy(res
->ctx
, res
->row
, mat
->row
, mat
->n_row
,
1554 dst_col
, src_col
, n
);
1555 isl_mat_sub_copy(res
->ctx
, res
->row
, mat
->row
, mat
->n_row
,
1556 dst_col
+ n
, dst_col
+ n
,
1557 res
->n_col
- dst_col
- n
);
1567 void isl_mat_gcd(__isl_keep isl_mat
*mat
, isl_int
*gcd
)
1572 isl_int_set_si(*gcd
, 0);
1577 for (i
= 0; i
< mat
->n_row
; ++i
) {
1578 isl_seq_gcd(mat
->row
[i
], mat
->n_col
, &g
);
1579 isl_int_gcd(*gcd
, *gcd
, g
);
1584 __isl_give isl_mat
*isl_mat_scale_down(__isl_take isl_mat
*mat
, isl_int m
)
1588 if (isl_int_is_one(m
))
1591 mat
= isl_mat_cow(mat
);
1595 for (i
= 0; i
< mat
->n_row
; ++i
)
1596 isl_seq_scale_down(mat
->row
[i
], mat
->row
[i
], m
, mat
->n_col
);
1601 __isl_give isl_mat
*isl_mat_scale_down_row(__isl_take isl_mat
*mat
, int row
,
1604 if (isl_int_is_one(m
))
1607 mat
= isl_mat_cow(mat
);
1611 isl_seq_scale_down(mat
->row
[row
], mat
->row
[row
], m
, mat
->n_col
);
1616 __isl_give isl_mat
*isl_mat_normalize(__isl_take isl_mat
*mat
)
1624 isl_mat_gcd(mat
, &gcd
);
1625 mat
= isl_mat_scale_down(mat
, gcd
);
1631 __isl_give isl_mat
*isl_mat_normalize_row(__isl_take isl_mat
*mat
, int row
)
1633 mat
= isl_mat_cow(mat
);
1637 isl_seq_normalize(mat
->ctx
, mat
->row
[row
], mat
->n_col
);
1642 /* Number of initial non-zero columns.
1644 int isl_mat_initial_non_zero_cols(__isl_keep isl_mat
*mat
)
1651 for (i
= 0; i
< mat
->n_col
; ++i
)
1652 if (row_first_non_zero(mat
->row
, mat
->n_row
, i
) < 0)