plug memory leak in isl_mat_product
[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         return NULL;
532 }
533
534 struct isl_mat *isl_mat_right_kernel(struct isl_mat *mat)
535 {
536         int i, rank;
537         struct isl_mat *U = NULL;
538         struct isl_mat *K;
539
540         mat = isl_mat_left_hermite(mat, 0, &U, NULL);
541         if (!mat || !U)
542                 goto error;
543
544         for (i = 0, rank = 0; rank < mat->n_col; ++rank) {
545                 while (i < mat->n_row && isl_int_is_zero(mat->row[i][rank]))
546                         ++i;
547                 if (i >= mat->n_row)
548                         break;
549         }
550         K = isl_mat_alloc(U->ctx, U->n_row, U->n_col - rank);
551         if (!K)
552                 goto error;
553         isl_mat_sub_copy(K->ctx, K->row, U->row, U->n_row, 0, rank, U->n_col-rank);
554         isl_mat_free(mat);
555         isl_mat_free(U);
556         return K;
557 error:
558         isl_mat_free(mat);
559         isl_mat_free(U);
560         return NULL;
561 }
562
563 struct isl_mat *isl_mat_lin_to_aff(struct isl_mat *mat)
564 {
565         int i;
566         struct isl_mat *mat2;
567
568         if (!mat)
569                 return NULL;
570         mat2 = isl_mat_alloc(mat->ctx, 1+mat->n_row, 1+mat->n_col);
571         if (!mat2)
572                 goto error;
573         isl_int_set_si(mat2->row[0][0], 1);
574         isl_seq_clr(mat2->row[0]+1, mat->n_col);
575         for (i = 0; i < mat->n_row; ++i) {
576                 isl_int_set_si(mat2->row[1+i][0], 0);
577                 isl_seq_cpy(mat2->row[1+i]+1, mat->row[i], mat->n_col);
578         }
579         isl_mat_free(mat);
580         return mat2;
581 error:
582         isl_mat_free(mat);
583         return NULL;
584 }
585
586 /* Given two matrices M1 and M2, return the block matrix
587  *
588  *      [ M1  0  ]
589  *      [ 0   M2 ]
590  */
591 __isl_give isl_mat *isl_mat_diagonal(__isl_take isl_mat *mat1,
592         __isl_take isl_mat *mat2)
593 {
594         int i;
595         isl_mat *mat;
596
597         if (!mat1 || !mat2)
598                 goto error;
599
600         mat = isl_mat_alloc(mat1->ctx, mat1->n_row + mat2->n_row,
601                                        mat1->n_col + mat2->n_col);
602         if (!mat)
603                 goto error;
604         for (i = 0; i < mat1->n_row; ++i) {
605                 isl_seq_cpy(mat->row[i], mat1->row[i], mat1->n_col);
606                 isl_seq_clr(mat->row[i] + mat1->n_col, mat2->n_col);
607         }
608         for (i = 0; i < mat2->n_row; ++i) {
609                 isl_seq_clr(mat->row[mat1->n_row + i], mat1->n_col);
610                 isl_seq_cpy(mat->row[mat1->n_row + i] + mat1->n_col,
611                                                     mat2->row[i], mat2->n_col);
612         }
613         isl_mat_free(mat1);
614         isl_mat_free(mat2);
615         return mat;
616 error:
617         isl_mat_free(mat1);
618         isl_mat_free(mat2);
619         return NULL;
620 }
621
622 static int row_first_non_zero(isl_int **row, unsigned n_row, unsigned col)
623 {
624         int i;
625
626         for (i = 0; i < n_row; ++i)
627                 if (!isl_int_is_zero(row[i][col]))
628                         return i;
629         return -1;
630 }
631
632 static int row_abs_min_non_zero(isl_int **row, unsigned n_row, unsigned col)
633 {
634         int i, min = row_first_non_zero(row, n_row, col);
635         if (min < 0)
636                 return -1;
637         for (i = min + 1; i < n_row; ++i) {
638                 if (isl_int_is_zero(row[i][col]))
639                         continue;
640                 if (isl_int_abs_lt(row[i][col], row[min][col]))
641                         min = i;
642         }
643         return min;
644 }
645
646 static void inv_exchange(struct isl_mat *left, struct isl_mat *right,
647         unsigned i, unsigned j)
648 {
649         left = isl_mat_swap_rows(left, i, j);
650         right = isl_mat_swap_rows(right, i, j);
651 }
652
653 static void inv_oppose(
654         struct isl_mat *left, struct isl_mat *right, unsigned row)
655 {
656         isl_seq_neg(left->row[row]+row, left->row[row]+row, left->n_col-row);
657         isl_seq_neg(right->row[row], right->row[row], right->n_col);
658 }
659
660 static void inv_subtract(struct isl_mat *left, struct isl_mat *right,
661         unsigned row, unsigned i, isl_int m)
662 {
663         isl_int_neg(m, m);
664         isl_seq_combine(left->row[i]+row,
665                         left->ctx->one, left->row[i]+row,
666                         m, left->row[row]+row,
667                         left->n_col-row);
668         isl_seq_combine(right->row[i], right->ctx->one, right->row[i],
669                         m, right->row[row], right->n_col);
670 }
671
672 /* Compute inv(left)*right
673  */
674 struct isl_mat *isl_mat_inverse_product(struct isl_mat *left,
675         struct isl_mat *right)
676 {
677         int row;
678         isl_int a, b;
679
680         if (!left || !right)
681                 goto error;
682
683         isl_assert(left->ctx, left->n_row == left->n_col, goto error);
684         isl_assert(left->ctx, left->n_row == right->n_row, goto error);
685
686         if (left->n_row == 0) {
687                 isl_mat_free(left);
688                 return right;
689         }
690
691         left = isl_mat_cow(left);
692         right = isl_mat_cow(right);
693         if (!left || !right)
694                 goto error;
695
696         isl_int_init(a);
697         isl_int_init(b);
698         for (row = 0; row < left->n_row; ++row) {
699                 int pivot, first, i, off;
700                 pivot = row_abs_min_non_zero(left->row+row, left->n_row-row, row);
701                 if (pivot < 0) {
702                         isl_int_clear(a);
703                         isl_int_clear(b);
704                         isl_assert(left->ctx, pivot >= 0, goto error);
705                 }
706                 pivot += row;
707                 if (pivot != row)
708                         inv_exchange(left, right, pivot, row);
709                 if (isl_int_is_neg(left->row[row][row]))
710                         inv_oppose(left, right, row);
711                 first = row+1;
712                 while ((off = row_first_non_zero(left->row+first,
713                                         left->n_row-first, row)) != -1) {
714                         first += off;
715                         isl_int_fdiv_q(a, left->row[first][row],
716                                         left->row[row][row]);
717                         inv_subtract(left, right, row, first, a);
718                         if (!isl_int_is_zero(left->row[first][row]))
719                                 inv_exchange(left, right, row, first);
720                         else
721                                 ++first;
722                 }
723                 for (i = 0; i < row; ++i) {
724                         if (isl_int_is_zero(left->row[i][row]))
725                                 continue;
726                         isl_int_gcd(a, left->row[row][row], left->row[i][row]);
727                         isl_int_divexact(b, left->row[i][row], a);
728                         isl_int_divexact(a, left->row[row][row], a);
729                         isl_int_neg(b, b);
730                         isl_seq_combine(left->row[i] + i,
731                                         a, left->row[i] + i,
732                                         b, left->row[row] + i,
733                                         left->n_col - i);
734                         isl_seq_combine(right->row[i], a, right->row[i],
735                                         b, right->row[row], right->n_col);
736                 }
737         }
738         isl_int_clear(b);
739
740         isl_int_set(a, left->row[0][0]);
741         for (row = 1; row < left->n_row; ++row)
742                 isl_int_lcm(a, a, left->row[row][row]);
743         if (isl_int_is_zero(a)){
744                 isl_int_clear(a);
745                 isl_assert(left->ctx, 0, goto error);
746         }
747         for (row = 0; row < left->n_row; ++row) {
748                 isl_int_divexact(left->row[row][row], a, left->row[row][row]);
749                 if (isl_int_is_one(left->row[row][row]))
750                         continue;
751                 isl_seq_scale(right->row[row], right->row[row],
752                                 left->row[row][row], right->n_col);
753         }
754         isl_int_clear(a);
755
756         isl_mat_free(left);
757         return right;
758 error:
759         isl_mat_free(left);
760         isl_mat_free(right);
761         return NULL;
762 }
763
764 void isl_mat_col_scale(struct isl_mat *mat, unsigned col, isl_int m)
765 {
766         int i;
767
768         for (i = 0; i < mat->n_row; ++i)
769                 isl_int_mul(mat->row[i][col], mat->row[i][col], m);
770 }
771
772 void isl_mat_col_combine(struct isl_mat *mat, unsigned dst,
773         isl_int m1, unsigned src1, isl_int m2, unsigned src2)
774 {
775         int i;
776         isl_int tmp;
777
778         isl_int_init(tmp);
779         for (i = 0; i < mat->n_row; ++i) {
780                 isl_int_mul(tmp, m1, mat->row[i][src1]);
781                 isl_int_addmul(tmp, m2, mat->row[i][src2]);
782                 isl_int_set(mat->row[i][dst], tmp);
783         }
784         isl_int_clear(tmp);
785 }
786
787 struct isl_mat *isl_mat_right_inverse(struct isl_mat *mat)
788 {
789         struct isl_mat *inv;
790         int row;
791         isl_int a, b;
792
793         mat = isl_mat_cow(mat);
794         if (!mat)
795                 return NULL;
796
797         inv = isl_mat_identity(mat->ctx, mat->n_col);
798         inv = isl_mat_cow(inv);
799         if (!inv)
800                 goto error;
801
802         isl_int_init(a);
803         isl_int_init(b);
804         for (row = 0; row < mat->n_row; ++row) {
805                 int pivot, first, i, off;
806                 pivot = isl_seq_abs_min_non_zero(mat->row[row]+row, mat->n_col-row);
807                 if (pivot < 0) {
808                         isl_int_clear(a);
809                         isl_int_clear(b);
810                         isl_assert(mat->ctx, pivot >= 0, goto error);
811                 }
812                 pivot += row;
813                 if (pivot != row)
814                         exchange(mat, &inv, NULL, row, pivot, row);
815                 if (isl_int_is_neg(mat->row[row][row]))
816                         oppose(mat, &inv, NULL, row, row);
817                 first = row+1;
818                 while ((off = isl_seq_first_non_zero(mat->row[row]+first,
819                                                     mat->n_col-first)) != -1) {
820                         first += off;
821                         isl_int_fdiv_q(a, mat->row[row][first],
822                                                     mat->row[row][row]);
823                         subtract(mat, &inv, NULL, row, row, first, a);
824                         if (!isl_int_is_zero(mat->row[row][first]))
825                                 exchange(mat, &inv, NULL, row, row, first);
826                         else
827                                 ++first;
828                 }
829                 for (i = 0; i < row; ++i) {
830                         if (isl_int_is_zero(mat->row[row][i]))
831                                 continue;
832                         isl_int_gcd(a, mat->row[row][row], mat->row[row][i]);
833                         isl_int_divexact(b, mat->row[row][i], a);
834                         isl_int_divexact(a, mat->row[row][row], a);
835                         isl_int_neg(a, a);
836                         isl_mat_col_combine(mat, i, a, i, b, row);
837                         isl_mat_col_combine(inv, i, a, i, b, row);
838                 }
839         }
840         isl_int_clear(b);
841
842         isl_int_set(a, mat->row[0][0]);
843         for (row = 1; row < mat->n_row; ++row)
844                 isl_int_lcm(a, a, mat->row[row][row]);
845         if (isl_int_is_zero(a)){
846                 isl_int_clear(a);
847                 goto error;
848         }
849         for (row = 0; row < mat->n_row; ++row) {
850                 isl_int_divexact(mat->row[row][row], a, mat->row[row][row]);
851                 if (isl_int_is_one(mat->row[row][row]))
852                         continue;
853                 isl_mat_col_scale(inv, row, mat->row[row][row]);
854         }
855         isl_int_clear(a);
856
857         isl_mat_free(mat);
858
859         return inv;
860 error:
861         isl_mat_free(mat);
862         isl_mat_free(inv);
863         return NULL;
864 }
865
866 struct isl_mat *isl_mat_transpose(struct isl_mat *mat)
867 {
868         struct isl_mat *transpose = NULL;
869         int i, j;
870
871         if (mat->n_col == mat->n_row) {
872                 mat = isl_mat_cow(mat);
873                 if (!mat)
874                         return NULL;
875                 for (i = 0; i < mat->n_row; ++i)
876                         for (j = i + 1; j < mat->n_col; ++j)
877                                 isl_int_swap(mat->row[i][j], mat->row[j][i]);
878                 return mat;
879         }
880         transpose = isl_mat_alloc(mat->ctx, mat->n_col, mat->n_row);
881         if (!transpose)
882                 goto error;
883         for (i = 0; i < mat->n_row; ++i)
884                 for (j = 0; j < mat->n_col; ++j)
885                         isl_int_set(transpose->row[j][i], mat->row[i][j]);
886         isl_mat_free(mat);
887         return transpose;
888 error:
889         isl_mat_free(mat);
890         return NULL;
891 }
892
893 struct isl_mat *isl_mat_swap_cols(struct isl_mat *mat, unsigned i, unsigned j)
894 {
895         int r;
896
897         mat = isl_mat_cow(mat);
898         if (!mat)
899                 return NULL;
900         isl_assert(mat->ctx, i < mat->n_col, goto error);
901         isl_assert(mat->ctx, j < mat->n_col, goto error);
902
903         for (r = 0; r < mat->n_row; ++r)
904                 isl_int_swap(mat->row[r][i], mat->row[r][j]);
905         return mat;
906 error:
907         isl_mat_free(mat);
908         return NULL;
909 }
910
911 struct isl_mat *isl_mat_swap_rows(struct isl_mat *mat, unsigned i, unsigned j)
912 {
913         isl_int *t;
914
915         if (!mat)
916                 return NULL;
917         mat = isl_mat_cow(mat);
918         if (!mat)
919                 return NULL;
920         t = mat->row[i];
921         mat->row[i] = mat->row[j];
922         mat->row[j] = t;
923         return mat;
924 }
925
926 struct isl_mat *isl_mat_product(struct isl_mat *left, struct isl_mat *right)
927 {
928         int i, j, k;
929         struct isl_mat *prod;
930
931         if (!left || !right)
932                 goto error;
933         isl_assert(left->ctx, left->n_col == right->n_row, goto error);
934         prod = isl_mat_alloc(left->ctx, left->n_row, right->n_col);
935         if (!prod)
936                 goto error;
937         if (left->n_col == 0) {
938                 for (i = 0; i < prod->n_row; ++i)
939                         isl_seq_clr(prod->row[i], prod->n_col);
940                 isl_mat_free(left);
941                 isl_mat_free(right);
942                 return prod;
943         }
944         for (i = 0; i < prod->n_row; ++i) {
945                 for (j = 0; j < prod->n_col; ++j) {
946                         isl_int_mul(prod->row[i][j],
947                                     left->row[i][0], right->row[0][j]);
948                         for (k = 1; k < left->n_col; ++k)
949                                 isl_int_addmul(prod->row[i][j],
950                                             left->row[i][k], right->row[k][j]);
951                 }
952         }
953         isl_mat_free(left);
954         isl_mat_free(right);
955         return prod;
956 error:
957         isl_mat_free(left);
958         isl_mat_free(right);
959         return NULL;
960 }
961
962 /* Replace the variables x in the rows q by x' given by x = M x',
963  * with M the matrix mat.
964  *
965  * If the number of new variables is greater than the original
966  * number of variables, then the rows q have already been
967  * preextended.  If the new number is smaller, then the coefficients
968  * of the divs, which are not changed, need to be shifted down.
969  * The row q may be the equalities, the inequalities or the
970  * div expressions.  In the latter case, has_div is true and
971  * we need to take into account the extra denominator column.
972  */
973 static int preimage(struct isl_ctx *ctx, isl_int **q, unsigned n,
974         unsigned n_div, int has_div, struct isl_mat *mat)
975 {
976         int i;
977         struct isl_mat *t;
978         int e;
979
980         if (mat->n_col >= mat->n_row)
981                 e = 0;
982         else
983                 e = mat->n_row - mat->n_col;
984         if (has_div)
985                 for (i = 0; i < n; ++i)
986                         isl_int_mul(q[i][0], q[i][0], mat->row[0][0]);
987         t = isl_mat_sub_alloc(mat->ctx, q, 0, n, has_div, mat->n_row);
988         t = isl_mat_product(t, mat);
989         if (!t)
990                 return -1;
991         for (i = 0; i < n; ++i) {
992                 isl_seq_swp_or_cpy(q[i] + has_div, t->row[i], t->n_col);
993                 isl_seq_cpy(q[i] + has_div + t->n_col,
994                             q[i] + has_div + t->n_col + e, n_div);
995                 isl_seq_clr(q[i] + has_div + t->n_col + n_div, e);
996         }
997         isl_mat_free(t);
998         return 0;
999 }
1000
1001 /* Replace the variables x in bset by x' given by x = M x', with
1002  * M the matrix mat.
1003  *
1004  * If there are fewer variables x' then there are x, then we perform
1005  * the transformation in place, which that, in principle,
1006  * this frees up some extra variables as the number
1007  * of columns remains constant, but we would have to extend
1008  * the div array too as the number of rows in this array is assumed
1009  * to be equal to extra.
1010  */
1011 struct isl_basic_set *isl_basic_set_preimage(struct isl_basic_set *bset,
1012         struct isl_mat *mat)
1013 {
1014         struct isl_ctx *ctx;
1015
1016         if (!bset || !mat)
1017                 goto error;
1018
1019         ctx = bset->ctx;
1020         bset = isl_basic_set_cow(bset);
1021         if (!bset)
1022                 goto error;
1023
1024         isl_assert(ctx, bset->dim->nparam == 0, goto error);
1025         isl_assert(ctx, 1+bset->dim->n_out == mat->n_row, goto error);
1026         isl_assert(ctx, mat->n_col > 0, goto error);
1027
1028         if (mat->n_col > mat->n_row) {
1029                 bset = isl_basic_set_extend(bset, 0, mat->n_col-1, 0, 0, 0);
1030                 if (!bset)
1031                         goto error;
1032         } else if (mat->n_col < mat->n_row) {
1033                 bset->dim = isl_dim_cow(bset->dim);
1034                 if (!bset->dim)
1035                         goto error;
1036                 bset->dim->n_out -= mat->n_row - mat->n_col;
1037         }
1038
1039         if (preimage(ctx, bset->eq, bset->n_eq, bset->n_div, 0,
1040                         isl_mat_copy(mat)) < 0)
1041                 goto error;
1042
1043         if (preimage(ctx, bset->ineq, bset->n_ineq, bset->n_div, 0,
1044                         isl_mat_copy(mat)) < 0)
1045                 goto error;
1046
1047         if (preimage(ctx, bset->div, bset->n_div, bset->n_div, 1, mat) < 0)
1048                 goto error2;
1049
1050         ISL_F_CLR(bset, ISL_BASIC_SET_NO_IMPLICIT);
1051         ISL_F_CLR(bset, ISL_BASIC_SET_NO_REDUNDANT);
1052         ISL_F_CLR(bset, ISL_BASIC_SET_NORMALIZED);
1053         ISL_F_CLR(bset, ISL_BASIC_SET_NORMALIZED_DIVS);
1054         ISL_F_CLR(bset, ISL_BASIC_SET_ALL_EQUALITIES);
1055
1056         bset = isl_basic_set_simplify(bset);
1057         bset = isl_basic_set_finalize(bset);
1058
1059         return bset;
1060 error:
1061         isl_mat_free(mat);
1062 error2:
1063         isl_basic_set_free(bset);
1064         return NULL;
1065 }
1066
1067 struct isl_set *isl_set_preimage(struct isl_set *set, struct isl_mat *mat)
1068 {
1069         struct isl_ctx *ctx;
1070         int i;
1071
1072         set = isl_set_cow(set);
1073         if (!set)
1074                 return NULL;
1075
1076         ctx = set->ctx;
1077         for (i = 0; i < set->n; ++i) {
1078                 set->p[i] = isl_basic_set_preimage(set->p[i],
1079                                                     isl_mat_copy(mat));
1080                 if (!set->p[i])
1081                         goto error;
1082         }
1083         if (mat->n_col != mat->n_row) {
1084                 set->dim = isl_dim_cow(set->dim);
1085                 if (!set->dim)
1086                         goto error;
1087                 set->dim->n_out += mat->n_col;
1088                 set->dim->n_out -= mat->n_row;
1089         }
1090         isl_mat_free(mat);
1091         ISL_F_CLR(set, ISL_SET_NORMALIZED);
1092         return set;
1093 error:
1094         isl_set_free(set);
1095         isl_mat_free(mat);
1096         return NULL;
1097 }
1098
1099 void isl_mat_dump(struct isl_mat *mat, FILE *out, int indent)
1100 {
1101         int i, j;
1102
1103         if (!mat) {
1104                 fprintf(out, "%*snull mat\n", indent, "");
1105                 return;
1106         }
1107
1108         if (mat->n_row == 0)
1109                 fprintf(out, "%*s[]\n", indent, "");
1110
1111         for (i = 0; i < mat->n_row; ++i) {
1112                 if (!i)
1113                         fprintf(out, "%*s[[", indent, "");
1114                 else
1115                         fprintf(out, "%*s[", indent+1, "");
1116                 for (j = 0; j < mat->n_col; ++j) {
1117                         if (j)
1118                             fprintf(out, ",");
1119                         isl_int_print(out, mat->row[i][j], 0);
1120                 }
1121                 if (i == mat->n_row-1)
1122                         fprintf(out, "]]\n");
1123                 else
1124                         fprintf(out, "]\n");
1125         }
1126 }
1127
1128 struct isl_mat *isl_mat_drop_cols(struct isl_mat *mat, unsigned col, unsigned n)
1129 {
1130         int r;
1131
1132         mat = isl_mat_cow(mat);
1133         if (!mat)
1134                 return NULL;
1135
1136         if (col != mat->n_col-n) {
1137                 for (r = 0; r < mat->n_row; ++r)
1138                         isl_seq_cpy(mat->row[r]+col, mat->row[r]+col+n,
1139                                         mat->n_col - col - n);
1140         }
1141         mat->n_col -= n;
1142         return mat;
1143 }
1144
1145 struct isl_mat *isl_mat_drop_rows(struct isl_mat *mat, unsigned row, unsigned n)
1146 {
1147         int r;
1148
1149         mat = isl_mat_cow(mat);
1150         if (!mat)
1151                 return NULL;
1152
1153         for (r = row; r+n < mat->n_row; ++r)
1154                 mat->row[r] = mat->row[r+n];
1155
1156         mat->n_row -= n;
1157         return mat;
1158 }
1159
1160 __isl_give isl_mat *isl_mat_insert_cols(__isl_take isl_mat *mat,
1161                                 unsigned col, unsigned n)
1162 {
1163         isl_mat *ext;
1164
1165         if (!mat)
1166                 return NULL;
1167         if (n == 0)
1168                 return mat;
1169
1170         ext = isl_mat_alloc(mat->ctx, mat->n_row, mat->n_col + n);
1171         if (!ext)
1172                 goto error;
1173
1174         isl_mat_sub_copy(mat->ctx, ext->row, mat->row, mat->n_row, 0, 0, col);
1175         isl_mat_sub_copy(mat->ctx, ext->row, mat->row, mat->n_row,
1176                                 col + n, col, mat->n_col - col);
1177
1178         isl_mat_free(mat);
1179         return ext;
1180 error:
1181         isl_mat_free(mat);
1182         return NULL;
1183 }
1184
1185 __isl_give isl_mat *isl_mat_insert_zero_cols(__isl_take isl_mat *mat,
1186         unsigned first, unsigned n)
1187 {
1188         int i;
1189
1190         if (!mat)
1191                 return NULL;
1192         mat = isl_mat_insert_cols(mat, first, n);
1193         if (!mat)
1194                 return NULL;
1195
1196         for (i = 0; i < mat->n_row; ++i)
1197                 isl_seq_clr(mat->row[i] + first, n);
1198
1199         return mat;
1200 }
1201
1202 __isl_give isl_mat *isl_mat_add_zero_cols(__isl_take isl_mat *mat, unsigned n)
1203 {
1204         if (!mat)
1205                 return NULL;
1206
1207         return isl_mat_insert_zero_cols(mat, mat->n_col, n);
1208 }
1209
1210 __isl_give isl_mat *isl_mat_insert_rows(__isl_take isl_mat *mat,
1211                                 unsigned row, unsigned n)
1212 {
1213         isl_mat *ext;
1214
1215         if (!mat)
1216                 return NULL;
1217         if (n == 0)
1218                 return mat;
1219
1220         ext = isl_mat_alloc(mat->ctx, mat->n_row + n, mat->n_col);
1221         if (!ext)
1222                 goto error;
1223
1224         isl_mat_sub_copy(mat->ctx, ext->row, mat->row, row, 0, 0, mat->n_col);
1225         isl_mat_sub_copy(mat->ctx, ext->row + row + n, mat->row + row,
1226                                 mat->n_row - row, 0, 0, mat->n_col);
1227
1228         isl_mat_free(mat);
1229         return ext;
1230 error:
1231         isl_mat_free(mat);
1232         return NULL;
1233 }
1234
1235 __isl_give isl_mat *isl_mat_add_rows(__isl_take isl_mat *mat, unsigned n)
1236 {
1237         if (!mat)
1238                 return NULL;
1239
1240         return isl_mat_insert_rows(mat, mat->n_row, n);
1241 }
1242
1243 void isl_mat_col_submul(struct isl_mat *mat,
1244                         int dst_col, isl_int f, int src_col)
1245 {
1246         int i;
1247
1248         for (i = 0; i < mat->n_row; ++i)
1249                 isl_int_submul(mat->row[i][dst_col], f, mat->row[i][src_col]);
1250 }
1251
1252 void isl_mat_col_add(__isl_keep isl_mat *mat, int dst_col, int src_col)
1253 {
1254         int i;
1255
1256         if (!mat)
1257                 return;
1258
1259         for (i = 0; i < mat->n_row; ++i)
1260                 isl_int_add(mat->row[i][dst_col],
1261                             mat->row[i][dst_col], mat->row[i][src_col]);
1262 }
1263
1264 void isl_mat_col_mul(struct isl_mat *mat, 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_mul(mat->row[i][dst_col], f, mat->row[i][src_col]);
1270 }
1271
1272 struct isl_mat *isl_mat_unimodular_complete(struct isl_mat *M, int row)
1273 {
1274         int r;
1275         struct isl_mat *H = NULL, *Q = NULL;
1276
1277         if (!M)
1278                 return NULL;
1279
1280         isl_assert(M->ctx, M->n_row == M->n_col, goto error);
1281         M->n_row = row;
1282         H = isl_mat_left_hermite(isl_mat_copy(M), 0, NULL, &Q);
1283         M->n_row = M->n_col;
1284         if (!H)
1285                 goto error;
1286         for (r = 0; r < row; ++r)
1287                 isl_assert(M->ctx, isl_int_is_one(H->row[r][r]), goto error);
1288         for (r = row; r < M->n_row; ++r)
1289                 isl_seq_cpy(M->row[r], Q->row[r], M->n_col);
1290         isl_mat_free(H);
1291         isl_mat_free(Q);
1292         return M;
1293 error:
1294         isl_mat_free(H);
1295         isl_mat_free(Q);
1296         isl_mat_free(M);
1297         return NULL;
1298 }
1299
1300 __isl_give isl_mat *isl_mat_concat(__isl_take isl_mat *top,
1301         __isl_take isl_mat *bot)
1302 {
1303         struct isl_mat *mat;
1304
1305         if (!top || !bot)
1306                 goto error;
1307
1308         isl_assert(top->ctx, top->n_col == bot->n_col, goto error);
1309         if (top->n_row == 0) {
1310                 isl_mat_free(top);
1311                 return bot;
1312         }
1313         if (bot->n_row == 0) {
1314                 isl_mat_free(bot);
1315                 return top;
1316         }
1317
1318         mat = isl_mat_alloc(top->ctx, top->n_row + bot->n_row, top->n_col);
1319         if (!mat)
1320                 goto error;
1321         isl_mat_sub_copy(mat->ctx, mat->row, top->row, top->n_row,
1322                          0, 0, mat->n_col);
1323         isl_mat_sub_copy(mat->ctx, mat->row + top->n_row, bot->row, bot->n_row,
1324                          0, 0, mat->n_col);
1325         isl_mat_free(top);
1326         isl_mat_free(bot);
1327         return mat;
1328 error:
1329         isl_mat_free(top);
1330         isl_mat_free(bot);
1331         return NULL;
1332 }
1333
1334 int isl_mat_is_equal(__isl_keep isl_mat *mat1, __isl_keep isl_mat *mat2)
1335 {
1336         int i;
1337
1338         if (!mat1 || !mat2)
1339                 return -1;
1340
1341         if (mat1->n_row != mat2->n_row)
1342                 return 0;
1343
1344         if (mat1->n_col != mat2->n_col)
1345                 return 0;
1346
1347         for (i = 0; i < mat1->n_row; ++i)
1348                 if (!isl_seq_eq(mat1->row[i], mat2->row[i], mat1->n_col))
1349                         return 0;
1350
1351         return 1;
1352 }
1353
1354 __isl_give isl_mat *isl_mat_from_row_vec(__isl_take isl_vec *vec)
1355 {
1356         struct isl_mat *mat;
1357
1358         if (!vec)
1359                 return NULL;
1360         mat = isl_mat_alloc(vec->ctx, 1, vec->size);
1361         if (!mat)
1362                 goto error;
1363
1364         isl_seq_cpy(mat->row[0], vec->el, vec->size);
1365
1366         isl_vec_free(vec);
1367         return mat;
1368 error:
1369         isl_vec_free(vec);
1370         return NULL;
1371 }
1372
1373 __isl_give isl_mat *isl_mat_vec_concat(__isl_take isl_mat *top,
1374         __isl_take isl_vec *bot)
1375 {
1376         return isl_mat_concat(top, isl_mat_from_row_vec(bot));
1377 }
1378
1379 __isl_give isl_mat *isl_mat_move_cols(__isl_take isl_mat *mat,
1380         unsigned dst_col, unsigned src_col, unsigned n)
1381 {
1382         isl_mat *res;
1383
1384         if (!mat)
1385                 return NULL;
1386         if (n == 0 || dst_col == src_col)
1387                 return mat;
1388
1389         res = isl_mat_alloc(mat->ctx, mat->n_row, mat->n_col);
1390         if (!res)
1391                 goto error;
1392
1393         if (dst_col < src_col) {
1394                 isl_mat_sub_copy(res->ctx, res->row, mat->row, mat->n_row,
1395                                  0, 0, dst_col);
1396                 isl_mat_sub_copy(res->ctx, res->row, mat->row, mat->n_row,
1397                                  dst_col, src_col, n);
1398                 isl_mat_sub_copy(res->ctx, res->row, mat->row, mat->n_row,
1399                                  dst_col + n, dst_col, src_col - dst_col);
1400                 isl_mat_sub_copy(res->ctx, res->row, mat->row, mat->n_row,
1401                                  src_col + n, src_col + n,
1402                                  res->n_col - src_col - n);
1403         } else {
1404                 isl_mat_sub_copy(res->ctx, res->row, mat->row, mat->n_row,
1405                                  0, 0, src_col);
1406                 isl_mat_sub_copy(res->ctx, res->row, mat->row, mat->n_row,
1407                                  src_col, src_col + n, dst_col - src_col);
1408                 isl_mat_sub_copy(res->ctx, res->row, mat->row, mat->n_row,
1409                                  dst_col, src_col, n);
1410                 isl_mat_sub_copy(res->ctx, res->row, mat->row, mat->n_row,
1411                                  dst_col + n, dst_col + n,
1412                                  res->n_col - dst_col - n);
1413         }
1414         isl_mat_free(mat);
1415
1416         return res;
1417 error:
1418         isl_mat_free(mat);
1419         return NULL;
1420 }
1421
1422 void isl_mat_gcd(__isl_keep isl_mat *mat, isl_int *gcd)
1423 {
1424         int i;
1425         isl_int g;
1426
1427         isl_int_set_si(*gcd, 0);
1428         if (!mat)
1429                 return;
1430
1431         isl_int_init(g);
1432         for (i = 0; i < mat->n_row; ++i) {
1433                 isl_seq_gcd(mat->row[i], mat->n_col, &g);
1434                 isl_int_gcd(*gcd, *gcd, g);
1435         }
1436         isl_int_clear(g);
1437 }
1438
1439 __isl_give isl_mat *isl_mat_scale_down(__isl_take isl_mat *mat, isl_int m)
1440 {
1441         int i;
1442
1443         if (!mat)
1444                 return NULL;
1445
1446         for (i = 0; i < mat->n_row; ++i)
1447                 isl_seq_scale_down(mat->row[i], mat->row[i], m, mat->n_col);
1448
1449         return mat;
1450 }
1451
1452 __isl_give isl_mat *isl_mat_normalize(__isl_take isl_mat *mat)
1453 {
1454         isl_int gcd;
1455
1456         if (!mat)
1457                 return NULL;
1458
1459         isl_int_init(gcd);
1460         isl_mat_gcd(mat, &gcd);
1461         mat = isl_mat_scale_down(mat, gcd);
1462         isl_int_clear(gcd);
1463
1464         return mat;
1465 }