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