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