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