isl_transitive_closure.c: anonymize input map during incremental computation
[platform/upstream/isl.git] / isl_mat.c
1 /*
2  * Copyright 2008-2009 Katholieke Universiteit Leuven
3  *
4  * Use of this software is governed by the GNU LGPLv2.1 license
5  *
6  * Written by Sven Verdoolaege, K.U.Leuven, Departement
7  * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
8  */
9
10 #include "isl_dim.h"
11 #include "isl_seq.h"
12 #include "isl_mat.h"
13 #include "isl_map_private.h"
14
15 struct isl_mat *isl_mat_alloc(struct isl_ctx *ctx,
16         unsigned n_row, unsigned n_col)
17 {
18         int i;
19         struct isl_mat *mat;
20
21         mat = isl_alloc_type(ctx, struct isl_mat);
22         if (!mat)
23                 return NULL;
24
25         mat->row = NULL;
26         mat->block = isl_blk_alloc(ctx, n_row * n_col);
27         if (isl_blk_is_error(mat->block))
28                 goto error;
29         mat->row = isl_alloc_array(ctx, isl_int *, n_row);
30         if (!mat->row)
31                 goto error;
32
33         for (i = 0; i < n_row; ++i)
34                 mat->row[i] = mat->block.data + i * n_col;
35
36         mat->ctx = ctx;
37         isl_ctx_ref(ctx);
38         mat->ref = 1;
39         mat->n_row = n_row;
40         mat->n_col = n_col;
41         mat->max_col = n_col;
42         mat->flags = 0;
43
44         return mat;
45 error:
46         isl_blk_free(ctx, mat->block);
47         free(mat);
48         return NULL;
49 }
50
51 struct isl_mat *isl_mat_extend(struct isl_mat *mat,
52         unsigned n_row, unsigned n_col)
53 {
54         int i;
55         isl_int *old;
56
57         if (!mat)
58                 return NULL;
59
60         if (mat->max_col >= n_col && mat->n_row >= n_row) {
61                 if (mat->n_col < n_col)
62                         mat->n_col = n_col;
63                 return mat;
64         }
65
66         if (mat->max_col < n_col) {
67                 struct isl_mat *new_mat;
68
69                 if (n_row < mat->n_row)
70                         n_row = mat->n_row;
71                 new_mat = isl_mat_alloc(mat->ctx, n_row, n_col);
72                 if (!new_mat)
73                         goto error;
74                 for (i = 0; i < mat->n_row; ++i)
75                         isl_seq_cpy(new_mat->row[i], mat->row[i], mat->n_col);
76                 isl_mat_free(mat);
77                 return new_mat;
78         }
79
80         mat = isl_mat_cow(mat);
81         if (!mat)
82                 goto error;
83
84         old = mat->block.data;
85         mat->block = isl_blk_extend(mat->ctx, mat->block, n_row * mat->max_col);
86         if (isl_blk_is_error(mat->block))
87                 goto error;
88         mat->row = isl_realloc_array(mat->ctx, mat->row, isl_int *, n_row);
89         if (!mat->row)
90                 goto error;
91
92         for (i = 0; i < mat->n_row; ++i)
93                 mat->row[i] = mat->block.data + (mat->row[i] - old);
94         for (i = mat->n_row; i < n_row; ++i)
95                 mat->row[i] = mat->block.data + i * mat->max_col;
96         mat->n_row = n_row;
97         if (mat->n_col < n_col)
98                 mat->n_col = n_col;
99
100         return mat;
101 error:
102         isl_mat_free(mat);
103         return NULL;
104 }
105
106 struct isl_mat *isl_mat_sub_alloc(struct isl_ctx *ctx, isl_int **row,
107         unsigned first_row, unsigned n_row, unsigned first_col, unsigned n_col)
108 {
109         int i;
110         struct isl_mat *mat;
111
112         mat = isl_alloc_type(ctx, struct isl_mat);
113         if (!mat)
114                 return NULL;
115         mat->row = isl_alloc_array(ctx, isl_int *, n_row);
116         if (!mat->row)
117                 goto error;
118         for (i = 0; i < n_row; ++i)
119                 mat->row[i] = row[first_row+i] + first_col;
120         mat->ctx = ctx;
121         isl_ctx_ref(ctx);
122         mat->ref = 1;
123         mat->n_row = n_row;
124         mat->n_col = n_col;
125         mat->block = isl_blk_empty();
126         mat->flags = ISL_MAT_BORROWED;
127         return mat;
128 error:
129         free(mat);
130         return NULL;
131 }
132
133 void isl_mat_sub_copy(struct isl_ctx *ctx, isl_int **dst, isl_int **src,
134         unsigned n_row, unsigned dst_col, unsigned src_col, unsigned n_col)
135 {
136         int i;
137
138         for (i = 0; i < n_row; ++i)
139                 isl_seq_cpy(dst[i]+dst_col, src[i]+src_col, n_col);
140 }
141
142 void isl_mat_sub_neg(struct isl_ctx *ctx, isl_int **dst, isl_int **src,
143         unsigned n_row, unsigned dst_col, unsigned src_col, unsigned n_col)
144 {
145         int i;
146
147         for (i = 0; i < n_row; ++i)
148                 isl_seq_neg(dst[i]+dst_col, src[i]+src_col, n_col);
149 }
150
151 struct isl_mat *isl_mat_copy(struct isl_mat *mat)
152 {
153         if (!mat)
154                 return NULL;
155
156         mat->ref++;
157         return mat;
158 }
159
160 struct isl_mat *isl_mat_dup(struct isl_mat *mat)
161 {
162         int i;
163         struct isl_mat *mat2;
164
165         if (!mat)
166                 return NULL;
167         mat2 = isl_mat_alloc(mat->ctx, mat->n_row, mat->n_col);
168         if (!mat2)
169                 return NULL;
170         for (i = 0; i < mat->n_row; ++i)
171                 isl_seq_cpy(mat2->row[i], mat->row[i], mat->n_col);
172         return mat2;
173 }
174
175 struct isl_mat *isl_mat_cow(struct isl_mat *mat)
176 {
177         struct isl_mat *mat2;
178         if (!mat)
179                 return NULL;
180
181         if (mat->ref == 1 && !ISL_F_ISSET(mat, ISL_MAT_BORROWED))
182                 return mat;
183
184         mat2 = isl_mat_dup(mat);
185         isl_mat_free(mat);
186         return mat2;
187 }
188
189 void isl_mat_free(struct isl_mat *mat)
190 {
191         if (!mat)
192                 return;
193
194         if (--mat->ref > 0)
195                 return;
196
197         if (!ISL_F_ISSET(mat, ISL_MAT_BORROWED))
198                 isl_blk_free(mat->ctx, mat->block);
199         isl_ctx_deref(mat->ctx);
200         free(mat->row);
201         free(mat);
202 }
203
204 struct isl_mat *isl_mat_identity(struct isl_ctx *ctx, unsigned n_row)
205 {
206         int i;
207         struct isl_mat *mat;
208
209         mat = isl_mat_alloc(ctx, n_row, n_row);
210         if (!mat)
211                 return NULL;
212         for (i = 0; i < n_row; ++i) {
213                 isl_seq_clr(mat->row[i], i);
214                 isl_int_set_si(mat->row[i][i], 1);
215                 isl_seq_clr(mat->row[i]+i+1, n_row-(i+1));
216         }
217
218         return mat;
219 }
220
221 struct isl_vec *isl_mat_vec_product(struct isl_mat *mat, struct isl_vec *vec)
222 {
223         int i;
224         struct isl_vec *prod;
225
226         if (!mat || !vec)
227                 goto error;
228
229         isl_assert(mat->ctx, mat->n_col == vec->size, goto error);
230
231         prod = isl_vec_alloc(mat->ctx, mat->n_row);
232         if (!prod)
233                 goto error;
234
235         for (i = 0; i < prod->size; ++i)
236                 isl_seq_inner_product(mat->row[i], vec->el, vec->size,
237                                         &prod->block.data[i]);
238         isl_mat_free(mat);
239         isl_vec_free(vec);
240         return prod;
241 error:
242         isl_mat_free(mat);
243         isl_vec_free(vec);
244         return NULL;
245 }
246
247 __isl_give isl_vec *isl_mat_vec_inverse_product(__isl_take isl_mat *mat,
248         __isl_take isl_vec *vec)
249 {
250         struct isl_mat *vec_mat;
251         int i;
252
253         if (!mat || !vec)
254                 goto error;
255         vec_mat = isl_mat_alloc(vec->ctx, vec->size, 1);
256         if (!vec_mat)
257                 goto error;
258         for (i = 0; i < vec->size; ++i)
259                 isl_int_set(vec_mat->row[i][0], vec->el[i]);
260         vec_mat = isl_mat_inverse_product(mat, vec_mat);
261         isl_vec_free(vec);
262         if (!vec_mat)
263                 return NULL;
264         vec = isl_vec_alloc(vec_mat->ctx, vec_mat->n_row);
265         if (vec)
266                 for (i = 0; i < vec->size; ++i)
267                         isl_int_set(vec->el[i], vec_mat->row[i][0]);
268         isl_mat_free(vec_mat);
269         return vec;
270 error:
271         isl_mat_free(mat);
272         isl_vec_free(vec);
273         return NULL;
274 }
275
276 struct isl_vec *isl_vec_mat_product(struct isl_vec *vec, struct isl_mat *mat)
277 {
278         int i, j;
279         struct isl_vec *prod;
280
281         if (!mat || !vec)
282                 goto error;
283
284         isl_assert(mat->ctx, mat->n_row == vec->size, goto error);
285
286         prod = isl_vec_alloc(mat->ctx, mat->n_col);
287         if (!prod)
288                 goto error;
289
290         for (i = 0; i < prod->size; ++i) {
291                 isl_int_set_si(prod->el[i], 0);
292                 for (j = 0; j < vec->size; ++j)
293                         isl_int_addmul(prod->el[i], vec->el[j], mat->row[j][i]);
294         }
295         isl_mat_free(mat);
296         isl_vec_free(vec);
297         return prod;
298 error:
299         isl_mat_free(mat);
300         isl_vec_free(vec);
301         return NULL;
302 }
303
304 struct isl_mat *isl_mat_aff_direct_sum(struct isl_mat *left,
305         struct isl_mat *right)
306 {
307         int i;
308         struct isl_mat *sum;
309
310         if (!left || !right)
311                 goto error;
312
313         isl_assert(left->ctx, left->n_row == right->n_row, goto error);
314         isl_assert(left->ctx, left->n_row >= 1, goto error);
315         isl_assert(left->ctx, left->n_col >= 1, goto error);
316         isl_assert(left->ctx, right->n_col >= 1, goto error);
317         isl_assert(left->ctx,
318             isl_seq_first_non_zero(left->row[0]+1, left->n_col-1) == -1,
319             goto error);
320         isl_assert(left->ctx,
321             isl_seq_first_non_zero(right->row[0]+1, right->n_col-1) == -1,
322             goto error);
323
324         sum = isl_mat_alloc(left->ctx, left->n_row, left->n_col + right->n_col - 1);
325         if (!sum)
326                 goto error;
327         isl_int_lcm(sum->row[0][0], left->row[0][0], right->row[0][0]);
328         isl_int_divexact(left->row[0][0], sum->row[0][0], left->row[0][0]);
329         isl_int_divexact(right->row[0][0], sum->row[0][0], right->row[0][0]);
330
331         isl_seq_clr(sum->row[0]+1, sum->n_col-1);
332         for (i = 1; i < sum->n_row; ++i) {
333                 isl_int_mul(sum->row[i][0], left->row[0][0], left->row[i][0]);
334                 isl_int_addmul(sum->row[i][0],
335                                 right->row[0][0], right->row[i][0]);
336                 isl_seq_scale(sum->row[i]+1, left->row[i]+1, left->row[0][0],
337                                 left->n_col-1);
338                 isl_seq_scale(sum->row[i]+left->n_col,
339                                 right->row[i]+1, right->row[0][0],
340                                 right->n_col-1);
341         }
342
343         isl_int_divexact(left->row[0][0], sum->row[0][0], left->row[0][0]);
344         isl_int_divexact(right->row[0][0], sum->row[0][0], right->row[0][0]);
345         isl_mat_free(left);
346         isl_mat_free(right);
347         return sum;
348 error:
349         isl_mat_free(left);
350         isl_mat_free(right);
351         return NULL;
352 }
353
354 static void exchange(struct isl_mat *M, struct isl_mat **U,
355         struct isl_mat **Q, unsigned row, unsigned i, unsigned j)
356 {
357         int r;
358         for (r = row; r < M->n_row; ++r)
359                 isl_int_swap(M->row[r][i], M->row[r][j]);
360         if (U) {
361                 for (r = 0; r < (*U)->n_row; ++r)
362                         isl_int_swap((*U)->row[r][i], (*U)->row[r][j]);
363         }
364         if (Q)
365                 isl_mat_swap_rows(*Q, i, j);
366 }
367
368 static void subtract(struct isl_mat *M, struct isl_mat **U,
369         struct isl_mat **Q, unsigned row, unsigned i, unsigned j, isl_int m)
370 {
371         int r;
372         for (r = row; r < M->n_row; ++r)
373                 isl_int_submul(M->row[r][j], m, M->row[r][i]);
374         if (U) {
375                 for (r = 0; r < (*U)->n_row; ++r)
376                         isl_int_submul((*U)->row[r][j], m, (*U)->row[r][i]);
377         }
378         if (Q) {
379                 for (r = 0; r < (*Q)->n_col; ++r)
380                         isl_int_addmul((*Q)->row[i][r], m, (*Q)->row[j][r]);
381         }
382 }
383
384 static void oppose(struct isl_mat *M, struct isl_mat **U,
385         struct isl_mat **Q, unsigned row, unsigned col)
386 {
387         int r;
388         for (r = row; r < M->n_row; ++r)
389                 isl_int_neg(M->row[r][col], M->row[r][col]);
390         if (U) {
391                 for (r = 0; r < (*U)->n_row; ++r)
392                         isl_int_neg((*U)->row[r][col], (*U)->row[r][col]);
393         }
394         if (Q)
395                 isl_seq_neg((*Q)->row[col], (*Q)->row[col], (*Q)->n_col);
396 }
397
398 /* Given matrix M, compute
399  *
400  *              M U = H
401  *              M   = H Q
402  *
403  * with U and Q unimodular matrices and H a matrix in column echelon form
404  * such that on each echelon row the entries in the non-echelon column
405  * are non-negative (if neg == 0) or non-positive (if neg == 1)
406  * and stricly smaller (in absolute value) than the entries in the echelon
407  * column.
408  * If U or Q are NULL, then these matrices are not computed.
409  */
410 struct isl_mat *isl_mat_left_hermite(struct isl_mat *M, int neg,
411         struct isl_mat **U, struct isl_mat **Q)
412 {
413         isl_int c;
414         int row, col;
415
416         if (U)
417                 *U = NULL;
418         if (Q)
419                 *Q = NULL;
420         if (!M)
421                 goto error;
422         M = isl_mat_cow(M);
423         if (!M)
424                 goto error;
425         if (U) {
426                 *U = isl_mat_identity(M->ctx, M->n_col);
427                 if (!*U)
428                         goto error;
429         }
430         if (Q) {
431                 *Q = isl_mat_identity(M->ctx, M->n_col);
432                 if (!*Q)
433                         goto error;
434         }
435
436         col = 0;
437         isl_int_init(c);
438         for (row = 0; row < M->n_row; ++row) {
439                 int first, i, off;
440                 first = isl_seq_abs_min_non_zero(M->row[row]+col, M->n_col-col);
441                 if (first == -1)
442                         continue;
443                 first += col;
444                 if (first != col)
445                         exchange(M, U, Q, row, first, col);
446                 if (isl_int_is_neg(M->row[row][col]))
447                         oppose(M, U, Q, row, col);
448                 first = col+1;
449                 while ((off = isl_seq_first_non_zero(M->row[row]+first,
450                                                        M->n_col-first)) != -1) {
451                         first += off;
452                         isl_int_fdiv_q(c, M->row[row][first], M->row[row][col]);
453                         subtract(M, U, Q, row, col, first, c);
454                         if (!isl_int_is_zero(M->row[row][first]))
455                                 exchange(M, U, Q, row, first, col);
456                         else
457                                 ++first;
458                 }
459                 for (i = 0; i < col; ++i) {
460                         if (isl_int_is_zero(M->row[row][i]))
461                                 continue;
462                         if (neg)
463                                 isl_int_cdiv_q(c, M->row[row][i], M->row[row][col]);
464                         else
465                                 isl_int_fdiv_q(c, M->row[row][i], M->row[row][col]);
466                         if (isl_int_is_zero(c))
467                                 continue;
468                         subtract(M, U, Q, row, col, i, c);
469                 }
470                 ++col;
471         }
472         isl_int_clear(c);
473
474         return M;
475 error:
476         if (Q) {
477                 isl_mat_free(*Q);
478                 *Q = NULL;
479         }
480         if (U) {
481                 isl_mat_free(*U);
482                 *U = NULL;
483         }
484         return NULL;
485 }
486
487 struct isl_mat *isl_mat_right_kernel(struct isl_mat *mat)
488 {
489         int i, rank;
490         struct isl_mat *U = NULL;
491         struct isl_mat *K;
492
493         mat = isl_mat_left_hermite(mat, 0, &U, NULL);
494         if (!mat || !U)
495                 goto error;
496
497         for (i = 0, rank = 0; rank < mat->n_col; ++rank) {
498                 while (i < mat->n_row && isl_int_is_zero(mat->row[i][rank]))
499                         ++i;
500                 if (i >= mat->n_row)
501                         break;
502         }
503         K = isl_mat_alloc(U->ctx, U->n_row, U->n_col - rank);
504         if (!K)
505                 goto error;
506         isl_mat_sub_copy(K->ctx, K->row, U->row, U->n_row, 0, rank, U->n_col-rank);
507         isl_mat_free(mat);
508         isl_mat_free(U);
509         return K;
510 error:
511         isl_mat_free(mat);
512         isl_mat_free(U);
513         return NULL;
514 }
515
516 struct isl_mat *isl_mat_lin_to_aff(struct isl_mat *mat)
517 {
518         int i;
519         struct isl_mat *mat2;
520
521         if (!mat)
522                 return NULL;
523         mat2 = isl_mat_alloc(mat->ctx, 1+mat->n_row, 1+mat->n_col);
524         if (!mat2)
525                 goto error;
526         isl_int_set_si(mat2->row[0][0], 1);
527         isl_seq_clr(mat2->row[0]+1, mat->n_col);
528         for (i = 0; i < mat->n_row; ++i) {
529                 isl_int_set_si(mat2->row[1+i][0], 0);
530                 isl_seq_cpy(mat2->row[1+i]+1, mat->row[i], mat->n_col);
531         }
532         isl_mat_free(mat);
533         return mat2;
534 error:
535         isl_mat_free(mat);
536         return NULL;
537 }
538
539 /* Given two matrices M1 and M2, return the block matrix
540  *
541  *      [ M1  0  ]
542  *      [ 0   M2 ]
543  */
544 __isl_give isl_mat *isl_mat_diagonal(__isl_take isl_mat *mat1,
545         __isl_take isl_mat *mat2)
546 {
547         int i;
548         isl_mat *mat;
549
550         if (!mat1 || !mat2)
551                 goto error;
552
553         mat = isl_mat_alloc(mat1->ctx, mat1->n_row + mat2->n_row,
554                                        mat1->n_col + mat2->n_col);
555         if (!mat)
556                 goto error;
557         for (i = 0; i < mat1->n_row; ++i) {
558                 isl_seq_cpy(mat->row[i], mat1->row[i], mat1->n_col);
559                 isl_seq_clr(mat->row[i] + mat1->n_col, mat2->n_col);
560         }
561         for (i = 0; i < mat2->n_row; ++i) {
562                 isl_seq_clr(mat->row[mat1->n_row + i], mat1->n_col);
563                 isl_seq_cpy(mat->row[mat1->n_row + i] + mat1->n_col,
564                                                     mat2->row[i], mat2->n_col);
565         }
566         isl_mat_free(mat1);
567         isl_mat_free(mat2);
568         return mat;
569 error:
570         isl_mat_free(mat1);
571         isl_mat_free(mat2);
572         return NULL;
573 }
574
575 static int row_first_non_zero(isl_int **row, unsigned n_row, unsigned col)
576 {
577         int i;
578
579         for (i = 0; i < n_row; ++i)
580                 if (!isl_int_is_zero(row[i][col]))
581                         return i;
582         return -1;
583 }
584
585 static int row_abs_min_non_zero(isl_int **row, unsigned n_row, unsigned col)
586 {
587         int i, min = row_first_non_zero(row, n_row, col);
588         if (min < 0)
589                 return -1;
590         for (i = min + 1; i < n_row; ++i) {
591                 if (isl_int_is_zero(row[i][col]))
592                         continue;
593                 if (isl_int_abs_lt(row[i][col], row[min][col]))
594                         min = i;
595         }
596         return min;
597 }
598
599 static void inv_exchange(struct isl_mat *left, struct isl_mat *right,
600         unsigned i, unsigned j)
601 {
602         left = isl_mat_swap_rows(left, i, j);
603         right = isl_mat_swap_rows(right, i, j);
604 }
605
606 static void inv_oppose(
607         struct isl_mat *left, struct isl_mat *right, unsigned row)
608 {
609         isl_seq_neg(left->row[row]+row, left->row[row]+row, left->n_col-row);
610         isl_seq_neg(right->row[row], right->row[row], right->n_col);
611 }
612
613 static void inv_subtract(struct isl_mat *left, struct isl_mat *right,
614         unsigned row, unsigned i, isl_int m)
615 {
616         isl_int_neg(m, m);
617         isl_seq_combine(left->row[i]+row,
618                         left->ctx->one, left->row[i]+row,
619                         m, left->row[row]+row,
620                         left->n_col-row);
621         isl_seq_combine(right->row[i], right->ctx->one, right->row[i],
622                         m, right->row[row], right->n_col);
623 }
624
625 /* Compute inv(left)*right
626  */
627 struct isl_mat *isl_mat_inverse_product(struct isl_mat *left,
628         struct isl_mat *right)
629 {
630         int row;
631         isl_int a, b;
632
633         if (!left || !right)
634                 goto error;
635
636         isl_assert(left->ctx, left->n_row == left->n_col, goto error);
637         isl_assert(left->ctx, left->n_row == right->n_row, goto error);
638
639         if (left->n_row == 0) {
640                 isl_mat_free(left);
641                 return right;
642         }
643
644         left = isl_mat_cow(left);
645         right = isl_mat_cow(right);
646         if (!left || !right)
647                 goto error;
648
649         isl_int_init(a);
650         isl_int_init(b);
651         for (row = 0; row < left->n_row; ++row) {
652                 int pivot, first, i, off;
653                 pivot = row_abs_min_non_zero(left->row+row, left->n_row-row, row);
654                 if (pivot < 0) {
655                         isl_int_clear(a);
656                         isl_int_clear(b);
657                         isl_assert(left->ctx, pivot >= 0, goto error);
658                 }
659                 pivot += row;
660                 if (pivot != row)
661                         inv_exchange(left, right, pivot, row);
662                 if (isl_int_is_neg(left->row[row][row]))
663                         inv_oppose(left, right, row);
664                 first = row+1;
665                 while ((off = row_first_non_zero(left->row+first,
666                                         left->n_row-first, row)) != -1) {
667                         first += off;
668                         isl_int_fdiv_q(a, left->row[first][row],
669                                         left->row[row][row]);
670                         inv_subtract(left, right, row, first, a);
671                         if (!isl_int_is_zero(left->row[first][row]))
672                                 inv_exchange(left, right, row, first);
673                         else
674                                 ++first;
675                 }
676                 for (i = 0; i < row; ++i) {
677                         if (isl_int_is_zero(left->row[i][row]))
678                                 continue;
679                         isl_int_gcd(a, left->row[row][row], left->row[i][row]);
680                         isl_int_divexact(b, left->row[i][row], a);
681                         isl_int_divexact(a, left->row[row][row], a);
682                         isl_int_neg(b, b);
683                         isl_seq_combine(left->row[i] + i,
684                                         a, left->row[i] + i,
685                                         b, left->row[row] + i,
686                                         left->n_col - i);
687                         isl_seq_combine(right->row[i], a, right->row[i],
688                                         b, right->row[row], right->n_col);
689                 }
690         }
691         isl_int_clear(b);
692
693         isl_int_set(a, left->row[0][0]);
694         for (row = 1; row < left->n_row; ++row)
695                 isl_int_lcm(a, a, left->row[row][row]);
696         if (isl_int_is_zero(a)){
697                 isl_int_clear(a);
698                 isl_assert(left->ctx, 0, goto error);
699         }
700         for (row = 0; row < left->n_row; ++row) {
701                 isl_int_divexact(left->row[row][row], a, left->row[row][row]);
702                 if (isl_int_is_one(left->row[row][row]))
703                         continue;
704                 isl_seq_scale(right->row[row], right->row[row],
705                                 left->row[row][row], right->n_col);
706         }
707         isl_int_clear(a);
708
709         isl_mat_free(left);
710         return right;
711 error:
712         isl_mat_free(left);
713         isl_mat_free(right);
714         return NULL;
715 }
716
717 void isl_mat_col_scale(struct isl_mat *mat, unsigned col, isl_int m)
718 {
719         int i;
720
721         for (i = 0; i < mat->n_row; ++i)
722                 isl_int_mul(mat->row[i][col], mat->row[i][col], m);
723 }
724
725 void isl_mat_col_combine(struct isl_mat *mat, unsigned dst,
726         isl_int m1, unsigned src1, isl_int m2, unsigned src2)
727 {
728         int i;
729         isl_int tmp;
730
731         isl_int_init(tmp);
732         for (i = 0; i < mat->n_row; ++i) {
733                 isl_int_mul(tmp, m1, mat->row[i][src1]);
734                 isl_int_addmul(tmp, m2, mat->row[i][src2]);
735                 isl_int_set(mat->row[i][dst], tmp);
736         }
737         isl_int_clear(tmp);
738 }
739
740 struct isl_mat *isl_mat_right_inverse(struct isl_mat *mat)
741 {
742         struct isl_mat *inv;
743         int row;
744         isl_int a, b;
745
746         mat = isl_mat_cow(mat);
747         if (!mat)
748                 return NULL;
749
750         inv = isl_mat_identity(mat->ctx, mat->n_col);
751         inv = isl_mat_cow(inv);
752         if (!inv)
753                 goto error;
754
755         isl_int_init(a);
756         isl_int_init(b);
757         for (row = 0; row < mat->n_row; ++row) {
758                 int pivot, first, i, off;
759                 pivot = isl_seq_abs_min_non_zero(mat->row[row]+row, mat->n_col-row);
760                 if (pivot < 0) {
761                         isl_int_clear(a);
762                         isl_int_clear(b);
763                         isl_assert(mat->ctx, pivot >= 0, goto error);
764                 }
765                 pivot += row;
766                 if (pivot != row)
767                         exchange(mat, &inv, NULL, row, pivot, row);
768                 if (isl_int_is_neg(mat->row[row][row]))
769                         oppose(mat, &inv, NULL, row, row);
770                 first = row+1;
771                 while ((off = isl_seq_first_non_zero(mat->row[row]+first,
772                                                     mat->n_col-first)) != -1) {
773                         first += off;
774                         isl_int_fdiv_q(a, mat->row[row][first],
775                                                     mat->row[row][row]);
776                         subtract(mat, &inv, NULL, row, row, first, a);
777                         if (!isl_int_is_zero(mat->row[row][first]))
778                                 exchange(mat, &inv, NULL, row, row, first);
779                         else
780                                 ++first;
781                 }
782                 for (i = 0; i < row; ++i) {
783                         if (isl_int_is_zero(mat->row[row][i]))
784                                 continue;
785                         isl_int_gcd(a, mat->row[row][row], mat->row[row][i]);
786                         isl_int_divexact(b, mat->row[row][i], a);
787                         isl_int_divexact(a, mat->row[row][row], a);
788                         isl_int_neg(a, a);
789                         isl_mat_col_combine(mat, i, a, i, b, row);
790                         isl_mat_col_combine(inv, i, a, i, b, row);
791                 }
792         }
793         isl_int_clear(b);
794
795         isl_int_set(a, mat->row[0][0]);
796         for (row = 1; row < mat->n_row; ++row)
797                 isl_int_lcm(a, a, mat->row[row][row]);
798         if (isl_int_is_zero(a)){
799                 isl_int_clear(a);
800                 goto error;
801         }
802         for (row = 0; row < mat->n_row; ++row) {
803                 isl_int_divexact(mat->row[row][row], a, mat->row[row][row]);
804                 if (isl_int_is_one(mat->row[row][row]))
805                         continue;
806                 isl_mat_col_scale(inv, row, mat->row[row][row]);
807         }
808         isl_int_clear(a);
809
810         isl_mat_free(mat);
811
812         return inv;
813 error:
814         isl_mat_free(mat);
815         return NULL;
816 }
817
818 struct isl_mat *isl_mat_transpose(struct isl_mat *mat)
819 {
820         struct isl_mat *transpose = NULL;
821         int i, j;
822
823         if (mat->n_col == mat->n_row) {
824                 mat = isl_mat_cow(mat);
825                 if (!mat)
826                         return NULL;
827                 for (i = 0; i < mat->n_row; ++i)
828                         for (j = i + 1; j < mat->n_col; ++j)
829                                 isl_int_swap(mat->row[i][j], mat->row[j][i]);
830                 return mat;
831         }
832         transpose = isl_mat_alloc(mat->ctx, mat->n_col, mat->n_row);
833         if (!transpose)
834                 goto error;
835         for (i = 0; i < mat->n_row; ++i)
836                 for (j = 0; j < mat->n_col; ++j)
837                         isl_int_set(transpose->row[j][i], mat->row[i][j]);
838         isl_mat_free(mat);
839         return transpose;
840 error:
841         isl_mat_free(mat);
842         return NULL;
843 }
844
845 struct isl_mat *isl_mat_swap_cols(struct isl_mat *mat, unsigned i, unsigned j)
846 {
847         int r;
848
849         mat = isl_mat_cow(mat);
850         if (!mat)
851                 return NULL;
852         isl_assert(mat->ctx, i < mat->n_col, goto error);
853         isl_assert(mat->ctx, j < mat->n_col, goto error);
854
855         for (r = 0; r < mat->n_row; ++r)
856                 isl_int_swap(mat->row[r][i], mat->row[r][j]);
857         return mat;
858 error:
859         isl_mat_free(mat);
860         return NULL;
861 }
862
863 struct isl_mat *isl_mat_swap_rows(struct isl_mat *mat, unsigned i, unsigned j)
864 {
865         isl_int *t;
866
867         if (!mat)
868                 return NULL;
869         mat = isl_mat_cow(mat);
870         if (!mat)
871                 return NULL;
872         t = mat->row[i];
873         mat->row[i] = mat->row[j];
874         mat->row[j] = t;
875         return mat;
876 }
877
878 struct isl_mat *isl_mat_product(struct isl_mat *left, struct isl_mat *right)
879 {
880         int i, j, k;
881         struct isl_mat *prod;
882
883         if (!left || !right)
884                 goto error;
885         isl_assert(left->ctx, left->n_col == right->n_row, goto error);
886         prod = isl_mat_alloc(left->ctx, left->n_row, right->n_col);
887         if (!prod)
888                 goto error;
889         if (left->n_col == 0) {
890                 for (i = 0; i < prod->n_row; ++i)
891                         isl_seq_clr(prod->row[i], prod->n_col);
892                 return prod;
893         }
894         for (i = 0; i < prod->n_row; ++i) {
895                 for (j = 0; j < prod->n_col; ++j) {
896                         isl_int_mul(prod->row[i][j],
897                                     left->row[i][0], right->row[0][j]);
898                         for (k = 1; k < left->n_col; ++k)
899                                 isl_int_addmul(prod->row[i][j],
900                                             left->row[i][k], right->row[k][j]);
901                 }
902         }
903         isl_mat_free(left);
904         isl_mat_free(right);
905         return prod;
906 error:
907         isl_mat_free(left);
908         isl_mat_free(right);
909         return NULL;
910 }
911
912 /* Replace the variables x in the rows q by x' given by x = M x',
913  * with M the matrix mat.
914  *
915  * If the number of new variables is greater than the original
916  * number of variables, then the rows q have already been
917  * preextended.  If the new number is smaller, then the coefficients
918  * of the divs, which are not changed, need to be shifted down.
919  * The row q may be the equalities, the inequalities or the
920  * div expressions.  In the latter case, has_div is true and
921  * we need to take into account the extra denominator column.
922  */
923 static int preimage(struct isl_ctx *ctx, isl_int **q, unsigned n,
924         unsigned n_div, int has_div, struct isl_mat *mat)
925 {
926         int i;
927         struct isl_mat *t;
928         int e;
929
930         if (mat->n_col >= mat->n_row)
931                 e = 0;
932         else
933                 e = mat->n_row - mat->n_col;
934         if (has_div)
935                 for (i = 0; i < n; ++i)
936                         isl_int_mul(q[i][0], q[i][0], mat->row[0][0]);
937         t = isl_mat_sub_alloc(mat->ctx, q, 0, n, has_div, mat->n_row);
938         t = isl_mat_product(t, mat);
939         if (!t)
940                 return -1;
941         for (i = 0; i < n; ++i) {
942                 isl_seq_swp_or_cpy(q[i] + has_div, t->row[i], t->n_col);
943                 isl_seq_cpy(q[i] + has_div + t->n_col,
944                             q[i] + has_div + t->n_col + e, n_div);
945                 isl_seq_clr(q[i] + has_div + t->n_col + n_div, e);
946         }
947         isl_mat_free(t);
948         return 0;
949 }
950
951 /* Replace the variables x in bset by x' given by x = M x', with
952  * M the matrix mat.
953  *
954  * If there are fewer variables x' then there are x, then we perform
955  * the transformation in place, which that, in principle,
956  * this frees up some extra variables as the number
957  * of columns remains constant, but we would have to extend
958  * the div array too as the number of rows in this array is assumed
959  * to be equal to extra.
960  */
961 struct isl_basic_set *isl_basic_set_preimage(struct isl_basic_set *bset,
962         struct isl_mat *mat)
963 {
964         struct isl_ctx *ctx;
965
966         if (!bset || !mat)
967                 goto error;
968
969         ctx = bset->ctx;
970         bset = isl_basic_set_cow(bset);
971         if (!bset)
972                 goto error;
973
974         isl_assert(ctx, bset->dim->nparam == 0, goto error);
975         isl_assert(ctx, 1+bset->dim->n_out == mat->n_row, goto error);
976         isl_assert(ctx, mat->n_col > 0, goto error);
977
978         if (mat->n_col > mat->n_row) {
979                 bset = isl_basic_set_extend(bset, 0, mat->n_col-1, 0, 0, 0);
980                 if (!bset)
981                         goto error;
982         } else if (mat->n_col < mat->n_row) {
983                 bset->dim = isl_dim_cow(bset->dim);
984                 if (!bset->dim)
985                         goto error;
986                 bset->dim->n_out -= mat->n_row - mat->n_col;
987         }
988
989         if (preimage(ctx, bset->eq, bset->n_eq, bset->n_div, 0,
990                         isl_mat_copy(mat)) < 0)
991                 goto error;
992
993         if (preimage(ctx, bset->ineq, bset->n_ineq, bset->n_div, 0,
994                         isl_mat_copy(mat)) < 0)
995                 goto error;
996
997         if (preimage(ctx, bset->div, bset->n_div, bset->n_div, 1, mat) < 0)
998                 goto error2;
999
1000         ISL_F_CLR(bset, ISL_BASIC_SET_NO_IMPLICIT);
1001         ISL_F_CLR(bset, ISL_BASIC_SET_NO_REDUNDANT);
1002         ISL_F_CLR(bset, ISL_BASIC_SET_NORMALIZED);
1003         ISL_F_CLR(bset, ISL_BASIC_SET_NORMALIZED_DIVS);
1004         ISL_F_CLR(bset, ISL_BASIC_SET_ALL_EQUALITIES);
1005
1006         bset = isl_basic_set_simplify(bset);
1007         bset = isl_basic_set_finalize(bset);
1008
1009         return bset;
1010 error:
1011         isl_mat_free(mat);
1012 error2:
1013         isl_basic_set_free(bset);
1014         return NULL;
1015 }
1016
1017 struct isl_set *isl_set_preimage(struct isl_set *set, struct isl_mat *mat)
1018 {
1019         struct isl_ctx *ctx;
1020         int i;
1021
1022         set = isl_set_cow(set);
1023         if (!set)
1024                 return NULL;
1025
1026         ctx = set->ctx;
1027         for (i = 0; i < set->n; ++i) {
1028                 set->p[i] = isl_basic_set_preimage(set->p[i],
1029                                                     isl_mat_copy(mat));
1030                 if (!set->p[i])
1031                         goto error;
1032         }
1033         if (mat->n_col != mat->n_row) {
1034                 set->dim = isl_dim_cow(set->dim);
1035                 if (!set->dim)
1036                         goto error;
1037                 set->dim->n_out += mat->n_col;
1038                 set->dim->n_out -= mat->n_row;
1039         }
1040         isl_mat_free(mat);
1041         ISL_F_CLR(set, ISL_SET_NORMALIZED);
1042         return set;
1043 error:
1044         isl_set_free(set);
1045         isl_mat_free(mat);
1046         return NULL;
1047 }
1048
1049 void isl_mat_dump(struct isl_mat *mat, FILE *out, int indent)
1050 {
1051         int i, j;
1052
1053         if (!mat) {
1054                 fprintf(out, "%*snull mat\n", indent, "");
1055                 return;
1056         }
1057
1058         if (mat->n_row == 0)
1059                 fprintf(out, "%*s[]\n", indent, "");
1060
1061         for (i = 0; i < mat->n_row; ++i) {
1062                 if (!i)
1063                         fprintf(out, "%*s[[", indent, "");
1064                 else
1065                         fprintf(out, "%*s[", indent+1, "");
1066                 for (j = 0; j < mat->n_col; ++j) {
1067                         if (j)
1068                             fprintf(out, ",");
1069                         isl_int_print(out, mat->row[i][j], 0);
1070                 }
1071                 if (i == mat->n_row-1)
1072                         fprintf(out, "]]\n");
1073                 else
1074                         fprintf(out, "]\n");
1075         }
1076 }
1077
1078 struct isl_mat *isl_mat_drop_cols(struct isl_mat *mat, unsigned col, unsigned n)
1079 {
1080         int r;
1081
1082         mat = isl_mat_cow(mat);
1083         if (!mat)
1084                 return NULL;
1085
1086         if (col != mat->n_col-n) {
1087                 for (r = 0; r < mat->n_row; ++r)
1088                         isl_seq_cpy(mat->row[r]+col, mat->row[r]+col+n,
1089                                         mat->n_col - col - n);
1090         }
1091         mat->n_col -= n;
1092         return mat;
1093 }
1094
1095 struct isl_mat *isl_mat_drop_rows(struct isl_mat *mat, unsigned row, unsigned n)
1096 {
1097         int r;
1098
1099         mat = isl_mat_cow(mat);
1100         if (!mat)
1101                 return NULL;
1102
1103         for (r = row; r+n < mat->n_row; ++r)
1104                 mat->row[r] = mat->row[r+n];
1105
1106         mat->n_row -= n;
1107         return mat;
1108 }
1109
1110 __isl_give isl_mat *isl_mat_insert_cols(__isl_take isl_mat *mat,
1111                                 unsigned col, unsigned n)
1112 {
1113         isl_mat *ext;
1114
1115         if (!mat)
1116                 return NULL;
1117         if (n == 0)
1118                 return mat;
1119
1120         ext = isl_mat_alloc(mat->ctx, mat->n_row, mat->n_col + n);
1121         if (!ext)
1122                 goto error;
1123
1124         isl_mat_sub_copy(mat->ctx, ext->row, mat->row, mat->n_row, 0, 0, col);
1125         isl_mat_sub_copy(mat->ctx, ext->row, mat->row, mat->n_row,
1126                                 col + n, col, mat->n_col - col);
1127
1128         isl_mat_free(mat);
1129         return ext;
1130 error:
1131         isl_mat_free(mat);
1132         return NULL;
1133 }
1134
1135 __isl_give isl_mat *isl_mat_insert_rows(__isl_take isl_mat *mat,
1136                                 unsigned row, unsigned n)
1137 {
1138         isl_mat *ext;
1139
1140         if (!mat)
1141                 return NULL;
1142         if (n == 0)
1143                 return mat;
1144
1145         ext = isl_mat_alloc(mat->ctx, mat->n_row + n, mat->n_col);
1146         if (!ext)
1147                 goto error;
1148
1149         isl_mat_sub_copy(mat->ctx, ext->row, mat->row, row, 0, 0, mat->n_col);
1150         isl_mat_sub_copy(mat->ctx, ext->row + row + n, mat->row + row,
1151                                 mat->n_row - row, 0, 0, mat->n_col);
1152
1153         isl_mat_free(mat);
1154         return ext;
1155 error:
1156         isl_mat_free(mat);
1157         return NULL;
1158 }
1159
1160 void isl_mat_col_submul(struct isl_mat *mat,
1161                         int dst_col, isl_int f, int src_col)
1162 {
1163         int i;
1164
1165         for (i = 0; i < mat->n_row; ++i)
1166                 isl_int_submul(mat->row[i][dst_col], f, mat->row[i][src_col]);
1167 }
1168
1169 void isl_mat_col_mul(struct isl_mat *mat, int dst_col, isl_int f, int src_col)
1170 {
1171         int i;
1172
1173         for (i = 0; i < mat->n_row; ++i)
1174                 isl_int_mul(mat->row[i][dst_col], f, mat->row[i][src_col]);
1175 }
1176
1177 struct isl_mat *isl_mat_unimodular_complete(struct isl_mat *M, int row)
1178 {
1179         int r;
1180         struct isl_mat *H = NULL, *Q = NULL;
1181
1182         if (!M)
1183                 return NULL;
1184
1185         isl_assert(M->ctx, M->n_row == M->n_col, goto error);
1186         M->n_row = row;
1187         H = isl_mat_left_hermite(isl_mat_copy(M), 0, NULL, &Q);
1188         M->n_row = M->n_col;
1189         if (!H)
1190                 goto error;
1191         for (r = 0; r < row; ++r)
1192                 isl_assert(M->ctx, isl_int_is_one(H->row[r][r]), goto error);
1193         for (r = row; r < M->n_row; ++r)
1194                 isl_seq_cpy(M->row[r], Q->row[r], M->n_col);
1195         isl_mat_free(H);
1196         isl_mat_free(Q);
1197         return M;
1198 error:
1199         isl_mat_free(H);
1200         isl_mat_free(Q);
1201         isl_mat_free(M);
1202         return NULL;
1203 }
1204
1205 __isl_give isl_mat *isl_mat_concat(__isl_take isl_mat *top,
1206         __isl_take isl_mat *bot)
1207 {
1208         struct isl_mat *mat;
1209
1210         if (!top || !bot)
1211                 goto error;
1212
1213         isl_assert(top->ctx, top->n_col == bot->n_col, goto error);
1214         if (top->n_row == 0) {
1215                 isl_mat_free(top);
1216                 return bot;
1217         }
1218         if (bot->n_row == 0) {
1219                 isl_mat_free(bot);
1220                 return top;
1221         }
1222
1223         mat = isl_mat_alloc(top->ctx, top->n_row + bot->n_row, top->n_col);
1224         if (!mat)
1225                 goto error;
1226         isl_mat_sub_copy(mat->ctx, mat->row, top->row, top->n_row,
1227                          0, 0, mat->n_col);
1228         isl_mat_sub_copy(mat->ctx, mat->row + top->n_row, bot->row, bot->n_row,
1229                          0, 0, mat->n_col);
1230         isl_mat_free(top);
1231         isl_mat_free(bot);
1232         return mat;
1233 error:
1234         isl_mat_free(top);
1235         isl_mat_free(bot);
1236         return NULL;
1237 }
1238
1239 int isl_mat_is_equal(__isl_keep isl_mat *mat1, __isl_keep isl_mat *mat2)
1240 {
1241         int i;
1242
1243         if (!mat1 || !mat2)
1244                 return -1;
1245
1246         if (mat1->n_row != mat2->n_row)
1247                 return 0;
1248
1249         if (mat1->n_col != mat2->n_col)
1250                 return 0;
1251
1252         for (i = 0; i < mat1->n_row; ++i)
1253                 if (!isl_seq_eq(mat1->row[i], mat2->row[i], mat1->n_col))
1254                         return 0;
1255
1256         return 1;
1257 }
1258
1259 __isl_give isl_mat *isl_mat_from_row_vec(__isl_take isl_vec *vec)
1260 {
1261         struct isl_mat *mat;
1262
1263         if (!vec)
1264                 return NULL;
1265         mat = isl_mat_alloc(vec->ctx, 1, vec->size);
1266         if (!mat)
1267                 goto error;
1268
1269         isl_seq_cpy(mat->row[0], vec->el, vec->size);
1270
1271         isl_vec_free(vec);
1272         return mat;
1273 error:
1274         isl_vec_free(vec);
1275         return NULL;
1276 }
1277
1278 __isl_give isl_mat *isl_mat_vec_concat(__isl_take isl_mat *top,
1279         __isl_take isl_vec *bot)
1280 {
1281         return isl_mat_concat(top, isl_mat_from_row_vec(bot));
1282 }
1283
1284 __isl_give isl_mat *isl_mat_move_cols(__isl_take isl_mat *mat,
1285         unsigned dst_col, unsigned src_col, unsigned n)
1286 {
1287         isl_mat *res;
1288
1289         if (!mat)
1290                 return NULL;
1291         if (n == 0 || dst_col == src_col)
1292                 return mat;
1293
1294         res = isl_mat_alloc(mat->ctx, mat->n_row, mat->n_col);
1295         if (!res)
1296                 goto error;
1297
1298         if (dst_col < src_col) {
1299                 isl_mat_sub_copy(res->ctx, res->row, mat->row, mat->n_row,
1300                                  0, 0, dst_col);
1301                 isl_mat_sub_copy(res->ctx, res->row, mat->row, mat->n_row,
1302                                  dst_col, src_col, n);
1303                 isl_mat_sub_copy(res->ctx, res->row, mat->row, mat->n_row,
1304                                  dst_col + n, dst_col, src_col - dst_col);
1305                 isl_mat_sub_copy(res->ctx, res->row, mat->row, mat->n_row,
1306                                  src_col + n, src_col + n,
1307                                  res->n_col - src_col - n);
1308         } else {
1309                 isl_mat_sub_copy(res->ctx, res->row, mat->row, mat->n_row,
1310                                  0, 0, src_col);
1311                 isl_mat_sub_copy(res->ctx, res->row, mat->row, mat->n_row,
1312                                  src_col, src_col + n, dst_col - src_col);
1313                 isl_mat_sub_copy(res->ctx, res->row, mat->row, mat->n_row,
1314                                  dst_col, src_col, n);
1315                 isl_mat_sub_copy(res->ctx, res->row, mat->row, mat->n_row,
1316                                  dst_col + n, dst_col + n,
1317                                  res->n_col - dst_col - n);
1318         }
1319         isl_mat_free(mat);
1320
1321         return res;
1322 error:
1323         isl_mat_free(mat);
1324         return NULL;
1325 }
1326
1327 void isl_mat_gcd(__isl_keep isl_mat *mat, isl_int *gcd)
1328 {
1329         int i;
1330         isl_int g;
1331
1332         isl_int_set_si(*gcd, 0);
1333         if (!mat)
1334                 return;
1335
1336         isl_int_init(g);
1337         for (i = 0; i < mat->n_row; ++i) {
1338                 isl_seq_gcd(mat->row[i], mat->n_col, &g);
1339                 isl_int_gcd(*gcd, *gcd, g);
1340         }
1341         isl_int_clear(g);
1342 }
1343
1344 __isl_give isl_mat *isl_mat_scale_down(__isl_take isl_mat *mat, isl_int m)
1345 {
1346         int i;
1347
1348         if (!mat)
1349                 return NULL;
1350
1351         for (i = 0; i < mat->n_row; ++i)
1352                 isl_seq_scale_down(mat->row[i], mat->row[i], m, mat->n_col);
1353
1354         return mat;
1355 }
1356
1357 __isl_give isl_mat *isl_mat_normalize(__isl_take isl_mat *mat)
1358 {
1359         isl_int gcd;
1360
1361         if (!mat)
1362                 return NULL;
1363
1364         isl_int_init(gcd);
1365         isl_mat_gcd(mat, &gcd);
1366         mat = isl_mat_scale_down(mat, gcd);
1367         isl_int_clear(gcd);
1368
1369         return mat;
1370 }