c55b979ad834503f811fab5d996d953091c513e7
[platform/upstream/isl.git] / isl_transitive_closure.c
1 /*
2  * Copyright 2010      INRIA Saclay
3  *
4  * Use of this software is governed by the GNU LGPLv2.1 license
5  *
6  * Written by Sven Verdoolaege, INRIA Saclay - Ile-de-France,
7  * Parc Club Orsay Universite, ZAC des vignes, 4 rue Jacques Monod,
8  * 91893 Orsay, France 
9  */
10
11 #include "isl_map.h"
12 #include "isl_map_private.h"
13 #include "isl_seq.h"
14  
15 /*
16  * The transitive closure implementation is based on the paper
17  * "Computing the Transitive Closure of a Union of Affine Integer
18  * Tuple Relations" by Anna Beletska, Denis Barthou, Wlodzimierz Bielecki and
19  * Albert Cohen.
20  */
21
22 /* Given a set of n offsets v_i (the rows of "steps"), construct a relation
23  * of the given dimension specification (Z^{n+1} -> Z^{n+1})
24  * that maps an element x to any element that can be reached
25  * by taking a non-negative number of steps along any of
26  * the extended offsets v'_i = [v_i 1].
27  * That is, construct
28  *
29  * { [x] -> [y] : exists k_i >= 0, y = x + \sum_i k_i v'_i }
30  *
31  * For any element in this relation, the number of steps taken
32  * is equal to the difference in the final coordinates.
33  */
34 static __isl_give isl_map *path_along_steps(__isl_take isl_dim *dim,
35         __isl_keep isl_mat *steps)
36 {
37         int i, j, k;
38         struct isl_basic_map *path = NULL;
39         unsigned d;
40         unsigned n;
41         unsigned nparam;
42
43         if (!dim || !steps)
44                 goto error;
45
46         d = isl_dim_size(dim, isl_dim_in);
47         n = steps->n_row;
48         nparam = isl_dim_size(dim, isl_dim_param);
49
50         path = isl_basic_map_alloc_dim(isl_dim_copy(dim), n, d, n);
51
52         for (i = 0; i < n; ++i) {
53                 k = isl_basic_map_alloc_div(path);
54                 if (k < 0)
55                         goto error;
56                 isl_assert(steps->ctx, i == k, goto error);
57                 isl_int_set_si(path->div[k][0], 0);
58         }
59
60         for (i = 0; i < d; ++i) {
61                 k = isl_basic_map_alloc_equality(path);
62                 if (k < 0)
63                         goto error;
64                 isl_seq_clr(path->eq[k], 1 + isl_basic_map_total_dim(path));
65                 isl_int_set_si(path->eq[k][1 + nparam + i], 1);
66                 isl_int_set_si(path->eq[k][1 + nparam + d + i], -1);
67                 if (i == d - 1)
68                         for (j = 0; j < n; ++j)
69                                 isl_int_set_si(path->eq[k][1 + nparam + 2 * d + j], 1);
70                 else
71                         for (j = 0; j < n; ++j)
72                                 isl_int_set(path->eq[k][1 + nparam + 2 * d + j],
73                                             steps->row[j][i]);
74         }
75
76         for (i = 0; i < n; ++i) {
77                 k = isl_basic_map_alloc_inequality(path);
78                 if (k < 0)
79                         goto error;
80                 isl_seq_clr(path->ineq[k], 1 + isl_basic_map_total_dim(path));
81                 isl_int_set_si(path->ineq[k][1 + nparam + 2 * d + i], 1);
82         }
83
84         isl_dim_free(dim);
85
86         path = isl_basic_map_simplify(path);
87         path = isl_basic_map_finalize(path);
88         return isl_map_from_basic_map(path);
89 error:
90         isl_dim_free(dim);
91         isl_basic_map_free(path);
92         return NULL;
93 }
94
95 #define IMPURE          0
96 #define PURE_PARAM      1
97 #define PURE_VAR        2
98
99 /* Return PURE_PARAM if only the coefficients of the parameters are non-zero.
100  * Return PURE_VAR if only the coefficients of the set variables are non-zero.
101  * Return IMPURE otherwise.
102  */
103 static int purity(__isl_keep isl_basic_set *bset, isl_int *c)
104 {
105         unsigned d;
106         unsigned n_div;
107         unsigned nparam;
108
109         n_div = isl_basic_set_dim(bset, isl_dim_div);
110         d = isl_basic_set_dim(bset, isl_dim_set);
111         nparam = isl_basic_set_dim(bset, isl_dim_param);
112
113         if (isl_seq_first_non_zero(c + 1 + nparam + d, n_div) != -1)
114                 return IMPURE;
115         if (isl_seq_first_non_zero(c + 1, nparam) == -1)
116                 return PURE_VAR;
117         if (isl_seq_first_non_zero(c + 1 + nparam, d) == -1)
118                 return PURE_PARAM;
119         return IMPURE;
120 }
121
122 /* Given a set of offsets "delta", construct a relation of the
123  * given dimension specification (Z^{n+1} -> Z^{n+1}) that
124  * is an overapproximation of the relations that
125  * maps an element x to any element that can be reached
126  * by taking a non-negative number of steps along any of
127  * the elements in "delta".
128  * That is, construct an approximation of
129  *
130  *      { [x] -> [y] : exists f \in \delta, k \in Z :
131  *                                      y = x + k [f, 1] and k >= 0 }
132  *
133  * For any element in this relation, the number of steps taken
134  * is equal to the difference in the final coordinates.
135  *
136  * In particular, let delta be defined as
137  *
138  *      \delta = [p] -> { [x] : A x + a >= and B p + b >= 0 and
139  *                              C x + C'p + c >= 0 }
140  *
141  * then the relation is constructed as
142  *
143  *      { [x] -> [y] : exists [f, k] \in Z^{n+1} : y = x + f and
144  *                      A f + k a >= 0 and B p + b >= 0 and k >= 1 }
145  *      union { [x] -> [x] }
146  *
147  * Existentially quantified variables in \delta are currently ignored.
148  * This is safe, but leads to an additional overapproximation.
149  */
150 static __isl_give isl_map *path_along_delta(__isl_take isl_dim *dim,
151         __isl_take isl_basic_set *delta)
152 {
153         isl_basic_map *path = NULL;
154         unsigned d;
155         unsigned n_div;
156         unsigned nparam;
157         unsigned off;
158         int i, k;
159
160         if (!delta)
161                 goto error;
162         n_div = isl_basic_set_dim(delta, isl_dim_div);
163         d = isl_basic_set_dim(delta, isl_dim_set);
164         nparam = isl_basic_set_dim(delta, isl_dim_param);
165         path = isl_basic_map_alloc_dim(isl_dim_copy(dim), n_div + d + 1,
166                         d + 1 + delta->n_eq, delta->n_ineq + 1);
167         off = 1 + nparam + 2 * (d + 1) + n_div;
168
169         for (i = 0; i < n_div + d + 1; ++i) {
170                 k = isl_basic_map_alloc_div(path);
171                 if (k < 0)
172                         goto error;
173                 isl_int_set_si(path->div[k][0], 0);
174         }
175
176         for (i = 0; i < d + 1; ++i) {
177                 k = isl_basic_map_alloc_equality(path);
178                 if (k < 0)
179                         goto error;
180                 isl_seq_clr(path->eq[k], 1 + isl_basic_map_total_dim(path));
181                 isl_int_set_si(path->eq[k][1 + nparam + i], 1);
182                 isl_int_set_si(path->eq[k][1 + nparam + d + 1 + i], -1);
183                 isl_int_set_si(path->eq[k][off + i], 1);
184         }
185
186         for (i = 0; i < delta->n_eq; ++i) {
187                 int p = purity(delta, delta->eq[i]);
188                 if (p == IMPURE)
189                         continue;
190                 k = isl_basic_map_alloc_equality(path);
191                 if (k < 0)
192                         goto error;
193                 isl_seq_clr(path->eq[k], 1 + isl_basic_map_total_dim(path));
194                 if (p == PURE_VAR) {
195                         isl_seq_cpy(path->eq[k] + off,
196                                     delta->eq[i] + 1 + nparam, d);
197                         isl_int_set(path->eq[k][off + d], delta->eq[i][0]);
198                 } else
199                         isl_seq_cpy(path->eq[k], delta->eq[i], 1 + nparam);
200         }
201
202         for (i = 0; i < delta->n_ineq; ++i) {
203                 int p = purity(delta, delta->ineq[i]);
204                 if (p == IMPURE)
205                         continue;
206                 k = isl_basic_map_alloc_inequality(path);
207                 if (k < 0)
208                         goto error;
209                 isl_seq_clr(path->ineq[k], 1 + isl_basic_map_total_dim(path));
210                 if (p == PURE_VAR) {
211                         isl_seq_cpy(path->ineq[k] + off,
212                                     delta->ineq[i] + 1 + nparam, d);
213                         isl_int_set(path->ineq[k][off + d], delta->ineq[i][0]);
214                 } else
215                         isl_seq_cpy(path->ineq[k], delta->ineq[i], 1 + nparam);
216         }
217
218         k = isl_basic_map_alloc_inequality(path);
219         if (k < 0)
220                 goto error;
221         isl_seq_clr(path->ineq[k], 1 + isl_basic_map_total_dim(path));
222         isl_int_set_si(path->ineq[k][0], -1);
223         isl_int_set_si(path->ineq[k][off + d], 1);
224                         
225         isl_basic_set_free(delta);
226         path = isl_basic_map_finalize(path);
227         return isl_basic_map_union(path,
228                                 isl_basic_map_identity(isl_dim_domain(dim)));
229 error:
230         isl_dim_free(dim);
231         isl_basic_set_free(delta);
232         isl_basic_map_free(path);
233         return NULL;
234 }
235
236 /* Given a dimenion specification Z^{n+1} -> Z^{n+1} and a parameter "param",
237  * construct a map that equates the parameter to the difference
238  * in the final coordinates and imposes that this difference is positive.
239  * That is, construct
240  *
241  *      { [x,x_s] -> [y,y_s] : k = y_s - x_s > 0 }
242  */
243 static __isl_give isl_map *equate_parameter_to_length(__isl_take isl_dim *dim,
244         unsigned param)
245 {
246         struct isl_basic_map *bmap;
247         unsigned d;
248         unsigned nparam;
249         int k;
250
251         d = isl_dim_size(dim, isl_dim_in);
252         nparam = isl_dim_size(dim, isl_dim_param);
253         bmap = isl_basic_map_alloc_dim(dim, 0, 1, 1);
254         k = isl_basic_map_alloc_equality(bmap);
255         if (k < 0)
256                 goto error;
257         isl_seq_clr(bmap->eq[k], 1 + isl_basic_map_total_dim(bmap));
258         isl_int_set_si(bmap->eq[k][1 + param], -1);
259         isl_int_set_si(bmap->eq[k][1 + nparam + d - 1], -1);
260         isl_int_set_si(bmap->eq[k][1 + nparam + d + d - 1], 1);
261
262         k = isl_basic_map_alloc_inequality(bmap);
263         if (k < 0)
264                 goto error;
265         isl_seq_clr(bmap->ineq[k], 1 + isl_basic_map_total_dim(bmap));
266         isl_int_set_si(bmap->ineq[k][1 + param], 1);
267         isl_int_set_si(bmap->ineq[k][0], -1);
268
269         bmap = isl_basic_map_finalize(bmap);
270         return isl_map_from_basic_map(bmap);
271 error:
272         isl_basic_map_free(bmap);
273         return NULL;
274 }
275
276 /* Check whether "path" is acyclic, where the last coordinates of domain
277  * and range of path encode the number of steps taken.
278  * That is, check whether
279  *
280  *      { d | d = y - x and (x,y) in path }
281  *
282  * does not contain any element with positive last coordinate (positive length)
283  * and zero remaining coordinates (cycle).
284  */
285 static int is_acyclic(__isl_take isl_map *path)
286 {
287         int i;
288         int acyclic;
289         unsigned dim;
290         struct isl_set *delta;
291
292         delta = isl_map_deltas(path);
293         dim = isl_set_dim(delta, isl_dim_set);
294         for (i = 0; i < dim; ++i) {
295                 if (i == dim -1)
296                         delta = isl_set_lower_bound_si(delta, isl_dim_set, i, 1);
297                 else
298                         delta = isl_set_fix_si(delta, isl_dim_set, i, 0);
299         }
300
301         acyclic = isl_set_is_empty(delta);
302         isl_set_free(delta);
303
304         return acyclic;
305 }
306
307 /* Given a union of basic maps R = \cup_i R_i \subseteq D \times D
308  * and a dimension specification (Z^{n+1} -> Z^{n+1}),
309  * construct a map that is an overapproximation of the map
310  * that takes an element from the space D \times Z to another
311  * element from the same space, such that the first n coordinates of the
312  * difference between them is a sum of differences between images
313  * and pre-images in one of the R_i and such that the last coordinate
314  * is equal to the number of steps taken.
315  * That is, let
316  *
317  *      \Delta_i = { y - x | (x, y) in R_i }
318  *
319  * then the constructed map is an overapproximation of
320  *
321  *      { (x) -> (x + d) | \exists k_i >= 0, \delta_i \in \Delta_i :
322  *                              d = (\sum_i k_i \delta_i, \sum_i k_i) }
323  *
324  * The elements of the singleton \Delta_i's are collected as the
325  * rows of the steps matrix.  For all these \Delta_i's together,
326  * a single path is constructed.
327  * For each of the other \Delta_i's, we compute an overapproximation
328  * of the paths along elements of \Delta_i.
329  * Since each of these paths performs an addition, composition is
330  * symmetric and we can simply compose all resulting paths in any order.
331  */
332 static __isl_give isl_map *construct_extended_path(__isl_take isl_dim *dim,
333         __isl_keep isl_map *map, int *project)
334 {
335         struct isl_mat *steps = NULL;
336         struct isl_map *path = NULL;
337         unsigned d;
338         int i, j, n;
339
340         d = isl_map_dim(map, isl_dim_in);
341
342         path = isl_map_identity(isl_dim_domain(isl_dim_copy(dim)));
343
344         steps = isl_mat_alloc(map->ctx, map->n, d);
345         if (!steps)
346                 goto error;
347
348         n = 0;
349         for (i = 0; i < map->n; ++i) {
350                 struct isl_basic_set *delta;
351
352                 delta = isl_basic_map_deltas(isl_basic_map_copy(map->p[i]));
353
354                 for (j = 0; j < d; ++j) {
355                         int fixed;
356
357                         fixed = isl_basic_set_fast_dim_is_fixed(delta, j,
358                                                             &steps->row[n][j]);
359                         if (fixed < 0) {
360                                 isl_basic_set_free(delta);
361                                 goto error;
362                         }
363                         if (!fixed)
364                                 break;
365                 }
366
367
368                 if (j < d) {
369                         path = isl_map_apply_range(path,
370                                 path_along_delta(isl_dim_copy(dim), delta));
371                 } else {
372                         isl_basic_set_free(delta);
373                         ++n;
374                 }
375         }
376
377         if (n > 0) {
378                 steps->n_row = n;
379                 path = isl_map_apply_range(path,
380                                 path_along_steps(isl_dim_copy(dim), steps));
381         }
382
383         if (project && *project) {
384                 *project = is_acyclic(isl_map_copy(path));
385                 if (*project < 0)
386                         goto error;
387         }
388
389         isl_dim_free(dim);
390         isl_mat_free(steps);
391         return path;
392 error:
393         isl_dim_free(dim);
394         isl_mat_free(steps);
395         isl_map_free(path);
396         return NULL;
397 }
398
399 /* Given a union of basic maps R = \cup_i R_i \subseteq D \times D,
400  * construct a map that is an overapproximation of the map
401  * that takes an element from the space D to another
402  * element from the same space, such that the difference between
403  * them is a strictly positive sum of differences between images
404  * and pre-images in one of the R_i.
405  * The number of differences in the sum is equated to parameter "param".
406  * That is, let
407  *
408  *      \Delta_i = { y - x | (x, y) in R_i }
409  *
410  * then the constructed map is an overapproximation of
411  *
412  *      { (x) -> (x + d) | \exists k_i >= 0, \delta_i \in \Delta_i :
413  *                              d = \sum_i k_i \delta_i and k = \sum_i k_i > 0 }
414  *
415  * We first construct an extended mapping with an extra coordinate
416  * that indicates the number of steps taken.  In particular,
417  * the difference in the last coordinate is equal to the number
418  * of steps taken to move from a domain element to the corresponding
419  * image element(s).
420  * In the final step, this difference is equated to the parameter "param"
421  * and made positive.  The extra coordinates are subsequently projected out.
422  */
423 static __isl_give isl_map *construct_path(__isl_keep isl_map *map,
424         unsigned param, int *project)
425 {
426         struct isl_map *path = NULL;
427         struct isl_map *diff;
428         struct isl_dim *dim = NULL;
429         unsigned d;
430
431         if (!map)
432                 return NULL;
433
434         dim = isl_map_get_dim(map);
435
436         d = isl_dim_size(dim, isl_dim_in);
437         dim = isl_dim_add(dim, isl_dim_in, 1);
438         dim = isl_dim_add(dim, isl_dim_out, 1);
439
440         path = construct_extended_path(isl_dim_copy(dim), map, project);
441
442         diff = equate_parameter_to_length(dim, param);
443         path = isl_map_intersect(path, diff);
444         path = isl_map_project_out(path, isl_dim_in, d, 1);
445         path = isl_map_project_out(path, isl_dim_out, d, 1);
446
447         return path;
448 }
449
450 /* Shift variable at position "pos" up by one.
451  * That is, replace the corresponding variable v by v - 1.
452  */
453 static __isl_give isl_basic_map *basic_map_shift_pos(
454         __isl_take isl_basic_map *bmap, unsigned pos)
455 {
456         int i;
457
458         bmap = isl_basic_map_cow(bmap);
459         if (!bmap)
460                 return NULL;
461
462         for (i = 0; i < bmap->n_eq; ++i)
463                 isl_int_sub(bmap->eq[i][0], bmap->eq[i][0], bmap->eq[i][pos]);
464
465         for (i = 0; i < bmap->n_ineq; ++i)
466                 isl_int_sub(bmap->ineq[i][0],
467                                 bmap->ineq[i][0], bmap->ineq[i][pos]);
468
469         for (i = 0; i < bmap->n_div; ++i) {
470                 if (isl_int_is_zero(bmap->div[i][0]))
471                         continue;
472                 isl_int_sub(bmap->div[i][1],
473                                 bmap->div[i][1], bmap->div[i][1 + pos]);
474         }
475
476         return bmap;
477 }
478
479 /* Shift variable at position "pos" up by one.
480  * That is, replace the corresponding variable v by v - 1.
481  */
482 static __isl_give isl_map *map_shift_pos(__isl_take isl_map *map, unsigned pos)
483 {
484         int i;
485
486         map = isl_map_cow(map);
487         if (!map)
488                 return NULL;
489
490         for (i = 0; i < map->n; ++i) {
491                 map->p[i] = basic_map_shift_pos(map->p[i], pos);
492                 if (!map->p[i])
493                         goto error;
494         }
495         ISL_F_CLR(map, ISL_MAP_NORMALIZED);
496         return map;
497 error:
498         isl_map_free(map);
499         return NULL;
500 }
501
502 /* Check whether the overapproximation of the power of "map" is exactly
503  * the power of "map".  Let R be "map" and A_k the overapproximation.
504  * The approximation is exact if
505  *
506  *      A_1 = R
507  *      A_k = A_{k-1} \circ R                   k >= 2
508  *
509  * Since A_k is known to be an overapproximation, we only need to check
510  *
511  *      A_1 \subset R
512  *      A_k \subset A_{k-1} \circ R             k >= 2
513  *
514  */
515 static int check_power_exactness(__isl_take isl_map *map,
516         __isl_take isl_map *app, unsigned param)
517 {
518         int exact;
519         isl_map *app_1;
520         isl_map *app_2;
521
522         app_1 = isl_map_fix_si(isl_map_copy(app), isl_dim_param, param, 1);
523
524         exact = isl_map_is_subset(app_1, map);
525         isl_map_free(app_1);
526
527         if (!exact || exact < 0) {
528                 isl_map_free(app);
529                 isl_map_free(map);
530                 return exact;
531         }
532
533         app_2 = isl_map_lower_bound_si(isl_map_copy(app),
534                                         isl_dim_param, param, 2);
535         app_1 = map_shift_pos(app, 1 + param);
536         app_1 = isl_map_apply_range(map, app_1);
537
538         exact = isl_map_is_subset(app_2, app_1);
539
540         isl_map_free(app_1);
541         isl_map_free(app_2);
542
543         return exact;
544 }
545
546 /* Check whether the overapproximation of the power of "map" is exactly
547  * the power of "map", possibly after projecting out the power (if "project"
548  * is set).
549  *
550  * If "project" is set and if "steps" can only result in acyclic paths,
551  * then we check
552  *
553  *      A = R \cup (A \circ R)
554  *
555  * where A is the overapproximation with the power projected out, i.e.,
556  * an overapproximation of the transitive closure.
557  * More specifically, since A is known to be an overapproximation, we check
558  *
559  *      A \subset R \cup (A \circ R)
560  *
561  * Otherwise, we check if the power is exact.
562  */
563 static int check_exactness(__isl_take isl_map *map, __isl_take isl_map *app,
564         unsigned param, int project)
565 {
566         isl_map *test;
567         int exact;
568
569         if (!project)
570                 return check_power_exactness(map, app, param);
571
572         map = isl_map_project_out(map, isl_dim_param, param, 1);
573         app = isl_map_project_out(app, isl_dim_param, param, 1);
574
575         test = isl_map_apply_range(isl_map_copy(map), isl_map_copy(app));
576         test = isl_map_union(test, isl_map_copy(map));
577
578         exact = isl_map_is_subset(app, test);
579
580         isl_map_free(app);
581         isl_map_free(test);
582
583         isl_map_free(map);
584
585         return exact;
586 error:
587         isl_map_free(app);
588         isl_map_free(map);
589         return -1;
590 }
591
592 /* Compute the positive powers of "map", or an overapproximation.
593  * The power is given by parameter "param".  If the result is exact,
594  * then *exact is set to 1.
595  * If project is set, then we are actually interested in the transitive
596  * closure, so we can use a more relaxed exactness check.
597  */
598 static __isl_give isl_map *map_power(__isl_take isl_map *map, unsigned param,
599         int *exact, int project)
600 {
601         struct isl_set *domain = NULL;
602         struct isl_set *range = NULL;
603         struct isl_map *app = NULL;
604         struct isl_map *path = NULL;
605
606         if (exact)
607                 *exact = 1;
608
609         map = isl_map_remove_empty_parts(map);
610         if (!map)
611                 return NULL;
612
613         if (isl_map_fast_is_empty(map))
614                 return map;
615
616         isl_assert(map->ctx, param < isl_map_dim(map, isl_dim_param), goto error);
617         isl_assert(map->ctx,
618                 isl_map_dim(map, isl_dim_in) == isl_map_dim(map, isl_dim_out),
619                 goto error);
620
621         domain = isl_map_domain(isl_map_copy(map));
622         domain = isl_set_coalesce(domain);
623         range = isl_map_range(isl_map_copy(map));
624         range = isl_set_coalesce(range);
625         app = isl_map_from_domain_and_range(isl_set_copy(domain),
626                                             isl_set_copy(range));
627
628         path = construct_path(map, param, exact ? &project : NULL);
629         app = isl_map_intersect(app, isl_map_copy(path));
630
631         if (exact &&
632             (*exact = check_exactness(isl_map_copy(map), isl_map_copy(app),
633                                       param, project)) < 0)
634                 goto error;
635
636         isl_set_free(domain);
637         isl_set_free(range);
638         isl_map_free(path);
639         isl_map_free(map);
640         return app;
641 error:
642         isl_set_free(domain);
643         isl_set_free(range);
644         isl_map_free(path);
645         isl_map_free(map);
646         isl_map_free(app);
647         return NULL;
648 }
649
650 /* Compute the positive powers of "map", or an overapproximation.
651  * The power is given by parameter "param".  If the result is exact,
652  * then *exact is set to 1.
653  */
654 __isl_give isl_map *isl_map_power(__isl_take isl_map *map, unsigned param,
655         int *exact)
656 {
657         return map_power(map, param, exact, 0);
658 }
659
660 /* Compute the transitive closure  of "map", or an overapproximation.
661  * If the result is exact, then *exact is set to 1.
662  * Simply compute the powers of map and then project out the parameter
663  * describing the power.
664  */
665 __isl_give isl_map *isl_map_transitive_closure(__isl_take isl_map *map,
666         int *exact)
667 {
668         unsigned param;
669
670         if (!map)
671                 goto error;
672
673         param = isl_map_dim(map, isl_dim_param);
674         map = isl_map_add(map, isl_dim_param, 1);
675         map = map_power(map, param, exact, 1);
676         map = isl_map_project_out(map, isl_dim_param, param, 1);
677
678         return map;
679 error:
680         isl_map_free(map);
681         return NULL;
682 }