isl_basic_set_opt: avoid invalid access on error path
[platform/upstream/isl.git] / isl_constraint.c
1 /*
2  * Copyright 2008-2009 Katholieke Universiteit Leuven
3  * Copyright 2010      INRIA Saclay
4  *
5  * Use of this software is governed by the MIT license
6  *
7  * Written by Sven Verdoolaege, K.U.Leuven, Departement
8  * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
9  * and INRIA Saclay - Ile-de-France, Parc Club Orsay Universite,
10  * ZAC des vignes, 4 rue Jacques Monod, 91893 Orsay, France 
11  */
12
13 #include <isl_map_private.h>
14 #include <isl_constraint_private.h>
15 #include <isl_space_private.h>
16 #include <isl/seq.h>
17 #include <isl_aff_private.h>
18 #include <isl_local_space_private.h>
19
20 isl_ctx *isl_constraint_get_ctx(__isl_keep isl_constraint *c)
21 {
22         return c ? isl_local_space_get_ctx(c->ls) : NULL;
23 }
24
25 static unsigned n(struct isl_constraint *c, enum isl_dim_type type)
26 {
27         return isl_local_space_dim(c->ls, type);
28 }
29
30 static unsigned offset(struct isl_constraint *c, enum isl_dim_type type)
31 {
32         return isl_local_space_offset(c->ls, type);
33 }
34
35 static unsigned basic_map_offset(__isl_keep isl_basic_map *bmap,
36                                                         enum isl_dim_type type)
37 {
38         return type == isl_dim_div ? 1 + isl_space_dim(bmap->dim, isl_dim_all)
39                                    : 1 + isl_space_offset(bmap->dim, type);
40 }
41
42 static unsigned basic_set_offset(struct isl_basic_set *bset,
43                                                         enum isl_dim_type type)
44 {
45         isl_space *dim = bset->dim;
46         switch (type) {
47         case isl_dim_param:     return 1;
48         case isl_dim_in:        return 1 + dim->nparam;
49         case isl_dim_out:       return 1 + dim->nparam + dim->n_in;
50         case isl_dim_div:       return 1 + dim->nparam + dim->n_in + dim->n_out;
51         default:                return 0;
52         }
53 }
54
55 __isl_give isl_constraint *isl_constraint_alloc_vec(int eq,
56         __isl_take isl_local_space *ls, __isl_take isl_vec *v)
57 {
58         isl_constraint *constraint;
59
60         if (!ls || !v)
61                 goto error;
62
63         constraint = isl_alloc_type(isl_vec_get_ctx(v), isl_constraint);
64         if (!constraint)
65                 goto error;
66
67         constraint->ref = 1;
68         constraint->eq = eq;
69         constraint->ls = ls;
70         constraint->v = v;
71
72         return constraint;
73 error:
74         isl_local_space_free(ls);
75         isl_vec_free(v);
76         return NULL;
77 }
78
79 __isl_give isl_constraint *isl_constraint_alloc(int eq,
80         __isl_take isl_local_space *ls)
81 {
82         isl_ctx *ctx;
83         isl_vec *v;
84
85         if (!ls)
86                 return NULL;
87
88         ctx = isl_local_space_get_ctx(ls);
89         v = isl_vec_alloc(ctx, 1 + isl_local_space_dim(ls, isl_dim_all));
90         v = isl_vec_clr(v);
91         return isl_constraint_alloc_vec(eq, ls, v);
92 }
93
94 struct isl_constraint *isl_basic_map_constraint(struct isl_basic_map *bmap,
95         isl_int **line)
96 {
97         int eq;
98         isl_ctx *ctx;
99         isl_vec *v;
100         isl_local_space *ls = NULL;
101         isl_constraint *constraint;
102
103         if (!bmap || !line)
104                 goto error;
105
106         eq = line >= bmap->eq;
107
108         ctx = isl_basic_map_get_ctx(bmap);
109         ls = isl_basic_map_get_local_space(bmap);
110         v = isl_vec_alloc(ctx, 1 + isl_local_space_dim(ls, isl_dim_all));
111         if (!v)
112                 goto error;
113         isl_seq_cpy(v->el, line[0], v->size);
114         constraint = isl_constraint_alloc_vec(eq, ls, v);
115
116         isl_basic_map_free(bmap);
117         return constraint;
118 error:
119         isl_local_space_free(ls);
120         isl_basic_map_free(bmap);
121         return NULL;
122 }
123
124 struct isl_constraint *isl_basic_set_constraint(struct isl_basic_set *bset,
125         isl_int **line)
126 {
127         return isl_basic_map_constraint((struct isl_basic_map *)bset, line);
128 }
129
130 __isl_give isl_constraint *isl_equality_alloc(__isl_take isl_local_space *ls)
131 {
132         return isl_constraint_alloc(1, ls);
133 }
134
135 __isl_give isl_constraint *isl_inequality_alloc(__isl_take isl_local_space *ls)
136 {
137         return isl_constraint_alloc(0, ls);
138 }
139
140 struct isl_constraint *isl_constraint_dup(struct isl_constraint *c)
141 {
142         if (!c)
143                 return NULL;
144
145         return isl_constraint_alloc_vec(c->eq, isl_local_space_copy(c->ls),
146                                                 isl_vec_copy(c->v));
147 }
148
149 struct isl_constraint *isl_constraint_cow(struct isl_constraint *c)
150 {
151         if (!c)
152                 return NULL;
153
154         if (c->ref == 1)
155                 return c;
156         c->ref--;
157         return isl_constraint_dup(c);
158 }
159
160 struct isl_constraint *isl_constraint_copy(struct isl_constraint *constraint)
161 {
162         if (!constraint)
163                 return NULL;
164
165         constraint->ref++;
166         return constraint;
167 }
168
169 void *isl_constraint_free(struct isl_constraint *c)
170 {
171         if (!c)
172                 return NULL;
173
174         if (--c->ref > 0)
175                 return NULL;
176
177         isl_local_space_free(c->ls);
178         isl_vec_free(c->v);
179         free(c);
180
181         return NULL;
182 }
183
184 /* Return the number of constraints in "bset", i.e., the
185  * number of times isl_basic_set_foreach_constraint will
186  * call the callback.
187  */
188 int isl_basic_set_n_constraint(__isl_keep isl_basic_set *bset)
189 {
190         if (!bset)
191                 return -1;
192
193         return bset->n_eq + bset->n_ineq;
194 }
195
196 int isl_basic_map_foreach_constraint(__isl_keep isl_basic_map *bmap,
197         int (*fn)(__isl_take isl_constraint *c, void *user), void *user)
198 {
199         int i;
200         struct isl_constraint *c;
201
202         if (!bmap)
203                 return -1;
204
205         isl_assert(bmap->ctx, ISL_F_ISSET(bmap, ISL_BASIC_MAP_FINAL),
206                         return -1);
207
208         for (i = 0; i < bmap->n_eq; ++i) {
209                 c = isl_basic_map_constraint(isl_basic_map_copy(bmap),
210                                                 &bmap->eq[i]);
211                 if (!c)
212                         return -1;
213                 if (fn(c, user) < 0)
214                         return -1;
215         }
216
217         for (i = 0; i < bmap->n_ineq; ++i) {
218                 c = isl_basic_map_constraint(isl_basic_map_copy(bmap),
219                                                 &bmap->ineq[i]);
220                 if (!c)
221                         return -1;
222                 if (fn(c, user) < 0)
223                         return -1;
224         }
225
226         return 0;
227 }
228
229 int isl_basic_set_foreach_constraint(__isl_keep isl_basic_set *bset,
230         int (*fn)(__isl_take isl_constraint *c, void *user), void *user)
231 {
232         return isl_basic_map_foreach_constraint((isl_basic_map *)bset, fn, user);
233 }
234
235 int isl_constraint_is_equal(struct isl_constraint *constraint1,
236         struct isl_constraint *constraint2)
237 {
238         int equal;
239
240         if (!constraint1 || !constraint2)
241                 return 0;
242         if (constraint1->eq != constraint2->eq)
243                 return 0;
244         equal = isl_local_space_is_equal(constraint1->ls, constraint2->ls);
245         if (equal < 0 || !equal)
246                 return equal;
247         return isl_vec_is_equal(constraint1->v, constraint2->v);
248 }
249
250 struct isl_basic_map *isl_basic_map_add_constraint(
251         struct isl_basic_map *bmap, struct isl_constraint *constraint)
252 {
253         isl_ctx *ctx;
254         isl_space *dim;
255         int equal_space;
256
257         if (!bmap || !constraint)
258                 goto error;
259
260         ctx = isl_constraint_get_ctx(constraint);
261         dim = isl_constraint_get_space(constraint);
262         equal_space = isl_space_is_equal(bmap->dim, dim);
263         isl_space_free(dim);
264         isl_assert(ctx, equal_space, goto error);
265
266         bmap = isl_basic_map_intersect(bmap,
267                                 isl_basic_map_from_constraint(constraint));
268         return bmap;
269 error:
270         isl_basic_map_free(bmap);
271         isl_constraint_free(constraint);
272         return NULL;
273 }
274
275 struct isl_basic_set *isl_basic_set_add_constraint(
276         struct isl_basic_set *bset, struct isl_constraint *constraint)
277 {
278         return (struct isl_basic_set *)
279                 isl_basic_map_add_constraint((struct isl_basic_map *)bset,
280                                                 constraint);
281 }
282
283 __isl_give isl_map *isl_map_add_constraint(__isl_take isl_map *map,
284         __isl_take isl_constraint *constraint)
285 {
286         isl_basic_map *bmap;
287
288         bmap = isl_basic_map_from_constraint(constraint);
289         map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
290
291         return map;
292 }
293
294 __isl_give isl_set *isl_set_add_constraint(__isl_take isl_set *set,
295         __isl_take isl_constraint *constraint)
296 {
297         return isl_map_add_constraint(set, constraint);
298 }
299
300 __isl_give isl_space *isl_constraint_get_space(
301         __isl_keep isl_constraint *constraint)
302 {
303         return constraint ? isl_local_space_get_space(constraint->ls) : NULL;
304 }
305
306 __isl_give isl_local_space *isl_constraint_get_local_space(
307         __isl_keep isl_constraint *constraint)
308 {
309         return constraint ? isl_local_space_copy(constraint->ls) : NULL;
310 }
311
312 int isl_constraint_dim(struct isl_constraint *constraint,
313         enum isl_dim_type type)
314 {
315         if (!constraint)
316                 return -1;
317         return n(constraint, type);
318 }
319
320 int isl_constraint_involves_dims(__isl_keep isl_constraint *constraint,
321         enum isl_dim_type type, unsigned first, unsigned n)
322 {
323         int i;
324         isl_ctx *ctx;
325         int *active = NULL;
326         int involves = 0;
327
328         if (!constraint)
329                 return -1;
330         if (n == 0)
331                 return 0;
332
333         ctx = isl_constraint_get_ctx(constraint);
334         if (first + n > isl_constraint_dim(constraint, type))
335                 isl_die(ctx, isl_error_invalid,
336                         "range out of bounds", return -1);
337
338         active = isl_local_space_get_active(constraint->ls,
339                                             constraint->v->el + 1);
340         if (!active)
341                 goto error;
342
343         first += isl_local_space_offset(constraint->ls, type) - 1;
344         for (i = 0; i < n; ++i)
345                 if (active[first + i]) {
346                         involves = 1;
347                         break;
348                 }
349
350         free(active);
351
352         return involves;
353 error:
354         free(active);
355         return -1;
356 }
357
358 /* Does the given constraint represent a lower bound on the given
359  * dimension?
360  */
361 int isl_constraint_is_lower_bound(__isl_keep isl_constraint *constraint,
362         enum isl_dim_type type, unsigned pos)
363 {
364         if (!constraint)
365                 return -1;
366
367         if (pos >= isl_local_space_dim(constraint->ls, type))
368                 isl_die(isl_constraint_get_ctx(constraint), isl_error_invalid,
369                         "position out of bounds", return -1);
370
371         pos += isl_local_space_offset(constraint->ls, type);
372         return isl_int_is_pos(constraint->v->el[pos]);
373 }
374
375 /* Does the given constraint represent an upper bound on the given
376  * dimension?
377  */
378 int isl_constraint_is_upper_bound(__isl_keep isl_constraint *constraint,
379         enum isl_dim_type type, unsigned pos)
380 {
381         if (!constraint)
382                 return -1;
383
384         if (pos >= isl_local_space_dim(constraint->ls, type))
385                 isl_die(isl_constraint_get_ctx(constraint), isl_error_invalid,
386                         "position out of bounds", return -1);
387
388         pos += isl_local_space_offset(constraint->ls, type);
389         return isl_int_is_neg(constraint->v->el[pos]);
390 }
391
392 const char *isl_constraint_get_dim_name(__isl_keep isl_constraint *constraint,
393         enum isl_dim_type type, unsigned pos)
394 {
395         return constraint ?
396             isl_local_space_get_dim_name(constraint->ls, type, pos) : NULL;
397 }
398
399 void isl_constraint_get_constant(struct isl_constraint *constraint, isl_int *v)
400 {
401         if (!constraint)
402                 return;
403         isl_int_set(*v, constraint->v->el[0]);
404 }
405
406 void isl_constraint_get_coefficient(struct isl_constraint *constraint,
407         enum isl_dim_type type, int pos, isl_int *v)
408 {
409         if (!constraint)
410                 return;
411
412         if (pos >= isl_local_space_dim(constraint->ls, type))
413                 isl_die(constraint->v->ctx, isl_error_invalid,
414                         "position out of bounds", return);
415
416         pos += isl_local_space_offset(constraint->ls, type);
417         isl_int_set(*v, constraint->v->el[pos]);
418 }
419
420 __isl_give isl_aff *isl_constraint_get_div(__isl_keep isl_constraint *constraint,
421         int pos)
422 {
423         if (!constraint)
424                 return NULL;
425
426         return isl_local_space_get_div(constraint->ls, pos);
427 }
428
429 __isl_give isl_constraint *isl_constraint_set_constant(
430         __isl_take isl_constraint *constraint, isl_int v)
431 {
432         constraint = isl_constraint_cow(constraint);
433         if (!constraint)
434                 return NULL;
435
436         constraint->v = isl_vec_cow(constraint->v);
437         if (!constraint->v)
438                 return isl_constraint_free(constraint);
439
440         isl_int_set(constraint->v->el[0], v);
441         return constraint;
442 }
443
444 __isl_give isl_constraint *isl_constraint_set_constant_si(
445         __isl_take isl_constraint *constraint, int v)
446 {
447         constraint = isl_constraint_cow(constraint);
448         if (!constraint)
449                 return NULL;
450
451         constraint->v = isl_vec_cow(constraint->v);
452         if (!constraint->v)
453                 return isl_constraint_free(constraint);
454
455         isl_int_set_si(constraint->v->el[0], v);
456         return constraint;
457 }
458
459 __isl_give isl_constraint *isl_constraint_set_coefficient(
460         __isl_take isl_constraint *constraint,
461         enum isl_dim_type type, int pos, isl_int v)
462 {
463         constraint = isl_constraint_cow(constraint);
464         if (!constraint)
465                 return NULL;
466
467         if (pos >= isl_local_space_dim(constraint->ls, type))
468                 isl_die(constraint->v->ctx, isl_error_invalid,
469                         "position out of bounds",
470                         return isl_constraint_free(constraint));
471
472         constraint = isl_constraint_cow(constraint);
473         if (!constraint)
474                 return NULL;
475
476         constraint->v = isl_vec_cow(constraint->v);
477         if (!constraint->v)
478                 return isl_constraint_free(constraint);
479
480         pos += isl_local_space_offset(constraint->ls, type);
481         isl_int_set(constraint->v->el[pos], v);
482
483         return constraint;
484 }
485
486 __isl_give isl_constraint *isl_constraint_set_coefficient_si(
487         __isl_take isl_constraint *constraint,
488         enum isl_dim_type type, int pos, int v)
489 {
490         constraint = isl_constraint_cow(constraint);
491         if (!constraint)
492                 return NULL;
493
494         if (pos >= isl_local_space_dim(constraint->ls, type))
495                 isl_die(constraint->v->ctx, isl_error_invalid,
496                         "position out of bounds",
497                         return isl_constraint_free(constraint));
498
499         constraint = isl_constraint_cow(constraint);
500         if (!constraint)
501                 return NULL;
502
503         constraint->v = isl_vec_cow(constraint->v);
504         if (!constraint->v)
505                 return isl_constraint_free(constraint);
506
507         pos += isl_local_space_offset(constraint->ls, type);
508         isl_int_set_si(constraint->v->el[pos], v);
509
510         return constraint;
511 }
512
513 /* Drop any constraint from "bset" that is identical to "constraint".
514  * In particular, this means that the local spaces of "bset" and
515  * "constraint" need to be the same.
516  *
517  * Since the given constraint may actually be a pointer into the bset,
518  * we have to be careful not to reorder the constraints as the user
519  * may be holding on to other constraints from the same bset.
520  * This should be cleaned up when the internal representation of
521  * isl_constraint is changed to use isl_aff.
522  */
523 __isl_give isl_basic_set *isl_basic_set_drop_constraint(
524         __isl_take isl_basic_set *bset, __isl_take isl_constraint *constraint)
525 {
526         int i;
527         unsigned n;
528         isl_int **row;
529         unsigned total;
530         isl_local_space *ls1;
531         int equal;
532
533         if (!bset || !constraint)
534                 goto error;
535
536         ls1 = isl_basic_set_get_local_space(bset);
537         equal = isl_local_space_is_equal(ls1, constraint->ls);
538         isl_local_space_free(ls1);
539         if (equal < 0)
540                 goto error;
541         if (!equal) {
542                 isl_constraint_free(constraint);
543                 return bset;
544         }
545
546         if (isl_constraint_is_equality(constraint)) {
547                 n = bset->n_eq;
548                 row = bset->eq;
549         } else {
550                 n = bset->n_ineq;
551                 row = bset->ineq;
552         }
553
554         total = isl_constraint_dim(constraint, isl_dim_all);
555         for (i = 0; i < n; ++i)
556                 if (isl_seq_eq(row[i], constraint->v->el, 1 + total))
557                         isl_seq_clr(row[i], 1 + total);
558                         
559         isl_constraint_free(constraint);
560         return bset;
561 error:
562         isl_constraint_free(constraint);
563         isl_basic_set_free(bset);
564         return NULL;
565 }
566
567 struct isl_constraint *isl_constraint_negate(struct isl_constraint *constraint)
568 {
569         isl_ctx *ctx;
570
571         constraint = isl_constraint_cow(constraint);
572         if (!constraint)
573                 return NULL;
574
575         ctx = isl_constraint_get_ctx(constraint);
576         if (isl_constraint_is_equality(constraint))
577                 isl_die(ctx, isl_error_invalid, "cannot negate equality",
578                         return isl_constraint_free(constraint));
579         constraint->v = isl_vec_neg(constraint->v);
580         constraint->v = isl_vec_cow(constraint->v);
581         if (!constraint->v)
582                 return isl_constraint_free(constraint);
583         isl_int_sub_ui(constraint->v->el[0], constraint->v->el[0], 1);
584         return constraint;
585 }
586
587 int isl_constraint_is_equality(struct isl_constraint *constraint)
588 {
589         if (!constraint)
590                 return -1;
591         return constraint->eq;
592 }
593
594 int isl_constraint_is_div_constraint(__isl_keep isl_constraint *constraint)
595 {
596         int i;
597         int n_div;
598
599         if (!constraint)
600                 return -1;
601         if (isl_constraint_is_equality(constraint))
602                 return 0;
603         n_div = isl_constraint_dim(constraint, isl_dim_div);
604         for (i = 0; i < n_div; ++i) {
605                 if (isl_local_space_is_div_constraint(constraint->ls,
606                                                         constraint->v->el, i))
607                         return 1;
608         }
609
610         return 0;
611 }
612
613 /* We manually set ISL_BASIC_SET_FINAL instead of calling
614  * isl_basic_map_finalize because we want to keep the position
615  * of the divs and we therefore do not want to throw away redundant divs.
616  * This is arguably a bit fragile.
617  */
618 __isl_give isl_basic_map *isl_basic_map_from_constraint(
619         __isl_take isl_constraint *constraint)
620 {
621         int k;
622         isl_local_space *ls;
623         struct isl_basic_map *bmap;
624         isl_int *c;
625         unsigned total;
626
627         if (!constraint)
628                 return NULL;
629
630         ls = isl_local_space_copy(constraint->ls);
631         bmap = isl_basic_map_from_local_space(ls);
632         bmap = isl_basic_map_extend_constraints(bmap, 1, 1);
633         if (isl_constraint_is_equality(constraint)) {
634                 k = isl_basic_map_alloc_equality(bmap);
635                 if (k < 0)
636                         goto error;
637                 c = bmap->eq[k];
638         }
639         else {
640                 k = isl_basic_map_alloc_inequality(bmap);
641                 if (k < 0)
642                         goto error;
643                 c = bmap->ineq[k];
644         }
645         total = isl_basic_map_total_dim(bmap);
646         isl_seq_cpy(c, constraint->v->el, 1 + total);
647         isl_constraint_free(constraint);
648         if (bmap)
649                 ISL_F_SET(bmap, ISL_BASIC_SET_FINAL);
650         return bmap;
651 error:
652         isl_constraint_free(constraint);
653         isl_basic_map_free(bmap);
654         return NULL;
655 }
656
657 struct isl_basic_set *isl_basic_set_from_constraint(
658         struct isl_constraint *constraint)
659 {
660         if (!constraint)
661                 return NULL;
662
663         if (isl_constraint_dim(constraint, isl_dim_in) != 0)
664                 isl_die(isl_constraint_get_ctx(constraint), isl_error_invalid,
665                         "not a set constraint",
666                         return isl_constraint_free(constraint));
667         return (isl_basic_set *)isl_basic_map_from_constraint(constraint);
668 }
669
670 int isl_basic_map_has_defining_equality(
671         __isl_keep isl_basic_map *bmap, enum isl_dim_type type, int pos,
672         __isl_give isl_constraint **c)
673 {
674         int i;
675         unsigned offset;
676         unsigned total;
677
678         if (!bmap)
679                 return -1;
680         offset = basic_map_offset(bmap, type);
681         total = isl_basic_map_total_dim(bmap);
682         isl_assert(bmap->ctx, pos < isl_basic_map_dim(bmap, type), return -1);
683         for (i = 0; i < bmap->n_eq; ++i)
684                 if (!isl_int_is_zero(bmap->eq[i][offset + pos]) &&
685                     isl_seq_first_non_zero(bmap->eq[i]+offset+pos+1,
686                                            1+total-offset-pos-1) == -1) {
687                         *c = isl_basic_map_constraint(isl_basic_map_copy(bmap),
688                                                                 &bmap->eq[i]);
689                         return 1;
690                 }
691         return 0;
692 }
693
694 int isl_basic_set_has_defining_equality(
695         __isl_keep isl_basic_set *bset, enum isl_dim_type type, int pos,
696         __isl_give isl_constraint **c)
697 {
698         return isl_basic_map_has_defining_equality((isl_basic_map *)bset,
699                                                     type, pos, c);
700 }
701
702 int isl_basic_set_has_defining_inequalities(
703         struct isl_basic_set *bset, enum isl_dim_type type, int pos,
704         struct isl_constraint **lower,
705         struct isl_constraint **upper)
706 {
707         int i, j;
708         unsigned offset;
709         unsigned total;
710         isl_int m;
711         isl_int **lower_line, **upper_line;
712
713         if (!bset)
714                 return -1;
715         offset = basic_set_offset(bset, type);
716         total = isl_basic_set_total_dim(bset);
717         isl_assert(bset->ctx, pos < isl_basic_set_dim(bset, type), return -1);
718         isl_int_init(m);
719         for (i = 0; i < bset->n_ineq; ++i) {
720                 if (isl_int_is_zero(bset->ineq[i][offset + pos]))
721                         continue;
722                 if (isl_int_is_one(bset->ineq[i][offset + pos]))
723                         continue;
724                 if (isl_int_is_negone(bset->ineq[i][offset + pos]))
725                         continue;
726                 if (isl_seq_first_non_zero(bset->ineq[i]+offset+pos+1,
727                                                 1+total-offset-pos-1) != -1)
728                         continue;
729                 for (j = i + 1; j < bset->n_ineq; ++j) {
730                         if (!isl_seq_is_neg(bset->ineq[i]+1, bset->ineq[j]+1,
731                                             total))
732                                 continue;
733                         isl_int_add(m, bset->ineq[i][0], bset->ineq[j][0]);
734                         if (isl_int_abs_ge(m, bset->ineq[i][offset+pos]))
735                                 continue;
736
737                         if (isl_int_is_pos(bset->ineq[i][offset+pos])) {
738                                 lower_line = &bset->ineq[i];
739                                 upper_line = &bset->ineq[j];
740                         } else {
741                                 lower_line = &bset->ineq[j];
742                                 upper_line = &bset->ineq[i];
743                         }
744                         *lower = isl_basic_set_constraint(
745                                         isl_basic_set_copy(bset), lower_line);
746                         *upper = isl_basic_set_constraint(
747                                         isl_basic_set_copy(bset), upper_line);
748                         isl_int_clear(m);
749                         return 1;
750                 }
751         }
752         *lower = NULL;
753         *upper = NULL;
754         isl_int_clear(m);
755         return 0;
756 }
757
758 /* Given two constraints "a" and "b" on the variable at position "abs_pos"
759  * (in "a" and "b"), add a constraint to "bset" that ensures that the
760  * bound implied by "a" is (strictly) larger than the bound implied by "b".
761  *
762  * If both constraints imply lower bounds, then this means that "a" is
763  * active in the result.
764  * If both constraints imply upper bounds, then this means that "b" is
765  * active in the result.
766  */
767 static __isl_give isl_basic_set *add_larger_bound_constraint(
768         __isl_take isl_basic_set *bset, isl_int *a, isl_int *b,
769         unsigned abs_pos, int strict)
770 {
771         int k;
772         isl_int t;
773         unsigned total;
774
775         k = isl_basic_set_alloc_inequality(bset);
776         if (k < 0)
777                 goto error;
778
779         total = isl_basic_set_dim(bset, isl_dim_all);
780
781         isl_int_init(t);
782         isl_int_neg(t, b[1 + abs_pos]);
783
784         isl_seq_combine(bset->ineq[k], t, a, a[1 + abs_pos], b, 1 + abs_pos);
785         isl_seq_combine(bset->ineq[k] + 1 + abs_pos,
786                 t, a + 1 + abs_pos + 1, a[1 + abs_pos], b + 1 + abs_pos + 1,
787                 total - abs_pos);
788
789         if (strict)
790                 isl_int_sub_ui(bset->ineq[k][0], bset->ineq[k][0], 1);
791
792         isl_int_clear(t);
793
794         return bset;
795 error:
796         isl_basic_set_free(bset);
797         return NULL;
798 }
799
800 /* Add constraints to "context" that ensure that "u" is the smallest
801  * (and therefore active) upper bound on "abs_pos" in "bset" and return
802  * the resulting basic set.
803  */
804 static __isl_give isl_basic_set *set_smallest_upper_bound(
805         __isl_keep isl_basic_set *context,
806         __isl_keep isl_basic_set *bset, unsigned abs_pos, int n_upper, int u)
807 {
808         int j;
809
810         context = isl_basic_set_copy(context);
811         context = isl_basic_set_cow(context);
812
813         context = isl_basic_set_extend_constraints(context, 0, n_upper - 1);
814
815         for (j = 0; j < bset->n_ineq; ++j) {
816                 if (j == u)
817                         continue;
818                 if (!isl_int_is_neg(bset->ineq[j][1 + abs_pos]))
819                         continue;
820                 context = add_larger_bound_constraint(context,
821                         bset->ineq[j], bset->ineq[u], abs_pos, j > u);
822         }
823
824         context = isl_basic_set_simplify(context);
825         context = isl_basic_set_finalize(context);
826
827         return context;
828 }
829
830 /* Add constraints to "context" that ensure that "u" is the largest
831  * (and therefore active) upper bound on "abs_pos" in "bset" and return
832  * the resulting basic set.
833  */
834 static __isl_give isl_basic_set *set_largest_lower_bound(
835         __isl_keep isl_basic_set *context,
836         __isl_keep isl_basic_set *bset, unsigned abs_pos, int n_lower, int l)
837 {
838         int j;
839
840         context = isl_basic_set_copy(context);
841         context = isl_basic_set_cow(context);
842
843         context = isl_basic_set_extend_constraints(context, 0, n_lower - 1);
844
845         for (j = 0; j < bset->n_ineq; ++j) {
846                 if (j == l)
847                         continue;
848                 if (!isl_int_is_pos(bset->ineq[j][1 + abs_pos]))
849                         continue;
850                 context = add_larger_bound_constraint(context,
851                         bset->ineq[l], bset->ineq[j], abs_pos, j > l);
852         }
853
854         context = isl_basic_set_simplify(context);
855         context = isl_basic_set_finalize(context);
856
857         return context;
858 }
859
860 static int foreach_upper_bound(__isl_keep isl_basic_set *bset,
861         enum isl_dim_type type, unsigned abs_pos,
862         __isl_take isl_basic_set *context, int n_upper,
863         int (*fn)(__isl_take isl_constraint *lower,
864                   __isl_take isl_constraint *upper,
865                   __isl_take isl_basic_set *bset, void *user), void *user)
866 {
867         isl_basic_set *context_i;
868         isl_constraint *upper = NULL;
869         int i;
870
871         for (i = 0; i < bset->n_ineq; ++i) {
872                 if (isl_int_is_zero(bset->ineq[i][1 + abs_pos]))
873                         continue;
874
875                 context_i = set_smallest_upper_bound(context, bset,
876                                                         abs_pos, n_upper, i);
877                 if (isl_basic_set_is_empty(context_i)) {
878                         isl_basic_set_free(context_i);
879                         continue;
880                 }
881                 upper = isl_basic_set_constraint(isl_basic_set_copy(bset),
882                                                 &bset->ineq[i]);
883                 if (!upper || !context_i)
884                         goto error;
885                 if (fn(NULL, upper, context_i, user) < 0)
886                         break;
887         }
888
889         isl_basic_set_free(context);
890
891         if (i < bset->n_ineq)
892                 return -1;
893
894         return 0;
895 error:
896         isl_constraint_free(upper);
897         isl_basic_set_free(context_i);
898         isl_basic_set_free(context);
899         return -1;
900 }
901
902 static int foreach_lower_bound(__isl_keep isl_basic_set *bset,
903         enum isl_dim_type type, unsigned abs_pos,
904         __isl_take isl_basic_set *context, int n_lower,
905         int (*fn)(__isl_take isl_constraint *lower,
906                   __isl_take isl_constraint *upper,
907                   __isl_take isl_basic_set *bset, void *user), void *user)
908 {
909         isl_basic_set *context_i;
910         isl_constraint *lower = NULL;
911         int i;
912
913         for (i = 0; i < bset->n_ineq; ++i) {
914                 if (isl_int_is_zero(bset->ineq[i][1 + abs_pos]))
915                         continue;
916
917                 context_i = set_largest_lower_bound(context, bset,
918                                                         abs_pos, n_lower, i);
919                 if (isl_basic_set_is_empty(context_i)) {
920                         isl_basic_set_free(context_i);
921                         continue;
922                 }
923                 lower = isl_basic_set_constraint(isl_basic_set_copy(bset),
924                                                 &bset->ineq[i]);
925                 if (!lower || !context_i)
926                         goto error;
927                 if (fn(lower, NULL, context_i, user) < 0)
928                         break;
929         }
930
931         isl_basic_set_free(context);
932
933         if (i < bset->n_ineq)
934                 return -1;
935
936         return 0;
937 error:
938         isl_constraint_free(lower);
939         isl_basic_set_free(context_i);
940         isl_basic_set_free(context);
941         return -1;
942 }
943
944 static int foreach_bound_pair(__isl_keep isl_basic_set *bset,
945         enum isl_dim_type type, unsigned abs_pos,
946         __isl_take isl_basic_set *context, int n_lower, int n_upper,
947         int (*fn)(__isl_take isl_constraint *lower,
948                   __isl_take isl_constraint *upper,
949                   __isl_take isl_basic_set *bset, void *user), void *user)
950 {
951         isl_basic_set *context_i, *context_j;
952         isl_constraint *lower = NULL;
953         isl_constraint *upper = NULL;
954         int i, j;
955
956         for (i = 0; i < bset->n_ineq; ++i) {
957                 if (!isl_int_is_pos(bset->ineq[i][1 + abs_pos]))
958                         continue;
959
960                 context_i = set_largest_lower_bound(context, bset,
961                                                         abs_pos, n_lower, i);
962                 if (isl_basic_set_is_empty(context_i)) {
963                         isl_basic_set_free(context_i);
964                         continue;
965                 }
966
967                 for (j = 0; j < bset->n_ineq; ++j) {
968                         if (!isl_int_is_neg(bset->ineq[j][1 + abs_pos]))
969                                 continue;
970
971                         context_j = set_smallest_upper_bound(context_i, bset,
972                                                             abs_pos, n_upper, j);
973                         context_j = isl_basic_set_extend_constraints(context_j,
974                                                                         0, 1);
975                         context_j = add_larger_bound_constraint(context_j,
976                                 bset->ineq[i], bset->ineq[j], abs_pos, 0);
977                         context_j = isl_basic_set_simplify(context_j);
978                         context_j = isl_basic_set_finalize(context_j);
979                         if (isl_basic_set_is_empty(context_j)) {
980                                 isl_basic_set_free(context_j);
981                                 continue;
982                         }
983                         lower = isl_basic_set_constraint(isl_basic_set_copy(bset),
984                                                         &bset->ineq[i]);
985                         upper = isl_basic_set_constraint(isl_basic_set_copy(bset),
986                                                         &bset->ineq[j]);
987                         if (!lower || !upper || !context_j)
988                                 goto error;
989                         if (fn(lower, upper, context_j, user) < 0)
990                                 break;
991                 }
992
993                 isl_basic_set_free(context_i);
994
995                 if (j < bset->n_ineq)
996                         break;
997         }
998
999         isl_basic_set_free(context);
1000
1001         if (i < bset->n_ineq)
1002                 return -1;
1003
1004         return 0;
1005 error:
1006         isl_constraint_free(lower);
1007         isl_constraint_free(upper);
1008         isl_basic_set_free(context_i);
1009         isl_basic_set_free(context_j);
1010         isl_basic_set_free(context);
1011         return -1;
1012 }
1013
1014 /* For each pair of lower and upper bounds on the variable "pos"
1015  * of type "type", call "fn" with these lower and upper bounds and the
1016  * set of constraints on the remaining variables where these bounds
1017  * are active, i.e., (stricly) larger/smaller than the other lower/upper bounds.
1018  *
1019  * If the designated variable is equal to an affine combination of the
1020  * other variables then fn is called with both lower and upper
1021  * set to the corresponding equality.
1022  *
1023  * If there is no lower (or upper) bound, then NULL is passed
1024  * as the corresponding bound.
1025  *
1026  * We first check if the variable is involved in any equality.
1027  * If not, we count the number of lower and upper bounds and
1028  * act accordingly.
1029  */
1030 int isl_basic_set_foreach_bound_pair(__isl_keep isl_basic_set *bset,
1031         enum isl_dim_type type, unsigned pos,
1032         int (*fn)(__isl_take isl_constraint *lower,
1033                   __isl_take isl_constraint *upper,
1034                   __isl_take isl_basic_set *bset, void *user), void *user)
1035 {
1036         int i;
1037         isl_constraint *lower = NULL;
1038         isl_constraint *upper = NULL;
1039         isl_basic_set *context = NULL;
1040         unsigned abs_pos;
1041         int n_lower, n_upper;
1042
1043         if (!bset)
1044                 return -1;
1045         isl_assert(bset->ctx, pos < isl_basic_set_dim(bset, type), return -1);
1046         isl_assert(bset->ctx, type == isl_dim_param || type == isl_dim_set,
1047                 return -1);
1048
1049         abs_pos = pos;
1050         if (type == isl_dim_set)
1051                 abs_pos += isl_basic_set_dim(bset, isl_dim_param);
1052
1053         for (i = 0; i < bset->n_eq; ++i) {
1054                 if (isl_int_is_zero(bset->eq[i][1 + abs_pos]))
1055                         continue;
1056
1057                 lower = isl_basic_set_constraint(isl_basic_set_copy(bset),
1058                                                 &bset->eq[i]);
1059                 upper = isl_constraint_copy(lower);
1060                 context = isl_basic_set_remove_dims(isl_basic_set_copy(bset),
1061                                         type, pos, 1);
1062                 if (!lower || !upper || !context)
1063                         goto error;
1064                 return fn(lower, upper, context, user);
1065         }
1066
1067         n_lower = 0;
1068         n_upper = 0;
1069         for (i = 0; i < bset->n_ineq; ++i) {
1070                 if (isl_int_is_pos(bset->ineq[i][1 + abs_pos]))
1071                         n_lower++;
1072                 else if (isl_int_is_neg(bset->ineq[i][1 + abs_pos]))
1073                         n_upper++;
1074         }
1075
1076         context = isl_basic_set_copy(bset);
1077         context = isl_basic_set_cow(context);
1078         if (!context)
1079                 goto error;
1080         for (i = context->n_ineq - 1; i >= 0; --i)
1081                 if (!isl_int_is_zero(context->ineq[i][1 + abs_pos]))
1082                         isl_basic_set_drop_inequality(context, i);
1083
1084         context = isl_basic_set_drop(context, type, pos, 1);
1085         if (!n_lower && !n_upper)
1086                 return fn(NULL, NULL, context, user);
1087         if (!n_lower)
1088                 return foreach_upper_bound(bset, type, abs_pos, context, n_upper,
1089                                                 fn, user);
1090         if (!n_upper)
1091                 return foreach_lower_bound(bset, type, abs_pos, context, n_lower,
1092                                                 fn, user);
1093         return foreach_bound_pair(bset, type, abs_pos, context, n_lower, n_upper,
1094                                         fn, user);
1095 error:
1096         isl_constraint_free(lower);
1097         isl_constraint_free(upper);
1098         isl_basic_set_free(context);
1099         return -1;
1100 }
1101
1102 __isl_give isl_aff *isl_constraint_get_bound(
1103         __isl_keep isl_constraint *constraint, enum isl_dim_type type, int pos)
1104 {
1105         isl_aff *aff;
1106         isl_ctx *ctx;
1107
1108         if (!constraint)
1109                 return NULL;
1110         ctx = isl_constraint_get_ctx(constraint);
1111         if (pos >= isl_constraint_dim(constraint, type))
1112                 isl_die(ctx, isl_error_invalid,
1113                         "index out of bounds", return NULL);
1114         if (isl_constraint_dim(constraint, isl_dim_in) != 0)
1115                 isl_die(ctx, isl_error_invalid,
1116                         "not a set constraint", return NULL);
1117
1118         pos += offset(constraint, type);
1119         if (isl_int_is_zero(constraint->v->el[pos]))
1120                 isl_die(ctx, isl_error_invalid,
1121                         "constraint does not define a bound on given dimension",
1122                         return NULL);
1123
1124         aff = isl_aff_alloc(isl_local_space_copy(constraint->ls));
1125         if (!aff)
1126                 return NULL;
1127
1128         if (isl_int_is_neg(constraint->v->el[pos]))
1129                 isl_seq_cpy(aff->v->el + 1, constraint->v->el, aff->v->size - 1);
1130         else
1131                 isl_seq_neg(aff->v->el + 1, constraint->v->el, aff->v->size - 1);
1132         isl_int_set_si(aff->v->el[1 + pos], 0);
1133         isl_int_abs(aff->v->el[0], constraint->v->el[pos]);
1134
1135         return aff;
1136 }
1137
1138 /* For an inequality constraint
1139  *
1140  *      f >= 0
1141  *
1142  * or an equality constraint
1143  *
1144  *      f = 0
1145  *
1146  * return the affine expression f.
1147  */
1148 __isl_give isl_aff *isl_constraint_get_aff(
1149         __isl_keep isl_constraint *constraint)
1150 {
1151         isl_aff *aff;
1152
1153         if (!constraint)
1154                 return NULL;
1155
1156         aff = isl_aff_alloc(isl_local_space_copy(constraint->ls));
1157         if (!aff)
1158                 return NULL;
1159
1160         isl_seq_cpy(aff->v->el + 1, constraint->v->el, aff->v->size - 1);
1161         isl_int_set_si(aff->v->el[0], 1);
1162
1163         return aff;
1164 }
1165
1166 /* Construct an equality constraint equating the given affine expression
1167  * to zero.
1168  */
1169 __isl_give isl_constraint *isl_equality_from_aff(__isl_take isl_aff *aff)
1170 {
1171         int k;
1172         isl_local_space *ls;
1173         isl_basic_set *bset;
1174
1175         if (!aff)
1176                 return NULL;
1177
1178         ls = isl_aff_get_domain_local_space(aff);
1179         bset = isl_basic_set_from_local_space(ls);
1180         bset = isl_basic_set_extend_constraints(bset, 1, 0);
1181         k = isl_basic_set_alloc_equality(bset);
1182         if (k < 0)
1183                 goto error;
1184
1185         isl_seq_cpy(bset->eq[k], aff->v->el + 1, aff->v->size - 1);
1186         isl_aff_free(aff);
1187
1188         return isl_basic_set_constraint(bset, &bset->eq[k]);
1189 error:
1190         isl_aff_free(aff);
1191         isl_basic_set_free(bset);
1192         return NULL;
1193 }
1194
1195 /* Construct an inequality constraint enforcing the given affine expression
1196  * to be non-negative.
1197  */
1198 __isl_give isl_constraint *isl_inequality_from_aff(__isl_take isl_aff *aff)
1199 {
1200         int k;
1201         isl_local_space *ls;
1202         isl_basic_set *bset;
1203
1204         if (!aff)
1205                 return NULL;
1206
1207         ls = isl_aff_get_domain_local_space(aff);
1208         bset = isl_basic_set_from_local_space(ls);
1209         bset = isl_basic_set_extend_constraints(bset, 0, 1);
1210         k = isl_basic_set_alloc_inequality(bset);
1211         if (k < 0)
1212                 goto error;
1213
1214         isl_seq_cpy(bset->ineq[k], aff->v->el + 1, aff->v->size - 1);
1215         isl_aff_free(aff);
1216
1217         return isl_basic_set_constraint(bset, &bset->ineq[k]);
1218 error:
1219         isl_aff_free(aff);
1220         isl_basic_set_free(bset);
1221         return NULL;
1222 }