change calling conventions of isl_basic_set_has_defining_{,in}equalit{y,ies}
[platform/upstream/isl.git] / isl_constraint.c
1 #include <isl_constraint.h>
2 #include "isl_map_private.h"
3
4 static unsigned n(struct isl_constraint *c, enum isl_dim_type type)
5 {
6         return isl_basic_map_dim(c->bmap, type);
7 }
8
9 static unsigned offset(struct isl_constraint *c, enum isl_dim_type type)
10 {
11         struct isl_dim *dim = c->bmap->dim;
12         switch (type) {
13         case isl_dim_param:     return 1;
14         case isl_dim_in:        return 1 + dim->nparam;
15         case isl_dim_out:       return 1 + dim->nparam + dim->n_in;
16         case isl_dim_div:       return 1 + dim->nparam + dim->n_in + dim->n_out;
17         }
18 }
19
20 static unsigned basic_set_offset(struct isl_basic_set *bset,
21                                                         enum isl_dim_type type)
22 {
23         struct isl_dim *dim = bset->dim;
24         switch (type) {
25         case isl_dim_param:     return 1;
26         case isl_dim_in:        return 1 + dim->nparam;
27         case isl_dim_out:       return 1 + dim->nparam + dim->n_in;
28         case isl_dim_div:       return 1 + dim->nparam + dim->n_in + dim->n_out;
29         }
30 }
31
32 struct isl_constraint *isl_basic_map_constraint(struct isl_basic_map *bmap,
33         isl_int **line)
34 {
35         struct isl_constraint *constraint;
36
37         if (!bmap || !line)
38                 goto error;
39         
40         constraint = isl_alloc_type(bmap->ctx, struct isl_constraint);
41         if (!constraint)
42                 goto error;
43
44         constraint->ctx = bmap->ctx;
45         isl_ctx_ref(constraint->ctx);
46         constraint->ref = 1;
47         constraint->bmap = bmap;
48         constraint->line = line;
49
50         return constraint;
51 error:
52         isl_basic_map_free(bmap);
53         return NULL;
54 }
55
56 struct isl_constraint *isl_basic_set_constraint(struct isl_basic_set *bset,
57         isl_int **line)
58 {
59         return isl_basic_map_constraint((struct isl_basic_map *)bset, line);
60 }
61
62 struct isl_constraint *isl_equality_alloc(struct isl_dim *dim)
63 {
64         struct isl_basic_map *bmap;
65
66         if (!dim)
67                 return NULL;
68
69         bmap = isl_basic_map_alloc_dim(dim, 0, 1, 0);
70         if (!bmap)
71                 return NULL;
72
73         isl_basic_map_alloc_equality(bmap);
74         isl_seq_clr(bmap->eq[0], 1 + isl_basic_map_total_dim(bmap));
75         return isl_basic_map_constraint(bmap, &bmap->eq[0]);
76 }
77
78 struct isl_constraint *isl_inequality_alloc(struct isl_dim *dim)
79 {
80         struct isl_basic_map *bmap;
81
82         if (!dim)
83                 return NULL;
84
85         bmap = isl_basic_map_alloc_dim(dim, 0, 0, 1);
86         if (!bmap)
87                 return NULL;
88
89         isl_basic_map_alloc_inequality(bmap);
90         isl_seq_clr(bmap->ineq[0], 1 + isl_basic_map_total_dim(bmap));
91         return isl_basic_map_constraint(bmap, &bmap->ineq[0]);
92 }
93
94 struct isl_constraint *isl_constraint_dup(struct isl_constraint *c)
95 {
96         if (!c)
97                 return NULL;
98
99         return isl_basic_map_constraint(isl_basic_map_copy(c->bmap), c->line);
100 }
101
102 struct isl_constraint *isl_constraint_cow(struct isl_constraint *c)
103 {
104         if (!c)
105                 return NULL;
106
107         if (c->ref == 1)
108                 return c;
109         c->ref--;
110         return isl_constraint_dup(c);
111 }
112
113 struct isl_constraint *isl_constraint_copy(struct isl_constraint *constraint)
114 {
115         if (!constraint)
116                 return NULL;
117
118         constraint->ref++;
119         return constraint;
120 }
121
122 struct isl_constraint *isl_constraint_free(struct isl_constraint *c)
123 {
124         if (!c)
125                 return;
126
127         if (--c->ref > 0)
128                 return;
129
130         isl_basic_map_free(c->bmap);
131         isl_ctx_deref(c->ctx);
132         free(c);
133 }
134
135 struct isl_constraint *isl_basic_set_first_constraint(
136         struct isl_basic_set *bset)
137 {
138         struct isl_constraint *c;
139
140         if (!bset)
141                 return NULL;
142
143         if (bset->n_eq > 0)
144                 return isl_basic_set_constraint(bset, &bset->eq[0]);
145
146         if (bset->n_ineq > 0)
147                 return isl_basic_set_constraint(bset, &bset->ineq[0]);
148
149         isl_basic_set_free(bset);
150         return NULL;
151 }
152
153 struct isl_constraint *isl_constraint_next(struct isl_constraint *c)
154 {
155         c = isl_constraint_cow(c);
156         c->line++;
157         if (c->line >= c->bmap->eq + c->bmap->n_eq && c->line < c->bmap->ineq)
158                 c->line = c->bmap->ineq;
159         if (c->line < c->bmap->ineq + c->bmap->n_ineq)
160                 return c;
161         isl_constraint_free(c);
162         return NULL;
163 }
164
165 int isl_constraint_is_equal(struct isl_constraint *constraint1,
166         struct isl_constraint *constraint2)
167 {
168         if (!constraint1 || !constraint2)
169                 return 0;
170         return constraint1->bmap == constraint2->bmap &&
171                constraint1->line == constraint2->line;
172 }
173
174 struct isl_basic_set *isl_basic_set_add_constraint(
175         struct isl_basic_set *bset, struct isl_constraint *constraint)
176 {
177         if (!bset || !constraint)
178                 goto error;
179
180         isl_assert(constraint->ctx,
181                 isl_dim_equal(bset->dim, constraint->bmap->dim), goto error);
182
183         bset = isl_basic_set_intersect(bset,
184                 isl_basic_set_copy((struct isl_basic_set *)constraint->bmap));
185         isl_constraint_free(constraint);
186         return bset;
187 error:
188         isl_basic_set_free(bset);
189         isl_constraint_free(constraint);
190         return NULL;
191 }
192
193 int isl_constraint_dim(struct isl_constraint *constraint,
194         enum isl_dim_type type)
195 {
196         if (!constraint)
197                 return -1;
198         return n(constraint, type);
199 }
200
201 void isl_constraint_get_constant(struct isl_constraint *constraint, isl_int *v)
202 {
203         if (!constraint)
204                 return;
205         isl_int_set(*v, constraint->line[0][0]);
206 }
207
208 void isl_constraint_get_coefficient(struct isl_constraint *constraint,
209         enum isl_dim_type type, int pos, isl_int *v)
210 {
211         if (!constraint)
212                 return;
213
214         isl_assert(constraint->ctx, pos < n(constraint, type), return);
215         isl_int_set(*v, constraint->line[0][offset(constraint, type) + pos]);
216 }
217
218 struct isl_div *isl_constraint_div(struct isl_constraint *constraint, int pos)
219 {
220         if (!constraint)
221                 return NULL;
222
223         isl_assert(constraint->ctx, pos < n(constraint, isl_dim_div),
224                         return NULL);
225         return isl_basic_map_div(constraint->bmap, constraint->bmap->div+pos);
226 }
227
228 void isl_constraint_set_constant(struct isl_constraint *constraint, isl_int v)
229 {
230         if (!constraint)
231                 return;
232         isl_int_set(constraint->line[0][0], v);
233 }
234
235 void isl_constraint_set_coefficient(struct isl_constraint *constraint,
236         enum isl_dim_type type, int pos, isl_int v)
237 {
238         if (!constraint)
239                 return;
240
241         isl_assert(constraint->ctx, pos < n(constraint, type), return);
242         isl_int_set(constraint->line[0][offset(constraint, type) + pos], v);
243 }
244
245 void isl_constraint_clear(struct isl_constraint *constraint)
246 {
247         struct isl_basic_set *bset;
248         unsigned total;
249
250         if (!constraint)
251                 return;
252         total = isl_basic_map_total_dim(constraint->bmap);
253         isl_seq_clr(constraint->line[0], 1 + total);
254 }
255
256 struct isl_constraint *isl_constraint_negate(struct isl_constraint *constraint)
257 {
258         unsigned total;
259
260         if (!constraint)
261                 return NULL;
262
263         isl_assert(constraint->ctx, !isl_constraint_is_equality(constraint),
264                         goto error);
265         isl_assert(constraint->ctx, constraint->bmap->ref == 1, goto error);
266         total = isl_basic_map_total_dim(constraint->bmap);
267         isl_seq_neg(constraint->line[0], constraint->line[0], 1 + total);
268         isl_int_sub_ui(constraint->line[0][0], constraint->line[0][0], 1);
269         F_CLR(constraint->bmap, ISL_BASIC_MAP_NORMALIZED);
270         return constraint;
271 error:
272         isl_constraint_free(constraint);
273         return NULL;
274 }
275
276 int isl_constraint_is_equality(struct isl_constraint *constraint)
277 {
278         if (!constraint)
279                 return -1;
280         return constraint->line < constraint->bmap->eq + constraint->bmap->n_eq;
281 }
282
283
284 struct isl_basic_set *isl_basic_set_from_constraint(
285         struct isl_constraint *constraint)
286 {
287         int k;
288         struct isl_basic_set *constraint_bset, *bset;
289         isl_int *c;
290         unsigned dim;
291         unsigned nparam;
292         unsigned total;
293
294         if (!constraint)
295                 return NULL;
296
297         isl_assert(constraint->ctx,n(constraint, isl_dim_in) == 0, goto error);
298
299         constraint_bset = (struct isl_basic_set *)constraint->bmap;
300         bset = isl_basic_set_universe_like(constraint_bset);
301         bset = isl_basic_set_align_divs(bset, constraint_bset);
302         nparam = isl_basic_set_n_param(bset);
303         dim = isl_basic_set_n_dim(bset);
304         bset = isl_basic_set_extend(bset, nparam, dim, 0, 1, 1);
305         if (isl_constraint_is_equality(constraint)) {
306                 k = isl_basic_set_alloc_equality(bset);
307                 if (k < 0)
308                         goto error;
309                 c = bset->eq[k];
310         }
311         else {
312                 k = isl_basic_set_alloc_inequality(bset);
313                 if (k < 0)
314                         goto error;
315                 c = bset->ineq[k];
316         }
317         total = isl_basic_set_total_dim(bset);
318         isl_seq_cpy(c, constraint->line[0], 1 + total);
319         isl_constraint_free(constraint);
320         return bset;
321 error:
322         isl_constraint_free(constraint);
323         isl_basic_set_free(bset);
324         return NULL;
325 }
326
327 int isl_basic_set_has_defining_equality(
328         struct isl_basic_set *bset, enum isl_dim_type type, int pos,
329         struct isl_constraint **c)
330 {
331         int i;
332         unsigned offset;
333         unsigned total;
334
335         if (!bset)
336                 return -1;
337         offset = basic_set_offset(bset, type);
338         total = isl_basic_set_total_dim(bset);
339         isl_assert(bset->ctx, pos < isl_basic_set_dim(bset, type), return -1);
340         for (i = 0; i < bset->n_eq; ++i)
341                 if (!isl_int_is_zero(bset->eq[i][offset + pos]) &&
342                     isl_seq_first_non_zero(bset->eq[i]+offset+pos+1,
343                                            1+total-offset-pos-1) == -1) {
344                         *c= isl_basic_set_constraint(isl_basic_set_copy(bset),
345                                                                 &bset->eq[i]);
346                         return 1;
347                 }
348         return 0;
349 }
350
351 int isl_basic_set_has_defining_inequalities(
352         struct isl_basic_set *bset, enum isl_dim_type type, int pos,
353         struct isl_constraint **lower,
354         struct isl_constraint **upper)
355 {
356         int i, j;
357         unsigned offset;
358         unsigned total;
359         isl_int m;
360         isl_int **lower_line, **upper_line;
361
362         if (!bset)
363                 return -1;
364         offset = basic_set_offset(bset, type);
365         total = isl_basic_set_total_dim(bset);
366         isl_assert(bset->ctx, pos < isl_basic_set_dim(bset, type), return -1);
367         isl_int_init(m);
368         for (i = 0; i < bset->n_ineq; ++i) {
369                 if (isl_int_is_zero(bset->ineq[i][offset + pos]))
370                         continue;
371                 if (isl_int_is_one(bset->ineq[i][offset + pos]))
372                         continue;
373                 if (isl_int_is_negone(bset->ineq[i][offset + pos]))
374                         continue;
375                 if (isl_seq_first_non_zero(bset->ineq[i]+offset+pos+1,
376                                                 1+total-offset-pos-1) != -1)
377                         continue;
378                 for (j = i + i; j < bset->n_ineq; ++j) {
379                         if (!isl_seq_is_neg(bset->ineq[i]+1, bset->ineq[j]+1,
380                                             total))
381                                 continue;
382                         isl_int_add(m, bset->ineq[i][0], bset->ineq[j][0]);
383                         if (isl_int_abs_ge(m, bset->ineq[i][offset+pos]))
384                                 continue;
385
386                         if (isl_int_is_pos(bset->ineq[i][offset+pos])) {
387                                 lower_line = &bset->ineq[i];
388                                 upper_line = &bset->ineq[j];
389                         } else {
390                                 lower_line = &bset->ineq[j];
391                                 upper_line = &bset->ineq[i];
392                         }
393                         *lower = isl_basic_set_constraint(
394                                         isl_basic_set_copy(bset), lower_line);
395                         *upper = isl_basic_set_constraint(
396                                         isl_basic_set_copy(bset), upper_line);
397                         isl_int_clear(m);
398                         return 1;
399                 }
400         }
401         *lower = NULL;
402         *upper = NULL;
403         isl_int_clear(m);
404         return 0;
405 }