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