add isl_basic_map_from_constraint
[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 void 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         if (!bset)
140                 return NULL;
141
142         if (bset->n_eq > 0)
143                 return isl_basic_set_constraint(bset, &bset->eq[0]);
144
145         if (bset->n_ineq > 0)
146                 return isl_basic_set_constraint(bset, &bset->ineq[0]);
147
148         isl_basic_set_free(bset);
149         return NULL;
150 }
151
152 struct isl_constraint *isl_constraint_next(struct isl_constraint *c)
153 {
154         c = isl_constraint_cow(c);
155         if (c->line >= c->bmap->eq) {
156                 c->line++;
157                 if (c->line < c->bmap->eq + c->bmap->n_eq)
158                         return c;
159                 c->line = c->bmap->ineq;
160         } else
161                 c->line++;
162         if (c->line < c->bmap->ineq + c->bmap->n_ineq)
163                 return c;
164         isl_constraint_free(c);
165         return NULL;
166 }
167
168 int isl_constraint_is_equal(struct isl_constraint *constraint1,
169         struct isl_constraint *constraint2)
170 {
171         if (!constraint1 || !constraint2)
172                 return 0;
173         return constraint1->bmap == constraint2->bmap &&
174                constraint1->line == constraint2->line;
175 }
176
177 struct isl_basic_map *isl_basic_map_add_constraint(
178         struct isl_basic_map *bmap, struct isl_constraint *constraint)
179 {
180         if (!bmap || !constraint)
181                 goto error;
182
183         isl_assert(constraint->ctx,
184                 isl_dim_equal(bmap->dim, constraint->bmap->dim), goto error);
185
186         bmap = isl_basic_map_intersect(bmap,
187                                     isl_basic_map_copy(constraint->bmap));
188         isl_constraint_free(constraint);
189         return bmap;
190 error:
191         isl_basic_map_free(bmap);
192         isl_constraint_free(constraint);
193         return NULL;
194 }
195
196 struct isl_basic_set *isl_basic_set_add_constraint(
197         struct isl_basic_set *bset, struct isl_constraint *constraint)
198 {
199         return (struct isl_basic_set *)
200                 isl_basic_map_add_constraint((struct isl_basic_map *)bset,
201                                                 constraint);
202 }
203
204 struct isl_constraint *isl_constraint_add_div(struct isl_constraint *constraint,
205         struct isl_div *div, int *pos)
206 {
207         if (!constraint || !div)
208                 goto error;
209
210         isl_assert(constraint->ctx,
211             isl_dim_equal(div->bmap->dim, constraint->bmap->dim), goto error);
212         isl_assert(constraint->ctx,
213             constraint->bmap->n_eq + constraint->bmap->n_ineq == 1, goto error);
214
215         constraint->bmap = isl_basic_map_cow(constraint->bmap);
216         constraint->bmap = isl_basic_map_extend_dim(constraint->bmap,
217                                 isl_dim_copy(constraint->bmap->dim), 1, 0, 0);
218         if (!constraint->bmap)
219                 goto error;
220         constraint->line = &constraint->bmap->eq[0];
221         *pos = isl_basic_map_alloc_div(constraint->bmap);
222         if (*pos < 0)
223                 goto error;
224         isl_seq_cpy(constraint->bmap->div[*pos], div->line[0],
225                         1 + 1 + isl_basic_map_total_dim(constraint->bmap));
226         isl_div_free(div);
227         return constraint;
228 error:
229         isl_constraint_free(constraint);
230         isl_div_free(div);
231         return NULL;
232 }
233
234 int isl_constraint_dim(struct isl_constraint *constraint,
235         enum isl_dim_type type)
236 {
237         if (!constraint)
238                 return -1;
239         return n(constraint, type);
240 }
241
242 void isl_constraint_get_constant(struct isl_constraint *constraint, isl_int *v)
243 {
244         if (!constraint)
245                 return;
246         isl_int_set(*v, constraint->line[0][0]);
247 }
248
249 void isl_constraint_get_coefficient(struct isl_constraint *constraint,
250         enum isl_dim_type type, int pos, isl_int *v)
251 {
252         if (!constraint)
253                 return;
254
255         isl_assert(constraint->ctx, pos < n(constraint, type), return);
256         isl_int_set(*v, constraint->line[0][offset(constraint, type) + pos]);
257 }
258
259 struct isl_div *isl_constraint_div(struct isl_constraint *constraint, int pos)
260 {
261         if (!constraint)
262                 return NULL;
263
264         isl_assert(constraint->ctx, pos < n(constraint, isl_dim_div),
265                         return NULL);
266         return isl_basic_map_div(isl_basic_map_copy(constraint->bmap), pos);
267 }
268
269 void isl_constraint_set_constant(struct isl_constraint *constraint, isl_int v)
270 {
271         if (!constraint)
272                 return;
273         isl_int_set(constraint->line[0][0], v);
274 }
275
276 void isl_constraint_set_coefficient(struct isl_constraint *constraint,
277         enum isl_dim_type type, int pos, isl_int v)
278 {
279         if (!constraint)
280                 return;
281
282         isl_assert(constraint->ctx, pos < n(constraint, type), return);
283         isl_int_set(constraint->line[0][offset(constraint, type) + pos], v);
284 }
285
286 void isl_constraint_clear(struct isl_constraint *constraint)
287 {
288         unsigned total;
289
290         if (!constraint)
291                 return;
292         total = isl_basic_map_total_dim(constraint->bmap);
293         isl_seq_clr(constraint->line[0], 1 + total);
294 }
295
296 struct isl_constraint *isl_constraint_negate(struct isl_constraint *constraint)
297 {
298         unsigned total;
299
300         if (!constraint)
301                 return NULL;
302
303         isl_assert(constraint->ctx, !isl_constraint_is_equality(constraint),
304                         goto error);
305         isl_assert(constraint->ctx, constraint->bmap->ref == 1, goto error);
306         total = isl_basic_map_total_dim(constraint->bmap);
307         isl_seq_neg(constraint->line[0], constraint->line[0], 1 + total);
308         isl_int_sub_ui(constraint->line[0][0], constraint->line[0][0], 1);
309         ISL_F_CLR(constraint->bmap, ISL_BASIC_MAP_NORMALIZED);
310         return constraint;
311 error:
312         isl_constraint_free(constraint);
313         return NULL;
314 }
315
316 int isl_constraint_is_equality(struct isl_constraint *constraint)
317 {
318         if (!constraint)
319                 return -1;
320         return constraint->line >= constraint->bmap->eq;
321 }
322
323 __isl_give isl_basic_map *isl_basic_map_from_constraint(
324         __isl_take isl_constraint *constraint)
325 {
326         int k;
327         struct isl_basic_map *bmap;
328         isl_int *c;
329         unsigned total;
330
331         if (!constraint)
332                 return NULL;
333
334         bmap = isl_basic_map_universe_like(constraint->bmap);
335         bmap = isl_basic_map_align_divs(bmap, constraint->bmap);
336         bmap = isl_basic_map_cow(bmap);
337         bmap = isl_basic_map_extend_constraints(bmap, 1, 1);
338         if (isl_constraint_is_equality(constraint)) {
339                 k = isl_basic_map_alloc_equality(bmap);
340                 if (k < 0)
341                         goto error;
342                 c = bmap->eq[k];
343         }
344         else {
345                 k = isl_basic_map_alloc_inequality(bmap);
346                 if (k < 0)
347                         goto error;
348                 c = bmap->ineq[k];
349         }
350         total = isl_basic_map_total_dim(bmap);
351         isl_seq_cpy(c, constraint->line[0], 1 + total);
352         isl_constraint_free(constraint);
353         return bmap;
354 error:
355         isl_constraint_free(constraint);
356         isl_basic_map_free(bmap);
357         return NULL;
358 }
359
360 struct isl_basic_set *isl_basic_set_from_constraint(
361         struct isl_constraint *constraint)
362 {
363         if (!constraint)
364                 return NULL;
365
366         isl_assert(constraint->ctx,n(constraint, isl_dim_in) == 0, goto error);
367         return (isl_basic_set *)isl_basic_map_from_constraint(constraint);
368 error:
369         isl_constraint_free(constraint);
370         return NULL;
371 }
372
373 int isl_basic_set_has_defining_equality(
374         struct isl_basic_set *bset, enum isl_dim_type type, int pos,
375         struct isl_constraint **c)
376 {
377         int i;
378         unsigned offset;
379         unsigned total;
380
381         if (!bset)
382                 return -1;
383         offset = basic_set_offset(bset, type);
384         total = isl_basic_set_total_dim(bset);
385         isl_assert(bset->ctx, pos < isl_basic_set_dim(bset, type), return -1);
386         for (i = 0; i < bset->n_eq; ++i)
387                 if (!isl_int_is_zero(bset->eq[i][offset + pos]) &&
388                     isl_seq_first_non_zero(bset->eq[i]+offset+pos+1,
389                                            1+total-offset-pos-1) == -1) {
390                         *c= isl_basic_set_constraint(isl_basic_set_copy(bset),
391                                                                 &bset->eq[i]);
392                         return 1;
393                 }
394         return 0;
395 }
396
397 int isl_basic_set_has_defining_inequalities(
398         struct isl_basic_set *bset, enum isl_dim_type type, int pos,
399         struct isl_constraint **lower,
400         struct isl_constraint **upper)
401 {
402         int i, j;
403         unsigned offset;
404         unsigned total;
405         isl_int m;
406         isl_int **lower_line, **upper_line;
407
408         if (!bset)
409                 return -1;
410         offset = basic_set_offset(bset, type);
411         total = isl_basic_set_total_dim(bset);
412         isl_assert(bset->ctx, pos < isl_basic_set_dim(bset, type), return -1);
413         isl_int_init(m);
414         for (i = 0; i < bset->n_ineq; ++i) {
415                 if (isl_int_is_zero(bset->ineq[i][offset + pos]))
416                         continue;
417                 if (isl_int_is_one(bset->ineq[i][offset + pos]))
418                         continue;
419                 if (isl_int_is_negone(bset->ineq[i][offset + pos]))
420                         continue;
421                 if (isl_seq_first_non_zero(bset->ineq[i]+offset+pos+1,
422                                                 1+total-offset-pos-1) != -1)
423                         continue;
424                 for (j = i + 1; j < bset->n_ineq; ++j) {
425                         if (!isl_seq_is_neg(bset->ineq[i]+1, bset->ineq[j]+1,
426                                             total))
427                                 continue;
428                         isl_int_add(m, bset->ineq[i][0], bset->ineq[j][0]);
429                         if (isl_int_abs_ge(m, bset->ineq[i][offset+pos]))
430                                 continue;
431
432                         if (isl_int_is_pos(bset->ineq[i][offset+pos])) {
433                                 lower_line = &bset->ineq[i];
434                                 upper_line = &bset->ineq[j];
435                         } else {
436                                 lower_line = &bset->ineq[j];
437                                 upper_line = &bset->ineq[i];
438                         }
439                         *lower = isl_basic_set_constraint(
440                                         isl_basic_set_copy(bset), lower_line);
441                         *upper = isl_basic_set_constraint(
442                                         isl_basic_set_copy(bset), upper_line);
443                         isl_int_clear(m);
444                         return 1;
445                 }
446         }
447         *lower = NULL;
448         *upper = NULL;
449         isl_int_clear(m);
450         return 0;
451 }