Polly 20.0.0git
isl_factorization.c
Go to the documentation of this file.
1/*
2 * Copyright 2005-2007 Universiteit Leiden
3 * Copyright 2008-2009 Katholieke Universiteit Leuven
4 * Copyright 2010 INRIA Saclay
5 *
6 * Use of this software is governed by the MIT license
7 *
8 * Written by Sven Verdoolaege, Leiden Institute of Advanced Computer Science,
9 * Universiteit Leiden, Niels Bohrweg 1, 2333 CA Leiden, The Netherlands
10 * and K.U.Leuven, Departement Computerwetenschappen, Celestijnenlaan 200A,
11 * B-3001 Leuven, Belgium
12 * and INRIA Saclay - Ile-de-France, Parc Club Orsay Universite,
13 * ZAC des vignes, 4 rue Jacques Monod, 91893 Orsay, France
14 */
15
16#include <isl_map_private.h>
17#include <isl_factorization.h>
18#include <isl_space_private.h>
19#include <isl_mat_private.h>
20
21/* Return the isl_ctx to which "f" belongs.
22 */
24{
25 if (!f)
26 return NULL;
27 return isl_basic_set_get_ctx(f->bset);
28}
29
32 int n_group)
33{
34 isl_factorizer *f = NULL;
35 int *len = NULL;
36
37 if (!morph)
38 return NULL;
39
40 if (n_group > 0) {
41 len = isl_alloc_array(morph->dom->ctx, int, n_group);
42 if (!len)
43 goto error;
44 }
45
46 f = isl_alloc_type(morph->dom->ctx, struct isl_factorizer);
47 if (!f)
48 goto error;
49
50 f->bset = isl_basic_set_copy(bset);
51 f->morph = morph;
52 f->n_group = n_group;
53 f->len = len;
54
55 return f;
56error:
57 free(len);
58 isl_morph_free(morph);
59 return NULL;
60}
61
63{
64 if (!f)
65 return NULL;
66
67 isl_basic_set_free(f->bset);
68 isl_morph_free(f->morph);
69 free(f->len);
70 free(f);
71 return NULL;
72}
73
75{
76 int i;
77
78 if (!f)
79 return;
80
81 isl_morph_print_internal(f->morph, stderr);
82 fprintf(stderr, "[");
83 for (i = 0; i < f->n_group; ++i) {
84 if (i)
85 fprintf(stderr, ", ");
86 fprintf(stderr, "%d", f->len[i]);
87 }
88 fprintf(stderr, "]\n");
89}
90
92{
93 return isl_factorizer_alloc(bset, isl_morph_identity(bset), 0);
94}
95
97 __isl_take isl_mat *Q, __isl_take isl_mat *U, int n, int *len)
98{
99 int i;
100 isl_size nvar;
101 unsigned ovar;
102 isl_space *space;
103 isl_basic_set *dom;
104 isl_basic_set *ran;
105 isl_morph *morph;
107 isl_mat *id;
108
109 nvar = isl_basic_set_dim(bset, isl_dim_set);
110 if (nvar < 0 || !Q || !U)
111 goto error;
112
113 ovar = 1 + isl_space_offset(bset->dim, isl_dim_set);
114 id = isl_mat_identity(bset->ctx, ovar);
115 Q = isl_mat_diagonal(isl_mat_copy(id), Q);
116 U = isl_mat_diagonal(id, U);
117
118 space = isl_basic_set_get_space(bset);
120 space = isl_space_drop_dims(space, isl_dim_set, 0, nvar);
121 space = isl_space_add_dims(space, isl_dim_set, nvar);
122 ran = isl_basic_set_universe(space);
123 morph = isl_morph_alloc(dom, ran, Q, U);
124 f = isl_factorizer_alloc(bset, morph, n);
125 if (!f)
126 return NULL;
127 for (i = 0; i < n; ++i)
128 f->len[i] = len[i];
129 return f;
130error:
131 isl_mat_free(Q);
132 isl_mat_free(U);
133 return NULL;
134}
135
137 int *pos; /* for each column: row position of pivot */
138 int *group; /* group to which a column belongs */
139 int *cnt; /* number of columns in the group */
140 int *rowgroup; /* group to which a constraint belongs */
141};
142
143/* Initialize isl_factor_groups structure: find pivot row positions,
144 * each column initially belongs to its own group and the groups
145 * of the constraints are still unknown.
146 */
148{
149 int i, j;
150
151 if (!H)
152 return -1;
153
154 g->pos = isl_alloc_array(H->ctx, int, H->n_col);
155 g->group = isl_alloc_array(H->ctx, int, H->n_col);
156 g->cnt = isl_alloc_array(H->ctx, int, H->n_col);
157 g->rowgroup = isl_alloc_array(H->ctx, int, H->n_row);
158
159 if (!g->pos || !g->group || !g->cnt || !g->rowgroup)
160 return -1;
161
162 for (i = 0; i < H->n_row; ++i)
163 g->rowgroup[i] = -1;
164 for (i = 0, j = 0; i < H->n_col; ++i) {
165 for ( ; j < H->n_row; ++j)
166 if (!isl_int_is_zero(H->row[j][i]))
167 break;
168 g->pos[i] = j;
169 }
170 for (i = 0; i < H->n_col; ++i) {
171 g->group[i] = i;
172 g->cnt[i] = 1;
173 }
174
175 return 0;
176}
177
178/* Update group[k] to the group column k belongs to.
179 * When merging two groups, only the group of the current
180 * group leader is changed. Here we change the group of
181 * the other members to also point to the group that the
182 * old group leader now points to.
183 */
184static void update_group(struct isl_factor_groups *g, int k)
185{
186 int p = g->group[k];
187 while (g->cnt[p] == 0)
188 p = g->group[p];
189 g->group[k] = p;
190}
191
192/* Merge group i with all groups of the subsequent columns
193 * with non-zero coefficients in row j of H.
194 * (The previous columns are all zero; otherwise we would have handled
195 * the row before.)
196 */
197static int update_group_i_with_row_j(struct isl_factor_groups *g, int i, int j,
199{
200 int k;
201
202 g->rowgroup[j] = g->group[i];
203 for (k = i + 1; k < H->n_col && j >= g->pos[k]; ++k) {
204 update_group(g, k);
205 update_group(g, i);
206 if (g->group[k] != g->group[i] &&
207 !isl_int_is_zero(H->row[j][k])) {
208 isl_assert(H->ctx, g->cnt[g->group[k]] != 0, return -1);
209 isl_assert(H->ctx, g->cnt[g->group[i]] != 0, return -1);
210 if (g->group[i] < g->group[k]) {
211 g->cnt[g->group[i]] += g->cnt[g->group[k]];
212 g->cnt[g->group[k]] = 0;
213 g->group[g->group[k]] = g->group[i];
214 } else {
215 g->cnt[g->group[k]] += g->cnt[g->group[i]];
216 g->cnt[g->group[i]] = 0;
217 g->group[g->group[i]] = g->group[k];
218 }
219 }
220 }
221
222 return 0;
223}
224
225/* Update the group information based on the constraint matrix.
226 */
228{
229 int i, j;
230
231 for (i = 0; i < H->n_col && g->cnt[0] < H->n_col; ++i) {
232 if (g->pos[i] == H->n_row)
233 continue; /* A line direction */
234 if (g->rowgroup[g->pos[i]] == -1)
235 g->rowgroup[g->pos[i]] = i;
236 for (j = g->pos[i] + 1; j < H->n_row; ++j) {
237 if (isl_int_is_zero(H->row[j][i]))
238 continue;
239 if (g->rowgroup[j] != -1)
240 continue;
241 if (update_group_i_with_row_j(g, i, j, H) < 0)
242 return -1;
243 }
244 }
245 for (i = 1; i < H->n_col; ++i)
246 update_group(g, i);
247
248 return 0;
249}
250
251static void clear_groups(struct isl_factor_groups *g)
252{
253 if (!g)
254 return;
255 free(g->pos);
256 free(g->group);
257 free(g->cnt);
258 free(g->rowgroup);
259}
260
261/* Determine if the set variables of the basic set can be factorized and
262 * return the results in an isl_factorizer.
263 *
264 * The algorithm works by first computing the Hermite normal form
265 * and then grouping columns linked by one or more constraints together,
266 * where a constraints "links" two or more columns if the constraint
267 * has nonzero coefficients in the columns.
268 */
271{
272 int i, j, n, done;
273 isl_mat *H, *U, *Q;
274 isl_size nvar;
275 struct isl_factor_groups g = { 0 };
277
278 nvar = isl_basic_set_dim(bset, isl_dim_set);
279 if (nvar < 0 || isl_basic_set_check_no_locals(bset) < 0)
280 return NULL;
281
282 if (nvar <= 1)
283 return isl_factorizer_identity(bset);
284
285 H = isl_mat_alloc(bset->ctx, bset->n_eq + bset->n_ineq, nvar);
286 if (!H)
287 return NULL;
288 isl_mat_sub_copy(bset->ctx, H->row, bset->eq, bset->n_eq,
289 0, 1 + isl_space_offset(bset->dim, isl_dim_set), nvar);
290 isl_mat_sub_copy(bset->ctx, H->row + bset->n_eq, bset->ineq, bset->n_ineq,
291 0, 1 + isl_space_offset(bset->dim, isl_dim_set), nvar);
292 H = isl_mat_left_hermite(H, 0, &U, &Q);
293
294 if (init_groups(&g, H) < 0)
295 goto error;
296 if (update_groups(&g, H) < 0)
297 goto error;
298
299 if (g.cnt[0] == nvar) {
300 isl_mat_free(H);
301 isl_mat_free(U);
302 isl_mat_free(Q);
303 clear_groups(&g);
304
305 return isl_factorizer_identity(bset);
306 }
307
308 done = 0;
309 n = 0;
310 while (done != nvar) {
311 int group = g.group[done];
312 for (i = 1; i < g.cnt[group]; ++i) {
313 if (g.group[done + i] == group)
314 continue;
315 for (j = done + g.cnt[group]; j < nvar; ++j)
316 if (g.group[j] == group)
317 break;
318 if (j == nvar)
319 isl_die(bset->ctx, isl_error_internal,
320 "internal error", goto error);
321 g.group[j] = g.group[done + i];
322 Q = isl_mat_swap_rows(Q, done + i, j);
323 U = isl_mat_swap_cols(U, done + i, j);
324 }
325 done += g.cnt[group];
326 g.pos[n++] = g.cnt[group];
327 }
328
329 f = isl_factorizer_groups(bset, Q, U, n, g.pos);
330
331 isl_mat_free(H);
332 clear_groups(&g);
333
334 return f;
335error:
336 isl_mat_free(H);
337 isl_mat_free(U);
338 isl_mat_free(Q);
339 clear_groups(&g);
340 return NULL;
341}
342
343/* Given the factorizer "f" of a basic set,
344 * call "test" on each resulting factor as long as each call succeeds.
345 */
348 isl_bool (*test)(__isl_keep isl_basic_set *bset, void *user),
349 void *user)
350{
351 int i, n;
352 isl_bool every = isl_bool_true;
353 isl_size nparam, nvar;
354 isl_basic_set *bset;
355
356 if (!f)
357 return isl_bool_error;
358 nparam = isl_basic_set_dim(f->bset, isl_dim_param);
359 nvar = isl_basic_set_dim(f->bset, isl_dim_set);
360 if (nparam < 0 || nvar < 0)
361 return isl_bool_error;
362
363 bset = isl_basic_set_copy(f->bset);
364 bset = isl_morph_basic_set(isl_morph_copy(f->morph), bset);
365
366 for (i = 0, n = 0; i < f->n_group; ++i) {
367 isl_basic_set *factor;
368
369 factor = isl_basic_set_copy(bset);
371 nparam + n + f->len[i], nvar - n - f->len[i]);
373 nparam, n);
374 factor = isl_basic_set_drop(factor, isl_dim_set,
375 n + f->len[i], nvar - n - f->len[i]);
376 factor = isl_basic_set_drop(factor, isl_dim_set, 0, n);
377 every = test(factor, user);
378 isl_basic_set_free(factor);
379
380 if (every < 0 || !every)
381 break;
382
383 n += f->len[i];
384 }
385
386 isl_basic_set_free(bset);
387
388 return every;
389}
for(int c0=1;c0< 3 *M - 1;c0+=3)
Definition: cholesky2.c:6
#define __isl_take
Definition: ctx.h:22
#define __isl_give
Definition: ctx.h:19
#define __isl_null
Definition: ctx.h:28
#define isl_die(ctx, errno, msg, code)
Definition: ctx.h:137
#define isl_assert(ctx, test, code)
Definition: ctx.h:152
@ isl_error_internal
Definition: ctx.h:79
#define isl_alloc_array(ctx, type, n)
Definition: ctx.h:131
#define __isl_keep
Definition: ctx.h:25
int isl_size
Definition: ctx.h:96
#define isl_alloc_type(ctx, type)
Definition: ctx.h:128
isl_bool
Definition: ctx.h:89
@ isl_bool_true
Definition: ctx.h:92
@ isl_bool_error
Definition: ctx.h:90
isl_stat isl_stat(*) void user)
Definition: hmap.h:39
isl_bool isl_bool(* test)(__isl_keep ISL_KEY *key, __isl_keep ISL_VAL *val, void *user)
Definition: hmap.h:41
static int update_group_i_with_row_j(struct isl_factor_groups *g, int i, int j, __isl_keep isl_mat *H)
static int update_groups(struct isl_factor_groups *g, __isl_keep isl_mat *H)
__isl_give isl_factorizer * isl_factorizer_identity(__isl_keep isl_basic_set *bset)
static void clear_groups(struct isl_factor_groups *g)
static void update_group(struct isl_factor_groups *g, int k)
void isl_factorizer_dump(__isl_take isl_factorizer *f)
static int init_groups(struct isl_factor_groups *g, __isl_keep isl_mat *H)
isl_ctx * isl_factorizer_get_ctx(__isl_keep isl_factorizer *f)
__isl_give isl_factorizer * isl_basic_set_factorizer(__isl_keep isl_basic_set *bset)
static __isl_give isl_factorizer * isl_factorizer_alloc(__isl_keep isl_basic_set *bset, __isl_take isl_morph *morph, int n_group)
__isl_give isl_bool isl_factorizer_every_factor_basic_set(__isl_keep isl_factorizer *f, isl_bool(*test)(__isl_keep isl_basic_set *bset, void *user), void *user)
__isl_give isl_factorizer * isl_factorizer_groups(__isl_keep isl_basic_set *bset, __isl_take isl_mat *Q, __isl_take isl_mat *U, int n, int *len)
__isl_null isl_factorizer * isl_factorizer_free(__isl_take isl_factorizer *f)
#define isl_int_is_zero(i)
Definition: isl_int.h:31
__isl_give isl_basic_set * isl_basic_set_drop(__isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned first, unsigned n)
Definition: isl_map.c:2455
__isl_give isl_basic_set * isl_basic_set_drop_constraints_involving(__isl_take isl_basic_set *bset, unsigned first, unsigned n)
Definition: isl_map.c:3063
isl_stat isl_basic_set_check_no_locals(__isl_keep isl_basic_set *bset)
Definition: isl_map.c:1551
void isl_mat_sub_copy(struct isl_ctx *ctx, isl_int **dst, isl_int **src, unsigned n_row, unsigned dst_col, unsigned src_col, unsigned n_col)
Definition: isl_mat.c:184
__isl_give isl_morph * isl_morph_identity(__isl_keep isl_basic_set *bset)
Definition: isl_morph.c:380
__isl_null isl_morph * isl_morph_free(__isl_take isl_morph *morph)
Definition: isl_morph.c:89
__isl_give isl_morph * isl_morph_alloc(__isl_take isl_basic_set *dom, __isl_take isl_basic_set *ran, __isl_take isl_mat *map, __isl_take isl_mat *inv)
Definition: isl_morph.c:31
void isl_morph_print_internal(__isl_take isl_morph *morph, FILE *out)
Definition: isl_morph.c:364
__isl_give isl_basic_set * isl_morph_basic_set(__isl_take isl_morph *morph, __isl_take isl_basic_set *bset)
Definition: isl_morph.c:641
__isl_give isl_morph * isl_morph_copy(__isl_keep isl_morph *morph)
Definition: isl_morph.c:59
unsigned isl_space_offset(__isl_keep isl_space *space, enum isl_dim_type type)
Definition: isl_space.c:365
const char * p
Definition: isl_test.c:8643
const char * f
Definition: isl_test.c:8642
const char * id
Definition: isl_test.c:7279
struct isl_basic_set isl_basic_set
Definition: map_type.h:20
__isl_give isl_mat * isl_mat_copy(__isl_keep isl_mat *mat)
Definition: isl_mat.c:202
__isl_give isl_mat * isl_mat_identity(isl_ctx *ctx, unsigned n_row)
Definition: isl_mat.c:419
__isl_give isl_mat * isl_mat_swap_cols(__isl_take isl_mat *mat, unsigned i, unsigned j)
Definition: isl_mat.c:1233
__isl_give isl_mat * isl_mat_left_hermite(__isl_take isl_mat *M, int neg, __isl_give isl_mat **U, __isl_give isl_mat **Q)
Definition: isl_mat.c:641
__isl_give isl_mat * isl_mat_diagonal(__isl_take isl_mat *mat1, __isl_take isl_mat *mat2)
Definition: isl_mat.c:921
__isl_give isl_mat * isl_mat_swap_rows(__isl_take isl_mat *mat, unsigned i, unsigned j)
Definition: isl_mat.c:1248
__isl_null isl_mat * isl_mat_free(__isl_take isl_mat *mat)
Definition: isl_mat.c:240
__isl_give isl_mat * isl_mat_alloc(isl_ctx *ctx, unsigned n_row, unsigned n_col)
Definition: isl_mat.c:53
isl_size isl_basic_set_dim(__isl_keep isl_basic_set *bset, enum isl_dim_type type)
Definition: isl_map.c:201
__isl_give isl_space * isl_basic_set_get_space(__isl_keep isl_basic_set *bset)
Definition: isl_map.c:421
__isl_null isl_basic_set * isl_basic_set_free(__isl_take isl_basic_set *bset)
Definition: isl_map.c:1523
isl_ctx * isl_basic_set_get_ctx(__isl_keep isl_basic_set *bset)
Definition: isl_map.c:386
__isl_give isl_basic_set * isl_basic_set_copy(__isl_keep isl_basic_set *bset)
Definition: isl_map.c:1465
__isl_give isl_basic_set * isl_basic_set_universe(__isl_take isl_space *space)
Definition: isl_map.c:6291
__isl_give isl_space * isl_space_copy(__isl_keep isl_space *space)
Definition: isl_space.c:436
__isl_give isl_space * isl_space_drop_dims(__isl_take isl_space *space, enum isl_dim_type type, unsigned first, unsigned num)
Definition: isl_space.c:2047
__isl_give isl_space * isl_space_add_dims(__isl_take isl_space *space, enum isl_dim_type type, unsigned n)
Definition: isl_space.c:1229
@ isl_dim_param
Definition: space_type.h:15
@ isl_dim_set
Definition: space_type.h:18
isl_int ** row
n
Definition: youcefn.c:8