isl_map.c: order_divs: swap with correct div
[isl.git] / isl_mat.c
blob4947c3d2dcc969d7780d439f8c3eacca70e69a5f
1 #include "isl_dim.h"
2 #include "isl_seq.h"
3 #include "isl_mat.h"
4 #include "isl_map_private.h"
6 struct isl_mat *isl_mat_alloc(struct isl_ctx *ctx,
7 unsigned n_row, unsigned n_col)
9 int i;
10 struct isl_mat *mat;
12 mat = isl_alloc_type(ctx, struct isl_mat);
13 if (!mat)
14 return NULL;
16 mat->row = NULL;
17 mat->block = isl_blk_alloc(ctx, n_row * n_col);
18 if (isl_blk_is_error(mat->block))
19 goto error;
20 mat->row = isl_alloc_array(ctx, isl_int *, n_row);
21 if (!mat->row)
22 goto error;
24 for (i = 0; i < n_row; ++i)
25 mat->row[i] = mat->block.data + i * n_col;
27 mat->ref = 1;
28 mat->n_row = n_row;
29 mat->n_col = n_col;
30 mat->flags = 0;
32 return mat;
33 error:
34 isl_blk_free(ctx, mat->block);
35 free(mat);
36 return NULL;
39 struct isl_mat *isl_mat_extend(struct isl_ctx *ctx, struct isl_mat *mat,
40 unsigned n_row, unsigned n_col)
42 int i;
43 isl_int *old;
45 if (!mat)
46 return NULL;
48 if (mat->n_col >= n_col && mat->n_row >= n_row)
49 return mat;
51 if (mat->n_col < n_col) {
52 struct isl_mat *new_mat;
54 new_mat = isl_mat_alloc(ctx, n_row, n_col);
55 if (!new_mat)
56 goto error;
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);
60 return new_mat;
63 mat = isl_mat_cow(ctx, mat);
64 if (!mat)
65 goto error;
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))
71 goto error;
72 mat->row = isl_realloc_array(ctx, mat->row, isl_int *, n_row);
73 if (!mat->row)
74 goto error;
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;
80 mat->n_row = n_row;
82 return mat;
83 error:
84 isl_mat_free(ctx, mat);
85 return NULL;
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)
91 int i;
92 struct isl_mat *mat;
94 mat = isl_alloc_type(ctx, struct isl_mat);
95 if (!mat)
96 return NULL;
97 mat->row = isl_alloc_array(ctx, isl_int *, n_row);
98 if (!mat->row)
99 goto error;
100 for (i = 0; i < n_row; ++i)
101 mat->row[i] = row[first_row+i] + first_col;
102 mat->ref = 1;
103 mat->n_row = n_row;
104 mat->n_col = n_col;
105 mat->block = isl_blk_empty();
106 mat->flags = ISL_MAT_BORROWED;
107 return mat;
108 error:
109 free(mat);
110 return NULL;
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)
116 int i;
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)
125 int i;
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)
133 if (!mat)
134 return NULL;
136 mat->ref++;
137 return mat;
140 struct isl_mat *isl_mat_dup(struct isl_ctx *ctx, struct isl_mat *mat)
142 int i;
143 struct isl_mat *mat2;
145 if (!mat)
146 return NULL;
147 mat2 = isl_mat_alloc(ctx, mat->n_row, mat->n_col);
148 if (!mat2)
149 return NULL;
150 for (i = 0; i < mat->n_row; ++i)
151 isl_seq_cpy(mat2->row[i], mat->row[i], mat->n_col);
152 return mat2;
155 struct isl_mat *isl_mat_cow(struct isl_ctx *ctx, struct isl_mat *mat)
157 struct isl_mat *mat2;
158 if (!mat)
159 return NULL;
161 if (mat->ref == 1 && !ISL_F_ISSET(mat, ISL_MAT_BORROWED))
162 return mat;
164 mat2 = isl_mat_dup(ctx, mat);
165 isl_mat_free(ctx, mat);
166 return mat2;
169 void isl_mat_free(struct isl_ctx *ctx, struct isl_mat *mat)
171 if (!mat)
172 return;
174 if (--mat->ref > 0)
175 return;
177 if (!ISL_F_ISSET(mat, ISL_MAT_BORROWED))
178 isl_blk_free(ctx, mat->block);
179 free(mat->row);
180 free(mat);
183 struct isl_mat *isl_mat_identity(struct isl_ctx *ctx, unsigned n_row)
185 int i;
186 struct isl_mat *mat;
188 mat = isl_mat_alloc(ctx, n_row, n_row);
189 if (!mat)
190 return NULL;
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));
197 return mat;
200 struct isl_vec *isl_mat_vec_product(struct isl_ctx *ctx,
201 struct isl_mat *mat, struct isl_vec *vec)
203 int i;
204 struct isl_vec *prod;
206 if (!mat || !vec)
207 goto error;
209 isl_assert(ctx, mat->n_col == vec->size, goto error);
211 prod = isl_vec_alloc(ctx, mat->n_row);
212 if (!prod)
213 goto error;
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);
220 return prod;
221 error:
222 isl_mat_free(ctx, mat);
223 isl_vec_free(ctx, vec);
224 return NULL;
227 struct isl_mat *isl_mat_aff_direct_sum(struct isl_ctx *ctx,
228 struct isl_mat *left, struct isl_mat *right)
230 int i;
231 struct isl_mat *sum;
233 if (!left || !right)
234 goto error;
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);
240 isl_assert(ctx,
241 isl_seq_first_non_zero(left->row[0]+1, left->n_col-1) == -1,
242 goto error);
243 isl_assert(ctx,
244 isl_seq_first_non_zero(right->row[0]+1, right->n_col-1) == -1,
245 goto error);
247 sum = isl_mat_alloc(ctx, left->n_row, left->n_col + right->n_col - 1);
248 if (!sum)
249 goto error;
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],
260 left->n_col-1);
261 isl_seq_scale(sum->row[i]+left->n_col,
262 right->row[i]+1, right->row[0][0],
263 right->n_col-1);
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);
270 return sum;
271 error:
272 isl_mat_free(ctx, left);
273 isl_mat_free(ctx, right);
274 return NULL;
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)
280 int r;
281 for (r = row; r < M->n_row; ++r)
282 isl_int_swap(M->row[r][i], M->row[r][j]);
283 if (U) {
284 for (r = 0; r < (*U)->n_row; ++r)
285 isl_int_swap((*U)->row[r][i], (*U)->row[r][j]);
287 if (Q)
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)
294 int r;
295 for (r = row; r < M->n_row; ++r)
296 isl_int_submul(M->row[r][j], m, M->row[r][i]);
297 if (U) {
298 for (r = 0; r < (*U)->n_row; ++r)
299 isl_int_submul((*U)->row[r][j], m, (*U)->row[r][i]);
301 if (Q) {
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)
310 int r;
311 for (r = row; r < M->n_row; ++r)
312 isl_int_neg(M->row[r][col], M->row[r][col]);
313 if (U) {
314 for (r = 0; r < (*U)->n_row; ++r)
315 isl_int_neg((*U)->row[r][col], (*U)->row[r][col]);
317 if (Q)
318 isl_seq_neg((*Q)->row[col], (*Q)->row[col], (*Q)->n_col);
321 /* Given matrix M, compute
323 * M U = H
324 * M = H Q
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
330 * column.
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)
336 isl_int c;
337 int row, col;
339 if (U)
340 *U = NULL;
341 if (Q)
342 *Q = NULL;
343 if (!M)
344 goto error;
345 M = isl_mat_cow(ctx, M);
346 if (!M)
347 goto error;
348 if (U) {
349 *U = isl_mat_identity(ctx, M->n_col);
350 if (!*U)
351 goto error;
353 if (Q) {
354 *Q = isl_mat_identity(ctx, M->n_col);
355 if (!*Q)
356 goto error;
359 col = 0;
360 isl_int_init(c);
361 for (row = 0; row < M->n_row; ++row) {
362 int first, i, off;
363 first = isl_seq_abs_min_non_zero(M->row[row]+col, M->n_col-col);
364 if (first == -1)
365 continue;
366 first += col;
367 if (first != 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);
371 first = col+1;
372 while ((off = isl_seq_first_non_zero(M->row[row]+first,
373 M->n_col-first)) != -1) {
374 first += off;
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);
379 else
380 ++first;
382 for (i = 0; i < col; ++i) {
383 if (isl_int_is_zero(M->row[row][i]))
384 continue;
385 if (neg)
386 isl_int_cdiv_q(c, M->row[row][i], M->row[row][col]);
387 else
388 isl_int_fdiv_q(c, M->row[row][i], M->row[row][col]);
389 if (isl_int_is_zero(c))
390 continue;
391 subtract(M, U, Q, row, col, i, c);
393 ++col;
395 isl_int_clear(c);
397 return M;
398 error:
399 if (Q) {
400 isl_mat_free(ctx, *Q);
401 *Q = NULL;
403 if (U) {
404 isl_mat_free(ctx, *U);
405 *U = NULL;
407 return NULL;
410 struct isl_mat *isl_mat_right_kernel(struct isl_ctx *ctx, struct isl_mat *mat)
412 int i, rank;
413 struct isl_mat *U = NULL;
414 struct isl_mat *K;
416 mat = isl_mat_left_hermite(ctx, mat, 0, &U, NULL);
417 if (!mat || !U)
418 goto error;
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]))
422 ++i;
423 if (i >= mat->n_row)
424 break;
426 K = isl_mat_alloc(ctx, U->n_row, U->n_col - rank);
427 if (!K)
428 goto error;
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);
432 return K;
433 error:
434 isl_mat_free(ctx, mat);
435 isl_mat_free(ctx, U);
436 return NULL;
439 struct isl_mat *isl_mat_lin_to_aff(struct isl_ctx *ctx, struct isl_mat *mat)
441 int i;
442 struct isl_mat *mat2;
444 if (!mat)
445 return NULL;
446 mat2 = isl_mat_alloc(ctx, 1+mat->n_row, 1+mat->n_col);
447 if (!mat2)
448 return NULL;
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);
456 return mat2;
459 static int row_first_non_zero(isl_int **row, unsigned n_row, unsigned col)
461 int i;
463 for (i = 0; i < n_row; ++i)
464 if (!isl_int_is_zero(row[i][col]))
465 return i;
466 return -1;
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);
472 if (min < 0)
473 return -1;
474 for (i = min + 1; i < n_row; ++i) {
475 if (isl_int_is_zero(row[i][col]))
476 continue;
477 if (isl_int_abs_lt(row[i][col], row[min][col]))
478 min = i;
480 return min;
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)
502 isl_int_neg(m, m);
503 isl_seq_combine(left->row[i]+row,
504 ctx->one, left->row[i]+row,
505 m, left->row[row]+row,
506 left->n_col-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)
516 int row;
517 isl_int a, b;
519 if (!left || !right)
520 goto error;
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);
527 return right;
530 left = isl_mat_cow(ctx, left);
531 right = isl_mat_cow(ctx, right);
532 if (!left || !right)
533 goto error;
535 isl_int_init(a);
536 isl_int_init(b);
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);
540 if (pivot < 0) {
541 isl_int_clear(a);
542 isl_int_clear(b);
543 isl_assert(ctx, pivot >= 0, goto error);
545 pivot += row;
546 if (pivot != row)
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);
550 first = row+1;
551 while ((off = row_first_non_zero(left->row+first,
552 left->n_row-first, row)) != -1) {
553 first += off;
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);
559 else
560 ++first;
562 for (i = 0; i < row; ++i) {
563 if (isl_int_is_zero(left->row[i][row]))
564 continue;
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);
568 isl_int_neg(a, a);
569 isl_seq_combine(left->row[i]+row,
570 a, left->row[i]+row,
571 b, left->row[row]+row,
572 left->n_col-row);
573 isl_seq_combine(right->row[i], a, right->row[i],
574 b, right->row[row], right->n_col);
577 isl_int_clear(b);
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)){
583 isl_int_clear(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]))
589 continue;
590 isl_seq_scale(right->row[row], right->row[row],
591 left->row[row][row], right->n_col);
593 isl_int_clear(a);
595 isl_mat_free(ctx, left);
596 return right;
597 error:
598 isl_mat_free(ctx, left);
599 isl_mat_free(ctx, right);
600 return NULL;
603 void isl_mat_col_scale(struct isl_mat *mat, unsigned col, isl_int m)
605 int i;
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)
614 int i;
615 isl_int tmp;
617 isl_int_init(tmp);
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);
623 isl_int_clear(tmp);
626 struct isl_mat *isl_mat_right_inverse(struct isl_ctx *ctx,
627 struct isl_mat *mat)
629 struct isl_mat *inv;
630 int row;
631 isl_int a, b;
633 mat = isl_mat_cow(ctx, mat);
634 if (!mat)
635 return NULL;
637 inv = isl_mat_identity(ctx, mat->n_col);
638 inv = isl_mat_cow(ctx, inv);
639 if (!inv)
640 goto error;
642 isl_int_init(a);
643 isl_int_init(b);
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);
647 if (pivot < 0) {
648 isl_int_clear(a);
649 isl_int_clear(b);
650 goto error;
652 pivot += row;
653 if (pivot != 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);
657 first = row+1;
658 while ((off = isl_seq_first_non_zero(mat->row[row]+first,
659 mat->n_col-first)) != -1) {
660 first += off;
661 isl_int_fdiv_q(a, mat->row[row][first],
662 mat->row[row][row]);
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);
666 else
667 ++first;
669 for (i = 0; i < row; ++i) {
670 if (isl_int_is_zero(mat->row[row][i]))
671 continue;
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);
675 isl_int_neg(a, a);
676 isl_mat_col_combine(mat, i, a, i, b, row);
677 isl_mat_col_combine(inv, i, a, i, b, row);
680 isl_int_clear(b);
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)){
686 isl_int_clear(a);
687 goto error;
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]))
692 continue;
693 isl_mat_col_scale(inv, row, mat->row[row][row]);
695 isl_int_clear(a);
697 isl_mat_free(ctx, mat);
699 return inv;
700 error:
701 isl_mat_free(ctx, mat);
702 return NULL;
705 struct isl_mat *isl_mat_transpose(struct isl_ctx *ctx, struct isl_mat *mat)
707 struct isl_mat *transpose = NULL;
708 int i, j;
710 if (mat->n_col == mat->n_row) {
711 mat = isl_mat_cow(ctx, mat);
712 if (!mat)
713 return NULL;
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]);
717 return mat;
719 transpose = isl_mat_alloc(ctx, mat->n_col, mat->n_row);
720 if (!transpose)
721 goto error;
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);
726 return transpose;
727 error:
728 isl_mat_free(ctx, mat);
729 return NULL;
732 struct isl_mat *isl_mat_swap_cols(struct isl_ctx *ctx,
733 struct isl_mat *mat, unsigned i, unsigned j)
735 int r;
737 mat = isl_mat_cow(ctx, mat);
738 if (!mat)
739 return NULL;
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]);
745 return mat;
746 error:
747 isl_mat_free(ctx, mat);
748 return NULL;
751 struct isl_mat *isl_mat_swap_rows(struct isl_ctx *ctx,
752 struct isl_mat *mat, unsigned i, unsigned j)
754 isl_int *t;
756 if (!mat)
757 return NULL;
758 mat = isl_mat_cow(ctx, mat);
759 if (!mat)
760 return NULL;
761 t = mat->row[i];
762 mat->row[i] = mat->row[j];
763 mat->row[j] = t;
764 return mat;
767 struct isl_mat *isl_mat_product(struct isl_ctx *ctx,
768 struct isl_mat *left, struct isl_mat *right)
770 int i, j, k;
771 struct isl_mat *prod;
773 if (!left || !right)
774 goto error;
775 isl_assert(ctx, left->n_col == right->n_row, goto error);
776 prod = isl_mat_alloc(ctx, left->n_row, right->n_col);
777 if (!prod)
778 goto error;
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);
782 return prod;
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);
795 return prod;
796 error:
797 isl_mat_free(ctx, left);
798 isl_mat_free(ctx, right);
799 return NULL;
802 /* Replace the variables x in bset by x' given by x = M x', with
803 * M the matrix mat.
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,
813 struct isl_mat *mat)
815 struct isl_ctx *ctx;
816 struct isl_mat *t;
817 int i;
819 if (!bset || !mat)
820 goto error;
822 ctx = bset->ctx;
823 bset = isl_basic_set_cow(bset);
824 if (!bset)
825 goto error;
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,
833 0, 0);
834 else if (mat->n_col < mat->n_row) {
835 bset->dim = isl_dim_cow(bset->dim);
836 if (!bset->dim)
837 goto error;
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));
843 if (!t)
844 goto error;
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);
853 if (!t)
854 goto error2;
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);
870 return bset;
871 error:
872 isl_mat_free(ctx, mat);
873 error2:
874 isl_basic_set_free(bset);
875 return NULL;
878 struct isl_set *isl_set_preimage(struct isl_set *set, struct isl_mat *mat)
880 struct isl_ctx *ctx;
881 int i;
883 set = isl_set_cow(set);
884 if (!set)
885 return NULL;
887 ctx = set->ctx;
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));
891 if (!set->p[i])
892 goto error;
894 if (mat->n_col != mat->n_row) {
895 set->dim = isl_dim_cow(set->dim);
896 if (!set->dim)
897 goto error;
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);
903 return set;
904 error:
905 isl_set_free(set);
906 isl_mat_free(ctx, mat);
907 return NULL;
910 void isl_mat_dump(struct isl_ctx *ctx, struct isl_mat *mat,
911 FILE *out, int indent)
913 int i, j;
915 if (!mat) {
916 fprintf(out, "%*snull mat\n", indent, "");
917 return;
920 if (mat->n_row == 0)
921 fprintf(out, "%*s[]\n", indent, "");
923 for (i = 0; i < mat->n_row; ++i) {
924 if (!i)
925 fprintf(out, "%*s[[", indent, "");
926 else
927 fprintf(out, "%*s[", indent+1, "");
928 for (j = 0; j < mat->n_col; ++j) {
929 if (j)
930 fprintf(out, ",");
931 isl_int_print(out, mat->row[i][j], 0);
933 if (i == mat->n_row-1)
934 fprintf(out, "]]\n");
935 else
936 fprintf(out, "]\n");
940 struct isl_mat *isl_mat_drop_cols(struct isl_ctx *ctx, struct isl_mat *mat,
941 unsigned col, unsigned n)
943 int r;
945 mat = isl_mat_cow(ctx, mat);
946 if (!mat)
947 return NULL;
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);
954 mat->n_col -= n;
955 return mat;
958 struct isl_mat *isl_mat_drop_rows(struct isl_ctx *ctx, struct isl_mat *mat,
959 unsigned row, unsigned n)
961 int r;
963 mat = isl_mat_cow(ctx, mat);
964 if (!mat)
965 return NULL;
967 for (r = row; r+n < mat->n_row; ++r)
968 mat->row[r] = mat->row[r+n];
970 mat->n_row -= n;
971 return mat;
974 void isl_mat_col_submul(struct isl_mat *mat,
975 int dst_col, isl_int f, int src_col)
977 int i;
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)
985 int i;
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)
994 int r;
995 struct isl_mat *H = NULL, *Q = NULL;
997 isl_assert(ctx, M->n_row == M->n_col, goto error);
998 M->n_row = row;
999 H = isl_mat_left_hermite(ctx, isl_mat_copy(ctx, M), 0, NULL, &Q);
1000 M->n_row = M->n_col;
1001 if (!H)
1002 goto error;
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);
1009 return M;
1010 error:
1011 isl_mat_free(ctx, H);
1012 isl_mat_free(ctx, Q);
1013 isl_mat_free(ctx, M);
1014 return NULL;