4 #include "isl_map_private.h"
6 struct isl_mat
*isl_mat_alloc(struct isl_ctx
*ctx
,
7 unsigned n_row
, unsigned n_col
)
12 mat
= isl_alloc_type(ctx
, struct isl_mat
);
17 mat
->block
= isl_blk_alloc(ctx
, n_row
* n_col
);
18 if (isl_blk_is_error(mat
->block
))
20 mat
->row
= isl_alloc_array(ctx
, isl_int
*, n_row
);
24 for (i
= 0; i
< n_row
; ++i
)
25 mat
->row
[i
] = mat
->block
.data
+ i
* n_col
;
34 isl_blk_free(ctx
, mat
->block
);
39 struct isl_mat
*isl_mat_extend(struct isl_ctx
*ctx
, struct isl_mat
*mat
,
40 unsigned n_row
, unsigned n_col
)
48 if (mat
->n_col
>= n_col
&& mat
->n_row
>= n_row
)
51 if (mat
->n_col
< n_col
) {
52 struct isl_mat
*new_mat
;
54 new_mat
= isl_mat_alloc(ctx
, n_row
, n_col
);
57 for (i
= 0; i
< mat
->n_row
; ++i
)
58 isl_seq_cpy(new_mat
->row
[i
], mat
->row
[i
], mat
->n_col
);
59 isl_mat_free(ctx
, mat
);
63 mat
= isl_mat_cow(ctx
, mat
);
67 assert(mat
->ref
== 1);
68 old
= mat
->block
.data
;
69 mat
->block
= isl_blk_extend(ctx
, mat
->block
, n_row
* mat
->n_col
);
70 if (isl_blk_is_error(mat
->block
))
72 mat
->row
= isl_realloc_array(ctx
, mat
->row
, isl_int
*, n_row
);
76 for (i
= 0; i
< mat
->n_row
; ++i
)
77 mat
->row
[i
] = mat
->block
.data
+ (mat
->row
[i
] - old
);
78 for (i
= mat
->n_row
; i
< n_row
; ++i
)
79 mat
->row
[i
] = mat
->block
.data
+ i
* mat
->n_col
;
84 isl_mat_free(ctx
, mat
);
88 struct isl_mat
*isl_mat_sub_alloc(struct isl_ctx
*ctx
, isl_int
**row
,
89 unsigned first_row
, unsigned n_row
, unsigned first_col
, unsigned n_col
)
94 mat
= isl_alloc_type(ctx
, struct isl_mat
);
97 mat
->row
= isl_alloc_array(ctx
, isl_int
*, n_row
);
100 for (i
= 0; i
< n_row
; ++i
)
101 mat
->row
[i
] = row
[first_row
+i
] + first_col
;
105 mat
->block
= isl_blk_empty();
106 mat
->flags
= ISL_MAT_BORROWED
;
113 void isl_mat_sub_copy(struct isl_ctx
*ctx
, isl_int
**dst
, isl_int
**src
,
114 unsigned n_row
, unsigned dst_col
, unsigned src_col
, unsigned n_col
)
118 for (i
= 0; i
< n_row
; ++i
)
119 isl_seq_cpy(dst
[i
]+dst_col
, src
[i
]+src_col
, n_col
);
122 void isl_mat_sub_neg(struct isl_ctx
*ctx
, isl_int
**dst
, isl_int
**src
,
123 unsigned n_row
, unsigned dst_col
, unsigned src_col
, unsigned n_col
)
127 for (i
= 0; i
< n_row
; ++i
)
128 isl_seq_neg(dst
[i
]+dst_col
, src
[i
]+src_col
, n_col
);
131 struct isl_mat
*isl_mat_copy(struct isl_ctx
*ctx
, struct isl_mat
*mat
)
140 struct isl_mat
*isl_mat_dup(struct isl_ctx
*ctx
, struct isl_mat
*mat
)
143 struct isl_mat
*mat2
;
147 mat2
= isl_mat_alloc(ctx
, mat
->n_row
, mat
->n_col
);
150 for (i
= 0; i
< mat
->n_row
; ++i
)
151 isl_seq_cpy(mat2
->row
[i
], mat
->row
[i
], mat
->n_col
);
155 struct isl_mat
*isl_mat_cow(struct isl_ctx
*ctx
, struct isl_mat
*mat
)
157 struct isl_mat
*mat2
;
161 if (mat
->ref
== 1 && !ISL_F_ISSET(mat
, ISL_MAT_BORROWED
))
164 mat2
= isl_mat_dup(ctx
, mat
);
165 isl_mat_free(ctx
, mat
);
169 void isl_mat_free(struct isl_ctx
*ctx
, struct isl_mat
*mat
)
177 if (!ISL_F_ISSET(mat
, ISL_MAT_BORROWED
))
178 isl_blk_free(ctx
, mat
->block
);
183 struct isl_mat
*isl_mat_identity(struct isl_ctx
*ctx
, unsigned n_row
)
188 mat
= isl_mat_alloc(ctx
, n_row
, n_row
);
191 for (i
= 0; i
< n_row
; ++i
) {
192 isl_seq_clr(mat
->row
[i
], i
);
193 isl_int_set_si(mat
->row
[i
][i
], 1);
194 isl_seq_clr(mat
->row
[i
]+i
+1, n_row
-(i
+1));
200 struct isl_vec
*isl_mat_vec_product(struct isl_ctx
*ctx
,
201 struct isl_mat
*mat
, struct isl_vec
*vec
)
204 struct isl_vec
*prod
;
209 isl_assert(ctx
, mat
->n_col
== vec
->size
, goto error
);
211 prod
= isl_vec_alloc(ctx
, mat
->n_row
);
215 for (i
= 0; i
< prod
->size
; ++i
)
216 isl_seq_inner_product(mat
->row
[i
], vec
->block
.data
, vec
->size
,
217 &prod
->block
.data
[i
]);
218 isl_mat_free(ctx
, mat
);
219 isl_vec_free(ctx
, vec
);
222 isl_mat_free(ctx
, mat
);
223 isl_vec_free(ctx
, vec
);
227 struct isl_mat
*isl_mat_aff_direct_sum(struct isl_ctx
*ctx
,
228 struct isl_mat
*left
, struct isl_mat
*right
)
236 isl_assert(ctx
, left
->n_row
== right
->n_row
, goto error
);
237 isl_assert(ctx
, left
->n_row
>= 1, goto error
);
238 isl_assert(ctx
, left
->n_col
>= 1, goto error
);
239 isl_assert(ctx
, right
->n_col
>= 1, goto error
);
241 isl_seq_first_non_zero(left
->row
[0]+1, left
->n_col
-1) == -1,
244 isl_seq_first_non_zero(right
->row
[0]+1, right
->n_col
-1) == -1,
247 sum
= isl_mat_alloc(ctx
, left
->n_row
, left
->n_col
+ right
->n_col
- 1);
250 isl_int_lcm(sum
->row
[0][0], left
->row
[0][0], right
->row
[0][0]);
251 isl_int_divexact(left
->row
[0][0], sum
->row
[0][0], left
->row
[0][0]);
252 isl_int_divexact(right
->row
[0][0], sum
->row
[0][0], right
->row
[0][0]);
254 isl_seq_clr(sum
->row
[0]+1, sum
->n_col
-1);
255 for (i
= 1; i
< sum
->n_row
; ++i
) {
256 isl_int_mul(sum
->row
[i
][0], left
->row
[0][0], left
->row
[i
][0]);
257 isl_int_addmul(sum
->row
[i
][0],
258 right
->row
[0][0], right
->row
[i
][0]);
259 isl_seq_scale(sum
->row
[i
]+1, left
->row
[i
]+1, left
->row
[0][0],
261 isl_seq_scale(sum
->row
[i
]+left
->n_col
,
262 right
->row
[i
]+1, right
->row
[0][0],
266 isl_int_divexact(left
->row
[0][0], sum
->row
[0][0], left
->row
[0][0]);
267 isl_int_divexact(right
->row
[0][0], sum
->row
[0][0], right
->row
[0][0]);
268 isl_mat_free(ctx
, left
);
269 isl_mat_free(ctx
, right
);
272 isl_mat_free(ctx
, left
);
273 isl_mat_free(ctx
, right
);
277 static void exchange(struct isl_ctx
*ctx
, struct isl_mat
*M
, struct isl_mat
**U
,
278 struct isl_mat
**Q
, unsigned row
, unsigned i
, unsigned j
)
281 for (r
= row
; r
< M
->n_row
; ++r
)
282 isl_int_swap(M
->row
[r
][i
], M
->row
[r
][j
]);
284 for (r
= 0; r
< (*U
)->n_row
; ++r
)
285 isl_int_swap((*U
)->row
[r
][i
], (*U
)->row
[r
][j
]);
288 isl_mat_swap_rows(ctx
, *Q
, i
, j
);
291 static void subtract(struct isl_mat
*M
, struct isl_mat
**U
,
292 struct isl_mat
**Q
, unsigned row
, unsigned i
, unsigned j
, isl_int m
)
295 for (r
= row
; r
< M
->n_row
; ++r
)
296 isl_int_submul(M
->row
[r
][j
], m
, M
->row
[r
][i
]);
298 for (r
= 0; r
< (*U
)->n_row
; ++r
)
299 isl_int_submul((*U
)->row
[r
][j
], m
, (*U
)->row
[r
][i
]);
302 for (r
= 0; r
< (*Q
)->n_col
; ++r
)
303 isl_int_addmul((*Q
)->row
[i
][r
], m
, (*Q
)->row
[j
][r
]);
307 static void oppose(struct isl_ctx
*ctx
, struct isl_mat
*M
, struct isl_mat
**U
,
308 struct isl_mat
**Q
, unsigned row
, unsigned col
)
311 for (r
= row
; r
< M
->n_row
; ++r
)
312 isl_int_neg(M
->row
[r
][col
], M
->row
[r
][col
]);
314 for (r
= 0; r
< (*U
)->n_row
; ++r
)
315 isl_int_neg((*U
)->row
[r
][col
], (*U
)->row
[r
][col
]);
318 isl_seq_neg((*Q
)->row
[col
], (*Q
)->row
[col
], (*Q
)->n_col
);
321 /* Given matrix M, compute
326 * with U and Q unimodular matrices and H a matrix in column echelon form
327 * such that on each echelon row the entries in the non-echelon column
328 * are non-negative (if neg == 0) or non-positive (if neg == 1)
329 * and stricly smaller (in absolute value) than the entries in the echelon
331 * If U or Q are NULL, then these matrices are not computed.
333 struct isl_mat
*isl_mat_left_hermite(struct isl_ctx
*ctx
,
334 struct isl_mat
*M
, int neg
, struct isl_mat
**U
, struct isl_mat
**Q
)
345 M
= isl_mat_cow(ctx
, M
);
349 *U
= isl_mat_identity(ctx
, M
->n_col
);
354 *Q
= isl_mat_identity(ctx
, M
->n_col
);
361 for (row
= 0; row
< M
->n_row
; ++row
) {
363 first
= isl_seq_abs_min_non_zero(M
->row
[row
]+col
, M
->n_col
-col
);
368 exchange(ctx
, M
, U
, Q
, row
, first
, col
);
369 if (isl_int_is_neg(M
->row
[row
][col
]))
370 oppose(ctx
, M
, U
, Q
, row
, col
);
372 while ((off
= isl_seq_first_non_zero(M
->row
[row
]+first
,
373 M
->n_col
-first
)) != -1) {
375 isl_int_fdiv_q(c
, M
->row
[row
][first
], M
->row
[row
][col
]);
376 subtract(M
, U
, Q
, row
, col
, first
, c
);
377 if (!isl_int_is_zero(M
->row
[row
][first
]))
378 exchange(ctx
, M
, U
, Q
, row
, first
, col
);
382 for (i
= 0; i
< col
; ++i
) {
383 if (isl_int_is_zero(M
->row
[row
][i
]))
386 isl_int_cdiv_q(c
, M
->row
[row
][i
], M
->row
[row
][col
]);
388 isl_int_fdiv_q(c
, M
->row
[row
][i
], M
->row
[row
][col
]);
389 if (isl_int_is_zero(c
))
391 subtract(M
, U
, Q
, row
, col
, i
, c
);
400 isl_mat_free(ctx
, *Q
);
404 isl_mat_free(ctx
, *U
);
410 struct isl_mat
*isl_mat_right_kernel(struct isl_ctx
*ctx
, struct isl_mat
*mat
)
413 struct isl_mat
*U
= NULL
;
416 mat
= isl_mat_left_hermite(ctx
, mat
, 0, &U
, NULL
);
420 for (i
= 0, rank
= 0; rank
< mat
->n_col
; ++rank
) {
421 while (i
< mat
->n_row
&& isl_int_is_zero(mat
->row
[i
][rank
]))
426 K
= isl_mat_alloc(ctx
, U
->n_row
, U
->n_col
- rank
);
429 isl_mat_sub_copy(ctx
, K
->row
, U
->row
, U
->n_row
, 0, rank
, U
->n_col
-rank
);
430 isl_mat_free(ctx
, mat
);
431 isl_mat_free(ctx
, U
);
434 isl_mat_free(ctx
, mat
);
435 isl_mat_free(ctx
, U
);
439 struct isl_mat
*isl_mat_lin_to_aff(struct isl_ctx
*ctx
, struct isl_mat
*mat
)
442 struct isl_mat
*mat2
;
446 mat2
= isl_mat_alloc(ctx
, 1+mat
->n_row
, 1+mat
->n_col
);
449 isl_int_set_si(mat2
->row
[0][0], 1);
450 isl_seq_clr(mat2
->row
[0]+1, mat
->n_col
);
451 for (i
= 0; i
< mat
->n_row
; ++i
) {
452 isl_int_set_si(mat2
->row
[1+i
][0], 0);
453 isl_seq_cpy(mat2
->row
[1+i
]+1, mat
->row
[i
], mat
->n_col
);
455 isl_mat_free(ctx
, mat
);
459 static int row_first_non_zero(isl_int
**row
, unsigned n_row
, unsigned col
)
463 for (i
= 0; i
< n_row
; ++i
)
464 if (!isl_int_is_zero(row
[i
][col
]))
469 static int row_abs_min_non_zero(isl_int
**row
, unsigned n_row
, unsigned col
)
471 int i
, min
= row_first_non_zero(row
, n_row
, col
);
474 for (i
= min
+ 1; i
< n_row
; ++i
) {
475 if (isl_int_is_zero(row
[i
][col
]))
477 if (isl_int_abs_lt(row
[i
][col
], row
[min
][col
]))
483 static void inv_exchange(struct isl_ctx
*ctx
,
484 struct isl_mat
*left
, struct isl_mat
*right
,
485 unsigned i
, unsigned j
)
487 left
= isl_mat_swap_rows(ctx
, left
, i
, j
);
488 right
= isl_mat_swap_rows(ctx
, right
, i
, j
);
491 static void inv_oppose(struct isl_ctx
*ctx
,
492 struct isl_mat
*left
, struct isl_mat
*right
, unsigned row
)
494 isl_seq_neg(left
->row
[row
]+row
, left
->row
[row
]+row
, left
->n_col
-row
);
495 isl_seq_neg(right
->row
[row
], right
->row
[row
], right
->n_col
);
498 static void inv_subtract(struct isl_ctx
*ctx
,
499 struct isl_mat
*left
, struct isl_mat
*right
,
500 unsigned row
, unsigned i
, isl_int m
)
503 isl_seq_combine(left
->row
[i
]+row
,
504 ctx
->one
, left
->row
[i
]+row
,
505 m
, left
->row
[row
]+row
,
507 isl_seq_combine(right
->row
[i
], ctx
->one
, right
->row
[i
],
508 m
, right
->row
[row
], right
->n_col
);
511 /* Compute inv(left)*right
513 struct isl_mat
*isl_mat_inverse_product(struct isl_ctx
*ctx
,
514 struct isl_mat
*left
, struct isl_mat
*right
)
522 isl_assert(ctx
, left
->n_row
== left
->n_col
, goto error
);
523 isl_assert(ctx
, left
->n_row
== right
->n_row
, goto error
);
525 if (left
->n_row
== 0) {
526 isl_mat_free(ctx
, left
);
530 left
= isl_mat_cow(ctx
, left
);
531 right
= isl_mat_cow(ctx
, right
);
537 for (row
= 0; row
< left
->n_row
; ++row
) {
538 int pivot
, first
, i
, off
;
539 pivot
= row_abs_min_non_zero(left
->row
+row
, left
->n_row
-row
, row
);
543 isl_assert(ctx
, pivot
>= 0, goto error
);
547 inv_exchange(ctx
, left
, right
, pivot
, row
);
548 if (isl_int_is_neg(left
->row
[row
][row
]))
549 inv_oppose(ctx
, left
, right
, row
);
551 while ((off
= row_first_non_zero(left
->row
+first
,
552 left
->n_row
-first
, row
)) != -1) {
554 isl_int_fdiv_q(a
, left
->row
[first
][row
],
555 left
->row
[row
][row
]);
556 inv_subtract(ctx
, left
, right
, row
, first
, a
);
557 if (!isl_int_is_zero(left
->row
[first
][row
]))
558 inv_exchange(ctx
, left
, right
, row
, first
);
562 for (i
= 0; i
< row
; ++i
) {
563 if (isl_int_is_zero(left
->row
[i
][row
]))
565 isl_int_gcd(a
, left
->row
[row
][row
], left
->row
[i
][row
]);
566 isl_int_divexact(b
, left
->row
[i
][row
], a
);
567 isl_int_divexact(a
, left
->row
[row
][row
], a
);
569 isl_seq_combine(left
->row
[i
]+row
,
571 b
, left
->row
[row
]+row
,
573 isl_seq_combine(right
->row
[i
], a
, right
->row
[i
],
574 b
, right
->row
[row
], right
->n_col
);
579 isl_int_set(a
, left
->row
[0][0]);
580 for (row
= 1; row
< left
->n_row
; ++row
)
581 isl_int_lcm(a
, a
, left
->row
[row
][row
]);
582 if (isl_int_is_zero(a
)){
584 isl_assert(ctx
, 0, goto error
);
586 for (row
= 0; row
< left
->n_row
; ++row
) {
587 isl_int_divexact(left
->row
[row
][row
], a
, left
->row
[row
][row
]);
588 if (isl_int_is_one(left
->row
[row
][row
]))
590 isl_seq_scale(right
->row
[row
], right
->row
[row
],
591 left
->row
[row
][row
], right
->n_col
);
595 isl_mat_free(ctx
, left
);
598 isl_mat_free(ctx
, left
);
599 isl_mat_free(ctx
, right
);
603 void isl_mat_col_scale(struct isl_mat
*mat
, unsigned col
, isl_int m
)
607 for (i
= 0; i
< mat
->n_row
; ++i
)
608 isl_int_mul(mat
->row
[i
][col
], mat
->row
[i
][col
], m
);
611 void isl_mat_col_combine(struct isl_mat
*mat
, unsigned dst
,
612 isl_int m1
, unsigned src1
, isl_int m2
, unsigned src2
)
618 for (i
= 0; i
< mat
->n_row
; ++i
) {
619 isl_int_mul(tmp
, m1
, mat
->row
[i
][src1
]);
620 isl_int_addmul(tmp
, m2
, mat
->row
[i
][src2
]);
621 isl_int_set(mat
->row
[i
][dst
], tmp
);
626 struct isl_mat
*isl_mat_right_inverse(struct isl_ctx
*ctx
,
633 mat
= isl_mat_cow(ctx
, mat
);
637 inv
= isl_mat_identity(ctx
, mat
->n_col
);
638 inv
= isl_mat_cow(ctx
, inv
);
644 for (row
= 0; row
< mat
->n_row
; ++row
) {
645 int pivot
, first
, i
, off
;
646 pivot
= isl_seq_abs_min_non_zero(mat
->row
[row
]+row
, mat
->n_col
-row
);
654 exchange(ctx
, mat
, &inv
, NULL
, row
, pivot
, row
);
655 if (isl_int_is_neg(mat
->row
[row
][row
]))
656 oppose(ctx
, mat
, &inv
, NULL
, row
, row
);
658 while ((off
= isl_seq_first_non_zero(mat
->row
[row
]+first
,
659 mat
->n_col
-first
)) != -1) {
661 isl_int_fdiv_q(a
, mat
->row
[row
][first
],
663 subtract(mat
, &inv
, NULL
, row
, row
, first
, a
);
664 if (!isl_int_is_zero(mat
->row
[row
][first
]))
665 exchange(ctx
, mat
, &inv
, NULL
, row
, row
, first
);
669 for (i
= 0; i
< row
; ++i
) {
670 if (isl_int_is_zero(mat
->row
[row
][i
]))
672 isl_int_gcd(a
, mat
->row
[row
][row
], mat
->row
[row
][i
]);
673 isl_int_divexact(b
, mat
->row
[row
][i
], a
);
674 isl_int_divexact(a
, mat
->row
[row
][row
], a
);
676 isl_mat_col_combine(mat
, i
, a
, i
, b
, row
);
677 isl_mat_col_combine(inv
, i
, a
, i
, b
, row
);
682 isl_int_set(a
, mat
->row
[0][0]);
683 for (row
= 1; row
< mat
->n_row
; ++row
)
684 isl_int_lcm(a
, a
, mat
->row
[row
][row
]);
685 if (isl_int_is_zero(a
)){
689 for (row
= 0; row
< mat
->n_row
; ++row
) {
690 isl_int_divexact(mat
->row
[row
][row
], a
, mat
->row
[row
][row
]);
691 if (isl_int_is_one(mat
->row
[row
][row
]))
693 isl_mat_col_scale(inv
, row
, mat
->row
[row
][row
]);
697 isl_mat_free(ctx
, mat
);
701 isl_mat_free(ctx
, mat
);
705 struct isl_mat
*isl_mat_transpose(struct isl_ctx
*ctx
, struct isl_mat
*mat
)
707 struct isl_mat
*transpose
= NULL
;
710 if (mat
->n_col
== mat
->n_row
) {
711 mat
= isl_mat_cow(ctx
, mat
);
714 for (i
= 0; i
< mat
->n_row
; ++i
)
715 for (j
= i
+ 1; j
< mat
->n_col
; ++j
)
716 isl_int_swap(mat
->row
[i
][j
], mat
->row
[j
][i
]);
719 transpose
= isl_mat_alloc(ctx
, mat
->n_col
, mat
->n_row
);
722 for (i
= 0; i
< mat
->n_row
; ++i
)
723 for (j
= 0; j
< mat
->n_col
; ++j
)
724 isl_int_set(transpose
->row
[j
][i
], mat
->row
[i
][j
]);
725 isl_mat_free(ctx
, mat
);
728 isl_mat_free(ctx
, mat
);
732 struct isl_mat
*isl_mat_swap_cols(struct isl_ctx
*ctx
,
733 struct isl_mat
*mat
, unsigned i
, unsigned j
)
737 mat
= isl_mat_cow(ctx
, mat
);
740 isl_assert(ctx
, i
< mat
->n_col
, goto error
);
741 isl_assert(ctx
, j
< mat
->n_col
, goto error
);
743 for (r
= 0; r
< mat
->n_row
; ++r
)
744 isl_int_swap(mat
->row
[r
][i
], mat
->row
[r
][j
]);
747 isl_mat_free(ctx
, mat
);
751 struct isl_mat
*isl_mat_swap_rows(struct isl_ctx
*ctx
,
752 struct isl_mat
*mat
, unsigned i
, unsigned j
)
758 mat
= isl_mat_cow(ctx
, mat
);
762 mat
->row
[i
] = mat
->row
[j
];
767 struct isl_mat
*isl_mat_product(struct isl_ctx
*ctx
,
768 struct isl_mat
*left
, struct isl_mat
*right
)
771 struct isl_mat
*prod
;
775 isl_assert(ctx
, left
->n_col
== right
->n_row
, goto error
);
776 prod
= isl_mat_alloc(ctx
, left
->n_row
, right
->n_col
);
779 if (left
->n_col
== 0) {
780 for (i
= 0; i
< prod
->n_row
; ++i
)
781 isl_seq_clr(prod
->row
[i
], prod
->n_col
);
784 for (i
= 0; i
< prod
->n_row
; ++i
) {
785 for (j
= 0; j
< prod
->n_col
; ++j
) {
786 isl_int_mul(prod
->row
[i
][j
],
787 left
->row
[i
][0], right
->row
[0][j
]);
788 for (k
= 1; k
< left
->n_col
; ++k
)
789 isl_int_addmul(prod
->row
[i
][j
],
790 left
->row
[i
][k
], right
->row
[k
][j
]);
793 isl_mat_free(ctx
, left
);
794 isl_mat_free(ctx
, right
);
797 isl_mat_free(ctx
, left
);
798 isl_mat_free(ctx
, right
);
802 /* Replace the variables x in bset by x' given by x = M x', with
805 * If there are fewer variables x' then there are x, then we perform
806 * the transformation in place, which that, in principle,
807 * this frees up some extra variables as the number
808 * of columns remains constant, but we would have to extend
809 * the div array too as the number of rows in this array is assumed
810 * to be equal to extra.
812 struct isl_basic_set
*isl_basic_set_preimage(struct isl_basic_set
*bset
,
823 bset
= isl_basic_set_cow(bset
);
827 isl_assert(ctx
, bset
->dim
->nparam
== 0, goto error
);
828 isl_assert(ctx
, bset
->n_div
== 0, goto error
);
829 isl_assert(ctx
, 1+bset
->dim
->n_out
== mat
->n_row
, goto error
);
831 if (mat
->n_col
> mat
->n_row
)
832 bset
= isl_basic_set_extend(bset
, 0, mat
->n_col
-1, 0,
834 else if (mat
->n_col
< mat
->n_row
) {
835 bset
->dim
= isl_dim_cow(bset
->dim
);
838 bset
->dim
->n_out
-= mat
->n_row
- mat
->n_col
;
841 t
= isl_mat_sub_alloc(ctx
, bset
->eq
, 0, bset
->n_eq
, 0, mat
->n_row
);
842 t
= isl_mat_product(ctx
, t
, isl_mat_copy(ctx
, mat
));
845 for (i
= 0; i
< bset
->n_eq
; ++i
) {
846 isl_seq_swp_or_cpy(bset
->eq
[i
], t
->row
[i
], t
->n_col
);
847 isl_seq_clr(bset
->eq
[i
]+t
->n_col
, bset
->extra
);
849 isl_mat_free(ctx
, t
);
851 t
= isl_mat_sub_alloc(ctx
, bset
->ineq
, 0, bset
->n_ineq
, 0, mat
->n_row
);
852 t
= isl_mat_product(ctx
, t
, mat
);
855 for (i
= 0; i
< bset
->n_ineq
; ++i
) {
856 isl_seq_swp_or_cpy(bset
->ineq
[i
], t
->row
[i
], t
->n_col
);
857 isl_seq_clr(bset
->ineq
[i
]+t
->n_col
, bset
->extra
);
859 isl_mat_free(ctx
, t
);
861 ISL_F_CLR(bset
, ISL_BASIC_SET_NO_IMPLICIT
);
862 ISL_F_CLR(bset
, ISL_BASIC_SET_NO_REDUNDANT
);
863 ISL_F_CLR(bset
, ISL_BASIC_SET_NORMALIZED
);
864 ISL_F_CLR(bset
, ISL_BASIC_SET_NORMALIZED_DIVS
);
865 ISL_F_CLR(bset
, ISL_BASIC_SET_ALL_EQUALITIES
);
867 bset
= isl_basic_set_simplify(bset
);
868 bset
= isl_basic_set_finalize(bset
);
872 isl_mat_free(ctx
, mat
);
874 isl_basic_set_free(bset
);
878 struct isl_set
*isl_set_preimage(struct isl_set
*set
, struct isl_mat
*mat
)
883 set
= isl_set_cow(set
);
888 for (i
= 0; i
< set
->n
; ++i
) {
889 set
->p
[i
] = isl_basic_set_preimage(set
->p
[i
],
890 isl_mat_copy(ctx
, mat
));
894 if (mat
->n_col
!= mat
->n_row
) {
895 set
->dim
= isl_dim_cow(set
->dim
);
898 set
->dim
->n_out
+= mat
->n_col
;
899 set
->dim
->n_out
-= mat
->n_row
;
901 isl_mat_free(ctx
, mat
);
902 ISL_F_CLR(set
, ISL_SET_NORMALIZED
);
906 isl_mat_free(ctx
, mat
);
910 void isl_mat_dump(struct isl_ctx
*ctx
, struct isl_mat
*mat
,
911 FILE *out
, int indent
)
916 fprintf(out
, "%*snull mat\n", indent
, "");
921 fprintf(out
, "%*s[]\n", indent
, "");
923 for (i
= 0; i
< mat
->n_row
; ++i
) {
925 fprintf(out
, "%*s[[", indent
, "");
927 fprintf(out
, "%*s[", indent
+1, "");
928 for (j
= 0; j
< mat
->n_col
; ++j
) {
931 isl_int_print(out
, mat
->row
[i
][j
], 0);
933 if (i
== mat
->n_row
-1)
934 fprintf(out
, "]]\n");
940 struct isl_mat
*isl_mat_drop_cols(struct isl_ctx
*ctx
, struct isl_mat
*mat
,
941 unsigned col
, unsigned n
)
945 mat
= isl_mat_cow(ctx
, mat
);
949 if (col
!= mat
->n_col
-n
) {
950 for (r
= 0; r
< mat
->n_row
; ++r
)
951 isl_seq_cpy(mat
->row
[r
]+col
, mat
->row
[r
]+col
+n
,
952 mat
->n_col
- col
- n
);
958 struct isl_mat
*isl_mat_drop_rows(struct isl_ctx
*ctx
, struct isl_mat
*mat
,
959 unsigned row
, unsigned n
)
963 mat
= isl_mat_cow(ctx
, mat
);
967 for (r
= row
; r
+n
< mat
->n_row
; ++r
)
968 mat
->row
[r
] = mat
->row
[r
+n
];
974 void isl_mat_col_submul(struct isl_mat
*mat
,
975 int dst_col
, isl_int f
, int src_col
)
979 for (i
= 0; i
< mat
->n_row
; ++i
)
980 isl_int_submul(mat
->row
[i
][dst_col
], f
, mat
->row
[i
][src_col
]);
983 void isl_mat_col_mul(struct isl_mat
*mat
, int dst_col
, isl_int f
, int src_col
)
987 for (i
= 0; i
< mat
->n_row
; ++i
)
988 isl_int_mul(mat
->row
[i
][dst_col
], f
, mat
->row
[i
][src_col
]);
991 struct isl_mat
*isl_mat_unimodular_complete(struct isl_ctx
*ctx
,
992 struct isl_mat
*M
, int row
)
995 struct isl_mat
*H
= NULL
, *Q
= NULL
;
997 isl_assert(ctx
, M
->n_row
== M
->n_col
, goto error
);
999 H
= isl_mat_left_hermite(ctx
, isl_mat_copy(ctx
, M
), 0, NULL
, &Q
);
1000 M
->n_row
= M
->n_col
;
1003 for (r
= 0; r
< row
; ++r
)
1004 isl_assert(ctx
, isl_int_is_one(H
->row
[r
][r
]), goto error
);
1005 for (r
= row
; r
< M
->n_row
; ++r
)
1006 isl_seq_cpy(M
->row
[r
], Q
->row
[r
], M
->n_col
);
1007 isl_mat_free(ctx
, H
);
1008 isl_mat_free(ctx
, Q
);
1011 isl_mat_free(ctx
, H
);
1012 isl_mat_free(ctx
, Q
);
1013 isl_mat_free(ctx
, M
);