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