isl_constraint: add limited support for adding divs
[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 struct isl_constraint *isl_constraint_add_div(struct isl_constraint *constraint,
194         struct isl_div *div, int *pos)
195 {
196         if (!constraint || !div)
197                 goto error;
198
199         isl_assert(constraint->ctx,
200             isl_dim_equal(div->bmap->dim, constraint->bmap->dim), goto error);
201         isl_assert(constraint->ctx,
202             constraint->bmap->n_eq + constraint->bmap->n_ineq == 1, goto error);
203
204         constraint->bmap = isl_basic_map_extend_dim(constraint->bmap,
205                                 isl_dim_copy(constraint->bmap->dim), 1, 0, 0);
206         if (!constraint->bmap)
207                 goto error;
208         constraint->line = &constraint->bmap->eq[0];
209         *pos = isl_basic_map_alloc_div(constraint->bmap);
210         if (*pos < 0)
211                 goto error;
212         isl_seq_cpy(constraint->bmap->div[*pos], div->line[0],
213                         1 + 1 + isl_basic_map_total_dim(constraint->bmap));
214         isl_div_free(div);
215         return constraint;
216 error:
217         isl_constraint_free(constraint);
218         isl_div_free(div);
219         return NULL;
220 }
221
222 int isl_constraint_dim(struct isl_constraint *constraint,
223         enum isl_dim_type type)
224 {
225         if (!constraint)
226                 return -1;
227         return n(constraint, type);
228 }
229
230 void isl_constraint_get_constant(struct isl_constraint *constraint, isl_int *v)
231 {
232         if (!constraint)
233                 return;
234         isl_int_set(*v, constraint->line[0][0]);
235 }
236
237 void isl_constraint_get_coefficient(struct isl_constraint *constraint,
238         enum isl_dim_type type, int pos, isl_int *v)
239 {
240         if (!constraint)
241                 return;
242
243         isl_assert(constraint->ctx, pos < n(constraint, type), return);
244         isl_int_set(*v, constraint->line[0][offset(constraint, type) + pos]);
245 }
246
247 struct isl_div *isl_constraint_div(struct isl_constraint *constraint, int pos)
248 {
249         if (!constraint)
250                 return NULL;
251
252         isl_assert(constraint->ctx, pos < n(constraint, isl_dim_div),
253                         return NULL);
254         return isl_basic_map_div(constraint->bmap, constraint->bmap->div+pos);
255 }
256
257 void isl_constraint_set_constant(struct isl_constraint *constraint, isl_int v)
258 {
259         if (!constraint)
260                 return;
261         isl_int_set(constraint->line[0][0], v);
262 }
263
264 void isl_constraint_set_coefficient(struct isl_constraint *constraint,
265         enum isl_dim_type type, int pos, isl_int v)
266 {
267         if (!constraint)
268                 return;
269
270         isl_assert(constraint->ctx, pos < n(constraint, type), return);
271         isl_int_set(constraint->line[0][offset(constraint, type) + pos], v);
272 }
273
274 void isl_constraint_clear(struct isl_constraint *constraint)
275 {
276         struct isl_basic_set *bset;
277         unsigned total;
278
279         if (!constraint)
280                 return;
281         total = isl_basic_map_total_dim(constraint->bmap);
282         isl_seq_clr(constraint->line[0], 1 + total);
283 }
284
285 struct isl_constraint *isl_constraint_negate(struct isl_constraint *constraint)
286 {
287         unsigned total;
288
289         if (!constraint)
290                 return NULL;
291
292         isl_assert(constraint->ctx, !isl_constraint_is_equality(constraint),
293                         goto error);
294         isl_assert(constraint->ctx, constraint->bmap->ref == 1, goto error);
295         total = isl_basic_map_total_dim(constraint->bmap);
296         isl_seq_neg(constraint->line[0], constraint->line[0], 1 + total);
297         isl_int_sub_ui(constraint->line[0][0], constraint->line[0][0], 1);
298         F_CLR(constraint->bmap, ISL_BASIC_MAP_NORMALIZED);
299         return constraint;
300 error:
301         isl_constraint_free(constraint);
302         return NULL;
303 }
304
305 int isl_constraint_is_equality(struct isl_constraint *constraint)
306 {
307         if (!constraint)
308                 return -1;
309         return constraint->line < constraint->bmap->eq + constraint->bmap->n_eq;
310 }
311
312
313 struct isl_basic_set *isl_basic_set_from_constraint(
314         struct isl_constraint *constraint)
315 {
316         int k;
317         struct isl_basic_set *constraint_bset, *bset;
318         isl_int *c;
319         unsigned dim;
320         unsigned nparam;
321         unsigned total;
322
323         if (!constraint)
324                 return NULL;
325
326         isl_assert(constraint->ctx,n(constraint, isl_dim_in) == 0, goto error);
327
328         constraint_bset = (struct isl_basic_set *)constraint->bmap;
329         bset = isl_basic_set_universe_like(constraint_bset);
330         bset = isl_basic_set_align_divs(bset, constraint_bset);
331         nparam = isl_basic_set_n_param(bset);
332         dim = isl_basic_set_n_dim(bset);
333         bset = isl_basic_set_extend(bset, nparam, dim, 0, 1, 1);
334         if (isl_constraint_is_equality(constraint)) {
335                 k = isl_basic_set_alloc_equality(bset);
336                 if (k < 0)
337                         goto error;
338                 c = bset->eq[k];
339         }
340         else {
341                 k = isl_basic_set_alloc_inequality(bset);
342                 if (k < 0)
343                         goto error;
344                 c = bset->ineq[k];
345         }
346         total = isl_basic_set_total_dim(bset);
347         isl_seq_cpy(c, constraint->line[0], 1 + total);
348         isl_constraint_free(constraint);
349         return bset;
350 error:
351         isl_constraint_free(constraint);
352         isl_basic_set_free(bset);
353         return NULL;
354 }
355
356 int isl_basic_set_has_defining_equality(
357         struct isl_basic_set *bset, enum isl_dim_type type, int pos,
358         struct isl_constraint **c)
359 {
360         int i;
361         unsigned offset;
362         unsigned total;
363
364         if (!bset)
365                 return -1;
366         offset = basic_set_offset(bset, type);
367         total = isl_basic_set_total_dim(bset);
368         isl_assert(bset->ctx, pos < isl_basic_set_dim(bset, type), return -1);
369         for (i = 0; i < bset->n_eq; ++i)
370                 if (!isl_int_is_zero(bset->eq[i][offset + pos]) &&
371                     isl_seq_first_non_zero(bset->eq[i]+offset+pos+1,
372                                            1+total-offset-pos-1) == -1) {
373                         *c= isl_basic_set_constraint(isl_basic_set_copy(bset),
374                                                                 &bset->eq[i]);
375                         return 1;
376                 }
377         return 0;
378 }
379
380 int isl_basic_set_has_defining_inequalities(
381         struct isl_basic_set *bset, enum isl_dim_type type, int pos,
382         struct isl_constraint **lower,
383         struct isl_constraint **upper)
384 {
385         int i, j;
386         unsigned offset;
387         unsigned total;
388         isl_int m;
389         isl_int **lower_line, **upper_line;
390
391         if (!bset)
392                 return -1;
393         offset = basic_set_offset(bset, type);
394         total = isl_basic_set_total_dim(bset);
395         isl_assert(bset->ctx, pos < isl_basic_set_dim(bset, type), return -1);
396         isl_int_init(m);
397         for (i = 0; i < bset->n_ineq; ++i) {
398                 if (isl_int_is_zero(bset->ineq[i][offset + pos]))
399                         continue;
400                 if (isl_int_is_one(bset->ineq[i][offset + pos]))
401                         continue;
402                 if (isl_int_is_negone(bset->ineq[i][offset + pos]))
403                         continue;
404                 if (isl_seq_first_non_zero(bset->ineq[i]+offset+pos+1,
405                                                 1+total-offset-pos-1) != -1)
406                         continue;
407                 for (j = i + i; j < bset->n_ineq; ++j) {
408                         if (!isl_seq_is_neg(bset->ineq[i]+1, bset->ineq[j]+1,
409                                             total))
410                                 continue;
411                         isl_int_add(m, bset->ineq[i][0], bset->ineq[j][0]);
412                         if (isl_int_abs_ge(m, bset->ineq[i][offset+pos]))
413                                 continue;
414
415                         if (isl_int_is_pos(bset->ineq[i][offset+pos])) {
416                                 lower_line = &bset->ineq[i];
417                                 upper_line = &bset->ineq[j];
418                         } else {
419                                 lower_line = &bset->ineq[j];
420                                 upper_line = &bset->ineq[i];
421                         }
422                         *lower = isl_basic_set_constraint(
423                                         isl_basic_set_copy(bset), lower_line);
424                         *upper = isl_basic_set_constraint(
425                                         isl_basic_set_copy(bset), upper_line);
426                         isl_int_clear(m);
427                         return 1;
428                 }
429         }
430         *lower = NULL;
431         *upper = NULL;
432         isl_int_clear(m);
433         return 0;
434 }