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